JavaScript之箭头函数(Arrow Function)

一、简介
箭头函数(Arrow Function)是 ES6 (ECMAScript2015)中的新语法特性。
它是函数表达式的一种简写形式,非常适合面向过程(相对于面向对象而言)的函数式编程。
但是它也有诸多限制和“缺点”,比如:没有自己的 this 对象,没有 arguments 参数,没有 prototype 属性,不能当作构建函数使用(无法用new关键字)等等。
下面将逐一介绍。


二、语法

1、常规写法
(param1, param2, …, paramN) => { statements } 


2、参数的简写
      如果只有一个参数,则可以省略小括号。
      如果没有参数,则不能省略。
//只有一个参数
singleParam => { statements }

//没有参数
() => { statements }


3、函数体的简写
      如果只有一个 statements 表达式,则可以省略后面的 花括号。
      但是,此时等价于把 表达式 返回。
// 函数体只有一个表达式
(param1, param2, …, paramN) => expression

// 等价于:
(param1, param2, …, paramN) => { return expression; }
//

      但是,如果表达式为一个 JSON 对象,则需要用小括号扩起来。
(param1, param2, …, paramN) => ({name:"John", age:18})


4、支持多参 和 给参数设置默认值
// 多参数 ...rest
(param1, param2, ...rest) => { statements } 

// 参数默认值
(param1 = defaultValue1, param2, …, paramN = defaultValueN) => { 
    statements 
} 


5、支持列表结构参数解析
var arr = [1, 2];

var f = ([a, b] = arr, {x: c} = {x: a + b}) => a + b + c; 

f(); // 6

    同样,如果参数为一个 JSON 对象,则需要用小括号扩起来。
// 参数结构化解析
var f = ({length}) => length; 

// 参数结构体:{length} 等价于 {length: ""}



6、书写格式:不要换行
    不要将参数和箭头写在二行中,它们需要写在同一行中。
// 错误
var func = ()
           => 1; 
// SyntaxError: expected expression, got '=>'



下面展示一个综合示例:
//
// 下面的写法,都会将  materials 转换为 [8, 6, 7, 9] 并输出。

var materials = ['Hydrogen', 'Helium', 'Lithium', 'Beryllium'];

// 1. 常规
console.log(
    materials.map(function(material) { 
      return material.length; 
    })
);

// 2. 箭头函数
console.log(
    materials.map((material) => {
      return material.length;
    })
);

// 3. 简写的箭头函数
console.log(
    materials.map(material => material.length)
);


// 4. 简写 + 参数结构解析 的 箭头函数
console.log(
   //表示传递进的参数的结构是这样的:{ length: '' }
    materials.map(({length}) => length)
); 

//




三、箭头函数没有自己的 this 对象

在箭头函数出现之前,new 出来的函数对象,都有一个 this 属性,指向该对象本身。
然而在箭头函数中,没有 this 对象。因此不存在外层this被重写或本身this被覆盖的问题。

1、不存在 外层 this 被重写问题

【错误】常规的写法:外层 this 被 window 取代
function Person() {
    this.age = 0;
    setInterval(function growUp() { 
        if(this.age) this.age++; 
        console.log(this === window); // true
        console.log(this.age === undefined); // true
    }, 1000);
}

var p = new Person();

// 因为是调用 window 对象的 setInterval 方法,
// 所以 this 指向 window
/*
   多说一句,window 的 setInterval 方法内部实现可能是这样的:
   window.setInterval = function(func, time){
         this.invoke = func;
         //...
   }
   参数中传递的function参数被设定成为了 window 对象的一个属性。
   所以调用时,参数中的 this 指向的是 window 对象。
*/


【正确】常规写法:借用一个 that。
function Person() {
    var that = this;
    that.age = 0;

    setInterval(function growUp() {
        that.age++;
        console.log(that.age);
    }, 1000);
}
var p = new Person();


【正确】箭头函数:外层的 this 被成功传递
function Person(){
    this.age = 0;
    setInterval(() => {
        this.age++; 
        console.log(this.age);
    }, 1000);
}

var p = new Person();



2、不存在 本身this被覆盖问题
    调用 call 或 apply 函数时,无法给定一个 this 对象给 箭头函数。
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
    };
    // 把 b 作为 this 对象传入,结果不起作用。
    return f.call(b, a);
  }
};

console.log(adder.add(1));         // 结果:2
console.log(adder.addThruCall(1)); // 结果:仍然是 2




四、箭头函数没有 arguments 对象 
箭头函数没有隐式的 arguments 数组对象。
// 例子一:
var arguments = [3, 2, 1];
var arr = () => arguments[0];
arr(); // 3

// 例子二:
function foo(n) {
  // 此处的 arguments 对象是 foo 函数的,
  // 不是 f 箭头函数的。因为它没有。
  var f = () => arguments[0] + n; 
  return f();
}
foo(2); // 4



五、箭头函数没有 prototype 属性 
var Foo = () => {};
console.log(Foo.prototype); // undefined



六、箭头函数不能使用 new 关键字 
var Foo = () => {};
var foo = new Foo(); // TypeError: Foo is not a constructor



七、箭头函数不能单独使用 yield 关键字 

不能直接在 箭头函数 中 使用 yield 关键字(除非它被嵌套在其它函数中)。
所以 箭头函数 不能直接作为 Generator 使用。


八、在逻辑运算中,需要用小括号把 箭头函数 括起来
let callback;

callback = callback || function() {}; // ok

callback = callback || (() => {});    // ok

callback = callback || () => {};      
// SyntaxError: invalid arrow-function arguments





引用:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions







转载请注明,
原文出处:http://lixh1986.iteye.com/blog/2409009






=

猜你喜欢

转载自lixh1986.iteye.com/blog/2409009