摘要:的指向問題是老生常談的難點(diǎn)了。網(wǎng)上也有很多關(guān)于的文章了,本文就簡單說說,再聊點(diǎn)不一樣的。所以箭頭函數(shù)雖然好用,但是不要濫用哦箭頭函數(shù)還常用于數(shù)組的等循環(huán)方法中,比如
JS 的 this 指向問題是老生常談的難點(diǎn)了。我當(dāng)初從 Java 轉(zhuǎn)過來時(shí)極其不適應(yīng),花了好長時(shí)間才擺脫這個(gè)陰影。網(wǎng)上也有很多關(guān)于 this 的文章了,本文就簡單說說,再聊點(diǎn)不一樣的。
console.log(this) // window var o = { global: this // window }在函數(shù)內(nèi)使用 this 時(shí),具體指向是由函數(shù)的調(diào)用方式?jīng)Q定,而不是根據(jù)函數(shù)定義方式?jīng)Q定
function hello() { console.log(this) } hello() // window 作為普通函數(shù)運(yùn)行
所以上面一條,普通函數(shù)可以看做是全局對象的方法,所以 this 指向全局對象
var name = "global" var obj = { name: "local", getName: function () { console.log(this.name) }, outer: function () { function inner() { console.log(this.name) } inner() // 這是第 12 行代碼 } } obj.getName() // local 作為 obj 的方法調(diào)用,此時(shí) this 指向 obj obj.outer() // 打印什么?控制臺(tái)試試吧
這里提到了一個(gè)大家容易忽視的點(diǎn): 嵌套函數(shù)
還記得上面標(biāo)題說的嗎? this 的指向是由函數(shù)的調(diào)用方式來決定的
由于大多數(shù)嵌套函數(shù)是直接被調(diào)用的, 比如:第 12 行代碼,調(diào)用 inner()
這時(shí) inner 是被當(dāng)做普通函數(shù)調(diào)用的,也可以看做是 window.inner() ,所以此時(shí) inner 內(nèi)部的 this 指向 window,打印 global
常見的解決方案如下:
var obj = { name: "local", outer: function () { var that = this function inner() { console.log(that.name) } inner() } } // 聲明變量 that ,在 inner 內(nèi)部用 that 代替 this obj.outer() // local
還有個(gè)問題
var name = "global" var obj = { name: "local", getName: function () { console.log(this.name) } } obj.getName() // local var getName = obj.getName getName() // ?
直接調(diào)用 getName() 會(huì)打印 global
還是前面說的,雖然 obj.getName() 在聲明的時(shí)候是作為 obj 的方法
但是把它賦值給 getName, 再調(diào)用 getName() 和 obj.getName() 的調(diào)用方式已經(jīng)不同了
這個(gè)沒啥還說的,強(qiáng)制改變 this 的指向,bind 的優(yōu)先級最高。
var name = "global" var obj = { name: "local", getName: function () { console.log(this.name) } } var obj2 = { name: "xiaoming" } var obj3 = { name: "laowang" } obj.getName() // local obj.getName.call(obj2) // xiaoming var getName = obj.getName.bind(obj3) // 將 getName 內(nèi)部的 this 綁定到 obj3 getName() // laowang 不再是 window getName.call(obj2) // laowang // bind 不會(huì)受到 apply 和 call 影響
var name = "global" var obj = { name: "local", getName: function () { console.log(this.name) } } var obj3 = { name: "laowang" } setTimeout(obj.getName, 1000) // global setTimeout(obj.getName.bind(obj3), 2000) // laowang
bind 強(qiáng)制綁定優(yōu)先級最高,不受定時(shí)器影響
正確調(diào)用方式如下:
外面包一層匿名函數(shù)
setTimeout(function () { obj.getName() }, 1000) // local
ES6 推出了箭頭函數(shù),詳細(xì)教程可以參考阮一峰老師的教程
箭頭函數(shù)沒有自己的 this 和 arguments, 因此在箭頭函數(shù)內(nèi)部使用 this 和 argments, 其實(shí)使用的是外層的 this 和 arguments
var name = "global" var obj = { name: "local", getName: () => console.log(this.name), outer: function () { var inner = () => console.log(this.name) inner() } } obj.getName() // global 由于箭頭函數(shù)沒有自己的 this,所以 getName 內(nèi)部的 this 其實(shí)是函數(shù)外部的 this,指向全局 obj.outer() // local
作為函數(shù)的方法,最好不要用箭頭函數(shù),因?yàn)榧^函數(shù)內(nèi)部的 this 不再指向該對象。
所以箭頭函數(shù)雖然好用,但是不要濫用哦
箭頭函數(shù)還常用于數(shù)組的 forEach/map/some/every/filter/reduce 等循環(huán)方法中,比如
var arr = [1, 2, 3].map(item => item * 2)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/86575.html
摘要:所以構(gòu)造函數(shù)里的指的就是將要被出來的新對象。希望看完這篇文章之后,再有人問指向的問題,你可以嘴角微微上揚(yáng),冷笑一聲不要再問我的指向問題了。 this的指向已經(jīng)是一個(gè)老生常談的問題,每逢面試都要去復(fù)習(xí)復(fù)習(xí),近來鞏固js的基礎(chǔ),決心徹底掌握這個(gè)知識(shí)點(diǎn),一勞永逸。說明一下,為了不影響大家的思考過程,下面的代碼都不會(huì)去注釋答案,想知道答案,只需要去控制臺(tái)執(zhí)行一下。 四類場景逐一擊破 首先,分析...
摘要:在構(gòu)造函數(shù)的內(nèi)部,的指向是新創(chuàng)建的對象。如果構(gòu)造函數(shù)沒有顯式的表達(dá)式,則會(huì)隱式的返回新創(chuàng)建的對象對象。原型模式在構(gòu)造函數(shù)模式中提到每次之后創(chuàng)建的新的對象是互相獨(dú)立的,是獨(dú)享的。 1.構(gòu)造函數(shù)模式 JavaScript中的構(gòu)造函數(shù)是通過new調(diào)用的,也就是說,通過new關(guān)鍵字調(diào)用的函數(shù)都被認(rèn)為是構(gòu)造函數(shù)。 在構(gòu)造函數(shù)的內(nèi)部,this的指向是新創(chuàng)建的對象Object。 如果構(gòu)造函數(shù)沒有顯式...
摘要:有了原型鏈,就有了繼承,繼承就是一個(gè)對象像繼承遺產(chǎn)一樣繼承從它的構(gòu)造函數(shù)中獲得一些屬性的訪問權(quán)。這里其實(shí)就是一個(gè)原型鏈與繼承的典型例子,開發(fā)中可能構(gòu)造函數(shù)復(fù)雜一點(diǎn),屬性定義的多一些,但是原理都是一樣的。 作用域、原型鏈、繼承與閉包詳解 注意:本章講的是在es6之前的原型鏈與繼承。es6引入了類的概念,只是在寫法上有所不同,原理是一樣的。 幾個(gè)面試常問的幾個(gè)問題,你是否知道 insta...
摘要:有了原型鏈,就有了繼承,繼承就是一個(gè)對象像繼承遺產(chǎn)一樣繼承從它的構(gòu)造函數(shù)中獲得一些屬性的訪問權(quán)。這里其實(shí)就是一個(gè)原型鏈與繼承的典型例子,開發(fā)中可能構(gòu)造函數(shù)復(fù)雜一點(diǎn),屬性定義的多一些,但是原理都是一樣的。 作用域、原型鏈、繼承與閉包詳解 注意:本章講的是在es6之前的原型鏈與繼承。es6引入了類的概念,只是在寫法上有所不同,原理是一樣的。 幾個(gè)面試常問的幾個(gè)問題,你是否知道 insta...
閱讀 1016·2019-08-30 14:24
閱讀 1064·2019-08-30 14:13
閱讀 1864·2019-08-29 17:21
閱讀 2823·2019-08-29 13:44
閱讀 1725·2019-08-29 11:04
閱讀 535·2019-08-26 10:44
閱讀 2647·2019-08-23 14:04
閱讀 960·2019-08-23 12:08