摘要:除此之外,還有一種情況也會修改,在一些庫中傳入回調函數,可能會強制改變的綁定,例如在中本例中的就是被強制改變綁定到了觸發事件的元素上。它們的第一個參數是一個對象,它們會把這個對象綁定到,接著在調用函數時指定這個。
理解JavaScript中的this關鍵詞
this關鍵詞是JavaScript語言中一個很重要,同時也是一個非常復雜的機制,它同時也是一個很特殊的關鍵詞,它一般會被自動定義在函數的作用域中。不少很有經驗的開發者也經常會被this的指向搞暈,當開發者搞不清楚它的指向的時候,內心的感受實際上差不多是這個樣子:this的綁定規則
接下來我們將會具體討論this關鍵詞到底指向什么。
首先明確一點,this的綁定和函數的聲明位置是沒有任何關系的,它只取決于函數的調用位置和調用方式。
1. 默認綁定首先我們先看一下最常見的也是最簡單的函數調用,全局中的獨立的函數調用:
var a = "hello"; function foo() { console.log(this.a); } foo();// "hello"
眾所周知,聲明在全局作用域中的變量,就是全局對象(window或者global)的一個同名的屬性,在本例中,this.a被解析成了全局變量a,而函數foo就是在直接在全局對象下、不帶有任何修飾地進行調用的,所以,this的默認綁定規則就是指向全局對象。但是,當我們使用嚴格模式(strict)進行開發的時候,情況發生了變化
"use strict"; var a = "hello"; function foo() { console.log(this.a); } foo();// undefined
在嚴格模式下,this被禁止綁定到全局對象中,所以在本例中,this指向了undefined。
2.作為對象方法的調用看下面的代碼:
var a ="world"; var foo = function () { console.log(this.a); }; var obj = { a:"hello", b:foo }; obj.b(); //"hello"
本例中,分別在全局對象中定義變量a,和在全局對象中定義屬性obj.a,運行結果是this被綁定到了被調用函數所在的對象中,而并非是全局對象中的a,或者你可以說,this指向了該函數的上級對象中。但是嚴格來說,無論是直接在obj對象中直接定義,還是先在全局對象中定義再添加到obj中,foo函數都并不屬于obj對象,然而調用位置會使用obj的上下文來引用函數。簡單說,當函數引用有上下文對象時,隱式綁定規則會將函數調用中的this綁定到這個上下文對象中。
3.在構造函數及prototype里的調用var Foo = function () { this.a = "hello"; } Foo.prototype.bar = function () { console.log(this.a); }; Foo.prototype.bar2 = function () { this.bar(); }; var foo = new Foo(); foo.bar2();//"hello"
本例與上例類似,this在“Foo類”(嚴格說Foo是應該是構造函數,但一般在開發過程中認為Foo是類,這樣有助于在面向對象編程中減少誤解)中綁定的是“類”里的共有變量和共有方法。
this隱式綁定丟失上述的幾種應用場景還是非常容易理解的,也是比較符合我們對this字面意義的理解的,相信對JavaScript有過接觸和研究的童鞋很快就會掌握。下面將繼續介紹幾種讓人感覺匪夷所思的this綁定丟失。
思考以下代碼:
var a = "world"; function foo (){ console.log(this.a); } var obj = { a:"hello", foo:foo }; var bar = obj.foo; //函數別名 bar(); //"world"
代碼執行完成后,我們看到this被綁定到了(或者說指向了)全局對象上,而并不是和前幾種情況下綁定到obj對象中,這是為啥呢?
雖然bar是obj.foo的一個引用,但是實際上它引用的是foo函數本身,因此此時bar其實是一個不帶任何修飾的函數調用,因此適用于默認綁定情況。
下面再來看看回調函數中this的綁定情況
function foo() { console.log(this.a); } function do(fnc) { fnc(); }; var obj = { a:2, foo:foo }; var a = "world"; do(obj.foo);//"world"
參數傳遞其實就是一種隱式賦值,因此傳入函數時也會被隱式賦值,所以結果和上一個例子沒有區別,即便是將函數傳入語言內置的的函數(比如setTimeout())中,結果也是沒有區別的,this要么被綁定到全局對象中,要么綁定到undefined。
除此之外,還有一種情況也會修改this,在一些JavaScript庫中傳入回調函數,可能會強制改變this的綁定,例如在jquery中
$("#some-id").on("click",function () { console.log(this.id);//"some-id" });
本例中的this就是被強制改變綁定到了觸發事件的DOM元素上。
顯式綁定隱式綁定實際上就是在一個對象的內部包含一個指向函數的屬性,并通過這個屬性間接地引用屬性,從而把this間接地綁定到這個對象上。
我們可以使用call和apply兩個函數進行顯式綁定。它們的第一個參數是一個對象,它們會把這個對象綁定到this,接著在調用函數時指定這個this。
var a = "world"; function foo() { console.log(this.a); } var obj = { a:"hello" }; foo.call(obj);//"hello" foo() //"world"
單純的實現this綁定的功能的話,call和apply是一樣的,它們的區別體現在別的參數中。
思考下面的代碼:
function foo() { console.log(this.a); } var obj = { a:"hello" }; function bar() { foo.call(obj); } bar(); //"hello" setTimeout(bar,500);// "hello" bar.call(window); //"hello",硬綁定的bar不能再修改它的this
我們創建了函數bar,并且手動在它的內部調用foo.call(obj),因此強制把foo的this綁定到obj,之后無論怎么調用函數bar,它總會在obj上調用foo,不會丟失,這種綁定方式被稱為硬綁定.
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/80302.html
摘要:在中,當使用關鍵字調用函數構造函數時,函數構造函數中也有這個概念,但是它不是惟一的規則,而且常常可以引用來自不同執行上下文的不同對象。因此,我們使用調用函數,可以看到這是對象,并且的屬性是正常的。 一直以來,javascript里邊的this都是一個很難理解的東西,之前看的最多的就是阮一峰老師關于this的理解: http://www.ruanyifeng.com/blo... htt...
摘要:理解了這句話,我們就可以來看閉包了閉包前面說過,函數可以訪問函數作用域鏈中的變量,但如果我們想在函數外訪問函數內卻不行了。 不管是閉包還是this關鍵字,都是困擾JS初學者的比較難懂的東西,如果你對它們的認識還不足夠清晰,那么現在就一起把它們掌握掉。還是那句話,我們從最基本的開始,建立起一個非常清晰的知識結構,好了,開始吧 ? 閉包 當然我們今天說的是javascript里的閉包。要學...
摘要:原文許多人被中的關鍵字給困擾住了,我想混亂的根源來自人們理所當然地認為中的應該像中的或中的一樣工作。盡管有點難理解,但它的原理并不神秘。在瀏覽器中,全局對象是對象。運算符創建一個新對象并且設置函數中的指向調用函數的新對象。 原文:Understanding the this keyword in JavaScript 許多人被JavaScript中的this關鍵字給困擾住了,我想混亂的...
摘要:原文鏈接參考深入理解原型和閉包完結王福朋博客園中的作用域詳解博客園 前言 王福朋老師的 JavaScript原型和閉包系列 文章看了不下三遍了,最為一個初學者,每次看的時候都會有一種 大徹大悟 的感覺,而看完之后卻總是一臉懵逼。原型與閉包 可以說是 JavaScirpt 中理解起來最難的部分了,當然,我也只是了解到了一些皮毛,對于 JavaScript OOP 更是缺乏經驗。這里我想總...
摘要:然而,異步函數不會立即被推入調用堆棧,而是會被推入任務隊列,并在調用堆棧為空后執行。將事件從任務隊列傳輸到調用堆棧稱為事件循環。我們調用接受和或返回另一個函數稱為高階函數的函數。 為了保證可讀性,本文采用意譯而非直譯 想閱讀更多優質文章請猛戳GitHub博客,一年百來篇優質文章等著你! 1.如何理解 JS 中的this關鍵字? JS 初學者總是對 this 關鍵字感到困惑,因為與其他現...
閱讀 2330·2021-09-30 09:47
閱讀 2949·2019-08-30 11:05
閱讀 2526·2019-08-29 17:20
閱讀 1912·2019-08-29 13:01
閱讀 1721·2019-08-26 13:39
閱讀 1221·2019-08-26 13:26
閱讀 3205·2019-08-23 18:40
閱讀 1810·2019-08-23 17:09