箭头函数是使用=>
语法对函数定义的简写。它们在语法上类似于 C#,Java 8 和 CoffeeScript 中的相关特性。它们支持表达式(Expression bodies)和函数体(Statement bodies)。与函数不同,箭头函数与其上下文代码共享相同的词法this
(愚人码头注:箭头函数并没有自己的this,它的this是派生而来的,根据“词法作用域”派生而来)。如果箭头函数在另一个函数体内,它共享其父函数的 arguments
变量。
JavaScript 代码:
- // 使用表达式(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转译一下上面的代码,结果:
JavaScript 代码:
- "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
:
JavaScript 代码:
- // 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
对象。
比较一下下面两段代码:
JavaScript 代码:
- var bob = {
- _name: "Bob",
- _friends: ["愚人码头"],
- printFriends() {
- this._friends.forEach(f =>
- console.log(this._name + " knows " + f));
- }
- };
- bob.printFriends();// Bob knows 愚人码头
JavaScript 代码:
- 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() :
JavaScript 代码:
- 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 0