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]

 

Babel转译

用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() 最简单的用法是使函数的上下文指向其参数。

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 回复