javascript的self和this使用小結(jié)

一、self
這個(gè)非常簡單神僵。我們知道雁刷,打開任何一個(gè)網(wǎng)頁,瀏覽器會(huì)首先創(chuàng)建一個(gè)窗口保礼,這個(gè)窗口就是一個(gè)window對(duì)象沛励,也是js運(yùn)行所依附的全局環(huán)境對(duì)象和全局作用域?qū)ο笤鹩铩elf 指窗口本身,它返回的對(duì)象跟window對(duì)象是一模一樣的侯勉。也正因?yàn)槿绱损谐铮瑆indow對(duì)象的常用方法和函數(shù)都可以用self代替window铝阐。舉個(gè)例子址貌,常見的寫法如“self.close();”,把它放在<a>標(biāo)記中:“<a href="javascript:self.close();">關(guān)閉窗口</a>”徘键,單擊“關(guān)閉窗口”鏈接练对,當(dāng)前頁面關(guān)閉。
二吹害、this關(guān)鍵字
在講this之前螟凭,看下面的一段代碼:

<body>
<script type="text/javascript">
function thisTest()
  {
      this.textValue = 'this的dom測試';
      this.element= document.createElement('span');
      this.element.innerHTML = this.textValue;
      this.element.style.color = "blue";
      this.element.style.cursor = "pointer";
      this.element.attachEvent('onclick', this.ToString);
  }
   
  thisTest.prototype.RenderDom = function()
  {
      document.body.appendChild(this.element);
  }     

  thisTest.prototype.ToString = function()
  {
      alert("單擊我:"+this.textValue);
  };
  var test= new thisTest();
  test.RenderDom(); 
  //test.ToString();
</script>
</body>

本來的目的是想在body中添加一個(gè)span元素,對(duì)于這個(gè)span元素它呀,制定了它的字體顏色螺男,懸浮在它上面的鼠標(biāo)樣式和單擊觸發(fā)事件。問題就出現(xiàn)在它的單擊事件上(彈出"單擊我:undefined")纵穿。也許有人會(huì)說你丫傻呀下隧,寫這么多sb代碼還不就是為了實(shí)現(xiàn)下面這個(gè)東東嗎?

<span style='cursor:pointer;color:blue;' onclick="alert(this.innerHTML)">this的dom測試</span>

你看多簡單直觀谓媒,而且還不容易出錯(cuò)淆院?!kao句惯,我暈土辩。我正要講的是您正在使用的this.innerHTML中的this呀。
1抢野、this到底指什么拷淘?
我們熟悉的c#有this關(guān)鍵字,它的主要作用就是指代當(dāng)前對(duì)象實(shí)例(參數(shù)傳遞和索引器都要用到this)指孤。在javascript中启涯,this通常指向的是我們正在執(zhí)行的函數(shù)本身,或者是指向該函數(shù)所屬的對(duì)象(運(yùn)行時(shí))邓厕。
2逝嚎、常見使用方式
(1)、直接在dom元素中使用

<input id="btnTest" type="button" value="提交" onclick="alert(this.value))" />

分析:對(duì)于dom元素的一個(gè)onclick(或其他如onblur等)屬性详恼,它為所屬的html元素所擁有补君,直接在它觸發(fā)的函數(shù)里寫this,this應(yīng)該指向該html元素昧互。
(2)挽铁、給dom元素注冊js函數(shù)
a伟桅、不正確的方式

<script type="text/javascript">
  function thisTest(){
  alert(this.value); // 彈出undefined, this在這里指向??
}
</script>

<input id="btnTest" type="button" value="提交" onclick="thisTest()" />

分析:onclick事件直接調(diào)用thisTest函數(shù),程序就會(huì)彈出undefined叽掘。因?yàn)閠hisTest函數(shù)是在window對(duì)象中定義的楣铁,
所以thisTest的擁有者(作用域)是window,thisTest的this也是window更扁。而window是沒有value屬性的盖腕,所以就報(bào)錯(cuò)了。
b浓镜、正確的方式

<input id="btnTest" type="button" value="提交" />

<script type="text/javascript">
  function thisTest(){
  alert(this.value); 
}
document.getElementById("btnTest").onclick=thisTest; //給button的onclick事件注冊一個(gè)函數(shù)
</script>

分析:在前面的示例中溃列,thisTest函數(shù)定義在全局作用域(這里就是window對(duì)象),所以this指代的是當(dāng)前的window對(duì)象膛薛。而通過document.getElementById("btnTest").onclick=thisTest;這樣的形式听隐,其實(shí)是將btnTest的onclick屬性設(shè)置為thisTest函數(shù)的一個(gè)副本,在btnTest的onclick屬性的函數(shù)作用域內(nèi)哄啄,this歸btnTest所有雅任,this也就指向了btnTest。其實(shí)如果有多個(gè)dom元素要注冊該事件咨跌,我們可以利用不同的dom元素id沪么,用下面的方式實(shí)現(xiàn):
document.getElementById("domID").onclick=thisTest; //給button的onclick事件注冊一個(gè)函數(shù)。
因?yàn)槎鄠€(gè)不同的HTML元素雖然創(chuàng)建了不同的函數(shù)副本虑润,但每個(gè)副本的擁有者都是相對(duì)應(yīng)的HTML元素成玫,各自的this也都指向它們的擁有者,不會(huì)造成混亂拳喻。
為了驗(yàn)證上述說法哭当,我們改進(jìn)一下代碼,讓button直接彈出它們對(duì)應(yīng)的觸發(fā)函數(shù):

<input id="btnTest1" type="button" value="提交1" onclick="thisTest()" />
<input id="btnTest2" type="button" value="提交2" />

<script type="text/javascript">
function thisTest(){
this.value="提交中";
}
var btn=document.getElementById("btnTest1");
alert(btn.onclick); //第一個(gè)按鈕函數(shù)

var btnOther=document.getElementById("btnTest2");
btnOther.onclick=thisTest;
alert(btnOther.onclick); //第二個(gè)按鈕函數(shù)
</script>

其彈出的結(jié)果是:

//第一個(gè)按鈕
function onclick(){
  thisTest()
}
 
//第二個(gè)按鈕
function thisTest(){
  this.value="提交中";
}

從上面的結(jié)果你一定理解的更透徹了冗澈。
By the way钦勘,每新建一個(gè)函數(shù)的副本,程序就會(huì)為這個(gè)函數(shù)副本分配一定的內(nèi)存亚亲。而實(shí)際應(yīng)用中彻采,大多數(shù)函數(shù)并不一定會(huì)被調(diào)用,于是這部分內(nèi)存就被白白浪費(fèi)了捌归。所以我們通常都這么寫:

<input id="btnTest1" type="button" value="提交1" onclick="thisTest(this)" />
<input id="btnTest2" type="button" value="提交2" onclick="thisTest(this)" />
<input id="btnTest3" type="button" value="提交3" onclick="thisTest(this)" />
<input id="btnTest4" type="button" value="提交4" onclick="thisTest(this)" />

<script type="text/javascript">
  function thisTest(obj){
  alert(obj.value); 
}
</script>

這是因?yàn)槲覀兪褂昧撕瘮?shù)引用的方式肛响,程序就只會(huì)給函數(shù)的本體分配內(nèi)存,而引用只分配指針惜索。這樣寫一個(gè)函數(shù)特笋,調(diào)用的地方給它分配一個(gè)(指針)引用,這樣效率就高很多巾兆。當(dāng)然猎物,如果你覺得這樣注冊事件不能兼容多種瀏覽器虎囚,可以寫下面的注冊事件的通用腳本:

//js事件 添加 EventUtil.addEvent(dom元素,事件名稱,事件觸發(fā)的函數(shù)名) 移除EventUtil.removeEvent(dom元素,事件名稱,事件觸發(fā)的函數(shù)名)
var EventUtil = new eventManager();

//js事件通用管理器 dom元素 添加或者移除事件
function eventManager() {
    //添加事件
    //oDomElement:dom元素,如按鈕,文本,document等; ****** oEventType:事件名稱(如:click,如果是ie瀏覽器,自動(dòng)將click轉(zhuǎn)換為onclick);****** oFunc:事件觸發(fā)的函數(shù)名
    this.addEvent = function(oDomElement, oEventType, oFunc) {
        //ie
        if (oDomElement.attachEvent) {
            oDomElement.attachEvent("on" + oEventType, oFunc);
        }
        //ff,opera,safari等
        else if (oDomElement.addEventListener) {
            oDomElement.addEventListener(oEventType, oFunc, false);
        }
        //其他
        else {
            oDomElement["on" + oEventType] = oFunc;
        }
    }

    this.removeEvent = function(oDomElement, oEventType, oFunc) {
        //ie
        if (oDomElement.detachEvent) {
            oDomElement.detachEvent("on" + oEventType, oFunc);
        }
        //ff,opera,safari等
        else if (oDomElement.removeEventListener) {
            oDomElement.removeEventListener(oEventType, oFunc, false);
        }
        //其他
        else {
            oDomElement["on" + oEventType] = null;
        }
    }
}

正像注釋寫的那樣,要注冊dom元素事件蔫磨,用EventUtil.addEvent(dom元素,事件名稱,事件觸發(fā)的函數(shù)名)即可淘讥, 移除時(shí)可以這樣寫:EventUtil.removeEvent(dom元素,事件名稱,事件觸發(fā)的函數(shù)名)。這是題外話堤如,不說了蒲列。
(3)、類定義中使用this關(guān)鍵字
這個(gè)其實(shí)再常見不過煤惩,看示例:

function thisTest()
  {
      var tmpName = 'jeff wong';
      this.userName= 'jeff wong';
  }

var test= new thisTest();
alert(test.userName==test.tmpName);//false
alert(test.userName); //jeff wong
alert(test.tmpName); //undefined

分析一下結(jié)果嫉嘀,其實(shí)這里的this和c#里的是類似的。
(4)魄揉、為腳本對(duì)象添加原形方法
理解這里的前提是你必須了解js里的原型概念(說道這里,kao拭宁,我還真的需要面壁一下):js中對(duì)象的prototype屬性洛退,是用來返回對(duì)象類型原型的引用的。所有js內(nèi)部對(duì)象都有只讀的prototype屬性杰标,可以向其原型中動(dòng)態(tài)添加功能(屬性和方法)兵怯,
但該對(duì)象不能被賦予不同的原型。但是對(duì)于用戶定義的對(duì)象可以被賦給新的原型腔剂∶角看個(gè)簡單的示例:

//js的內(nèi)部對(duì)象String,向其原型中動(dòng)態(tài)添加功能(屬性和方法)
//去掉字符串兩端的空白字符
String.prototype.Trim = function() {
    return this.replace(/(^\s+)|(\s+$)/g, "");
}

function thisTest()
  {
      var tmpName = 'jeff wong';
      this.userName= '      jeff wong  ';
  }
//給用戶定義的對(duì)象添加原型方法
thisTest.prototype.ToString = function()
  {
      alert(this.userName); //jeff wong(*有空格*)
      alert(this.userName.Trim()); //jeff wong (*無空格*)
      //alert(tmpName); //腳本錯(cuò)誤,tmpName未定義
  }

var test= new thisTest();
test.ToString(); //調(diào)用原型的ToString()

function myTest(){
  this.userName= '  test ';
}
var test1=new myTest();
//test1.ToString(); //這里暫時(shí)不支持調(diào)用ToString()方法

//用戶定義的對(duì)象被賦給新的原型
myTest.prototype = new thisTest();
test1.ToString(); //調(diào)用原型的ToString()

測試結(jié)果顯示,這里的this指代的是被添加原形(方法或?qū)傩裕┑念惖膶?shí)例掸犬,和(3)中的定義基本相似袜漩。
(5)、在函數(shù)的內(nèi)部函數(shù)中使用this關(guān)鍵字
這個(gè)你要是理解作用域和閉包湾碎,問題就迎刃而解宙攻。看最典型的示例:

function thisTest()
  {
      this.userName= 'outer userName';
      function innerThisTest(){
        var userName="inner userName";
        alert(userName); //inner userName
        alert(this.userName); //outer userName
      }
     return innerThisTest;
  }

thisTest()();

分析:thisTest()調(diào)用內(nèi)部的innerThisTest函數(shù)介褥,形成一個(gè)閉包座掘。innerThisTest執(zhí)行時(shí),第一次彈出innerUserName柔滔,是因?yàn)閕nnerThisTest函數(shù)作用域內(nèi)有一個(gè)變量叫userName溢陪,所以直接彈出當(dāng)前作用域下變量的指定值;第二次彈出outer userName是因?yàn)閕nnerThisTest作用域內(nèi)沒有userName屬性(示例中的this.userName),所以它向上一級(jí)作用域中找userName屬性睛廊,這次在thisTest中找到(示例中的this.userName= 'outer userName';)形真,所以彈出對(duì)應(yīng)值。
(6)通過Function的call和apply函數(shù)指定特定的this
這個(gè)指定來指定去喉前,this就有可能造成“你中有我没酣,我中有你”的局面王财,不想把自己弄暈了的話,了解一下就可以了裕便。改變this指定對(duì)象對(duì)于代碼維護(hù)也是一件很不好的事情绒净。貼出舊文中的示例代碼結(jié)束吧:

function myFuncOne() {
    this.p = "myFuncOne-";
    this.A = function(arg) {
        alert(this.p + arg);
    }
}

function myFuncTwo() {
    this.p = "myFuncTwo-";
    this.B = function(arg) {
        alert(this.p + arg);
    }
}
function test() {
    var obj1 = new myFuncOne();
    var obj2 = new myFuncTwo();
    obj1.A("testA");                       //顯示myFuncOne-testA 
    obj2.B("testB");                        //顯示myFuncTwo-testB 
    obj1.A.apply(obj2, ["testA"]);          //顯示myFuncTwo-testA,其中[ testA”]是僅有一個(gè)元素的數(shù)組
    obj2.B.apply(obj1, ["testB"]);          //顯示myFuncOne-testB,其中[ testB”]是僅有一個(gè)元素的數(shù)組
    obj1.A.call(obj2, "testA");             //顯示myFuncTwo-testA 
    obj2.B.call(obj1, "testB");             //顯示myFuncOne-testB 
}

總結(jié):到這里,對(duì)于開篇中的span彈出undefined的問題你是不是已經(jīng)豁然開朗偿衰?如果你還在懵懂中挂疆,給個(gè)可有可無的提示:當(dāng)前的這個(gè)span元素有沒有textValue屬性啊O卖帷缤言?
三、void
1视事、定義
javascript中void是一個(gè)操作符胆萧,該操作符指定要計(jì)算一個(gè)表達(dá)式但是不返回值。
2俐东、語法
void 操作符用法格式如下:
(1). javascript:void (expression)
(2). javascript:void expression
注意:expression是一個(gè)要計(jì)算的js標(biāo)準(zhǔn)的表達(dá)式跌穗。表達(dá)式外側(cè)的圓括號(hào)是可選的,但是寫上去你可以一眼就知道括弧內(nèi)的是一個(gè)表達(dá)式(這和typeof后面的表達(dá)式語法是一樣的)虏辫。
3蚌吸、實(shí)例代碼

        function voidTest() {

            void (alert("it is a void test")); //執(zhí)行函數(shù)

            var oTestNum = 1;
            void (oTestNum++); //整數(shù)自加
            alert(oTestNum);

            oTestNum = 1;
            void (oTestNum += " void test"); //整數(shù)加字符串
            alert(oTestNum);
        }
        voidTest();

4、在a元素下使用void(0)
(1)適用情況
在網(wǎng)頁中砌庄,我們經(jīng)掣耄看到html里的a標(biāo)簽不需要它導(dǎo)航到某一個(gè)頁面時(shí),href屬性設(shè)置的寫法:

    <a href="#">link1</a>
    <a href="javascript:void(0);">link2</a>

注意:第一種“#”的寫法(其實(shí)#可以是多個(gè)娄昆,通常都是1個(gè))佩微,當(dāng)a元素所在的鏈接在瀏覽器一屏以下時(shí),會(huì)導(dǎo)致頁面回滾到頂部稿黄;所以當(dāng)我們需要a標(biāo)簽不導(dǎo)航到其他頁面喊衫,不需要網(wǎng)頁位置的回滾,都會(huì)采取void(0)那種寫法杆怕。
(2)ie6下void(0)造成的詭異問題
這個(gè)問題網(wǎng)上有很多討論族购,個(gè)人認(rèn)為“落葉滿長沙”總結(jié)的很有代表性,這里就不再贅述了陵珍。

本文摘自 http://www.cnblogs.com

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末寝杖,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子互纯,更是在濱河造成了極大的恐慌瑟幕,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異只盹,居然都是意外死亡辣往,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門殖卑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來站削,“玉大人,你說我怎么就攤上這事孵稽⌒砥穑” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵菩鲜,是天一觀的道長园细。 經(jīng)常有香客問我,道長接校,這世上最難降的妖魔是什么猛频? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮馅笙,結(jié)果婚禮上伦乔,老公的妹妹穿的比我還像新娘。我一直安慰自己董习,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布爱只。 她就那樣靜靜地躺著皿淋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪恬试。 梳的紋絲不亂的頭發(fā)上窝趣,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音训柴,去河邊找鬼哑舒。 笑死,一個(gè)胖子當(dāng)著我的面吹牛幻馁,可吹牛的內(nèi)容都是我干的洗鸵。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼仗嗦,長吁一口氣:“原來是場噩夢啊……” “哼膘滨!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起稀拐,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤火邓,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體铲咨,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡躲胳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了纤勒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坯苹。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖踊东,靈堂內(nèi)的尸體忽然破棺而出北滥,到底是詐尸還是另有隱情,我是刑警寧澤闸翅,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布再芋,位于F島的核電站,受9級(jí)特大地震影響坚冀,放射性物質(zhì)發(fā)生泄漏济赎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一记某、第九天 我趴在偏房一處隱蔽的房頂上張望司训。 院中可真熱鬧,春花似錦液南、人聲如沸壳猜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽统扳。三九已至,卻和暖如春畅姊,著一層夾襖步出監(jiān)牢的瞬間咒钟,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來泰國打工若未, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留朱嘴,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓粗合,卻偏偏與公主長得像萍嬉,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子舌劳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • JavaScript 程序采用了異步事件驅(qū)動(dòng)編程模型帚湘。在這種程序設(shè)計(jì)風(fēng)格下,當(dāng)文檔甚淡、瀏覽器大诸、元素或與之相關(guān)的對(duì)象發(fā)...
    劼哥stone閱讀 1,250評(píng)論 3 11
  • 工廠模式類似于現(xiàn)實(shí)生活中的工廠可以產(chǎn)生大量相似的商品捅厂,去做同樣的事情,實(shí)現(xiàn)同樣的效果;這時(shí)候需要使用工廠模式资柔。簡單...
    舟漁行舟閱讀 7,718評(píng)論 2 17
  • 第1章 認(rèn)識(shí)JS JavaScript能做什么焙贷?1.增強(qiáng)頁面動(dòng)態(tài)效果(如:下拉菜單、圖片輪播贿堰、信息滾動(dòng)等)2.實(shí)現(xiàn)...
    mo默22閱讀 1,246評(píng)論 0 5
  • 關(guān)于搜索引擎優(yōu)化的方法一直眾說紛紜辙芍,不同搜索引擎,不同國家的優(yōu)化方法可能也不盡相同羹与,本文總結(jié)了一些國外的搜索引擎優(yōu)...
    文風(fēng)Yu閱讀 2,364評(píng)論 1 3
  • 【日更083】 5月9日晚故硅,錘子科技發(fā)布了2017年第一款新手機(jī),我跟著看完了全場纵搁。自從老羅做手機(jī)以來吃衅,他已經(jīng)有意...
    唐斬2086閱讀 163評(píng)論 1 2