最近在学ES6的时候,发现使用箭头函数的时候的this指向不太清楚,和普通的对象创建做了一些对比,讲讲自己的理解,有问题希望大家和我一起讨论研究
箭头函数 和 function(){}定义的区别,箭头函数的
这里的所有代码基于chrome进行测试
这里有几个帖子是作为参考的
(1)阮一峰老师ES6
为了分清箭头函数中的this和普通的this的区别,了解两个概念
普通函数里面的this:
总是代表它的直接调用者,没找到直接调用者,则this指的是 window(匿名函数,定时器中的函数,由于没有默认的宿主对象,所以默认this指向window)
箭头函数中的this:箭头函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象,箭头函数中没有自己的this的,而箭头函数会默认使用父级的this,箭头函数的this是父域中的!!!!
自己理解(错误请给我指正):无论是不是在箭头函数中,只要指向的this的量没找到(undefined),就会到全局的window里面找,找到就返回window的值. 下面这个例子说明:
var x=11;
var obj={
x:22,
say1:function(){
console.log(this.x)
},
say2:()=>console.log(this.x)
}
obj.say1(); // 22
obj.say2(); // 11
这里调用他的是say1, say1所在的类是 obj 所以这里的say1中的this指的是obj.x 因此输出为22
对于say2来说,此时 say2这一行,看做this.say2,那么say2的父作用域是谁呢,他的父是obj,父类所在的作用域是window,也就是最外面的作用域啊,所以在这里输出是11关系如下:
var x=11;
//这是say2父类obj所在的作用域
var obj={
x:22,
say1:function(){
console.log(this.x)
},
// 这里是say2存在的作用域
say2:()=>console.log(this.x)
}
obj.say1(); // 22
obj.say2(); // 11
接下来我们看个例子:
var a = 11
function test1(bb){
this.a = bb;
this.b=function(){
console.log(`b:${this.a}`);
};
this.b();
let c = function(){console.log(`c:${this.a}`)}
c();
let d = () => console.log(`d:${this.a}`);
d();
}
var x=new test1(15);
// b:15 c: 11 d:15
先看d, d而言这里d是箭头函数,箭头函数本身有一个作用域,let d并未像第一个例子中指向一个对象,所以其父类所在的作用域(当然不存在父类这里),就是test1,所以在test1中去找this.a 找到bb,bb在这里的值位15 所以d输出为15
接下里看c:let c不像第一个对象他有一个默认的宿主对象,他作为一个函数,并不属于test1类 如果要属于test1类要写成b的形式,那他的默认类就为window,所以他在window中找a,在当前类中找a,找到了var a =11返回11
最后来看b,b就太简单了,b默认的类是test1,该类中的a是15所以返回15
var s2 = 10;
function Timer() {
this.s1 = 0;
this.s2 = 0;
// 箭头函数
setInterval(() => this.s1++, 1000);
// 普通函数
setInterval(function () {
this.s2++;
}, 1000);
}
var timer = new Timer();
setTimeout(() => console.log('s1: ', timer.s1), 5100);
setTimeout(() => {console.log('s2: ', timer.s2), console.log(window.s2)}, 5100);
console.log(window.s2);
补充一个阮老师给的例子,在这里,s1是封闭函数所指向的,他指向的父类的作用域是Timer,Timer里面的s1找到向上加
而s2是匿名函数指向window所以最后window.s2在第二个定时结束后输出为15 10+5计算得到
总结:如果是箭头函数,其this是其所在作用域的父作用域内 找到他的指代内容的值
普通函数,是其所对应类(宿主对象)的当前作用域中进行寻找
(匿名函数,定时器中的函数,由于没有默认的宿主对象,所以默认this指向window)