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