摘要:構(gòu)造函數(shù)中的當(dāng)一個函數(shù)被作為一個構(gòu)造函數(shù)來使用使用關(guān)鍵字,它的與即將被創(chuàng)建的新對象綁定。因此,如果傳遞的值是一個原始值比如或,那么就會使用相關(guān)構(gòu)造函數(shù)將它轉(zhuǎn)換為對象,所以原始值通過被轉(zhuǎn)換為對象,而字符串使用轉(zhuǎn)化為對象,例如方法引入了。
1 全局上下文中的this
在瀏覽器引擎的全局運(yùn)行上下文中(在任何函數(shù)體外部),this 指代全局對象,無論是否在嚴(yán)格模式下。
在node的全局上下文,發(fā)現(xiàn)this是一個空對象,無論是否在嚴(yán)格模式下。
在函數(shù)內(nèi)部,this的值取決于函數(shù)是如何調(diào)用的。
2 直接調(diào)用函數(shù)中的this
在非嚴(yán)格的模式下,this的值默認(rèn)為全局對象,window或者global。
在嚴(yán)格模式下,this的值為undefined。
一般我們利用this的場景,都不是指代全局對象,所以出現(xiàn)這種this是全局對象或者undefined的時(shí)候 往往是我們出錯了
3 調(diào)用對象方法中的this
當(dāng)以對象的方法調(diào)用函數(shù)時(shí),函數(shù)中的this指向調(diào)用該函數(shù)的方法
var o = { prop: 37, f: function() { return this.prop; } }; console.log(o.f()); // logs 37 /**********************************/ var o = {prop: 37}; function independent() { return this.prop; } o.f = independent; console.log(o.f()); // logs 37 //只取決于最后的函數(shù)調(diào)用
函數(shù)的this指向調(diào)用它的最近對象,這里independent函數(shù)中的this指向的是o.b 而不是o。
o.b = { g: independent, prop: 42 }; console.log(o.b.g()); // logs 42
以下原型鏈和getter、setter中的this,都是調(diào)用對象方法中this的場景。
之前犯過一個反過來的錯誤,在一個對象中定義的方法中調(diào)用this,但是使用方法的時(shí)候沒有通過對象調(diào)用,所以this為undefined而不是原來的對象。
3.1 原型鏈中的 this相同的概念在定義在原型鏈中的方法也是一致的。如果該方法存在于一個對象的原型鏈上,那么this指向的是調(diào)用這個方法的對象,表現(xiàn)得好像是這個方法就存在于這個對象上一樣。
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
在這個例子中,對象p沒有屬于它自己的f屬性,它的f屬性繼承自它的原型。但是這對于最終在o中找到f屬性的查找過程來說沒有關(guān)系;查找過程首先從p.f的引用開始,所以函數(shù)中的this指向p。也就是說,因?yàn)閒是作為p的方法調(diào)用的,所以它的this指向了p。這是JavaScript的原型繼承中的一個有趣的特性。
3.2 getter 與 setter 中的 this再次,相同的概念也適用時(shí)的函數(shù)作為一個 getter 或者 一個setter調(diào)用。作為getter或setter函數(shù)都會綁定 this 到從設(shè)置屬性或得到屬性的那個對象。
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", { get: modulus, enumerable:true, configurable:true}); console.log(o.phase, o.modulus); // logs -0.78 1.4144 構(gòu)造函數(shù)中的 this
當(dāng)一個函數(shù)被作為一個構(gòu)造函數(shù)來使用(使用new關(guān)鍵字),它的this與即將被創(chuàng)建的新對象綁定。
注意:當(dāng)構(gòu)造器返回的默認(rèn)值是一個this引用的對象時(shí),可以手動設(shè)置返回其他的對象,如果返回值不是一個對象,返回this。
function C(){ this.a = 37; } var o = new C(); console.log(o.a); // logs 37 function C2(){ this.a = 37; return {a:38}; } o = new C2(); console.log(o.a); // logs 38
在最后的例子中(C2),因?yàn)樵谡{(diào)用構(gòu)造函數(shù)的過程中,手動的設(shè)置了返回對象,與this綁定的默認(rèn)對象被取消(本質(zhì)上這使得語句“this.a = 37;”成了“僵尸”代碼,實(shí)際上并不是真正的“僵尸”,這條語句執(zhí)行了但是對于外部沒有任何影響,因此完全可以忽略它)。
5 call 和 applycall和apply可以指定函數(shù)執(zhí)行時(shí)this的指向。
當(dāng)一個函數(shù)的函數(shù)體中使用了this關(guān)鍵字時(shí),通過所有函數(shù)都從Function對象的原型中繼承的call()方法和apply()方法調(diào)用時(shí),它的值可以綁定到一個指定的對象上。
function add(c, d){ return this.a + this.b + c + d; } var o = {a:1, b:3}; // The first parameter is the object to use as "this", subsequent parameters are passed as // arguments in the function call add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16 // The first parameter is the object to use as "this", the second is an array whose // members are used as the arguments in the function call add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34
使用 call 和 apply 函數(shù)的時(shí)候要注意,如果傳遞的 this 值不是一個對象,JavaScript 將會嘗試使用內(nèi)部 ToObject 操作將其轉(zhuǎn)換為對象。因此,如果傳遞的值是一個原始值比如 7 或 "foo" ,那么就會使用相關(guān)構(gòu)造函數(shù)將它轉(zhuǎn)換為對象,所以原始值 7 通過new Number(7)被轉(zhuǎn)換為對象,而字符串"foo"使用 new String("foo") 轉(zhuǎn)化為對象,例如:
function bar() { console.log(Object.prototype.toString.call(this)); } bar.call(7); // [object Number]6 bind 方法
ECMAScript 5 引入了 Function.prototype.bind。調(diào)用f.bind(someObject)會創(chuàng)建一個與f具有相同函數(shù)體和作用域的函數(shù),但是在這個新函數(shù)中,this將永久地被綁定到了bind的第一個參數(shù),無論這個函數(shù)是如何被調(diào)用的。
可以看到,call和apply是不改變原來的函數(shù),只是在執(zhí)行的時(shí)候指定函數(shù)的this,而bind方法則是生成了一個this指向固定的函數(shù),
function f(){ return this.a; } var g = f.bind({a:"azerty"}); console.log(g()); // azerty var o = {a:37, f:f, g:g}; console.log(o.f(), o.g()); // 37, azerty
在ES6的語法中,箭頭函數(shù)默認(rèn)綁定當(dāng)前函數(shù)聲明環(huán)境的this。
7 DOM事件處理函數(shù)中的 this當(dāng)函數(shù)被用作事件處理函數(shù)時(shí),它的this指向函數(shù)所綁定的DOM對象。
event.currentTarget指向事件所綁定的元素,而event.target始終指向事件發(fā)生時(shí)的元素
所以this 始終和 event.currentTarget 相同。
8 內(nèi)聯(lián)事件處理函數(shù)中的 this
當(dāng)代碼被內(nèi)聯(lián)處理函數(shù)調(diào)用時(shí),它的this指向監(jiān)聽器所在的DOM元素:
//上面的alert會顯示button。注意只有外層代碼中的this是這樣設(shè)置。
在這種情況下,沒有設(shè)置內(nèi)部函數(shù)的 this,所以它指向 global/window 對象(即非嚴(yán)格模式下調(diào)用的函數(shù)未設(shè)置 this 時(shí)指向的默認(rèn)對象)。
本文絕大多數(shù)內(nèi)容參考自: https://developer.mozilla.org...
僅作少許修改
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/86637.html
摘要:理解了這句話,我們就可以來看閉包了閉包前面說過,函數(shù)可以訪問函數(shù)作用域鏈中的變量,但如果我們想在函數(shù)外訪問函數(shù)內(nèi)卻不行了。 不管是閉包還是this關(guān)鍵字,都是困擾JS初學(xué)者的比較難懂的東西,如果你對它們的認(rèn)識還不足夠清晰,那么現(xiàn)在就一起把它們掌握掉。還是那句話,我們從最基本的開始,建立起一個非常清晰的知識結(jié)構(gòu),好了,開始吧 ? 閉包 當(dāng)然我們今天說的是javascript里的閉包。要學(xué)...
摘要:最后重點(diǎn)理解結(jié)論箭頭函數(shù)的,總是指向定義時(shí)所在的對象,而不是運(yùn)行時(shí)所在的對象。輸出,箭頭函數(shù)不會綁定所以傳入指向無效。原因是,要徹底理解應(yīng)該是建立在已經(jīng)大致理解了中的執(zhí)行上下文,作用域作用域鏈,閉包,變量對象,函數(shù)執(zhí)行過程的基礎(chǔ)上。 本文共 2025 字,看完只需 8 分鐘 概述 前面的文章講解了 JavaScript 中的執(zhí)行上下文,作用域,變量對象,this 的相關(guān)原理,但是我...
摘要:是完全的面向?qū)ο笳Z言,它們通過類的形式組織函數(shù)和變量,使之不能脫離對象存在。而在基于原型的面向?qū)ο蠓绞街校瑢ο髣t是依靠構(gòu)造器利用原型構(gòu)造出來的。 JavaScript 函數(shù)式腳本語言特性以及其看似隨意的編寫風(fēng)格,導(dǎo)致長期以來人們對這一門語言的誤解,即認(rèn)為 JavaScript 不是一門面向?qū)ο蟮恼Z言,或者只是部分具備一些面向?qū)ο蟮奶卣鳌1疚膶⒒貧w面向?qū)ο蟊疽猓瑥膶φZ言感悟的角度闡述為什...
摘要:在節(jié)中,我們學(xué)習(xí)到了通過構(gòu)造函數(shù)創(chuàng)建對象的三個重要步驟,其中的一步是把構(gòu)造函數(shù)的對象設(shè)置為創(chuàng)建對象的原型。利用而不是直接用創(chuàng)建一個實(shí)例對象的目的是,減少一次調(diào)用父構(gòu)造函數(shù)的執(zhí)行。 JavaScript語言不像面向?qū)ο蟮木幊陶Z言中有類的概念,所以也就沒有類之間直接的繼承,JavaScript中只有對象,使用函數(shù)模擬類,基于對象之間的原型鏈來實(shí)現(xiàn)繼承關(guān)系,ES6的語法中新增了class關(guān)鍵...
溫馨提示:作者的爬坑記錄,對你等大神完全沒有價(jià)值,別在我這浪費(fèi)生命 這一切,源于阮大神博文學(xué)習(xí)Javascript閉包(Closure)- 阮一峰中的一道思考題 //問題1: var name = The Window; var object = { name : My Object, getNameFunc : function(){ return function(){ ...
閱讀 1903·2021-11-25 09:43
閱讀 1963·2019-08-30 13:56
閱讀 1222·2019-08-30 12:58
閱讀 3427·2019-08-29 13:52
閱讀 759·2019-08-26 12:17
閱讀 1464·2019-08-26 11:32
閱讀 940·2019-08-23 13:50
閱讀 1304·2019-08-23 11:53