视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
js的箭头函数简介
2020-11-27 19:57:50 责编:小采
文档


箭头函数就是个简写形式的函数表达式,并且它拥有词法作用域的this值(即不会新产生自己作用域下的this,arguments,super和new.target等对象)。此外,箭头函数总是匿名的。

基础语法

  1. (param1, param2, …, paramN) => { statements } 
    (param1, param2, …, paramN) => expression 
     // equivalent to: => { return expression; } 
     
    // 如果只有一个参数,圆括号是可选的: 
    (singleParam) => { statements } 
    singleParam => { statements } 
     
    // 无参数的函数需要使用圆括号: 
    () => { statements }

高级语法

  1. // 返回对象字面量时应当用圆括号将其包起来: 
    params => ({foo: bar}) 
     
    // 支持 Rest parameters 和 default parameters: 
    (param1, param2, ...rest) => { statements } 
    (param1 = defaultValue1, param2, …, paramN = defaultValueN) => { statements } 
     
    // Destructuring within the parameter list is also supported 
    var f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c; 
    f(); // 6

描述


箭头函数的引入有两个方面的影响:一是更简短的函数书写,二是对 this 的词法解析。

更短的函数

在一些函数式编程模式里,更短的函数书写方式很受欢迎。试比较:

  1. var a = [ 
     "Hydrogen", 
     "Helium", 
     "Lithium", 
     "Beryl?lium" 
    ]; 
     
    var a2 = a.map(function(s){ return s.length }); 
     
    var a3 = a.map( s => s.length );

不绑定 this

在箭头函数出现之前,每个新定义的函数都有其自己的this值(例如,构造函数的 this 指向了一个新的对象;严格模式下的函数的 this 值为 undefined;如果函数是作为对象的方法被调用的,则其 this 指向了那个调用它的对象)。在面向对象风格的编程中,这被证明是非常恼人的事情。

function Person() { 
 // 构造函数 Person() 定义的 `this` 就是新实例对象自己 
 this.age = 0; 
 setInterval(function growUp() { 
 // 在非严格模式下,growUp() 函数定义了其内部的 `this` 
 // 为全局对象, 不同于构造函数Person()的定义的 `this` 
 this.age++; 
 }, 1000); 
} 
 
var p = new Person();
  1. 在 ECMAScript 3/5 中,这个问题可以通过新增一个变量来指向期望的 this 对象,然后将该变量放到闭包中来解决。

  2. function Person() { 
     var self = this; // 也有人选择使用 `that` 而非 `self`. 
     // 只要保证一致就好. 
     self.age = 0; 
     
     setInterval(function growUp() { 
     // 回调里面的 `self` 变量就指向了期望的那个对象了 
     self.age++; 
     }, 1000); 
    }

除此之外,还可以使用bind函数,把期望的 this 值传递给 growUp() 函数。

箭头函数则会捕获其所在上下文的 this 值,作为自己的 this 值,因此下面的代码将如期运行。

  1. function Person(){ 
     this.age = 0; 
     
     setInterval(() => { 
     this.age++; // |this| 正确地指向了 person 对象 
     }, 1000); 
    } 
     
    var p = new Person();

与 strict mode 的关系

考虑到this是词法层面上的,严格模式中与this相关的规则都将被忽略。

  1. var f = () => {'use strict'; return this}; 
    f() === window; // 或全局对象

严格模式的其他规则依然不变.

使用 call 或 apply 调用

由于this已经在词法层面完成了绑定,通过call()或apply()方法调用一个函数时,只是传入了参数而已,对this并没有什么影响:

  1. <span style="font-size:14px;">var adder = { 
     base : 1, 
     
     add : function(a) { 
     var f = v => v + this.base; 
     return f(a); 
     }, 
     
     addThruCall: function(a) { 
     var f = v => v + this.base; 
     var b = { 
     base : 2 
     }; 
     
     return f.call(b, a); 
     } 
    }; 
     
    console.log(adder.add(1)); // 
    输出 2 console.log(adder.addThruCall(1)); // 仍然输出 2(而不是3 ——译者注)</span>

不绑定 arguments

箭头函数不会在其内部暴露出arguments对象: arguments.length, arguments[0], arguments[1] 等等,都不会指向箭头函数的 arguments,而是指向了箭头函数所在作用域的一个名为 arguments 的值(如果有的话,否则,就是 undefined)。

  1. var arguments = 42; 
    var arr = () => arguments; 
     
    arr(); // 42 
     
    function foo() { 
     var f = () => arguments[0]; // foo's implicit arguments binding 
     return f(2); 
    } 
     
    foo(1); // 1


箭头函数没有自己的 arguments 对象,不过在大多数情形下,rest参数可以给出一个解决方案:

  1. function foo() { 
     var f = (...args) => args[0]; 
     return f(2); 
    } 
     
    foo(1); // 2

像方法一样使用箭头函数

如上所述, 箭头函数表达式对没有方法名的函数是最合适的.让我们看看当我们试着把它们作为方法时发生了什么.

  1. 'use strict'; 
    var obj = { 
     i: 10, 
     b: () => console.log(this.i, this), 
     c: function() { 
     console.log( this.i, this) 
     } 
    } 
    obj.b(); // prints undefined, Window 
    obj.c(); // prints 10, Object {...}

箭头函数没有定义this绑定。

  1. 'use strict'; 
    var obj = { 
     a: 10 
    }; 
     
    Object.defineProperty(obj, "b", { 
     get: () => { 
     console.log(this.a, typeof this.a, this); 
     return this.a+10; // represents global object 'Window', therefore 'this.a' returns 'undefined' 
     } 
    });

使用new操作符

箭头函数不能用作构造器,和 new 一起用就会抛出错误。

使用yield关键字

yield关键字通常不能在箭头函数中使用(except when permitted within functions further nested within it)。因此,箭头函数不能用作Generator函数。

返回对象字面量

请牢记,用 params => {object:literal} 这种简单的语法返回一个对象字面量是行不通的:

  1. var func = () => { foo: 1 }; 
    // Calling func() returns undefined! 
     
    var func = () => { foo: function() {} }; 
    // SyntaxError: function statement requires a name

这是因为花括号(即 {} )里面的代码被解析为声明序列了(例如, foo 被认为是一个 label, 而非对象字面量里的键)。

所以,记得用圆括号把对象字面量包起来:

  1. var func = () => ({ foo: 1 });

换行

箭头函数在参数和箭头之间不能换行哦

  1. var func = () 
     => 1; // SyntaxError: expected expression, got '=>'


解析顺序

在箭头函数中的箭头不是操作符(或者运算符,就像'+ -'那些), 但是 箭头函数有特殊的解析规则就是:相比普通的函数, 随着操作符优先级不同交互也不同(建议看英文版)。

let callback; 
 
callback = callback || function() {}; // ok 
callback = callback || () => {}; // SyntaxError: invalid arrow-function arguments 
callback = callback || (() => {}); // ok
  1. 示例

  2. // 一个空箭头函数,返回 undefined 
    let empty = () => {}; 
     
    (() => "foobar")() // 返回 "foobar" 
     
    var simple = a => a > 15 ? 15 : a; 
    simple(16); // 15 
    simple(10); // 10 
     
    let max = (a, b) => a > b ? a : b; 
     
    // Easy array filtering, mapping, ... 
     
    var arr = [5, 6, 13, 0, 1, 18, 23]; 
    var sum = arr.reduce((a, b) => a + b); // 66 
    var even = arr.filter(v => v % 2 == 0); // [6, 0, 18] 
    var double = arr.map(v => v * 2); // [10, 12, 26, 0, 2, 36, 46] 
     
    // 更多简明的promise链 
    promise.then(a => { 
     // ... 
    }).then(b => { 
     // ... 
    });

下载本文
显示全文
专题