乐趣区

关于前端:前端百题斩014js中的这些this指向都值得了解

写该系列文章的初衷是“让每位前端工程师把握高频知识点,为工作助力”。这是前端百题斩的第 14 斩,心愿敌人们关注公众号“执鸢者”,用常识武装本人的头脑。

14.1 简介

this 是 javascript 中的一个关键字,其应用办法相似于一个变量,是执行上下文中一个重要组成部分。其作用是能够在函数体外部获取以后的运行环境。

14.2 指向

每个函数的 this 是在调用的时候基于函数的执行环境绑定的,this 的指向齐全取决于函数的调用地位。(上面均是在浏览器环境下进行测试的后果)

  1. 在全局环境下,this 始终指向全局对象(window), 无论是否严格模式;
console.log(this); // window
  1. 一般函数外部的 this 分两种状况,严格模式和非严格模式。

​(1)非严格模式下,this 默认指向全局对象 window

​(2)严格模式下,this 为 undefined

function fun() {console.log(this); // window
}
  1. 对象外部办法的 this 指向调用这些办法的对象

    (1)函数的定义地位不影响其 this 指向,this 指向只和调用函数的对象无关;

    (2)多层嵌套的对象,外部办法的 this 指向离被调用函数最近的对象(window 也是对象,其外部对象调用办法的 this 指向外部对象,而非 window)。

const obj = {
    a: 10,
    b: 20,
    add: function () {return this.a + this.b;}
};

console.log(obj.add()); // 30
const add = obj.add;
console.log(add()); // NaN
  1. 原型链中的办法的 this 依然指向调用它的对象
const obj = {
    a: 10,
    b: 20
};

const prototypeObj = {add: function () {return this.a + this.b;}
};

Object.setPrototypeOf(obj, prototypeObj);

console.log(obj.add()); // 30
  1. 构造函数中的 this 与被创立的新对象绑定。
function Fun() {this.a = 10;}

const fun = new Fun();
console.log(fun.a); // 10
  1. 当函数通过 Function 对象的原型中继承的办法 call() 和 apply() 办法调用时,其函数外部的 this 值可绑定到 call() & apply() 办法指定的第一个对象上,如果第一个参数不是对象,JavaScript 外部会尝试将其转换成对象而后指向它。(见后续代码)
  2. 通过 bind 办法绑定后,函数将被永远绑定在其第一个参数对象上,而无论其在什么状况下被调用。(见后续代码)
  3. 当函数被当做监听事件处理函数时,其 this 指向触发该事件的元素(针对于 addEventListener 事件)
<button id="testId"> 按钮 </button>

const btn = document.getElementById('testId');
btn.addEventListener('click', function() {console.log(this); // <button id="testId"> 按钮 </button>
});
  1. 内联事件中的 this 指向分两种状况:

    (1)当代码被内联解决函数调用时,它的 this 指向监听器所在的 DOM 元素

    <button onclick="console.log(this)"> 按钮 </button> // 输入该 DOM 节点

(2)当代码被包含在函数外部执行时,其 this 指向等同于 函数间接调用的状况,即在非严格模式指向全局对象 window,在严格模式指向 undefined

<button onclick="clickFun()"> 按钮 </button>

function clickFun() {console.log(this); // window
}
  1. 对于延时函数外部的回调函数的 this 指向全局对象 window(当然能够通过 bind 办法扭转其外部函数的 this 指向)
function Fun() {
    this.a = 10;
    this.method = function() {setTimeout(function() {console.log(this); // window
        }, 1000);
    }
}

const fun = new Fun();
fun.method();
  1. 因为箭头函数不绑定 this,它会捕捉其所在(即定义的地位)上下文的 this 值,作为本人的 this 值,所以 call() / apply() / bind() 办法对于箭头函数来说只是传入参数,对它的 this 毫无影响。
function Fun() {
    this.a = 10;
    this.method = function() {setTimeout(() => {console.log(this); // Fun {a: 10, method: ƒ}
        }, 1000);
    }
}

const fun = new Fun();
fun.method();

14.3 扭转 this 指向

除了隐式绑定 this 的形式,还可能通过显示绑定的形式,通过 call、apply、bind 形式扭转 this 指向,对于这三者的区别后续将有专门的百题斩去论述,本节次要进行一波简略应用。

  1. call()

call() 办法应用一个指定的 this 值和独自给出的一个或多个参数来调用一个函数。

function method(val1, val2) {return this.a + this.b + val1 + val2;}

const obj = {
    a: 1,
    b: 2
};

console.log(method.call(obj, 3, 4)); // 10
  1. apply()

apply() 办法调用一个具备给定 this 值的函数,以及以一个数组(或类数组对象)的模式提供的参数。

function method(val1, val2) {return this.a + this.b + val1 + val2;}

const obj = {
    a: 1,
    b: 2
};

console.log(method.apply(obj, [3, 4])); // 10
  1. bind()

bind() 办法创立一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时应用。

function method(val1, val2) {return this.a + this.b + val1 + val2;}

const obj = {
    a: 1,
    b: 2
};

const bindMethod = method.bind(obj, 3, 4);
console.log(bindMethod); // [Function: bound method]
console.log(bindMethod()); // 10

扩大

  1. call()apply()的区别是 call() 办法承受的是 参数列表 ,而apply() 办法承受的是 一个参数数组
  2. bind 返回的是一个绑定函数,而 call 和 apply 返回的是运行后果;
  3. 屡次 bind() 是有效的,只会绑定到第一次调用的对象上;
  4. call() / apply() / bind() 办法对于箭头函数来说只是传入参数,对它的 this 毫无影响。

1. 如果感觉这篇文章还不错,来个分享、点赞吧,让更多的人也看到

2. 关注公众号执鸢者,与号主一起斩杀前端百题。

退出移动版