普通函数与箭头函数
普通函数指的是用定义的函数:
var hello = function () { console.log("Hello, itzou!"); }
箭头函数指的是用=>定义的函数:
var hello = () => { console.log("Hello, itzou!"); }
箭头函数与普通函数不只是写法上的区别,它们还有一些微妙的不同点,其中一个不同点就是this。
箭头函数没有自己的this值,箭头函数中所使用的this来自于函数作用域链。
这句话很简单,不过听着稍微有点莫名其妙,得从头说起。
this到底是什么?
关于this的文章也够多了,有时候越描越黑,我就不再添乱了,我只负责搬运一下MDN文档:this,感兴趣的可以仔细阅读一下,我摘录一些最重要的话就好了。
A ’s this a in to other . It also has some mode and non- mode.
是一门比较奇特的语言,它的this与其他语言不一样,并且它的取值还取决于代码是否为严格模式(“use ”)。
this的值是什么?
The in which the code is .
this就是代码执行时当前的 。
In the ( of any ), this to the in mode or not.
代码没有在任何函数中执行,而是在全局作用域中执行时,this的值就是对象,对于浏览器来说,this就是。
这一条规则还是比较容易接受的。
a , the value of this on how the is .
函数中的this值取决于这个函数是怎样被调用的,这一条规则就有点变态了,也是很容易出BUG的地方。
另外,this的值还与函数是否为严格模式(“use ”)有关,这就非常的丧心病狂了…
大家如果好奇的话,出门左转看MDN文档,我多说无益,只说明一种简单的情况。
As an
When a is as a of an , its this is set to the the is on.
当函数作为对象的方法被调用时,它的this值就是该对象。
var circle = { radius: 10, getRadius() { console.log(this.radius); } }; circle.getRadius(); // 打印 10
self = this?
当我们需要在对象方法中嵌套一个内层函数时,this就会给我们带来实际的困扰了,大家应该写过这样的代码:
// 使用临时变量self var circle = { radius: 10, outerDiameter() { var self = this; var innerDiameter = function() { console.log(2 * self.radius); }; innerDiameter(); } }; circle.outerDiameter(); // 打印20
函数是对象的方法,因此其this值就是对象。
那我们直接写this.多好啊,可惜不能这么写,因为内层函数并不会继承外层函数的this值。函数的this值就是对象,this.等于10。
但是,函数的this值不是对象,那它到底是啥?它是函数执行时当前的 ,这个 又是啥?其实我也晕了,所以不妨测试一下:
// innerDiameter函数中的this是window var circle = { radius: 10, outerDiameter() { var innerDiameter = function() { console.log(this === window); }; innerDiameter(); } }; circle.outerDiameter(); // 打印true
函数中的this是,为啥是这个不去管它,反正不是对象。
因此,如果我们直接在函数中使用this的话,就出问题了:
// 使用普通函数 var circle = { radius: 10, outerDiameter() { var innerDiameter = function() { console.log(2 * this.radius); }; innerDiameter(); } }; circle.outerDiameter(); // 打印NaN
于是,我们不得不使用一个临时变量self将外层函数的this值搬运到内层函数。
.bind(this)
我们也可以使用.bind(this)来规避this变来变去的问题:
// 使用.bind(this) var circle = { radius: 10, outerDiameter() { var innerDiameter = function() { console.log(2 * this.radius); }; innerDiameter = innerDiameter.bind(this); innerDiameter(); } }; circle.outerDiameter(); // 打印20
但是,无论是使用临时变量self,还是使用.bind(this),都不是什么很简洁的方式。
总之,普通函数的this取值多少有点奇怪,尤其当我们采用面向对象的方式编程时,很多时候都需要用到this,大多数时候我们都不会去使用.bind(this),而是使用临时变量self或者that来搬运this的取值,写起来当然不是很爽,而且一不小心就会写出BUG来。
正如MDN文档所说:
Until arrow , every new its own this value based on how the was 。This to be less than ideal with an – style of .
箭头函数
箭头函数的this取值,规则非常简单,因为this在箭头函数中,可以看做一个普通变量。
An arrow does not have its own this. The this value of the scope is used; arrow the rules.
箭头函数没有自己的this值,箭头函数中所使用的this都是来自函数作用域链,它的取值遵循普通普通变量一样的规则,在函数作用域链中一层一层往上找。
有了箭头函数,我只要遵守下面的规则,this的问题就可以基本上不用管了:
// 使用箭头函数 var circle = { radius: 10, outerDiameter() { var innerDiameter = () => { console.log(2 * this.radius); }; innerDiameter(); } }; circle.outerDiameter(); // 打印20
对于内层函数,它本身并没有this值,其使用的this来自作用域链,来自更高层函数的作用域。的外层函数是普通函数,它是有this值的,它的this值就是对象。因此,函数中所使用的this来自函数,其值为对象。
结论
是 Eich花了10天时间设计出来的,因此各种莫名其妙的特性,this也算是其中一个奇葩。好在这些年标准发展很快也很稳定,每年撸一个新的标准,多少可以弥补一下JS的先天不足。
箭头函数对于this取值规则的简化,其实也就是为了少给大家添乱,谁能记得住普通函数this取值的那么多条条框框啊。。。
另外,MDN文档绝对是一个宝藏,大家可以多看看。
———END———
限 时 特 惠: 本站每日持续更新海量各大内部创业教程,永久会员只需109元,全站资源免费下载 点击查看详情
站 长 微 信: nanadh666