首頁  >  文章  >  web前端  >  ES6中箭頭函數的詳細梳理

ES6中箭頭函數的詳細梳理

WBOY
WBOY轉載
2022-08-08 10:17:551349瀏覽

本篇文章為大家帶來了關於javascript的相關知識,其中主要介紹了es6中箭頭函數的相關問題,ES6中允許使用=>來定義函數。箭頭函數相當於匿名函數,並簡化了函數定義,下面一起來看一下,希望對大家有幫助。

ES6中箭頭函數的詳細梳理

【相關推薦:javascript影片教學web前端

一、箭頭函數的介紹

1.1 什麼是箭頭函數

ES6中允許使用=>定義函數。箭頭函數相當於匿名函數,並簡化了函數定義。

1.2 基本語法

// 箭头函数let fn = (name) => {
    // 函数体
    return `Hello ${name} !`;};// 等同于let fn = function (name) {
    // 函数体
    return `Hello ${name} !`;};

箭頭函數在語法上比一般函數簡潔多。箭頭函數就是採用箭頭=>定義函數,省去關鍵字function。

函數的參數放在=>前面的括號中,函數體跟在=>後面的花括號中

1.3 箭頭函數的參數

如果箭頭函數沒有參數,寫空括號

//没有参数,写空括号
    let fn = () => {
        console.log('hello');
    };

如果箭頭函數有一個參數,也可以省去包裹參數的括號

//只有一个参数,可以省去参数括号
    let fn = name => {
        console.log(`hello ${name}!`)
    };

如果箭頭函數有多個參數,將參數依序用逗號(,)分隔,包裹在括號中。

    let fn = (val1, val2, val3, val4) => {
        return [val1, val2, val3, val4];
    }

1.4 箭頭函數的函數體

#如果箭頭函數的函數體只有一句執行程式碼,簡單傳回某個變數或傳回一個簡單的js表達​​式,可以省去函數體花括號{ }

//返回某个简单变量vallet f = val => val;// 等同于let f = function (val) { return val };//返回一个简单的js表达式num1+num2let sum = (num1, num2) => num1 + num2;// 等同于let sum = function(num1, num2) {
  return num1 + num2;};

如果箭頭函數的函數體只有一句程式碼,傳回的不是變數和簡單的js表達​​式,而是一個物件。

//错误写法—花括号会被解释为函数体
    let getItem = id => {
        id: id,
        name: 'gaby'
    };//正确写法
    let getItem = id => ({
        id: id,
        name: 'gaby'
    });

如果箭頭函數的函數體只有一條語句且不需要傳回值(最常用於回呼函數),加上void關鍵字

let fn = () => void doesNotReturn();

箭頭函數用於回呼函數,常見簡潔

//栗子1//普通函数
    [1, 2, 3].map(function (x) {
        return x + x;
    });//ES6箭头函数[1, 2, 3].map(x => x + x);
//栗子2//普通函数
    var result = [2, 4, 5, 1, 6].sort(function (a, b) {
        return a - b;
    });//ES6箭头函数
	var result = [2, 4, 5, 1, 6].sort((a, b) => a - b);

二、箭頭函數的this指向規則

#2.1 箭頭函數沒有原型prototype,因此箭頭函數沒有this指向

    let fn = () => {
        console.log('Hello World !')
    };
    console.log(fn.prototype); // undefined

ES6中箭頭函數的詳細梳理

2.2 箭頭函數不會建立自己的this,如果存在外層第一個普通函數,在定義的時候會繼承它的this

箭頭函數沒有自己的this指向,它會捕捉自己定義所處的外層執行環境,並且繼承這個this值。箭頭函數的this指向在被定義的時候就確定了,之後永遠都不會改變。 (!永遠)

(1)栗子1
    var id = 'Global';
    //普通函数
    function fn1() {
        setTimeout(function () {
            console.log(this.id)

        }, 1000);
    }
    //箭头函数
    function fn2() {
        setTimeout(() => {
            console.log(this.id)
        }, 1000);
    }

    fn1.call({
        id: 'obj'
    });//Global

    fn2.call({
        id: 'obj'
    });//obj

ES6中箭頭函數的詳細梳理

解析:普通函數的setTimeout 一秒後執行是在全域作用域,所有this指向window對象,this.id指向了全域變數id,輸出Golbal。箭頭函數的this在定義的時候就確定了,繼承fn2的執行環境中的this,fn2的this指向被call方法改變綁定到obj這個物件

#(2)栗子2
    var id = 'Global';
    var obj = {
        id: 'OBJ',
        a: function () {
            console.log(this.id)
        },//方法a普通函数定义
        b: () => {
            console.log(this.id)
        }//方法b用箭头函数定义
    };
    obj.a();//OBJ
    obj.b();//Global

ES6中箭頭函數的詳細梳理

解析:普通函數作為物件的方法調用,this指向所屬的物件(誰調用它就指向誰),this.id 就是obj.id;箭頭函數繼承定義它的執行環境的this,指向window對象,指向全域變量,輸出Global。花括號{}無法形成一個單獨的執行環境,所有它依然在全局。

2.3 箭頭函數的this是繼承而來的永遠不會變,call/apply/bind也無法改變

.call( )/.apply()/.bind()方法可以用來動態修改函數執行時this的指向,但由於箭頭函數的this定義時就已經確定且永遠不會改變

    var name = 'gaby'
    var person = {
        name: 'gabrielle',
        say: function () {
            console.log('say hello', this.name)
        }, //普通函数
        say2: () => {
            console.log('say2 hello', this.name)
        } //箭头函数
    }
    person.say.call({
        name: 'Mike'
    })
    person.say2.call({
        name: 'Amy'
    })

ES6中箭頭函數的詳細梳理

解析:say的普通函數透過call呼叫已經改變this指向。 say2箭頭函數呼叫call綁定嘗試改變this指向,但仍印出外一層普通函數的this指向,window物件的全域變數name。

2.4 箭頭函數this指向只能間接修改

#間接修改:修改被繼承的普通函數的this指向,箭頭函數的this指向也會跟著改變。

箭头函数的this指向定义时所在的外层第一个普通函数,跟使用的位置没有关系。

    let al    let aObj = {
        msg: 'a的this指向'
    };
    bObj = {
        msg: 'b的this指向'
    };
    a.call(aObj); //将a的this指向aObj
    b.call(bObj); //将b普通函数的this指向bObj 箭头函数内部的this指向也会指向bObj

    function b() {
        al();
    }

    function a() {
        al = () => {
            console.log(this, 'this指向定义时外层第一个普通函数 ')
        };
    }

ES6中箭頭函數的詳細梳理

2.5 箭头函数外层没有函数,严格模式和非严格模式下它的this都会指向window全局对象

箭头函数的this指向继承自外层第一个普通函数的this,那么如果没有外层函数,它的this指向哪里?

this的绑定规则:非严格模式下,默认绑定的this指向全局对象,严格模式下this指向undefined。

如果箭头函数外层没有普通函数继承,箭头函数在全局作用域下,严格模式和非严格模式下它的this都会指向window(全局对象)

2.6 多层嵌套函数this指向

箭头函数中的this引用的是最近作用域中的this,是向外层作用域中,一层层查找this,直到有this的定义。

2.7 箭头函数不能作为构造函数使用new

构造函数做了什么?

JS内部首先会先生成一个对象

再把函数中的this指向该对象

然后执行构造函数中的语句

最终返回该对象实例

箭头函数没有自己的this,this继承外层执行环境中的this,且this永远不会改变。new会报错

    let fn = (name, age) => {
        this.name = name;
        this.age = age;
    };

    let person = new fn('gaby', 20)

ES6中箭頭函數的詳細梳理

2.8 箭头函数不支持new.target

ES6新引入的属性,普通函数可以通过new调用,new.target返回该函数的引用。用于确定构造函数是否为new调用。箭头函数并不能作为构造函数使用new,自然也不支持new.targer。

(1)箭头函数的this指向全局对象,在箭头函数中使用箭头函数会报错
    let fn = () => {
        console.log(new.target)
    };
    fn()

ES6中箭頭函數的詳細梳理

(2)箭头函数的this指向普通函数,它的new.target就是指向该普通函数的引用
    new fn2();

    function fn2() {
        let fn = () => {
            console.log(new.target)
        };
        fn();
    }

ES6中箭頭函數的詳細梳理

三、箭头函数的arguments规则

3.1 箭头函数没有自己的arguments

(1)箭头函数处于全局作用域中

箭头函数的this指向全局对象,会报arguments未声明的错。

    let fn = name => {
        console.log(arguments)
    }
    let fn2 = function (name) {
        console.log(arguments)
    }
    //fn()
    fn2()

ES6中箭頭函數的詳細梳理

    let fn = name => {
        console.log(arguments)
    }
    let fn2 = function (name) {
        console.log(arguments)
    }
    fn()
    fn2()

ES6中箭頭函數的詳細梳理

解析:普通函数可以打印arguments,箭头函数报错。因为箭头函数处于全局作用域中,在全局作用域没有arguments的定义,箭头函数本身没有arguments,所以报错。

(2)箭头函数的this如果指向普通函数,它的argumens继承于该普通函数
    let fn2 = function (name) {
        console.log('fn2:', arguments)
        let fn = name => {
            console.log('fn:', arguments)
        }
        fn()
    }
    fn2('gaby')

ES6中箭頭函數的詳細梳理

解析:两个函数打印的argument相同,都是fn2函数的arguments。

总结

箭头函数没有自己的arguments对象。在箭头函数中访问arguments实际上获得的是外层局部(函数)执行环境中的值。

3.2 可以用rest替代,rest参数获取函数的多余参数

rest是ES6的API,用于获取函数不定数量的参数数组。这个API可以用来替代arguments。

(1)基本用法
    //形式是...变量名 
	let fn = (first, ...arr) => {
        console.log(first, arr);
    }
    fn(1, 2, 3, 4);

ES6中箭頭函數的詳細梳理

解析:rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。获取函数的第一个确定的参数,以及用一个变量接收其他剩余函数的实例。

(2)使用注意事项

rest必须是函数的最后一位参数

    let a = (first, ...rest, three) => {
        console.log(first, rest, three);
    };
    a(1, 2, 3, 4);

ES6中箭頭函數的詳細梳理

函数的length属性不包括rest

(3)rest和arguments函数比较

箭头函数和普通函数都可以使用rest参数,而arguments只能普通函数用。

接收参数rest比arguments更加灵活,完全可以自定义。

rest是一个真正的数组可以使用数组API,arguments只是一个类数组。

3.3 箭头函数不支持重复函数参数的名称

    function fn(name, name) {
        console.log('fn2:', name)
    }
    let fn2 = (name, name) => {
        console.log('fn:', name)
    }
    fn('wang', 'gaby')
    fn2('wang', 'gaby')

ES6中箭頭函數的詳細梳理

3.4 箭头函数不能用作Generator,不能使用yeild关键字

四、箭头函数的注意事项

函数箭头一条语句返回对象字面量,需要加括号。

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

箭头函数的解析顺序相对||靠前

五、箭头函数不适用场景

(1)对象方法,且方法使用了this

对象无法构造单独的作用域

    var name = 'gaby'
    var person = {
        name: 'gabrielle',
        say: function () {
            console.log('say hello', this.name)
        }, //普通函数
        say2: () => {
            console.log('say2 hello', this.name)
        } //箭头函数
    }
    person.say()
    person.say2()

ES6中箭頭函數的詳細梳理

解析:person.say2()方法是一个箭头函数,调用person.say2()的时候this指向全局对象,达不到预期。对象无法构成单独的作用域,定义say2()箭头函数的时候作用域在全局作用域。

(2)回调函数的动态this
    var button = document.querySelector('.btn');
    button.addEventListener('click', () => {
        this.classList.toggle('on');
    });

ES6中箭頭函數的詳細梳理

解析:报错。按钮点击是一个回调函数,而箭头函数内部的this指向外一层普通函数的this,在这里就是window,所以报错。改成普通函数就不会报错

六、箭头函数与普通函数简单区别总结

(1)箭头函数语法更简洁清晰,快捷。

(2)箭头函数没有原型prototype,并不会自己创建this,并且this不能被修改,call等都不能修改到。只能间接修改被继承的this

(3)箭头函数的this在定义时就定了,继承外一层的普通函数

(4)如果箭头函数外一层再外一层都不能找到普通函数,在严格和非严格情况下都会指向window对象

(5)箭头函数的this指向全局,使用arguments会报未声明的错误

(6)箭头函数的this指向外一层的普通函数,使用argument继承该普通函数

(7)箭头函数不能构造函数,不能new.target,不能new,没有constructor

(8)箭头函数不支持重复命名参数,普通函数可以重复命名参数

【相关推荐:javascript视频教程web前端

以上是ES6中箭頭函數的詳細梳理的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:csdn.net。如有侵權,請聯絡admin@php.cn刪除