• 欢迎访问web前端中文站,JavaScript,CSS3,HTML5,web前端demo
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏web前端中文站吧

ES2015 中的箭头函数和词法 this

ES2015(ES6) web前端中文站 2年前 (2017-04-25) 732次浏览 已收录 0个评论

箭头函数是使用=>语法对函数定义的简写。它们在语法上类似于 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)。


web 前端中文站 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:ES2015 中的箭头函数和词法 this
喜欢 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址