摘要:沒有箭頭函數沒有自己的對象,這不一定是件壞事,因為箭頭函數可以訪問外圍函數的對象那如果我們就是要訪問箭頭函數的參數呢你可以通過命名參數或者參數的形式訪問參數不能通過關鍵字調用函數有兩個內部方法和。
1、基本語法回顧
我們先來回顧下箭頭函數的基本語法。
ES6 增加了箭頭函數:
var f = v => v; // 等同于 var f = function (v) { return v; };
如果箭頭函數不需要參數或需要多個參數,就使用一個圓括號代表參數部分。
var f = () => 5; // 等同于 var f = function () { return 5 }; var sum = (num1, num2) => num1 + num2; // 等同于 var sum = function(num1, num2) { return num1 + num2; };
由于大括號被解釋為代碼塊,所以如果箭頭函數直接返回一個對象,必須在對象外面加上括號,否則會報錯。
// 報錯 let getTempItem = id => { id: id, name: "Temp" }; // 不報錯 let getTempItem = id => ({ id: id, name: "Temp" });
下面是一種特殊情況,雖然可以運行,但會得到錯誤的結果。
let foo = () => { a: 1 }; foo() // undefined
上面代碼中,原始意圖是返回一個對象{ a: 1 },但是由于引擎認為大括號是代碼塊,所以執行了一行語句a: 1。這時,a可以被解釋為語句的標簽,因此實際執行的語句是1;,然后函數就結束了,沒有返回值。
關于作用域
箭頭函數內定義的變量及其作用域 // 常規寫法 var greeting = () => {let now = new Date(); return ("Good" + ((now.getHours() > 17) ? " evening." : " day."));} greeting(); //"Good day." console.log(now); // ReferenceError: now is not defined 標準的let作用域 // 參數括號內定義的變量是局部變量(默認參數) var greeting = (now=new Date()) => "Good" + (now.getHours() > 17 ? " evening." : " day."); greeting(); //"Good day." console.log(now); // ReferenceError: now is not defined // 對比:函數體內{}不使用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 (中國標準時間) // 對比:函數體內{} 用var定義的變量是局部變量 var greeting = () => {var now = new Date(); return ("Good" + ((now.getHours() > 17) ? " evening." : " day."));} greeting(); //"Good day." console.log(now); // ReferenceError: now is not defined2、關于this 2.1、默認綁定外層this
箭頭函數沒有 this,所以需要通過查找作用域鏈來確定 this 的值。
這就意味著如果箭頭函數被非箭頭函數包含,this 綁定的就是最近一層非箭頭函數的 this。
function foo() { setTimeout(() => { console.log("id:", this.id); }, 100); } var id = 21; foo.call({ id: 42 }); // id: 42
上面代碼中,setTimeout的參數是一個箭頭函數,這個箭頭函數的定義生效是在foo函數生成時,而它的真正執行要等到 100 毫秒后。如果是普通函數,執行時this應該指向全局對象window,這時應該輸出21。但是,箭頭函數導致this總是指向函數定義生效時所在的對象(本例是{id: 42}),所以輸出的是42。
箭頭函數可以讓setTimeout里面的this,綁定定義時所在的作用域,而不是指向運行時所在的作用域。
所以,箭頭函數轉成 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"]
上面代碼中,箭頭函數沒有自己的this,所以bind方法無效,內部的this指向外部的this。
3、沒有 arguments箭頭函數沒有自己的 arguments 對象,這不一定是件壞事,因為箭頭函數可以訪問外圍函數的 arguments 對象:
function constant() { return () => arguments[0] } var result = constant(1); console.log(result()); // 1
那如果我們就是要訪問箭頭函數的參數呢?
你可以通過命名參數或者 rest 參數的形式訪問參數:
let nums = (...nums) => nums;4、 不能通過 new 關鍵字調用
JavaScript 函數有兩個內部方法:[[Call]] 和 [[Construct]]。
當通過new調用函數時,執行[Construct]]方法,創建一個實例對象,然后再執行函數體,將 this 綁定到實例上。
當直接調用的時候,執行[[Call]]方法,直接執行函數體。
箭頭函數并沒有[[Construct]]方法,不能被用作構造函數,如果通過 new 的方式調用,會報錯。
var Foo = () => {}; var foo = new Foo(); // TypeError: Foo is not a constructor5、沒有原型
由于不能使用new調用箭頭函數,所以也沒有構建原型的需求,于是箭頭函數也不存在prototype這個屬性。
var Foo = () => {}; console.log(Foo.prototype); // undefined5、不適用場合
第一個場合是定義函數的方法,且該方法內部包括this。
const cat = { lives: 9, jumps: () => { this.lives--; } }
上面代碼中,cat.jumps()方法是一個箭頭函數,這是錯誤的。調用cat.jumps()時,如果是普通函數,該方法內部的this指向cat;如果寫成上面那樣的箭頭函數,使得this指向全局對象,因此不會得到預期結果。
第二個場合是需要動態this的時候,也不應使用箭頭函數。
var button = document.getElementById("press"); button.addEventListener("click", () => { this.classList.toggle("on"); });
上面代碼運行時,點擊按鈕會報錯,因為button的監聽函數是一個箭頭函數,導致里面的this就是全局對象。如果改成普通函數,this就會動態指向被點擊的按鈕對象。
6、使用場景下面這個是我們開發經常遇到的。我們一般會通過this賦值給一個變量,然后再通過變量訪問。
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
這里我們就可以通過箭頭函數來解決
... success: (result)=> { console.log(this.birth);//10 }, ...
箭頭函數在react中的運用場景
class Foo extends Component { constructor(props) { super(props); } handleClick() { console.log("Click happened", this); this.setState({a: 1}); } render() { return ; } }
在react中我們這樣直接調用方法是有問題的,在handleClick函數中的this是有問題,我們平時需要這么做
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)給函數綁定this。但是這樣寫起來有些麻煩,有沒有簡單的方法呢?這時候我們的箭頭函數就出場了
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 ; } }
箭頭函數中 this 的值是繼承自 外圍作用域,很好的解決了這個問題。
除此之外我們還可以用箭頭函數傳參(這個不是必須的),而且會有性能問題。更多信息請查看
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學習(一)之var、let、const
ES6學習(二)之解構賦值及其原理
ES6學習(三)之Set的模擬實現
ES6學習(四)之Promise的模擬實現
如果有錯誤或者不嚴謹的地方,請務必給予指正,十分感謝。如果喜歡或者有所啟發,歡迎star對作者也是一種鼓勵。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/103207.html
摘要:如下在第一個例子中,被點擊元素是通過,這個形式參數來代替的。它的作用和形式參數類似,其本質上是一個對象的引用,它的特殊性在于不需要手動傳值,所以使用起來會更加簡單和方便。 無論在 javascript 的日常使用中還是前端面試過程中,this 的出鏡率都極高。這無疑說明了,this 的重要性。但是 this 非常靈活,導致很多人覺得 this 的行為難以理解。本文從為什么要有 this...
摘要:應屆生零基礎可以學習軟件測試嗎俗話說,人怕入錯行。霸哥這里分別從入行難度入行方式行業前景薪資待遇四個方面來分析一下。目前市場上的測試人員,一部分是企業自己培養的,另一部分是來自培訓機構。軟件測試的行業門檻低,市場需求量大。 ...
摘要:七月流火,燃情盛夏值此季節,阿里云又推出了年中鉅惠,精選百款產品,助力創業新勢力。阿里云云盾安全防護體系,不僅合規,更加安全。七月流火,燃情盛夏!值此季節,阿里云又推出了年中鉅惠,精選百款產品,助力創業新勢力。從7月26日開始,每天上午10點、下午4點將會放出爆款產品,進行限量秒殺,大家不要錯過。注冊登陸還可抽取 iPhone 12 Pro、Cherry 機械鍵盤、企業電子書大禮包等好禮。 ...
摘要:在以太坊出現后,進入了第二階段。以太坊可以被視作區塊鏈世界類似于和的底層操作系統。通證經濟的設計方向模式的組織,是天然的生態型組織。區塊鏈時代的生態組織,大致可以分成這幾種類型。 簡介 ??區塊鏈最重要的應用就是將實物價值或虛擬資產映射成鏈上Token,通過資產上鏈,實現跨地域、低成本的進行資產交易與轉移,本質上是權益再分配,核心是提高激勵性和效益。??很多人把Token譯為代幣,我更...
閱讀 2136·2023-04-25 18:49
閱讀 1840·2019-08-30 14:02
閱讀 2642·2019-08-29 17:24
閱讀 3323·2019-08-28 18:10
閱讀 2925·2019-08-28 18:03
閱讀 488·2019-08-26 12:01
閱讀 3308·2019-08-26 11:31
閱讀 1409·2019-08-26 10:29