Javascript淺談之this
介紹
this在各種對(duì)面對(duì)象編程中起著非常重要的作用,主要用于指向調(diào)用的對(duì)象。不過在JavaScript中,this的表現(xiàn)存在很大差異,特別是不同執(zhí)行上下文。
由前文我們知道this也是屬于執(zhí)行上下文中的一個(gè)屬性,所有它命中注定和執(zhí)行上下文脫不了干系。
activeExecutionContext = {
VO: {...},
this: thisValue};
在Javascript中,this的取值取決于調(diào)用的模式。調(diào)用模式一共有四種:方法調(diào)用模式、函數(shù)調(diào)用模式、構(gòu)造器調(diào)用模式和apply調(diào)用模式。
調(diào)用模式
方法調(diào)用模式
當(dāng)一個(gè)函數(shù)被保存為對(duì)象的一個(gè)屬性時(shí),我們稱它為一個(gè)方法。當(dāng)一個(gè)方法被調(diào)用時(shí),this被綁定到該對(duì)象,即方法調(diào)用模式中的this指向調(diào)用對(duì)象。這個(gè)理解起來非常容易,你是我的一個(gè)方法,你屬于我,你的this當(dāng)然指向我啦。
var myObject = {
value : 0,
increment : function(inc) {
this.value += typeof inc === "number" ? inc : 1;
}
}
myObject.increment();
console.log(myObject.value); //輸出:1
myObject.increment(3);
console.log(myObject.value); //輸出:4
因?yàn)榭梢酝ㄟ^this訪問到自己所屬的對(duì)象,所有可以通過它調(diào)用和修改對(duì)象中屬性或者方法。由前文可知,this作為執(zhí)行上下文中屬性的一員,必然是在上下文創(chuàng)建時(shí)才創(chuàng)建,所有this到對(duì)象的綁定發(fā)生在調(diào)用的時(shí)候,這屬于“延遲綁定”。通過延遲綁定可以實(shí)現(xiàn)對(duì)this的高度復(fù)用。
function showValue(){
console.log(this.value);
}
var a = { value : "a"};
var b = { value : "b"};
a.showValue = showValue;
b.showValue = showValue;
a.showValue(); //輸出“a”
b.showValue(); //輸出“b”
上例中函數(shù)showValue就屬于延遲綁定。
函數(shù)調(diào)用模式
當(dāng)一個(gè)函數(shù)并非作為一個(gè)對(duì)象的方法來調(diào)用,這時(shí)就是函數(shù)調(diào)用。函數(shù)調(diào)用模式中,this被綁定到全局對(duì)象。(這是語言設(shè)計(jì)上的一個(gè)錯(cuò)誤)
myObject.double = function(){
var that = this; //解決方法
var helper = function(){
console.log(that, ": ", that.value); //輸出 Object {value: 4, increment: function, double: function} ": " 4
console.log(this, ": ", this.value); //輸出 Window {top: Window, window: Window…} ": " undefined
}
helper(); //以函數(shù)形式調(diào)用
}
按照正常思路,應(yīng)該如第四行所輸出那樣,this指向函數(shù)所屬對(duì)象,可是由于語言設(shè)計(jì)上面的問題導(dǎo)致this指向的卻是全局對(duì)象。這個(gè)更是讓this變得神秘,令人捉摸不透。但是作為開發(fā)者,這種情況肯定是我們所不愿意見到的,不按常理出牌這是,還好補(bǔ)救措施也很簡(jiǎn)單,就是上例中用that指代this。這樣,在helper方法中調(diào)用that就可以當(dāng)this使用,簡(jiǎn)單方便。至于函數(shù)調(diào)用模式為什么this會(huì)這樣,后面在分析引用類型時(shí)會(huì)詳加說明。
構(gòu)造器調(diào)用模式
由于javascript是基于原型繼承,但是它的設(shè)計(jì)者又想要它能像傳統(tǒng)的面向?qū)ο笳Z言那樣能通過new和構(gòu)造函數(shù)創(chuàng)建對(duì)象,現(xiàn)實(shí)面向?qū)ο缶幊?。這個(gè)貌似不是什么好的構(gòu)想,有點(diǎn)畫虎不成反類的尷尬。一是學(xué)不來,而是沒必要學(xué)。javascript的原型繼承機(jī)制已經(jīng)非常強(qiáng)大,足以滿足面向?qū)ο笏璧睦^承多態(tài)。
閑話少敘,還行言歸正傳說說構(gòu)造器調(diào)用模式。構(gòu)造器調(diào)用模式這個(gè)非常簡(jiǎn)單,它就是就一個(gè)函數(shù)當(dāng)做構(gòu)造器,然后將你打算公用的屬性和方法用this引進(jìn)聲明。如下
function Person(name, age){
this.name = name;
this.age = age;
this.say = function(){
console.log("name : %s, age : %n", this.name, this.age);
}
}
var p1 = new Person("jink", 24);
p1.say(); //輸出 name : jink, age : 24
var p2 = new Person("張三", 33);
p2.say();//輸出 name : 張三, age : 33
上面例子我們可以清楚看出,this是指向通過new和構(gòu)造函數(shù)創(chuàng)建的對(duì)象。為什么會(huì)這樣?這是因?yàn)樵趈avascript中通過new調(diào)用構(gòu)造函數(shù)時(shí),new運(yùn)算符調(diào)用“Person”函數(shù)的內(nèi)部的[[Construct]] 方法,接著,在對(duì)象創(chuàng)建后,調(diào)用內(nèi)部的[[Call]] 方法。 所有相同的函數(shù)“Person”都將this的值設(shè)置為新創(chuàng)建的對(duì)象。
apply調(diào)用模式
javascript中所有函數(shù)創(chuàng)建之后,都會(huì)自帶兩個(gè)方法:apply和call。這兩個(gè)方法的的具體使用,我在此就不想詳細(xì)說明,不知道的同學(xué)可以百度一下,挺簡(jiǎn)單的。通過兩個(gè)方法,我們可以手動(dòng)設(shè)置this。雖然this在創(chuàng)建時(shí)候是不允許修改的,但是,我們?cè)趧?chuàng)建之前,手動(dòng)設(shè)置過,那就是另外一回事了。這一設(shè)置,可不得了,你就可以讓你的對(duì)象調(diào)用任意方法,就好像你可以讓汽車大海中航行,非洲象如美洲豹一樣飛馳,程序員像鋼琴師一樣彈奏。哈哈想象總是美好的,調(diào)用歸調(diào)用,但是調(diào)用了能不能實(shí)現(xiàn)功能就另說了。
var programmer = {
name : "程序員",
hand : "靈活的雙手",
programme : function(){
console.log(this.name+"用"+this.hand+"編寫代碼。");
}
}
var pianist = {
name : "鋼琴家",
hand : "靈活的雙手",
play : function(){
console.log(this.name+"用"+this.hand+"彈奏動(dòng)聽的樂曲。");
}
}
var player = {
name : "運(yùn)動(dòng)員",
foot : "矯健的雙腿",
run : function(){
console.log(this.name+"用"+this.foot+"在賽場(chǎng)奔馳。");
}
}
//循規(guī)蹈矩
programmer.programme(); //程序員用靈活的雙手編寫代碼。
pianist.play(); //鋼琴家用靈活的雙手彈奏動(dòng)聽的樂曲。
player.run(); //運(yùn)動(dòng)員用矯健的雙腿在賽場(chǎng)奔馳。
//異想天開
pianist.play.apply(programmer); //程序員用靈活的雙手彈奏動(dòng)聽的樂曲。
player.run.apply(programmer); //程序員用undefined在賽場(chǎng)奔馳。 由于自身運(yùn)動(dòng)缺少,沒有矯健的雙腿
上面看著是不是挺有意思的,apply的第一個(gè)參數(shù)就是執(zhí)行方法中的this指向。這樣我們就可以借用別人的方法自己私下偷偷的用,可謂方便至極。在一些框架中經(jīng)常用的此類技巧。
總結(jié)
關(guān)于this就說這么多,相信大家看過之后,對(duì)在不同情境中this的判定都有些了解了,本來打算討論接下來討論引用對(duì)象的,闡述一下方法調(diào)用模式和函數(shù)調(diào)用模式中this取值的原理,但害怕篇幅過長(zhǎng),所以決定用單獨(dú)一章向大家分析一下引用對(duì)象這個(gè)概念。
相關(guān)文章
將光標(biāo)定位于輸入框最右側(cè)實(shí)現(xiàn)代碼
如何將光標(biāo)定位于輸入框最右側(cè)的實(shí)現(xiàn)方式,這種做法很多人都需要,本文將詳細(xì)介紹,需要的朋友可以參考下2012-12-12Js從頭學(xué)起(基本數(shù)據(jù)類型和引用類型的參數(shù)傳遞詳細(xì)分析)
Js中所有函數(shù)的參數(shù)傳遞都是按值傳遞的,也就是把函數(shù)外面的值復(fù)制給函數(shù)內(nèi)部的參數(shù),就和把值從一個(gè)變量復(fù)制到另一個(gè)變量一樣。下面舉幾個(gè)特別的例子2012-02-02對(duì)javascript基本對(duì)象的屬性以及方法的實(shí)例介紹
對(duì)javascript基本對(duì)象的屬性以及方法的實(shí)例介紹...2007-01-01