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,请填写昵称和邮箱!

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

(4)条精彩评论:
  1. <a href='http://www.iphone6splusforsale.com/' rel='external nofollow' class='url'>Wholesale iPhone 7 For Sale</a>
    For the same reasons that I am loath to dispose of stained band T-shirts I bought at concerts in high school, I'm unwilling to delete any digital file I think I might miss one day. In turn, I've been forced to get creative in order to make room for more.
  2. <a href='http://www.iphone7forsale.net/' rel='external nofollow' class='url'>Wholesale iPhone 7 For Sale</a>
    Imposed
  3. <a href='http://community.usc.edu.tt/site/bookmarks/view/623429/wholesale-iphone-7iphone-7-plus-for-salecheap-iphone-7-onlinewholesale-iphone-7-plus-store100-original' rel='external nofollow' class='url'>Wholesale iPhone 7</a>
    Other than the wood panelling, the design of X-Doria’s Defense Lux remains the same as before — a soft inner rubber layer wraps around your iPhone, onto which a machined aluminum outer frame snaps to surround the edges, providing additional drop protection and metallic button covers. The result is “military-grade” drop protection (X-Doria claims its tested to survive 6.6-foot drops onto concrete) in an attractive case. There’s also an oversized lip on the front for added screen protection, and full coverage on all edges; of course, you’ll have the usual issues with dock compatibility, but that’s true of almost any properly protective case, however Defense Lux does provide a slightly better degree of dock compatibility — if you snap open the bottom edge of the aluminum frame you can fit your iPhone into some docking accessories without having to remove the case entirely, but it’s still a tradeoff between using a protective case and being able to dock your iPhone in a typical Lightning dock.
    Wholesale iPhone 72017-04-28 05:00 回复
  4. <a href='http://www.viveibague.com/members/colon3twist/activity/332170/' rel='external nofollow' class='url'>Wholesale iPhone 7</a>
    The iPhone wasn't the only Apple product that got a color update today. Along with the new red iPhone 7 and iPhone 7 Plus, Apple added new colors to its line of silicone and leather iPhone 7 and 7 Plus cases.
    Wholesale iPhone 72017-04-27 14:18 回复