天天看點

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那裡把參數傳了進去,我也不懂這個地方
           

首頁傳送門

繼續閱讀