javascript
深入理解JavaScript this
this是什么?做什么?指向是什么?
函數中this調用:this-----》window
方法中this調用:this-----》當前對象(嗲用方法的對象)
構造函數中this調用:this------》該構造函數的實例對象
借用方法調用:改變this的指向
分析this的問題,需要明白兩點:(只看函數是怎么被調用的,不管函數是怎么來的)
1.分析this是屬于哪個函數
2.分析該函數是以什么模式被調用的
嚴格模式中,函數調用模式內部的this為:undefined?
?
要說?JavaScript?這門語言最容易讓人困惑的知識點,this?關鍵詞肯定算一個。JavaScript?語言面世多年,一直在進化完善,現在在服務器上還可以通過 node.js 來跑 JavaScript。顯然,這門語言還會活很久。
所以說,我一直相信,如果你是一個 JavaScript 開發者或者說?web?開發者,學好 JavaScript 的運作原理以及語言特點肯定對你以后大有好處。
開始之前
在開始正文之前,我強烈推薦你先掌握好下面的知識:
- 變量作用域和作用域提升
- JavaScript 的函數
- 閉包
如果沒有對這些基礎知識掌握踏實,直接討論 JavaScript 的?this?關鍵詞只會讓你感到更加地困惑和挫敗。
我為什么要學?this?
如果上面的簡單介紹沒有說服你來深入探索?this?關鍵詞,那我用這節來講講為什么要學。
考慮這樣一個重要問題,假設開發者,比如 Douglas Crockford (譯者注:JavaScript 領域必知牛人),不再使用?new?和?this,轉而使用完完全全的函數式寫法來做代碼復用,會怎樣?
事實上,基于 JavaScript 內置的現成的原型繼承功能,我們已經使用并且將繼續廣泛使用?new?和?this?關鍵詞來實現代碼復用。
理由一,如果只能使用自己寫過的代碼,你是沒法工作的。現有的代碼以及你讀到這句話時別人正在寫的代碼都很有可能包含?this?關鍵詞。那么學習怎么用好它是不是很有用呢?
因此,即使你不打算在你的代碼庫中使用它,深入掌握?this?的原理也能讓你在接手別人的代碼理解其邏輯時事半功倍。
理由二,拓展你的編碼視野和技能。使用不同的設計模式會加深你對代碼的理解,怎么去看、怎么去讀、怎么去寫、怎么去理解。我們寫代碼不僅是給機器去解析,還是寫給我們自己看的。這不僅適用于 JavaScript,對其他編程語言亦是如此。
隨著對編程理念的逐步深入理解,它會逐漸塑造你的編碼風格,不管你用的是什么語言什么框架。
就像畢加索會為了獲得靈感而涉足那些他并不是很贊同很感興趣的領域,學習 this 會拓展你的知識,加深對代碼的理解。
什么是?this??
在我開始講解前,如果你學過一門基于類的面向對象編程語言(比如 C#,Java,C++),那請將你對?this?這個關鍵詞應該是做什么用的先入為主的概念扔到垃圾桶里。JavaScript 的?this?關鍵詞是很不一樣,因為 JavaScript 本來就不是一門基于類的面向對象編程語言。
雖說?ES6?里面 JavaScript 提供了類這個特性給我們用,但它只是一個語法糖,一個基于原型繼承的語法糖。
this?就是一個指針,指向我們調用函數的對象。
我難以強調上一句話有多重要。請記住,在 Class 添加到 ES6 之前,JavaScript 中沒有 Class 這種東西。Class 只不過是一個將對象串在一起表現得像類繼承一樣的語法糖,以一種我們已經習慣的寫法。所有的魔法背后都是用原型鏈編織起來的。
如果上面的話不好理解,那你可以這樣想,this 的上下文跟英語句子的表達很相似。比如下面的例子
Bob.callPerson(John);
就可以用英語寫成 “Bob called a person named John”。由于?callPerson()?是 Bob 發起的,那?this?就指向 Bob。我們將在下面的章節深入更多的細節。到了這篇文章結束時,你會對?this?關鍵詞有更好的理解(和信心)。
執行上下文
執行上下文?是語言規范中的一個概念,用通俗的話講,大致等同于函數的執行“環境”。具體的有:變量作用域(和?作用域鏈條,閉包里面來自外部作用域的變量),函數參數,以及?this?對象的值。
引自: Stackoverflow.com
記住,現在起,我們專注于查明?this?關鍵詞到底指向哪。因此,我們現在要思考的就一個問題:
- 是什么調用函數?是哪個對象調用了函數?
為了理解這個關鍵概念,我們來測一下下面的代碼。
var person = {name: "Jay",greet: function() { console.log("hello, " + this.name); } }; person.greet();誰調用了?greet 函數?是?person?這個對象對吧?在?greet()?調用的左邊是一個 person 對象,那么 this 關鍵詞就指向?person,this.name?就等于?"Jay"。現在,還是用上面的例子,我加點料:
var greet = person.greet; // 將函數引用存起來; greet(); // 調用函數你覺得在這種情況下控制臺會輸出什么?“Jay”?undefined?還是別的?
正確答案是?undefined。如果你對這個結果感到驚訝,不必慚愧。你即將學習的東西將幫助你在 JavaScript 旅程中打開關鍵的大門。
this?的值并不是由函數定義放在哪個對象里面決定,而是函數執行時由誰來喚起決定。
對于這個意外的結果我們暫且壓下,繼續看下去。(感覺前后銜接得不夠流暢)
帶著這個困惑,我們接著測試下?this?三種不同的定義方式。
找出?this?的指向
上一節我們已經對?this?做了測試。但是這塊知識實在重要,我們需要再好好琢磨一下。在此之前,我想用下面的代碼給你出個題:
var name = "Jay Global"; var person = {name: 'Jay Person', details: { name: 'Jay Details', print: function() { return this.name; } }, print: function() { return this.name; } }; console.log(person.details.print()); // ? console.log(person.print()); // ? var name1 = person.print; var name2 = person.details; console.log(name1()); // ? console.log(name2.print()) // ?console.log()?將會輸出什么,把你的答案寫下來。如果你還想不清楚,復習下上一節。
準備好了嗎?放松心情,我們來看下面的答案。
答案和解析
person.details.print()
首先,誰調用了 print 函數?在 JavaScript 中我們都是從左讀到右。于是 this 指向?details?而不是?person。這是一個很重要的區別,如果你對這個感到陌生,那趕緊把它記下。
print?作為?details?對象的一個 key,指向一個返回?this.name?的函數。既然我們已經找出 this 指向 details ,那函數的輸出就應該是?'Jay Details'。
person.print()
再來一次,找出?this?的指向。print()?是被?person?對象調用的,沒錯吧?
在這種情況,person?里的?print?函數返回?this.name。this?現在指向?person?了,那?'Jay Person'就是返回值。
console.log(name1)
這一題就有點狡猾了。在上一行有這樣一句代碼:
var name1 = person.print;如果你是通過這句來思考的,我不會怪你。很遺憾,這樣去想是錯的。要記住,this?關鍵詞是在函數調用時才做綁定的。name1()?前面是什么?什么都沒有。因此?this?關鍵詞就將指向全局的?window對象去。
因此,答案是?'Jay Global'。
name2.print()
看一下?name2?指向哪個對象,是?details?對象沒錯吧?
所以下面這句會打印出什么呢?如果到目前為止的所有小點你都理解了,那這里稍微思考下你就自然有答案了。
console.log(name2.print()) // ??答案是?'Jay Details',因為?print?是?name2?調起的,而?name2?指向?details。
詞法作用域
你可能會問:“什么是詞法作用域?”
逗我呢,我們不是在探討?this?關鍵詞嗎,這個又是哪里冒出來的?好吧,當我們用起 ES6 的箭頭函數,這個就要考慮了。如果你已經寫了不止一年的 JavaScript,那你很可能已經碰到箭頭函數。隨著 ES6 逐漸成為現實標準,箭頭函數也變得越來越常用。
JavaScript 的詞法作用域 并不好懂。如果你 理解閉包,那要理解這個概念就容易多了。來看下下面的小段代碼。
// outerFn 的詞法作用域 var outerFn = function() {var n = 5; console.log(innerItem); // innerFn 的詞法作用域 var innerFn = function() { var innerItem = "inner"; // 錯了。只能坐著電梯向上,不能向下。 console.log(n); }; return innerFn; }; outerFn()();想象一下一棟樓里面有一架只能向上走的詭異電梯。
建筑的頂層就是全局 windows 對象。如果你現在在一樓,你就可以看到并訪問那些放在樓上的東西,比如放在二樓的?outerFn?和放在三樓的?window?對象。
這就是為什么我們執行代碼?outerFn()(),它在控制臺打出了 5 而不是?undefined。
然而,當我們試著在?outerFn?詞法作用域下打出日志?innerItem,我們遇到了下面的報錯。請記住,JavaScript 的詞法作用域就好像建筑里面那個只能向上走的詭異電梯。由于 outerFn 的詞法作用域在 innerFn 上面,所以它不能向下走到 innerFn 的詞法作用域里面并拿到里面的值。這就是觸發下面報錯的原因:
test.html:304 Uncaught ReferenceError: innerItem is not defined at outerFn (test.html:304) at test.html:313this?和箭頭函數
在 ES6 里面,不管你喜歡與否,箭頭函數被引入了進來。對于那些還沒用慣箭頭函數或者新學 JavaScript 的人來說,當箭頭函數和?this?關鍵詞混合使用時會發生什么,這個點可能會給你帶來小小的困惑和淡淡的憂傷。那這個小節就是為你們準備的!
當涉及到?this?關鍵詞,箭頭函數?和?普通函數?主要的不同是什么?
答案:
箭頭函數按詞法作用域來綁定它的上下文,所以?this?實際上會引用到原來的上下文。
引自:hackernoon.com
我實在沒法給出比這個更好的總結。
箭頭函數保持它當前執行上下文的詞法作用域不變,而普通函數則不會。換句話說,箭頭函數從包含它的詞法作用域中繼承到了?this?的值。
我們不妨來測試一些代碼片段,確保你真的理解了。想清楚這塊知識點未來會讓你少點頭痛,因為你會發現?this?關鍵詞和箭頭函數太經常一起用了。
示例
仔細閱讀下面的代碼片段。
var object = {data: [1,2,3], dataDouble: [1,2,3], double: function() { console.log("this inside of outerFn double()"); console.log(this); return this.data.map(function(item) { console.log(this); // 這里的 this 是什么?? return item * 2; }); }, doubleArrow: function() { console.log("this inside of outerFn doubleArrow()"); console.log(this); return this.dataDouble.map(item => { console.log(this); // 這里的 this 是什么?? return item * 2; }); } }; object.double(); object.doubleArrow();如果我們看執行上下文,那這兩個函數都是被?object?調用的。所以,就此斷定這兩個函數里面的 this 都指向?object?不為過吧?是的,但我建議你拷貝這段代碼然后自己測一下。
這里有個大問題:
arrow()?和?doubleArrow()?里面的?map?函數里面的?this?又指向哪里呢?
上一張圖已經給了一個大大的提示。如果你還不確定,那請花5分鐘將我們上一節討論的內容再好好想想。然后,根據你的理解,在實際執行代碼前把你認為的 this 應該指向哪里寫下來。在下一節我們將會回答這個問題。
回顧執行上下文
這個標題已經把答案泄露出來了。在你看不到的地方,map 函數對調用它的數組進行遍歷,將數組的每一項傳到回調函數里面并把執行結果返回。如果你對 JavaScript 的 map 函數不太了解或有所好奇,可以讀讀這個了解更多。
總之,由于?map()?是被?this.data?調起的,于是 this 將指向那個存儲在?data?這個 key 里面的數組,即?[1,2,3]。同樣的邏輯,this.dataDouble?應該指向另一個數組,值為?[1,2,3]。
現在,如果函數是?object?調用的,我們已經確定 this 指向?object?對吧?好,那來看看下面的代碼片段。
double: function() {return this.data.map(function(item) { console.log(this); // 這里的 this 是什么?? return item * 2; }); }這里有個很有迷惑性的問題:傳給?map()?的那個匿名函數是誰調用的?答案是:這里沒有一個對象是。為了看得更明白,這里給出一個?map?函數的基本實現。
// Array.map polyfill if (Array.prototype.map === undefined) {Array.prototype.map = function(fn) { var rv = []; for(var i=0, l=this.length; i<l; i++) rv.push(fn(this[i])); return rv; }; }fn(this[i]));?前面有什么對象嗎?沒。因此,this?關鍵詞指向全局的 windows 對象。那,為什么?this.dataDouble.map?使用了箭頭函數會使得 this 指向?object?呢?
我想再說一遍這句話,因為它實在很重要:
箭頭函數按詞法作用域將它的上下文綁定到?原來的上下文
現在,你可能會問:原來的上下文是什么?問得好!
誰是?doubleArrow()?的初始調用者?就是?object?對吧?那它就是原來的上下文
this 和?use strict
為了讓 JavaScript 更加健壯及盡量減少人為出錯,ES5 引進了嚴格模式。一個典型的例子就是 this 在嚴格模式下的表現。你如果想按照嚴格模式來寫代碼,你只需要在你正在寫的代碼的作用域最頂端加上這么一行?"use strict;"。
記住,傳統的 JavaScript 只有函數作用域,沒有塊作用域。舉個例子:
function strict() {// 函數級嚴格模式寫法代碼片段來自 Mozilla Developer Network。
不過呢,ES6 里面通過 let 關鍵詞提供了塊作用域的特性。
現在,來看一段簡單代碼,看下 this 在嚴格模式和非嚴格模式下會怎么表現。在繼續之前,請將下面的代碼運行一下。
(function() {正如你看到的,this?在嚴格模式下指向?undefined。相對的,非嚴格模式下?this?指向全局變量?window。大部分情況下,開發者使用 this ,并不希望它指向全局 window 對象。嚴格模式幫我們在使用?this?關鍵詞時,盡量少做搬起石頭砸自己腳的蠢事。
舉個例子,如果全局的 window 對象剛好有一個 key 的名字和你希望訪問到的對象的 key 相同,會怎樣?上代碼吧:
(function() {// "use strict";var item = {document: "My document", getDoc: function() { return this.document; } } var getDoc = item.getDoc; console.log(getDoc()); })();這段代碼有兩個問題。
在這個簡單示例中,因為代碼較短也就不會形成大問題。
如果你是在生產環境像上面那樣寫,當用到?getDoc?返回的數據時,你將收獲一堆難以定位的報錯。如果你代碼庫比較大,對象間互動比較多,那問題就更嚴重了。
值得慶幸的是,如果我們是在嚴格模式下跑這段代碼,由于 this 是?undefined,于是立刻就有一個報錯拋給我們:
test.html:312 Uncaught TypeError: Cannot read property 'document' of undefined?at getDoc (test.html:312)?at test.html:316?at test.html:317
明確設置執行上下文
先前假定大家都對執行上下文不熟,于是我們聊了很多關于執行上下文和 this 的知識。
讓人歡喜讓人憂的是,在 JavaScript 中通過使用內置的特性開發者就可以直接操作執行上下文了。這些特性包括:
- bind():不需要執行函數就可以將?this?的值準確設置到你選擇的一個對象上。還可以通過逗號隔開傳遞多個參數,如?func.bind(this, param1, param2, ...)?。
- apply():將?this?的值準確設置到你選擇的一個對象上。第二個參數是一個數組,數組的每一項是你希望傳遞給函數的參數。最后,執行函數。
- call():將?this?的值準確設置到你選擇的一個對象上,然后想?bind?一樣通過逗號分隔傳遞多個參數給函數。如:print.call(this, param1, param2, ...)。最后,執行函數。
上面提到的所有內置函數都有一個共同點,就是它們都是用來將?this?關鍵詞指向到其他地方。這些特性可以讓我們玩一些騷操作。只是呢,這個話題太廣了都夠寫好幾篇文章了,所以簡潔起見,這篇文章我不打算展開它的實際應用。
重點:上面那三個函數,只有?bind()?在設置好?this?關鍵詞后不立刻執行函數。
什么時候用 bind、call 和 apply
你可能在想:現在已經很亂了,學習所有這些的目的是什么?
首先,你會看到 bind、call 和 apply 這幾個函數到處都會用到,特別是在一些大型的庫和框架。如果你沒理解它做了些什么,那可憐的你就只用上了 JavaScript 提供的強大能力的一小部分而已。
如果你不想了解一些可能的用法而想立刻讀下去,當然了,你可以直接跳過這節,沒關系。
下面列出來的應用場景都是一些具有深度和廣度的話題(一篇文章基本上是講不完的),所以我放了一些鏈接供你深度閱讀用。未來我可能會在這篇終極指南里面繼續添加新的小節,這樣大家就可以一次看過癮。
如果我漏掉了其他實踐案例,請留言告知。我會經常來優化這篇指南,這樣你作為讀者就可以讀到最豐富的內容。
閱讀高質量的開源代碼可以升級你的知識和技能。
講真,你會在一些開源代碼上看到 this 關鍵詞、call、apply 和 bind 的實際應用。我會將這塊結合著其他能幫你成為更好的程序員的方法一起講。
在我看來,開始閱讀最好的開源代碼是 underscore。它并不像其他開源項目,如 d3,那樣鐵板一塊,而是內部代碼相互比較獨立,因而它是教學用的最佳選擇。另外,它代碼簡潔,文檔詳細,編碼風格也是相當容易學習。
JavaScript 的?this?和 bind
前面提到了,bind?允許你明確設定 this 的指向而不用實際去執行函數。這里是一個簡單示例:
var bobObj = {name: "Bob" }; function print() { return this.name; } // 將 this 明確指向 "bobObj" var printNameBob = print.bind(bobObj); console.log(printNameBob()); // this 會指向 bob,于是輸出結果是 "Bob"在上面的示例中,如果你把 bind 那行去掉,那 this 將會指向全局?window?對象。
這好像很蠢,但在你想將?this?綁定到具體對象前你就必須用?bind?來綁定。在某些場景下,我們可能想從另一個對象中借用一些方法。舉個例子,
var obj1 = {data: [1,2,3], printFirstData: function() { if (this.data.length) return this.data[0]; } }; var obj2 = { data: [4,5,6], printSecondData: function() { if (this.data.length > 1) return this.data[1]; } }; // 在 obj1 中借用 obj2 的方法 var getSecondData = obj2.printSecondData.bind(obj1); console.log(getSecondData()); // 輸出 2在這個代碼片段里,obj2?有一個名為?printSecondData?的方法,而我們想將這個方法借給?obj1。在下一行
var getSecondData = obj2.printSecondData.bind(obj1);通過使用 bind ,我們讓?obj1?可以訪問?obj2?的?printSecondData?方法。
練習
在下面的代碼中
var object = {data: [1,2,3], double: function() { this.data.forEach(function() { // Get this to point to object. console.log(this); }); } }; object.double();怎么讓 this 關鍵詞指向?object。提示:你并不需要重寫?this.data.forEach。
答案
在上一節中,我們了解了執行上下文。如果你對匿名函數調用那部分看得夠細心,你就知道它并不會作為某個對象的方法被調用。因此,this?關鍵詞指向了全局?window?對象。
于是我們需要將 object 作為上下文綁定到匿名函數上,使得里面的 this 指向?object。現在,double?函數跑起來時,是?object?調用了它,那么?double?里面的?this?指向?object。
var object = {data: [1,2,3], double: function() { return this.data.forEach(function() { // Get this to point to object. console.log(this); }.bind(this)); } }; object.double();那,如果我們像下面這樣做呢?
var double = object.double; double(); // ??double()?的調用上下文是什么?是全局上下文。于是,我們就會看到下面的報錯。
Uncaught TypeError: Cannot read property 'forEach' of undefined?at double (test.html:282)?at test.html:289
所以,當我們用到?this?關鍵詞時,就要小心在意我們調用函數的方式。我們可以在提供 API 給用戶時固定 this 關鍵詞,以此減少這種類型的錯誤。但請記住,這么做的代價是犧牲了靈活性,所以做決定前要考慮清楚。
var double = object.double.bind(object); double(); // 不再報錯JavaScript?this?和 call
call 方法和 bind 很相似,但就如它名字所暗示的,call?會立刻呼起(執行)函數,這是兩個函數的最大區別。
var item = {name: "I am" }; function print() { return this.name; } // 立刻執行 var printNameBob = console.log(print.call(item));call、apply、bind?大部分使用場景是重疊的。作為一個程序員最重要的還是先了解清楚這三個方法之間的差異,從而能根據它們的設計和目的的不同來選用。只要你了解清楚了,你就可以用一種更有創意的方式來使用它們,寫出更獨到精彩的代碼。
在參數數量固定的場景,call?或?bind?是不錯的選擇。比如說,一個叫?doLogin?的函數經常是接受兩個參數:username?和?password。在這個場景下,如果你需要將 this 綁定到一個特定的對象上,call?或?bind?會挺好用的。
如何使用 call
以前一個最常用的場景是把一個類數組對象,比如?arguments?對象,轉化成數組。舉個例子:
function convertArgs() {var convertedArgs = Array.prototype.slice.call(arguments); console.log(arguments); console.log(Array.isArray(arguments)); // false console.log(convertedArgs); console.log(Array.isArray(convertedArgs)); // true } convertArgs(1,2,3,4);在上面的例子中,我們使用 call 將?argument?對象轉化成一個數組。在下一個例子中,我們將會調用一個?Array?對象的方法,并將 argument 對象設置為方法的 this,以此來將傳進來參數加在一起。
function add (a, b) { return a + b; } function sum() { return Array.prototype.reduce.call(arguments, add); } console.log(sum(1,2,3,4)); // 10我們在一個類數組對象上調用了 reduce 函數。要知道 arguments 不是一個數組,但我們給了它調用 reduce 方法的能力。如果你對 reduce 感興趣,可以在這里了解更多。
練習
現在是時候鞏固下你新學到的知識。
JavaScript this 和 apply
apply 就是接受數組版本的 call。于是當使用?apply?時,多聯想下數組。
將一個方法應用(apply)到一個數組上。
我用這句話來記住它,而且還挺管用。apply 為你的現有堆積的軍火庫又添加了一樣利器,增加了很多新的可能,你很快就能體會到這一點。
當你要處理參數數量動態變化的場景,用 apply 吧。將一系列數據轉化為數組并用上 apply 能讓你寫出更好用和更具彈性的代碼,會讓你的工作更輕松。
如何使用 apply
Math.min 和?max?都是可以接受多個參數并返回最小值和最大值的函數。除了直接傳 n 個參數,你也可以將這 n 個參數放到一個數組里然后借助?apply?將它傳到 min 函數里。
Math.min(1,2,3,4); // 返回 1 Math.min([1,2,3,4]); // 返回 NaN。只接受數字 Math.min.apply(null, [1,2,3,4]); // 返回 1看暈了嗎?如果真暈了,那我來解釋下。使用 apply 時我們要傳一個數組因為它需要數組作為第二個參數。而下面
Math.min.apply(null, [1,2,3,4]); // 返回 1做的事情基本等同于
Math.min(1,2,3,4); // 返回 1
這就是我想指出來的 apply 的神奇之處。它和?call?工作原理,不過我們只要傳給它一個數組而不是 n 個參數。很好玩對吧?橋豆麻袋,這是否意味著?Math.min.call(null, 1,2,3,4);?執行起來和?Math.min.apply(null, [1,2,3,4]);?一樣?
啊,你說對了!看來你已經開始掌握它了
讓我們來看下另一種用法。
function logArgs() {console.log.apply(console, arguments); } logArgs(1,3,'I am a string', {name: "jay", age: "1337"}, [4,5,6,7]);沒錯,你甚至可以傳一個類數組對象作為?apply?的第二個參數。很酷對吧?
練習
其他文章和資料
假如我上面的解釋沒能讓你釋疑,那下面這些額外的資料可以幫你更好地理解 bind 在 JavaScript 里面是怎么運作的。
- 理解 JavaScript 函數 bind 的原型方法
- Stackoverflow – 使用 JavaScript 的 bind 函數
- JavaScript 中 call(), apply() 和 bind() 如何使用
- 一看就懂 —— JavaScript 的 .call() .apply() 和 .bind()
我還強烈推薦你去學習 JavaScript 原型鏈,不單是因為里面用到大量的?this?關鍵詞,而且它還是 JavaScript 實現繼承的標準方式。
下面列出一些幫你了解?this?如何使用的書籍:
- 編寫高質量 JavaScript代碼的68個有效方法:雖然是本古董,但此書確實寫得挺好而且還提供了簡單易懂的示例,教你怎么用好 this、apply、call 和 bind 來寫出好代碼。書的作者是 TC39 的一個成員 Dave Hermann,所以你大可放心,他對 JavaScript 肯定理解深刻。
- 你不知道的?JS?—— this 和對象原型:Kyle Simpson 以一種清晰明了、對初學者很友好的方式,解釋了對象和原型是怎么相互影響運作起來的,寫得很棒!
總結
考慮到?this?關鍵詞已經用到了難以計量的代碼中,它是 JavaScript 中我們不得不聊的話題。
一個優秀的藝術家肯定精于工具的使用。作為一個 JavaScript 開發者,怎么用好它的特性是最最重要的。
如果你想看到一些從特定角度對?this?關鍵詞深入剖析的文章或者更多的代碼,請別忘了告訴我。這些可能的角度可以是(但不限于)下面這些:
- this?和?new?關鍵詞。
- JavaScript 的原型鏈。
- this?和 JavaScript 的類。
作者:老教授
鏈接:https://juejin.im/post/5aefe76e6fb9a07abc29d4a1
來源:掘金
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
轉載于:https://www.cnblogs.com/jcxfighting/p/10894028.html
總結
以上是生活随笔為你收集整理的深入理解JavaScript this的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL临时表
- 下一篇: vi在一般指令模式下几个实用的命令