關(guān)于ES6中的箭頭函數(shù)超詳細(xì)梳理
一、箭頭函數(shù)的介紹
1.1 什么是箭頭函數(shù)
ES6中允許使用=>來定義函數(shù)。箭頭函數(shù)相當(dāng)于匿名函數(shù),并簡化了函數(shù)定義。
1.2 基本語法
// 箭頭函數(shù) let fn = (name) => { // 函數(shù)體 return `Hello ${name} !`; }; // 等同于 let fn = function (name) { // 函數(shù)體 return `Hello ${name} !`; };
箭頭函數(shù)在語法上比普通函數(shù)簡潔多。箭頭函數(shù)就是采用箭頭=>來定義函數(shù),省去關(guān)鍵字function。
函數(shù)的參數(shù)放在=>前面的括號中,函數(shù)體跟在=>后的花括號中
1.3 箭頭函數(shù)的參數(shù)
①如果箭頭函數(shù)沒有參數(shù),寫空括號
//沒有參數(shù),寫空括號 let fn = () => { console.log('hello'); };
②如果箭頭函數(shù)有一個參數(shù),也可以省去包裹參數(shù)的括號
//只有一個參數(shù),可以省去參數(shù)括號 let fn = name => { console.log(`hello ${name}!`) };
③如果箭頭函數(shù)有多個參數(shù),將參數(shù)依次用逗號(,)分隔,包裹在括號中。
let fn = (val1, val2, val3, val4) => { return [val1, val2, val3, val4]; }
1.4 箭頭函數(shù)的函數(shù)體
①如果箭頭函數(shù)的函數(shù)體只有一句執(zhí)行代碼,簡單返回某個變量或者返回一個簡單的js表達(dá)式,可以省去函數(shù)體花括號{ }
//返回某個簡單變量val let f = val => val; // 等同于 let f = function (val) { return val }; //返回一個簡單的js表達(dá)式num1+num2 let sum = (num1, num2) => num1 + num2; // 等同于 let sum = function(num1, num2) { return num1 + num2; };
②如果箭頭函數(shù)的函數(shù)體只有一句代碼,返回的不是變量和簡單的js表達(dá)式,而是一個對象。
//錯誤寫法—花括號會被解釋為函數(shù)體 let getItem = id => { id: id, name: 'gaby' }; //正確寫法 let getItem = id => ({ id: id, name: 'gaby' });
③如果箭頭函數(shù)的函數(shù)體只有一條語句且不需要返回值(最常用于回調(diào)函數(shù)),加上void關(guān)鍵字
let fn = () => void doesNotReturn();
箭頭函數(shù)用于回調(diào)函數(shù),常見簡潔
//栗子1 //普通函數(shù) [1, 2, 3].map(function (x) { return x + x; }); //ES6箭頭函數(shù) [1, 2, 3].map(x => x + x);
//栗子2 //普通函數(shù) var result = [2, 4, 5, 1, 6].sort(function (a, b) { return a - b; }); //ES6箭頭函數(shù) var result = [2, 4, 5, 1, 6].sort((a, b) => a - b);
二、箭頭函數(shù)的this指向規(guī)則
2.1 箭頭函數(shù)沒有原型prototype,因此箭頭函數(shù)沒有this指向
let fn = () => { console.log('Hello World !') }; console.log(fn.prototype); // undefined
2.2 箭頭函數(shù)不會創(chuàng)建自己的this,如果存在外層第一個普通函數(shù),在定義的時候會繼承它的this
箭頭函數(shù)沒有自己的this指向,它會捕獲自己定義所處的外層執(zhí)行環(huán)境,并且繼承這個this值。箭頭函數(shù)的this指向在被定義的時候就確定了,之后永遠(yuǎn)都不會改變。(!永遠(yuǎn))
(1)栗子1
var id = 'Global'; //普通函數(shù) function fn1() { setTimeout(function () { console.log(this.id) }, 1000); } //箭頭函數(shù) function fn2() { setTimeout(() => { console.log(this.id) }, 1000); } fn1.call({ id: 'obj' });//Global fn2.call({ id: 'obj' });//obj
解析:普通函數(shù)的setTimeout 一秒后執(zhí)行是在全局作用域,所有this指向window對象,this.id指向了全局變量id,輸出Golbal。箭頭函數(shù)的this在定義的時候就確定了,繼承fn2的執(zhí)行環(huán)境中的this,fn2的this指向被call方法改變綁定到obj這個對象
(2)栗子2
var id = 'Global'; var obj = { id: 'OBJ', a: function () { console.log(this.id) },//方法a普通函數(shù)定義 b: () => { console.log(this.id) }//方法b用箭頭函數(shù)定義 }; obj.a();//OBJ obj.b();//Global
解析:普通函數(shù)作為對象的方法調(diào)用,this指向所屬的對象(誰調(diào)用它就指向誰),this.id 就是obj.id;箭頭函數(shù)繼承定義它的執(zhí)行環(huán)境的this,指向window對象,指向全局變量,輸出Global?;ɡㄌ杮}無法形成一個單獨的執(zhí)行環(huán)境,所有它依然在全局中。
2.3 箭頭函數(shù)的this是繼承而來的永遠(yuǎn)不會變,call/apply/bind也無法改變
.call()/.apply()/.bind()方法可以用來動態(tài)修改函數(shù)執(zhí)行時this的指向,但由于箭頭函數(shù)的this定義時就已經(jīng)確定且永遠(yuǎn)不會改變
var name = 'gaby' var person = { name: 'gabrielle', say: function () { console.log('say hello', this.name) }, //普通函數(shù) say2: () => { console.log('say2 hello', this.name) } //箭頭函數(shù) } person.say.call({ name: 'Mike' }) person.say2.call({ name: 'Amy' })
解析:say的普通函數(shù)通過call調(diào)用已經(jīng)改變this指向。say2箭頭函數(shù)調(diào)用call綁定嘗試改變this指向,但是仍然打印出外一層普通函數(shù)的this指向,window對象的全局變量name。
2.4 箭頭函數(shù)this指向只能間接修改
間接修改:修改被繼承的普通函數(shù)的this指向,箭頭函數(shù)的this指向也會跟著改變。
箭頭函數(shù)的this指向定義時所在的外層第一個普通函數(shù),跟使用的位置沒有關(guān)系。
let al let aObj = { msg: 'a的this指向' }; bObj = { msg: 'b的this指向' }; a.call(aObj); //將a的this指向aObj b.call(bObj); //將b普通函數(shù)的this指向bObj 箭頭函數(shù)內(nèi)部的this指向也會指向bObj function b() { al(); } function a() { al = () => { console.log(this, 'this指向定義時外層第一個普通函數(shù) ') }; }
2.5 箭頭函數(shù)外層沒有函數(shù),嚴(yán)格模式和非嚴(yán)格模式下它的this都會指向window全局對象
箭頭函數(shù)的this指向繼承自外層第一個普通函數(shù)的this,那么如果沒有外層函數(shù),它的this指向哪里?
this的綁定規(guī)則:非嚴(yán)格模式下,默認(rèn)綁定的this指向全局對象,嚴(yán)格模式下this指向undefined。
如果箭頭函數(shù)外層沒有普通函數(shù)繼承,箭頭函數(shù)在全局作用域下,嚴(yán)格模式和非嚴(yán)格模式下它的this都會指向window(全局對象)
2.6 多層嵌套函數(shù)this指向
箭頭函數(shù)中的this引用的是最近作用域中的this,是向外層作用域中,一層層查找this,直到有this的定義。
2.7 箭頭函數(shù)不能作為構(gòu)造函數(shù)使用new
構(gòu)造函數(shù)做了什么?
①JS內(nèi)部首先會先生成一個對象
②再把函數(shù)中的this指向該對象
③然后執(zhí)行構(gòu)造函數(shù)中的語句
④最終返回該對象實例
箭頭函數(shù)沒有自己的this,this繼承外層執(zhí)行環(huán)境中的this,且this永遠(yuǎn)不會改變。new會報錯
let fn = (name, age) => { this.name = name; this.age = age; }; let person = new fn('gaby', 20)
2.8 箭頭函數(shù)不支持new.target
ES6新引入的屬性,普通函數(shù)可以通過new調(diào)用,new.target返回該函數(shù)的引用。用于確定構(gòu)造函數(shù)是否為new調(diào)用。箭頭函數(shù)并不能作為構(gòu)造函數(shù)使用new,自然也不支持new.targer。
(1)箭頭函數(shù)的this指向全局對象,在箭頭函數(shù)中使用箭頭函數(shù)會報錯
let fn = () => { console.log(new.target) }; fn()
(2)箭頭函數(shù)的this指向普通函數(shù),它的new.target就是指向該普通函數(shù)的引用
new fn2(); function fn2() { let fn = () => { console.log(new.target) }; fn(); }
三、箭頭函數(shù)的arguments規(guī)則
3.1 箭頭函數(shù)沒有自己的arguments
(1)箭頭函數(shù)處于全局作用域中
箭頭函數(shù)的this指向全局對象,會報arguments未聲明的錯。
let fn = name => { console.log(arguments) } let fn2 = function (name) { console.log(arguments) } //fn() fn2()
let fn = name => { console.log(arguments) } let fn2 = function (name) { console.log(arguments) } fn() fn2()
解析:普通函數(shù)可以打印arguments,箭頭函數(shù)報錯。因為箭頭函數(shù)處于全局作用域中,在全局作用域沒有arguments的定義,箭頭函數(shù)本身沒有arguments,所以報錯。
(2)箭頭函數(shù)的this如果指向普通函數(shù),它的argumens繼承于該普通函數(shù)
let fn2 = function (name) { console.log('fn2:', arguments) let fn = name => { console.log('fn:', arguments) } fn() } fn2('gaby')
解析:兩個函數(shù)打印的argument相同,都是fn2函數(shù)的arguments。
總結(jié)
箭頭函數(shù)沒有自己的arguments對象。在箭頭函數(shù)中訪問arguments實際上獲得的是外層局部(函數(shù))執(zhí)行環(huán)境中的值。
3.2 可以用rest替代,rest參數(shù)獲取函數(shù)的多余參數(shù)
rest是ES6的API,用于獲取函數(shù)不定數(shù)量的參數(shù)數(shù)組。這個API可以用來替代arguments。
(1)基本用法
//形式是...變量名 let fn = (first, ...arr) => { console.log(first, arr); } fn(1, 2, 3, 4);
解析:rest 參數(shù)搭配的變量是一個數(shù)組,該變量將多余的參數(shù)放入數(shù)組中。獲取函數(shù)的第一個確定的參數(shù),以及用一個變量接收其他剩余函數(shù)的實例。
(2)使用注意事項
①rest必須是函數(shù)的最后一位參數(shù)
let a = (first, ...rest, three) => { console.log(first, rest, three); }; a(1, 2, 3, 4);
②函數(shù)的length屬性不包括rest
(3)rest和arguments函數(shù)比較
①箭頭函數(shù)和普通函數(shù)都可以使用rest參數(shù),而arguments只能普通函數(shù)用。
②接收參數(shù)rest比arguments更加靈活,完全可以自定義。
③rest是一個真正的數(shù)組可以使用數(shù)組API,arguments只是一個類數(shù)組。
3.3 箭頭函數(shù)不支持重復(fù)函數(shù)參數(shù)的名稱
function fn(name, name) { console.log('fn2:', name) } let fn2 = (name, name) => { console.log('fn:', name) } fn('wang', 'gaby') fn2('wang', 'gaby')
3.4 箭頭函數(shù)不能用作Generator,不能使用yeild關(guān)鍵字 四、箭頭函數(shù)的注意事項
①函數(shù)箭頭一條語句返回對象字面量,需要加括號。
②箭頭函數(shù)在參數(shù)和箭頭之間不能換行
③箭頭函數(shù)的解析順序相對||靠前
五、箭頭函數(shù)不適用場景
(1)對象方法,且方法使用了this
對象無法構(gòu)造單獨的作用域
var name = 'gaby' var person = { name: 'gabrielle', say: function () { console.log('say hello', this.name) }, //普通函數(shù) say2: () => { console.log('say2 hello', this.name) } //箭頭函數(shù) } person.say() person.say2()
解析:person.say2()方法是一個箭頭函數(shù),調(diào)用person.say2()的時候this指向全局對象,達(dá)不到預(yù)期。對象無法構(gòu)成單獨的作用域,定義say2()箭頭函數(shù)的時候作用域在全局作用域。
(2)回調(diào)函數(shù)的動態(tài)this
var button = document.querySelector('.btn'); button.addEventListener('click', () => { this.classList.toggle('on'); });
解析:報錯。按鈕點擊是一個回調(diào)函數(shù),而箭頭函數(shù)內(nèi)部的this指向外一層普通函數(shù)的this,在這里就是window,所以報錯。改成普通函數(shù)就不會報錯
六、箭頭函數(shù)與普通函數(shù)簡單區(qū)別總結(jié)
(1)箭頭函數(shù)語法更簡潔清晰,快捷。
(2)箭頭函數(shù)沒有原型prototype,并不會自己創(chuàng)建this,并且this不能被修改,call等都不能修改到。只能間接修改被繼承的this
(3)箭頭函數(shù)的this在定義時就定了,繼承外一層的普通函數(shù)
(4)如果箭頭函數(shù)外一層再外一層都不能找到普通函數(shù),在嚴(yán)格和非嚴(yán)格情況下都會指向window對象
(5)箭頭函數(shù)的this指向全局,使用arguments會報未聲明的錯誤
(6)箭頭函數(shù)的this指向外一層的普通函數(shù),使用argument繼承該普通函數(shù)
(7)箭頭函數(shù)不能構(gòu)造函數(shù),不能new.target,不能new,沒有constructor
(8)箭頭函數(shù)不支持重復(fù)命名參數(shù),普通函數(shù)可以重復(fù)命名參數(shù)
到此這篇關(guān)于ES6中箭頭函數(shù)的文章就介紹到這了,更多相關(guān)ES6箭頭函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
屏蔽鼠標(biāo)右鍵、Ctrl+N、Shift+F10、Alt+F4、F11、F5刷新、退格鍵
js 防止刷新網(wǎng)頁、禁止后退,右鍵等操作的代碼2010-03-03JavaScript在IE和Firefox瀏覽器下的7個差異兼容寫法小結(jié)
盡管那需要用長串的、沉悶的不同分支代碼來應(yīng)付不同瀏覽器的日子已經(jīng)過去,偶爾還是有必要做一些簡單的區(qū)分和目標(biāo)檢測來確保某塊代碼能在用戶的機器上正常運行。2010-06-06如何使Chrome控制臺支持多行js模式——意外發(fā)現(xiàn)
一直以來,Chrome控制臺都缺少象IE調(diào)試臺那樣的多行執(zhí)行模式,今天意外發(fā)現(xiàn)Chrome其實也支持多行模式2013-06-06JavaScript canvas實現(xiàn)七彩太陽光暈效果
這篇文章主要為大家詳細(xì)介紹了JavaScript canvas實現(xiàn)七彩太陽光暈效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-05-05