JavaScript中的this比較靈活,根據在不同環境下,或是同一個函數在不同方式呼叫下,this都有可能是不同的。但是有一個總的原則,那就是this指的是,呼叫函數的那個物件。
系列目錄
深入淺出JavaScript之閉包(Closure)
深入淺出JavaScript之this
#深入淺出JavaScript之原型鍊和繼承
#下面是我的學習筆記,把它羅列成8種情況。
全域的this(瀏覽器)
全域作用域的this一般指向全域對象,在瀏覽器中這對象就是window,在node中這物件就是global。
console.log(this.document === document); // true (document === window.document) console.log(this === window); // true this.a = 37; //相当于创建了一个全局变量a console.log(window.a); // 37
一般函數的this(瀏覽器)
一般的函數宣告或是函數表達式,直接呼叫函數的話,this依然指向全域對象,在瀏覽器中這物件就是window,在node中這物件就是global。
function f1(){ return this; } f1() === window; // true, global object
再舉一個例子,看完就非常透徹了
function test(){ this.x = 1; alert(this.x); } test(); // 1
為了證明this就是全域對象,對程式碼做一些改變:
var x = 1; function test(){ alert(this.x); } test(); // 1
運行結果還是1。再變一下:
var x = 1; function test(){ this.x = 0; } test(); alert(x); //0
但是在嚴格模式下,一般函數呼叫的時候this指向undefined,這也是node為什麼要用嚴格模式的一個原因。
function f2(){ "use strict"; // see strict mode return this; } f2() === undefined; // true
作為物件方法的函數的this
this作為物件方法來使用是比較常見的。
下面這個例子,我們創建了一個對象字面量o,o裡面有個屬性f,它的值是一個函數對象,把函數當作對象屬性的值這種方式我們常常叫作對象的方法。作為對象的方法呼叫的時候,這時候this指向對象o
var o = { prop: 37, f: function() { return this.prop; } }; console.log(o.f()); // logs 37
我們不一定要定義成函數字面量這樣子的對象,像下面這種情況,我們只定義了一個對象o,如果直接呼叫independent()函數的話,this會指向window,但是我們透過賦值的方式,暫時建立一個屬性f,並指向函數物件的時候,我們還是拿到了37。
var o = {prop: 37}; function independent() { return this.prop; } o.f = independent; console.log(o.f()); // logs 37
所以並不是看函數是怎麼創建的,而是只要將函數作為物件的方法去調用,this就會指向這個物件。
物件原型鏈上的this
下面這個範例中:我們先建立了一個物件o,裡面有一個屬性f,函數作為物件屬性的值,我們透過Object.create(o)創建了一個物件p,p是一個空對象,它的原型會指向o,然後使用p.a = 1; p.b = 4建立物件p上的屬性,那麼當我們呼叫原型上的方法時,this.a,this.b仍能取到物件p上的a和b。 這裡要注意的是p的原型才是o,我們呼叫p.f(),呼叫的是原型鏈o上的屬性f,原型鏈上的this可以拿到目前的物件p。
var o = {f:function(){ return this.a + this.b; }}; var p = Object.create(o); p.a = 1; p.b = 4; console.log(p.f()); // 5
get/set方法與this
get/set方法中的this一般會指向get/set方法所在物件裡面
function modulus(){ return Math.sqrt(this.re * this.re + this.im * this.im); } var o = { re: 1, im: -1, get phase(){ return Math.atan2(this.im, this.re); } }; Object.defineProperty(o, 'modulus', { //临时动态给o对象创建modules属性 get: modulus, enumerable:true, configurable:true}); console.log(o.phase, o.modulus); // logs -0.78 1.4142
建構子中的this
用new把MyClass當作建構函式呼叫的話,this會指向空的對象,而這個物件的原型會指向MyClass.prototype(可以看這篇文章對原型鏈的總結),但是呼叫的時候做了this.a = 37的賦值,所以最後this會作為返回值(沒寫return語句,或者return的是基本類型的話,會將this作為返回值),第二個例子return語句返回了對象,那麼就會將a = 38作為回傳值
function MyClass(){ this.a = 37; } var o = new MyClass(); console.log(o.a); // 37 function C2(){ this.a = 37; return {a : 38}; } o = new C2(); console.log(o.a); // 38
call/apply方法與this
除了不同的呼叫方式外,函數物件有些方法能修改函數執行的this,例如call/ apply。
call和apply基本上沒差別,只不過call傳參的方式是平的,而apply是把一個陣列傳進去。如下面這個範例
什麼時候用call和apply呢?例如我們想要呼叫Object.prototype.toString,但是我們想指定某個this的時候,那我們就可以就用Object.prototype.toString.call(this)這樣子的方式來呼叫些無法直接呼叫的方法。如下面這個例子:
function add(c, d){ return this.a + this.b + c + d; } var o = {a:1, b:3}; add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16 //第一个参数接收的是你想作为this的对象 add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34 function bar() { console.log(Object.prototype.toString.call(this)); } bar.call(7); // "[object Number]"
bind方法與this
bind方法是es5開始提供的,所以ie9+才支援
function f(){ return this.a; } var g = f.bind({a : "test"}); //想把某个对象作为this的时候,就把它传进去,得到一个新对象g console.log(g()); // test //重复调用的时候,this已经指向bind参数。这对于我们绑定一次需要重复调用依然实现绑定的话,会比apply和call更加高效(看下面这个例子) var o = {a : 37, f : f, g : g}; console.log(o.f(), o.g()); // 37, test //o.f()通过对象的属性调用,this指向对象o;比较特殊的是即使我们把新绑定的方法作为对象的属性调用,o.g()依然会按之前的绑定去走,所以答案是test不是g
總結
#做項目的時候才發現這些基礎概念有多麼的重要,如果不把它們逐一落實了,真的是一不小心就會掉進坑裡。後續我還會對原型鏈,作用域,繼承,鍊式調用,正則等知識進行總結,歡迎關注
以上就是深入淺出JavaScript之this的詳解的內容,更多相關內容請關注PHP中文網(www.php.cn)!
#

JavaScript在現實世界中的應用包括前端和後端開發。 1)通過構建TODO列表應用展示前端應用,涉及DOM操作和事件處理。 2)通過Node.js和Express構建RESTfulAPI展示後端應用。

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

理解JavaScript引擎內部工作原理對開發者重要,因為它能幫助編寫更高效的代碼並理解性能瓶頸和優化策略。 1)引擎的工作流程包括解析、編譯和執行三個階段;2)執行過程中,引擎會進行動態優化,如內聯緩存和隱藏類;3)最佳實踐包括避免全局變量、優化循環、使用const和let,以及避免過度使用閉包。

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

Python和JavaScript在社區、庫和資源方面的對比各有優劣。 1)Python社區友好,適合初學者,但前端開發資源不如JavaScript豐富。 2)Python在數據科學和機器學習庫方面強大,JavaScript則在前端開發庫和框架上更勝一籌。 3)兩者的學習資源都豐富,但Python適合從官方文檔開始,JavaScript則以MDNWebDocs為佳。選擇應基於項目需求和個人興趣。

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

SublimeText3漢化版
中文版,非常好用

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

Dreamweaver CS6
視覺化網頁開發工具

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

禪工作室 13.0.1
強大的PHP整合開發環境