ES6-箭头函数

1、概述

箭头函数是指经过=>语法定义的函数。JS编程中常常定义一些短小的匿名函数,使用箭头函数语法可以使得这类函数的定义更加简洁。javascript

// ES3/5方式
var fun1 = function(x, y) {
    return x + y;
}

var arr1 = [1,2,3].map(function(item){
    return item * item;
})

// 箭头函数方式
var fun2 = (x, y) => x + y;

var arr2 = [1,2,3].map((item) => item * item)

少些了很多代码,看着也简洁许多,有木有。html

2、语法

  • 通常的语法格式:java

    (param1, param2, …, paramN) => { 语句 }

    注意参数部分和箭头=>之间不能换行,如:es6

    // 正确
    var add1 = (x, y) => x + y; 
    
    // 正确
    var add2 = (x,             
        y) => x + y;
        
    // 正确(=>后面不会自动插入分号的)
    var add3 = (x, y) => 
    x + y;
    
    // 语法错误 Uncaught SyntaxError: Unexpected token =>
    var add4 = (x, y) 
        => x + y;
    
     // 语法错误 Uncaught SyntaxError: Unexpected token =>
    var add5= x 
        => x + 2;

    上例中add4定义会报错,缘由在解析的时候(x, y)后面会自动插入分号,因此当解析=>时就报错了。编程

  • 若是花括号里只包含一个return语句,则能够简写为:闭包

    (param1, param2, …, paramN) => 表达式 // 等价于 => { return 表达式; }

    由于对象字面量也是用花括号表示的,因此当表达式是个对象字面量时须要用括号包住:app

    var a = p => ({a: p}) // 不能写成:p => {a: p}
  • 若是有且只有一个形参,则能够省略括号,简写为:函数

    param => {语句} // 等价于 (param) => {语句}

如上例中的fun1定义:学习

var fun1 = (x, y) => x + y;
// 等价于
var fun1 = (x, y) => { return x + y; }

3、特性

箭头函数不单单更方便定义匿名函数,它还具备一些特性,这些使得箭头函数在使用上也更方便。
箭头函数通常定义在一个函数内部,箭头函数的函数体内是能够访问外部函数定义的局部变量的(闭包),可是外部函数还有两个特殊的变量:this和arguments。由于每一个函数都具备本身的this和arguments变量,因此当内部函数访问外部函数这两个变量时,咱们通常采用这种方式:this

var outer = {
    name: 'outer',
    say: function() {
        var _arguments = arguments, // 先把arguments赋值给局部变量_arguments 
            _this = this; // 先把this赋值给局部变量_this
        
        function inner() {
            console.log(arguments.length); // 内部函数的arguments
            console.log(_arguments.length); // 经过局部变量_arguments访问外部函数的arguments变量
            
            console.log(this.name); // 内部函数的this
            console.log(_this.name); // 经过局部变量_this访问外部函数的this变量
        }
        
        return inner;
    }
}

可是箭头函数体能够直接访问外部函数的this和arguments变量!!!逆天啊。

3.1 箭头函数“不具备本身的this变量”

1 特性语法

箭头函数体内this变量指向外部函数的this。如上例能够写为:

var outer = {
    name: 'outer',
    say: function() {
        return () => { console.log(this.name); } // 外部函数outer的this,
    }
}

而且经过call,apply,bind函数也是没法修改箭头函数的this变量的。

var outer = {
    name: 'outer',
    say: function() {
        var inner = () => { console.log(this.name); } // 依旧外部函数outer的this,
        return inner.bind({name: 'inner'}) //
    }
}

2 特性原理

箭头函数并非真的不具备本身的this变量,只是它从新修改this变量的值。

var outer = {
    name: 'outer',
    say: function() {
        return () => { console.log(this.name); } // 外部函数outer的this,
    }
}

// 等价于:
var outer = {
    name: 'outer',
    say: function say() {
        var _this = this; // 定义个局部变量_this
        return function () {
            this = _this; // 修改内部的this
            console.log(this.name);
        };
    }
};

因此这样call,apply,bind也就没法修改箭头函数的this值的。

3.2 箭头函数“不具备本身的arguments变量”

跟this变量相似箭头函数也“不具备本身的arguments变量”,原理跟this相似。

总结一句话:箭头函数是为了特殊的使用场景(即更方便的定义和使用匿名函数),它的这些特性也是为了方便其使用。

4、使用限制

4.1 不能用new 操做符

对箭头函数使用new操做符会抛TypeError异常。

var A = () => {}
var a = new A(); //抛异常 Uncaught TypeError: A is not a constructor

即箭头函数不能做为构造函数,其也不具备prototype属性。缘由应该是其内部的this变量被重写了,不能做为构造函数理所固然。可是箭头函数也是函数:

var a = () => {};
console.log(a instanceof Function); // true

总结一句话:箭头函数是不能做为构造函数的特殊函数。

4.2 跟其余运算符一块儿用

箭头函数=>不是运算符,当箭头函数做为右值跟其余运算符一块儿运算操做时其具备特殊的解析顺序

function func(callback) {
    // 通常函数方式
    callback = callback || function() {} // 没问题
    // 报错了,语法错误:Uncaught SyntaxError: Unexpected token )
    callback = callback || () => {};
    // 这样写就对了
    callback = callback || (() => {});
}

总结一句话:箭头函数虽然不是运算符,但其写法和解析有点像运算符的操做。当箭头函数做为右值参与其余运算符的运算时记得加上括号。

4.3 须要使用本身this的函数

箭头函数"没有本身的this",因此它不适用那些须要使用本身this的场景(如成员方法,事件回调函数等)

// 成员方法
var outer = {
    name: 'outer',
    say: () => { 
        // 这里的this不是outer,可是咱们指望在成员方法的this应该指向对象自己
        console.log(this.name);  
    }
}

// 事件处理函数
document.getElementById('test').onclick = function() {
  console.log(this); // 这里的this不是触发事件的DOM对象
}

总结一句话:箭头函数虽然写起了比较爽,但不能滥用,它是有特殊应用场景的。要懂得何时不应用。

参考

  1. MDN 箭头函数
  2. w3cPlus ES6学习笔记:箭头函数
  3. JavaScript 语句后应该加分号么?
相关文章
相关标签/搜索