ES2015 中的箭头函数和词法 this

箭头函数是使用=>语法对函数定义的简写。它们在语法上类似于 C#,Java 8 和 CoffeeScript 中的相关特性。它们支持表达式(Expression bodies)和函数体(Statement bodies)。与函数不同,箭头函数与其上下文代码共享相同的词法this(愚人码头注:箭头函数并没有自己的this,它的this是派生而来的,根据“词法作用域”派生而来)。如果箭头函数在另一个函数体内,它共享其父函数的 arguments 变量。

 // 使用表达式(Expression bodies) var odds = evens.map(v => v + 1); var nums = evens.map((v, i) => v + i);  // 使用函数体(Statement bodies) nums.forEach(v => {   if (v % 5 === 0)     fives.push(v); });  // 词法`this` var bob = {   _name: "Bob",   _friends: [],   printFriends() {     this._friends.forEach(f =>       console.log(this._name + " knows " + f));   } };  // 词法 arguments function square() {   let example = () => {     let numbers = [];     for (let number of arguments) {       numbers.push(number * number);     }      return numbers;   };    return example(); }  square(2, 4, 7.5, 8, 11.5, 21); // returns: [4, 16, 56.25, 64, 132.25, 441]

 

更多信息: MDN Arrow Functions

愚人码头注:

用Babel转译一下上面的代码,结果:

 "use strict";  // Expression bodies var odds = evens.map(function (v) {   return v + 1; }); var nums = evens.map(function (v, i) {   return v + i; });  // Statement bodies nums.forEach(function (v) {   if (v % 5 === 0) fives.push(v); });  // Lexical this var bob = {   _name: "Bob",   _friends: [],   printFriends: function printFriends() {     var _this = this;      this._friends.forEach(function (f) {       return console.log(_this._name + " knows " + f);     });   } };  // Lexical arguments function square() {   var _arguments = arguments;    var example = function example() {     var numbers = [];     var _iteratorNormalCompletion = true;     var _didIteratorError = false;     var _iteratorError = undefined;      try {       for (var _iterator = _arguments[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {         var number = _step.value;          numbers.push(number * number);       }     } catch (err) {       _didIteratorError = true;       _iteratorError = err;     } finally {       try {         if (!_iteratorNormalCompletion && _iterator.return) {           _iterator.return();         }       } finally {         if (_didIteratorError) {           throw _iteratorError;         }       }     }      return numbers;   };    return example(); }  square(2, 4, 7.5, 8, 11.5, 21); // returns: [4, 16, 56.25, 64, 132.25, 441]

值得注意的是,这里的this

 // Lexical this var bob = {   _name: "Bob",   _friends: [],   printFriends: function printFriends() {     var _this = this;      this._friends.forEach(function (f) {       return console.log(_this._name + " knows " + f);     });   } };

从转译结果的printFriends函数中var _this = this;可以看出,_this指向bob对象。

比较一下下面两段代码:

 var bob = {   _name: "Bob",   _friends: ["愚人码头"],   printFriends() {     this._friends.forEach(f =>       console.log(this._name + " knows " + f));   } }; bob.printFriends();// Bob knows 愚人码头
 var bob = {   _name: "Bob",   _friends: ["愚人码头"],   printFriends() {     this._friends.forEach(function (f) {       return console.log(this._name + " knows " + f);     });   } }; bob.printFriends();// undefined knows 愚人码头

原因很简单:箭头函数与其上下文代码共享相同的词法this,所以this指向bob对象,第2段代码forEach中的匿名函数上下文是window对象,所以this指向window对象。

题外话,要想修复第2段代码的问题,除了Babel提供的转译外,还可以使用 ES5 的 bind() :

 var bob = {   _name: "Bob",   _friends: ["愚人码头"],   printFriends() {     this._friends.forEach(function (f) {       return console.log(this._name + " knows " + f);     }.bind(this));   } }; bob.printFriends();// Bob knows 愚人码头

bind() 最简单的用法是使函数的上下文指向其参数。(http://www.css88.com/archives/5611)。

0
如无特殊说明,文章均为原作者原创,转载请注明出处

该文章由 发布

这货来去如风,什么鬼都没留下!!!
发表我的评论

Hi,请填写昵称和邮箱!

取消评论
代码 贴图 加粗 链接 删除线 签到