摘要:沒有箭頭函數(shù)沒有自己的對象,這不一定是件壞事,因?yàn)榧^函數(shù)可以訪問外圍函數(shù)的對象那如果我們就是要訪問箭頭函數(shù)的參數(shù)呢你可以通過命名參數(shù)或者參數(shù)的形式訪問參數(shù)不能通過關(guān)鍵字調(diào)用函數(shù)有兩個(gè)內(nèi)部方法和。
1、基本語法回顧
我們先來回顧下箭頭函數(shù)的基本語法。
ES6 增加了箭頭函數(shù):
var f = v => v;
// 等同于
var f = function (v) {
return v;
};
如果箭頭函數(shù)不需要參數(shù)或需要多個(gè)參數(shù),就使用一個(gè)圓括號(hào)代表參數(shù)部分。
var f = () => 5;
// 等同于
var f = function () { return 5 };
var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
return num1 + num2;
};
由于大括號(hào)被解釋為代碼塊,所以如果箭頭函數(shù)直接返回一個(gè)對象,必須在對象外面加上括號(hào),否則會(huì)報(bào)錯(cuò)。
// 報(bào)錯(cuò)
let getTempItem = id => { id: id, name: "Temp" };
// 不報(bào)錯(cuò)
let getTempItem = id => ({ id: id, name: "Temp" });
下面是一種特殊情況,雖然可以運(yùn)行,但會(huì)得到錯(cuò)誤的結(jié)果。
let foo = () => { a: 1 };
foo() // undefined
上面代碼中,原始意圖是返回一個(gè)對象{ a: 1 },但是由于引擎認(rèn)為大括號(hào)是代碼塊,所以執(zhí)行了一行語句a: 1。這時(shí),a可以被解釋為語句的標(biāo)簽,因此實(shí)際執(zhí)行的語句是1;,然后函數(shù)就結(jié)束了,沒有返回值。
關(guān)于作用域
箭頭函數(shù)內(nèi)定義的變量及其作用域
// 常規(guī)寫法
var greeting = () => {let now = new Date(); return ("Good" + ((now.getHours() > 17) ? " evening." : " day."));}
greeting(); //"Good day."
console.log(now); // ReferenceError: now is not defined 標(biāo)準(zhǔn)的let作用域
// 參數(shù)括號(hào)內(nèi)定義的變量是局部變量(默認(rèn)參數(shù))
var greeting = (now=new Date()) => "Good" + (now.getHours() > 17 ? " evening." : " day.");
greeting(); //"Good day."
console.log(now); // ReferenceError: now is not defined
// 對比:函數(shù)體內(nèi){}不使用var定義的變量是全局變量
var greeting = () => {now = new Date(); return ("Good" + ((now.getHours() > 17) ? " evening." : " day."));}
greeting(); //"Good day."
console.log(now); // Fri Dec 22 2017 10:01:00 GMT+0800 (中國標(biāo)準(zhǔn)時(shí)間)
// 對比:函數(shù)體內(nèi){} 用var定義的變量是局部變量
var greeting = () => {var now = new Date(); return ("Good" + ((now.getHours() > 17) ? " evening." : " day."));}
greeting(); //"Good day."
console.log(now); // ReferenceError: now is not defined
2、關(guān)于this
2.1、默認(rèn)綁定外層this
箭頭函數(shù)沒有 this,所以需要通過查找作用域鏈來確定 this 的值。
這就意味著如果箭頭函數(shù)被非箭頭函數(shù)包含,this 綁定的就是最近一層非箭頭函數(shù)的 this。
function foo() {
setTimeout(() => {
console.log("id:", this.id);
}, 100);
}
var id = 21;
foo.call({ id: 42 });
// id: 42
上面代碼中,setTimeout的參數(shù)是一個(gè)箭頭函數(shù),這個(gè)箭頭函數(shù)的定義生效是在foo函數(shù)生成時(shí),而它的真正執(zhí)行要等到 100 毫秒后。如果是普通函數(shù),執(zhí)行時(shí)this應(yīng)該指向全局對象window,這時(shí)應(yīng)該輸出21。但是,箭頭函數(shù)導(dǎo)致this總是指向函數(shù)定義生效時(shí)所在的對象(本例是{id: 42}),所以輸出的是42。
箭頭函數(shù)可以讓setTimeout里面的this,綁定定義時(shí)所在的作用域,而不是指向運(yùn)行時(shí)所在的作用域。
所以,箭頭函數(shù)轉(zhuǎn)成 ES5 的代碼如下。
// ES6
function foo() {
setTimeout(() => {
console.log("id:", this.id);
}, 100);
}
// ES5
function foo() {
var _this = this;
setTimeout(function () {
console.log("id:", _this.id);
}, 100);
}
2.2、 不能用call()、apply()、bind()方法修改里面的this
(function() {
return [
(() => this.x).bind({ x: "inner" })() // 無效的bind,最終this還是指向外層
];
}).call({ x: "outer" });
// ["outer"]
上面代碼中,箭頭函數(shù)沒有自己的this,所以bind方法無效,內(nèi)部的this指向外部的this。
3、沒有 arguments箭頭函數(shù)沒有自己的 arguments 對象,這不一定是件壞事,因?yàn)榧^函數(shù)可以訪問外圍函數(shù)的 arguments 對象:
function constant() {
return () => arguments[0]
}
var result = constant(1);
console.log(result()); // 1
那如果我們就是要訪問箭頭函數(shù)的參數(shù)呢?
你可以通過命名參數(shù)或者 rest 參數(shù)的形式訪問參數(shù):
let nums = (...nums) => nums;4、 不能通過 new 關(guān)鍵字調(diào)用
JavaScript 函數(shù)有兩個(gè)內(nèi)部方法:[[Call]] 和 [[Construct]]。
當(dāng)通過new調(diào)用函數(shù)時(shí),執(zhí)行[Construct]]方法,創(chuàng)建一個(gè)實(shí)例對象,然后再執(zhí)行函數(shù)體,將 this 綁定到實(shí)例上。
當(dāng)直接調(diào)用的時(shí)候,執(zhí)行[[Call]]方法,直接執(zhí)行函數(shù)體。
箭頭函數(shù)并沒有[[Construct]]方法,不能被用作構(gòu)造函數(shù),如果通過 new 的方式調(diào)用,會(huì)報(bào)錯(cuò)。
var Foo = () => {};
var foo = new Foo(); // TypeError: Foo is not a constructor
5、沒有原型
由于不能使用new調(diào)用箭頭函數(shù),所以也沒有構(gòu)建原型的需求,于是箭頭函數(shù)也不存在prototype這個(gè)屬性。
var Foo = () => {};
console.log(Foo.prototype); // undefined
5、不適用場合
第一個(gè)場合是定義函數(shù)的方法,且該方法內(nèi)部包括this。
const cat = {
lives: 9,
jumps: () => {
this.lives--;
}
}
上面代碼中,cat.jumps()方法是一個(gè)箭頭函數(shù),這是錯(cuò)誤的。調(diào)用cat.jumps()時(shí),如果是普通函數(shù),該方法內(nèi)部的this指向cat;如果寫成上面那樣的箭頭函數(shù),使得this指向全局對象,因此不會(huì)得到預(yù)期結(jié)果。
第二個(gè)場合是需要?jiǎng)討B(tài)this的時(shí)候,也不應(yīng)使用箭頭函數(shù)。
var button = document.getElementById("press");
button.addEventListener("click", () => {
this.classList.toggle("on");
});
上面代碼運(yùn)行時(shí),點(diǎn)擊按鈕會(huì)報(bào)錯(cuò),因?yàn)?b>button的監(jiān)聽函數(shù)是一個(gè)箭頭函數(shù),導(dǎo)致里面的this就是全局對象。如果改成普通函數(shù),this就會(huì)動(dòng)態(tài)指向被點(diǎn)擊的按鈕對象。
6、使用場景下面這個(gè)是我們開發(fā)經(jīng)常遇到的。我們一般會(huì)通過this賦值給一個(gè)變量,然后再通過變量訪問。
class Test {
constructor() {
this.birth = 10;
}
submit(){
let self = this;
$.ajax({
type: "POST",
dataType: "json",
url: "xxxxx" ,//url
data: "xxxxx",
success: function (result) {
console.log(self.birth);//10
},
error : function() {}
});
}
}
let test = new Test();
test.submit();//undefined
這里我們就可以通過箭頭函數(shù)來解決
...
success: (result)=> {
console.log(this.birth);//10
},
...
箭頭函數(shù)在react中的運(yùn)用場景
class Foo extends Component {
constructor(props) {
super(props);
}
handleClick() {
console.log("Click happened", this);
this.setState({a: 1});
}
render() {
return ;
}
}
在react中我們這樣直接調(diào)用方法是有問題的,在handleClick函數(shù)中的this是有問題,我們平時(shí)需要這么做
class Foo extends Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log("Click happened", this);
this.setState({a: 1});
}
render() {
return ;
}
}
這里通過this.handleClick.bind(this)給函數(shù)綁定this。但是這樣寫起來有些麻煩,有沒有簡單的方法呢?這時(shí)候我們的箭頭函數(shù)就出場了
class Foo extends Component {
// Note: this syntax is experimental and not standardized yet.
handleClick = () => {
console.log("Click happened", this);
this.setState({a: 1});
}
render() {
return ;
}
}
箭頭函數(shù)中 this 的值是繼承自 外圍作用域,很好的解決了這個(gè)問題。
除此之外我們還可以用箭頭函數(shù)傳參(這個(gè)不是必須的),而且會(huì)有性能問題。更多信息請查看
const A = 65 // ASCII character code
class Alphabet extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
this.state = {
justClicked: null,
letters: Array.from({length: 26}, (_, i) => String.fromCharCode(A + i)).
};
}
handleClick(letter) {
this.setState({ justClicked: letter });
}
render() {
return (
Just clicked: {this.state.justClicked}
{this.state.letters.map(letter =>
- this.handleClick(letter)}>
{letter}
)}
)
}
}
最后
更多系列文章請看
ES6學(xué)習(xí)(一)之var、let、const
ES6學(xué)習(xí)(二)之解構(gòu)賦值及其原理
ES6學(xué)習(xí)(三)之Set的模擬實(shí)現(xiàn)
ES6學(xué)習(xí)(四)之Promise的模擬實(shí)現(xiàn)
如果有錯(cuò)誤或者不嚴(yán)謹(jǐn)?shù)牡胤剑垊?wù)必給予指正,十分感謝。如果喜歡或者有所啟發(fā),歡迎star對作者也是一種鼓勵(lì)。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.hztianpu.com/yun/103207.html
摘要:如下在第一個(gè)例子中,被點(diǎn)擊元素是通過,這個(gè)形式參數(shù)來代替的。它的作用和形式參數(shù)類似,其本質(zhì)上是一個(gè)對象的引用,它的特殊性在于不需要手動(dòng)傳值,所以使用起來會(huì)更加簡單和方便。 無論在 javascript 的日常使用中還是前端面試過程中,this 的出鏡率都極高。這無疑說明了,this 的重要性。但是 this 非常靈活,導(dǎo)致很多人覺得 this 的行為難以理解。本文從為什么要有 this...
摘要:應(yīng)屆生零基礎(chǔ)可以學(xué)習(xí)軟件測試嗎俗話說,人怕入錯(cuò)行。霸哥這里分別從入行難度入行方式行業(yè)前景薪資待遇四個(gè)方面來分析一下。目前市場上的測試人員,一部分是企業(yè)自己培養(yǎng)的,另一部分是來自培訓(xùn)機(jī)構(gòu)。軟件測試的行業(yè)門檻低,市場需求量大。 ...
摘要:七月流火,燃情盛夏值此季節(jié),阿里云又推出了年中鉅惠,精選百款產(chǎn)品,助力創(chuàng)業(yè)新勢力。阿里云云盾安全防護(hù)體系,不僅合規(guī),更加安全。七月流火,燃情盛夏!值此季節(jié),阿里云又推出了年中鉅惠,精選百款產(chǎn)品,助力創(chuàng)業(yè)新勢力。從7月26日開始,每天上午10點(diǎn)、下午4點(diǎn)將會(huì)放出爆款產(chǎn)品,進(jìn)行限量秒殺,大家不要錯(cuò)過。注冊登陸還可抽取 iPhone 12 Pro、Cherry 機(jī)械鍵盤、企業(yè)電子書大禮包等好禮。 ...
摘要:來看看箭頭函數(shù)的情況可以發(fā)現(xiàn)在定時(shí)器這個(gè)匿名函數(shù)作用域里,所指向的對象,就是定義時(shí)所指的對象。對于構(gòu)造函數(shù)來說,它就是的實(shí)例。如下?lián)耍偨Y(jié)箭頭函數(shù)的三個(gè)優(yōu)點(diǎn)語法簡潔,能夠?qū)懗銎恋膯涡泻瘮?shù)。 ES6新引入了箭頭函數(shù),它是一種表達(dá)簡潔的函數(shù),下面我們來看看它有哪三個(gè)顯著優(yōu)勢。假設(shè)定義了一個(gè)名為names的數(shù)組,如下: showImg(https://segmentfault.com/i...
摘要:在以太坊出現(xiàn)后,進(jìn)入了第二階段。以太坊可以被視作區(qū)塊鏈?zhǔn)澜珙愃朴诤偷牡讓硬僮飨到y(tǒng)。通證經(jīng)濟(jì)的設(shè)計(jì)方向模式的組織,是天然的生態(tài)型組織。區(qū)塊鏈時(shí)代的生態(tài)組織,大致可以分成這幾種類型。 簡介 ??區(qū)塊鏈最重要的應(yīng)用就是將實(shí)物價(jià)值或虛擬資產(chǎn)映射成鏈上Token,通過資產(chǎn)上鏈,實(shí)現(xiàn)跨地域、低成本的進(jìn)行資產(chǎn)交易與轉(zhuǎn)移,本質(zhì)上是權(quán)益再分配,核心是提高激勵(lì)性和效益。??很多人把Token譯為代幣,我更...
閱讀 2421·2023-04-25 18:49
閱讀 2029·2019-08-30 14:02
閱讀 2840·2019-08-29 17:24
閱讀 3499·2019-08-28 18:10
閱讀 3130·2019-08-28 18:03
閱讀 710·2019-08-26 12:01
閱讀 3545·2019-08-26 11:31
閱讀 1761·2019-08-26 10:29