弄清几个简单的规则就能掌握函数中的this指向问题~\(≧▽≦)/~啦啦啦。
要知道this指向谁其实很简单,定位this的首要规则就是判断一个函数被首次调用的环境。通常遵循以下这几个规则,有优先级关系。
规则
1. 当调用函数的时候用到了 new 关键词, 那么在函数中this 指向的是一个全新的对象。
function ConstructorExample() {
console.log(this);
this.value = 10;
console.log(this);
}
new ConstructorExample();// -> {}
// -> { value: 10 }2. 调用函数的时候如果用到了apply, call 或者 bind,那么函数中this的指向就是给之前所说的方法传递的参数。
function fn() {
console.log(this);
}
const obj = {
value: 5
}
const boundFn = fn.bind(obj);
boundFn(); // -> { value: 5 }
fn.call(obj); // -> { value: 5 }fn.apply(obj); // -> { value: 5 }3. 如果一个函数是通过.符号调用的话,this 指向的是包含这个函数属性的对象。换句话说就是当.在一个函数的左边,this指向的就是.左边的那个对象。
const obj = {
value: 5,
printThis: function() {
console.log(this);
}
}
obj.printThis(); // -> { value: 5, printThis: f }4. 如果一个函数被调用的时候没有任何条件,那么this指向的是全局对象,在浏览器中this 指向的就是window。
function fn() {
console.log(this);
}
// if called in browser
fn(); // -> Window {....}*注意,这个规则其实和规则3很相像,不同之处在于一个函数如果不是通过对象方法申明的时候,那么它自动就变成全局对象的一个属性。因此这种方法是一种隐式的方法调用。当我们调用fn()的时候,它自动被解释成window.fn(), 这里this 指向的就是window。
console.log(fn === window.fn ); // -> true5. 如果以上的5种规则出现了几种,优先级别高的会先应用。
6.如果是es6的箭头函数,那么以上的规则都不适用了。箭头函数的this是根据创建时的上下文环境决定的。要找到this,将目光由箭头函数上移一行,找this在这里指向的是什么,在箭头函数外就可以使用上面的规则拉。找到的this指向就代表箭头函数的this 指向。
const obj = {
value: 'abc',
createArrowFn: function() {
return () => console.log(this);
}
}
const arrowFn = obj.createArrowFn();
arrowFn(); // { value: 'abc', createArrowFn: f }解释: 看到obj.createArrowFn()的时候,我们就要想到第三条规则,this 指向的是.左边的那个对象即obj,因此arrowFn函数中的this指向的就是obj。如果我们在全局环境中建立箭头函数,那么箭头函数中this指向的就是window。
练习一下
找出以下代码中哪个规则适用
var obj = {
value: 'hi',
printThis: function() {
console.log(this);
}
}
var print = obj.printThis;
obj.printThis(); // { value: 'hi', printThis: f}
print(); // Window {...}obj.printThis() 应用的就是第三个规则,运用点操作符。而print()应用的是第四条规则。
当有多个规则时
var obj1 = {
value: 'hi',
print: function() {
console.log(this)
}
}
var obj2 = { value: 17 }当第二条和第三条规则同时存在时,优先应用第二条规则
obj1.print().call(obj2); // { value: 17 }当第一条和第三条同时存在,优先应用第一条规则
new obj1.print(); // {}翻译自https://codeburst.io/the-simple-rules-to-this-in-javascript-35d97f31bde3