记录一下自己关于this的理解
1.this的官方说法---参考JavaScript高级程序设计语言
this对象是在运行时基于函数的执行环境绑定的。也就是说,this代表的是函数执行时,所运行环境的主体对象。
2.this设计的目的--参考阮一峰日志
函数一经创建,会存在内存中,赋值给变量的是函数在内存中的地址。这样函数在各种环境中就是一个单独的值,可以在不同环境中执行。因此需要有一种机制,能够在函数体内部获得当前的运行环境,以便于获取当前环境中的数据(个人理解)。
3.this的指向(个人理解)
我们所说的this指向,也就是this代表谁,绑定给了谁。我所理解地就是,this代表了函数被调用时,调用这个函数的对象,就是点前面的那个对象。
例如:window.fn() obj.fn(),前者是函数正常调用时,指向了window这个对象,后者是方法调用时,指向了这个调用方法的obj对象,它们都是点前面的对象。当然这只是一般情况下而言。
4.this的调用模式
我们都知道,this在函数刚被定义的时候,是没有任何意义的,只有函数在执行时(被调用),才会绑定执行主体,即确定指向,那么就可以通过函数的调用模式来确定this是如何确定指向的。
①函数调用模式,即普通的函数调用,this指向window
var name = "bobo"
function global(){
var name = "lele"
console.log(this.name)
}
global(); // "bobo" this指向window,thi.name就是window.name
只要是函数单独调用,前面没有点的,都是函数调用模式,this指向window.例如:
var name = "bobo"
var obj = {
name: 'lele',
say: function () {
console.log('hi,' + this.name);
},
};
obj.say(); // hi,lele
var sayHi = obj.say;
sayHi(); // hi,bobo,sayHi被赋值了say方法的函数地址,本身已经是一个独立的函数,在执行时跟定义在全局中的函数一样,都是被window调用
②方法调用模式,即定义在对像中的方法是一个函数,当方法被调用时,就是该函数被调用
在上面的例子中已经写了,调用obj对象中的say方法时,方法中的this指向的是obj这个对象,所以this.name相当于是obj.name,结果是hi,lele
但是,方法调用模式中,我们常常迷惑的不是这么简单的调用,而是当出现多层调用时,this到底指向的是哪一层的调用对象,例如:
var obj = {
name: 'bobo',
first: {
name: 'lele',
second: {
name: 'mingming',
say: function () {
console.log('hi,' + this.name);
},
},
},
};
obj.first.second.say(); // hi,mingming this指向了second
由此可见,this最终指向的是最后调用它的那一级对象,这里我用自己的理解方式,this指向的就是最终找到它的那个对象。
③构造函数调用模式
构造函数中的this,是由于new的作用,将this指向了它创建的实例对象
function Person() {
this.name = 'bobo';
this.age = '23';
this.say = function () {
console.log('hi,bobo');
};
}
var p = new Person();
console.log(p.name); // bobo
这个应该比较容易理解,因为new已经帮我们确定好了this到底绑定给了谁,那就是new创造的实例对象。
④apply,call,bind方法调用,又叫做上下文调用
apply,call,bind是函数的方法,函数调用该方法之后,通过传参可以改变函数内部的this指向。
var bobo = {
hobby: '滑板',
say: function () {
console.log('我喜欢' + this.hobby);
},
};
var lele = {
hobby: '唱歌',
};
bobo.say(); // 我喜欢滑板
bobo.say.apply(lele);// 我喜欢唱歌
bobo.say.call(lele);// 我喜欢唱歌
var leleSay = bobo.say.bind(lele);
leleSay();// 我喜欢唱歌
这三种方法都可以改变函数内部的this指向,但是又有所不同,这里对它们的区别暂时不做讨论。
这种方法我觉得应该叫做借用模式,就是通过改变this指向,使this指向的这个对象借用到这个方法,从而来获取该对象内的数据。
⑤特殊情况下的this指向
例如:事件函数内的this指向的是事件源,setTimeout setInterval 指向的是window,匿名函数的自调用(立即执行函数)指向window。
另外:在严格模式下,没有显示函数的调用主体时,即在函数调用模式下,不再指向window,而是指向undefined。
⑥箭头函数里面的this指向
箭头函数里面没有定义this,因此箭头函数里面写有this时,就会按照作用域链去查找有定义this的那一级作用域的this,这时的this就指向调用这个作用域函数的调用者。
var id = 3;
function foo() {
var id = 2;
// var that = this;
//var this
setTimeout(() => {
console.log('id:', this.id);
}, 100);
}
foo(); // id=2; 箭头函数没有定义this,所以this应该时foo函数中的this,而foo是window调用的,因此this指向window
var obj = {
id: 4,
time: function () {
var id = 5;
var aa = {
bb: () => {
console.log('id:', this.id);
},
};
aa.bb();
},
};
obj.time(); // id=4,这时的this按照作用域查找,是time方法中的this,time方法被obj调用,this就指向obj
总结目前到这里,有新的发现,或者发现理解上的错误,再来修改。加油!