最近看了很多篇关于this
的文章,总结一下吧,这样才能印象深刻。
函数的this
在调用时绑定的,完全取决于函数的调用位置(也就是函数的调用方法)。为了搞清楚this
的指向是什么,必须知道相关函数是如何调用的。
全局上下文
非严格模式和严格模式中this都是指向顶层对象(严格模式下顶层对象为undefined,非严格模式下顶层对象浏览器中是window
,node的顶层对象是global
对象)
this === window // true
函数上下文
- 普通函数调用模式
- 对象中的函数(方法)调用模式
- call、apply、bind 调用模式
- 构造函数调用模式
- 原型链中的调用模式
- 箭头函数调用模式
- DOM事件处理函数调用
有常见上面几种方式,下面一条条解释
普通函数调用模式
// demo01
var a = 20;
function fn() {
console.log(this.a);
}
fn();
打印20,非严格模式自动指向window
// demo02
var a = 20;
function fn() {
function foo() {
console.log(this.a);
}
foo();
}
fn();
打印20,非严格模式自动指向window
如果函数独立调用,那么该函数内部的this,则指向undefined。
在非严格模式中,当this指向undefined时,它会被自动指向全局对象,严格模式下指向undefined。
对象中的函数(方法)调用模式
// demo03
var a = 20;
var obj = {
a: 10,
c: this.a + 20,
fn: function () {
return this.a;
}
}
console.log(obj.c);
console.log(obj.fn());
打印40 10,指向obj
如果调用者函数,被某一个对象所拥有,那么该函数在调用时,内部的this指向该对象。
call、apply、bind 调用模式
function fn(num1, num2) {
console.log(this.a + num1 + num2);
}
var obj = {
a: 20
}
fn.call(obj, 100, 10); // 130
fn.apply(obj, [20, 10]); // 50
构造函数调用模式
function Student(name){
this.name = name;
console.log(this); // {name: '若川'}
// 相当于返回了
// return this;
}
var result = new Student('若川');
使用new操作符调用函数,会自动执行以下步骤。
- 创建一个新对象
- 构造函数的this指向该对象
- 指向构造函数的代码,为这个对象添加属性,方法等;
- 返回新对象
原型链中的调用模式
function Student(name){
this.name = name;
}
var s1 = new Student('若川');
Student.prototype.doSth = function(){
console.log(this.name);
}
s1.doSth(); // '若川'
箭头函数调用模式
var name = 'window';
var student = {
name: '若川',
doSth: function(){
// var self = this;
var arrowDoSth = () => {
// console.log(self.name);
console.log(this.name);
}
arrowDoSth();
},
arrowDoSth2: () => {
console.log(this.name);
}
}
student.doSth(); // '若川'
student.arrowDoSth2(); // 'window'
箭头函数中没有this绑定,必须通过查找作用域链来决定其值。 如果箭头函数被非箭头函数包含,则this绑定的是最近一层非箭头函数的this
,否则this的值则被设置为全局对象
DOM事件处理函数调用
总结
如果要判断一个运行中函数的 this 绑定, 就需要找到这个函数的直接调用位置
。
- 普通函数调用: 在严格模式下绑定到 undefined,否则绑定到全局对象。
- new 调用:绑定到新创建的对象,注意:显示return函数或对象,返回值不是新创建的对象,而是显式返回的函数或对象。
- call 或者 apply( 或者 bind) 调用:严格模式下,绑定到指定的第一个参数。非严格模式下,null和undefined,指向全局对象(浏览器中是window),其余值指向被new Object()包装的对象。
- 对象上的函数调用:绑定到那个对象。
- 箭头函数没有this,会根据作用域链寻找上一个普通函数的this
希望大家看完后多参考几篇文章,最后自己一定要总结一遍,梳理思路,这样才会印象深刻,不要模棱两可。
参考:
https://juejin.cn/post/6844903746984476686#heading-4
https://www.jianshu.com/p/d647aa6d1ae6