说说你对this的理解
在我的印象中,一直有这么一句话 “谁调用,this指向谁”,但在工作的时候,还是有时候会感到疑惑,所以决定好好的了解一下这个this
这个时候我们不能知道this会指向谁
function fn() {
console.log(this);
}
下面两种情况,this的指向又不同
function fn() {
console.log(this);
}
let obj = {fn};
fn(); // window
obj.fn(); // obj
其实this的指向就有这么几种情况:
1. 函数独立调用时,在严格模式下和非严格模式下this指向不一致
let a = 1
function test() {
'use strict';
let a = 2
console.log(this.a) // 报错
}
test()
let a = 1
function test() {
let a = 2
console.log(this.a) // 1
}
test()
严格模式下this为undefined,非严格模式下指向window
2. 通过对象调用
let o = {
name:"haha",
fn:function(){
console.log(this.name); // haha
}
}
o.fn();
数组中调用
function fn() {
console.log(this)
}
arr[fn, fn2, fn3]
arr[0]() // ??
// answer:arr
// 解析
// 数组也是对象的一种
// arr[0]() 可以看做 arr.0().call(arr)
通过上面可以知道,this的指向在定义时是没法确认的,只有在调用的时候,才能决定
3. 多层调用
let o = {
name:'aa',
user:{
name:'bb',
fn:function(){
console.log(this.name); // bb
}
}
}
o.user.fn(); // bb
this的指向指向user,是因为,this的指向只看上一级是谁
4. 函数自调用
let o = {
name:'aa',
user:{
name:'bb',
fn:function(){
console.log(this.name); // undefined
console.log(this); //window
}
}
}
let fn2 = o.user.fn;
fn2();
this永远指向最后调用它的对象,也就是执行的时候是谁调用的。这里fn2执行的时候相当于window.fn2(),所以它指向的是window。
要记住,严格模式下,函数自调用,this为undefined
5. 函数中有函数自执行
let obj = {
a: function () {
console.log(this,77);
},
b: function () {
console.log(this,88)
let f = obj.a;
f();
}
}
obj.b();
// obj,88
// window,77
可以看到第一个输出不出我们所料,但第二个输入让我们有点混乱了。其实第二个输出的情况就是第四种情况,函数自执行,所以相当于window.fn()
6. 构造函数下的this
function Fn(){
this.name = "haha";
}
var f = new Fn();
console.log(f.name); // haha
为什么这里的this指向了f呢,是因为new做的事情,这里就得说说new做的事情了
//自己定义的new方法
let newMethod = function (Parent, ...rest) {
// 1.以构造器的prototype属性为原型,创建新对象;
let child = Object.create(Parent.prototype);
// 2.将this和调用参数传给构造器执行
let result = Parent.apply(child, rest);
// 3.如果构造器没有手动返回对象,则返回第一步的对象
return typeof result === 'object' ? result : child;
};
中间有一个 Parent.apply(child, rest); 这里apply将构造函数的this指向了child实例,所以上面Fn的this指向了f。可以看到,new函数里面return有个判断,如果构造函数里面有返回的话,而且返回的是对象,那么,this就指向了构造函数的返回对象。
7. setTimeout、setInterval的this
<div>
<span id="test">666</span>
</div>
<script>
let q = document.getElementById('test')
q.addEventListener('click', function (e) {
console.log(this); // <span id="test">666</span>这个元素
setTimeout(function () {
console.log(this); // 这里的this是全局变量window
}, 200);
}, false)
</script>
8. 事件中的this
上面的代码已经说明了,事件中的this指向触发事件的dom节点
9. 箭头函数中的this
箭头函数中没有this,直接把父级作用域的this拿来用
10。 自己指定this指向
call、apply、bind
参考文章: