彻底掌握this在JavaScript中的指向,吹散笼罩在this周围的重重迷雾,理解谁决定了this的指向,看完本篇你能在代码运行以前就能够判断出this的指向。编程
咱们都曾以不一样的方式在函数中看见过this,但仍然不能准确的指出this在JavaScript中指向谁,本篇将让你彻底掌握this。浏览器
(1) 若是 new 关键词出如今被调用函数的前面,那么JavaScript引擎会建立一个新的对象,被调用函数中的this指向的就是这个新建立的函数。markdown
function ConstructorExample() {
console.log(this);
this.value = 10;
console.log(this);
}
new ConstructorExample();
// -> ConstructorExample {}
// -> ConstructorExample { value: 10 }
复制代码
(2) 若是经过apply、call或者bind的方式触发函数,那么函数中的this指向传入函数的第一个参数。app
function fn() {
console.log(this);
}
var obj = {
value: 5
};
var boundFn = fn.bind(obj);
boundFn(); // -> { value: 5 }
fn.call(obj); // -> { value: 5 }
fn.apply(obj); // -> { value: 5 }
复制代码
(3) 若是一个函数是某个对象的方法,而且对象使用句点符号触发函数,那么this指向的就是该函数做为那个对象的属性的对象,也就是,this指向句点左边的对象。函数
var obj = {
value: 5,
printThis: function() {
console.log(this);
}
};
obj.printThis(); // -> { value: 5, printThis: ƒ }
复制代码
(4) 若是一个函数做为FFI被调用,意味着这个函数不符合以上任意一种调用方式,this指向全局对象,在浏览器中,便是window。oop
var obj = {
value: 5,
printThis: function() {
console.log(this);
}
};
obj.printThis(); // -> { value: 5, printThis: ƒ }
复制代码
注意,第4条规则和第3条很相似,不一样的是当函数没有做为方法被调用时,它将自动隐式编程全局对象的属性——window。也就是当咱们调用 fn(),能够理解为window.fn(),根据第三条规则,fn()函数中的this指向的就是window。this
var obj = {
value: 5,
printThis: function() {
console.log(this);
}
};
obj.printThis(); // -> { value: 5, printThis: ƒ }
复制代码
(5) 若是出现上面对条规则的累加状况,则优先级自1至4递减,this的指向按照优先级最高的规则判断。spa
看一个代码示例,并使用上面的规则判断this的指向。code
var obj = {
value: 'hi',
printThis: function() {
console.log(this);
}
};
var print = obj.printThis;
obj.printThis(); // -> {value: "hi", printThis: ƒ}
print(); // -> Window {stop: ƒ, open: ƒ, alert: ƒ, ...}
复制代码
obj.prinThis() ,根据第三条规则this指向的就是obj。根据第四条规则print()是FFI,所以this指向window。orm
其实上面的示例也考察你对于 值和引用 在JavaScript中的区别,能够看这篇文章:
obj对象中printThis这一方法实际上是函数的地址的一个引用,当咱们将obj.printThis赋值给print时,print包含的也是函数的引用,和obj对象一点关系也没有。obj只是碰巧拥有一个指向这个函数的引用的属性。
当不适用obj对象触发函数时,这个函数就是FFI。
当出现多个上述规则时,将优先级高的“获胜”,若是规则2和规则3同时存在,则规则2优先:
var obj1 = {
value: 'hi',
print: function() {
console.log(this);
},
};
var obj2 = { value: 17 };
obj1.print.call(obj2); // -> { value: 17 }
复制代码
若是规则1和规则3同时被应用,则规则1优先:
var obj1 = {
value: 'hi',
print: function() {
console.log(this);
},
};
new obj1.print(); // -> print {}
复制代码
有些库会将this的指向绑定更有用的对象上,好比jQuery库,在事件处理程序中,this的指向不是全局对象而被绑定到了元素对象上。所以,若是你发现一些不能用上述5项规则解释的状况,请阅读你所使用的库的官方文档,找到关于该库是如何改变this的指向的,一般经过 bind 方法改变this的指向。