天天看点

JavaScriptES6箭头函数

ES6允许使用箭头(=>)定义函数

var f = v => v;
//等同于
var f = function(v){
     return v;
}
           

如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分。

var f = () => 5;
console.log(f());
//相当于
var f = function(){
     return 5;
}
var sum = (num1,num2) => num1 + num2;
console.log(sum(1,2));
//相当于
var sum = function(sum1,sum2){
     return sum1 + sum2;
}
           

如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且可以使用return 返回语句。

var f = () => {
     var a = 1;
     var b = 2;
     return a + b;
}
console.log(f());
           

由于大括号被解释为代码块,所以如果箭头函数直接返回的一个对象,必须在对象外面加上大括号,否则会报错。

let func = id => { id : id, name : 'Temp'}  //报错
let func = id => ({ id : id , name : 'wng'});
           

上面代码中,原始意图是返回一个对象{a : 1},但是由于引擎认为大括号是代码块,所以执行了一行语句 a : 1 。这是,a可以被解释为语句的标签,因此实际执行的语句是1,然后函数就结束了,没有返回值。

如果箭头函数只有一行语句,且不需要返回值,可以采用下面的写法,就不用写大括号了。

let fu = () => 1 + 2;
let fn = () => void fu();
console.log(fn()); 
           

箭头函数可以与变量解构赋值结合使用。

const full = ({first,last}) =>  first + " " +last;
console.log(full({first : 1, last : 2})); 
           

箭头函数的一个用处是可以简化回调函数。

let arr2 = arr.map((x) => x = x + 1);
           

rest参数结合箭头函数。

const number = (...values) => values;
console.log(number(1,2,3,4,5,6,7,8,9));
const fun = (first,...last) => [first,last];
console.log(fun(1,2,3,4,5,6));
           

箭头函数的注意点

    1.函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

    2.不可以当做构造函数,也就是说不可以使用new命令,否则会抛出一个错误

    3.不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以使用rest参数。

    4.不可以使用yield命令,因此箭头函数不能用作Generator函数

    第一点注意:this对象的指向是可变的,但是,在箭头函数中,它是固定不变的

var obj = {
     fun : function(){
         setTimeout(function(){
             console.log(this);
         },1000)
     }
 }
 obj.fun();  //window
 var obj1 = {
     fun : function(){
         setTimeout(() =>{
             console.log(this);
         },1000);
     }
 }
 obj1.fun();
 var obj2 = {
    num : 123,
    fun : function(){
         console.log(this);
         var f =  () => {
            console.log(this);
         }
         f();
         setTimeout(() => {
             console.log(this.num);
         },1000);
     }
 }
 obj2.fun()
//自己可以运行一下
           

箭头函数可以让this指向固定化,这种特性很有利于封装回调函数。但是,this指向的固定化,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码块的this。正式因为它没有this,所以也就不能用作构造函数。

箭头函数转成ES5的代码如下
function foo(){     //ES6
     setTimeout( () => {
         console.log('id:',this.id);
     },100);
 }
 //ES5
function foo(){
     var _this = this;
     setTimeout( () => {
        console.log("id :" , _this.id);
     })
}
           

除了this,以下三个变量在箭头函数之中也是不存在的,指向外层函数的对应变量:arguments,super,new.target。

function foo(){
     setTimeout( () => {
         console.log(arguments);     //callee :foo
     },100);
 }
foo(2,4,6,8);
//上面代码中,箭头函数内部的变量arguments,其实是函数foo的arguments变量
           

另外,由于箭头函数没有自己的this,所以当然也不能用call(),apply(),bind()这些方法去改变this的指向。

(function(){
     return [
        (() => this.x).bind({x : 'inner'})()
     ]
 }).call({x : 'outer'});
//箭头函数没有自己的this,所以bind方法无效,内部的this指向外部的this
           

嵌套的的箭头函数:箭头函数内部,还可以再使用箭头函数。

function insert(value) {
     return {
         init : function (array){
             return {
                 after : function(afterValue) {
                     array.splice(array.indexOf(afterValue) + 1,0,value);
                     return array;
                 }
             }
         }
     }
 }
 console.log(insert(2).init([1,3]).after(1));
 let insert = (value) => ({init : (array) => ({after : (afterValue) => {
    array.splice(array.indexOf(afterValue) + 1 , 0 , value);
     return array;
/ }})});
 console.log(insert(2).init([1,3]).after(1));
           

部署管道机制:下面reduce方法中的b方法把a方法作为参数传过去,这个我也不理解这个执行过程。

const pipeline = (...funcs) => val => funcs.reduce((a,b) => b(a),val);
const plus1 = a => a + 1;
const mult2 = a => a * 2;
const addThenMult = pipeline(plus1,mult2);
console.log(addThenMult(5));
           

在别的地方看到别人写的ES5的形式,也就是addThenMult这个方法。

const addThenMult = function(num){
    return pipeline(plus1(num),mult2)
}
//这里在plus1那里把参数传了进去,我也不懂这个地方
           

主页传送门

继续阅读