欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript的this關(guān)鍵字的理解

 更新時(shí)間:2016年06月18日 09:11:25   作者:酷小孩  
今天的教程來自天才的Cody Lindley的新書:《JavaScript啟蒙教程 / JavaScript Enlightenment》。他討論了令人迷惑的關(guān)鍵字this,以及確定和設(shè)置this的值的方法。

概念性的概述this

當(dāng)一個(gè)函數(shù)創(chuàng)建后,一個(gè)關(guān)鍵字this就隨之(在后臺(tái))創(chuàng)建,它鏈接到一個(gè)對(duì)象,而函數(shù)正是在這個(gè)對(duì)象中進(jìn)行操作。換句話說,關(guān)鍵字this可在函數(shù)中使用,是對(duì)一個(gè)對(duì)象的引用,而函數(shù)正是該對(duì)象的屬性或方法。

讓我們來看這個(gè)對(duì)象:

<!DOCTYPE html><html lang="en"><body><script> 
var cody = { 
living:true, 
age:23, 
gender:'male', 
getGender:function(){return cody.gender;} 
}; 
console.log(cody.getGender()); // logs 'male' 
</script></body></html>

注意在函數(shù)getGender里,由于在cody對(duì)象內(nèi)部,我們可以通過.來獲取gender屬性(也就是cody.gender)。也可以用this來獲取cody對(duì)象,因?yàn)閠his正是指向cody對(duì)象。

<!DOCTYPE html><html lang="en"><body><script> 
var cody = { 
living:true, 
age:23, 
gender:'male', 
getGender:function(){return this.gender;} 
}; 
console.log(cody.getGender()); // logs 'male' 
</script></body></html>

this.gender中this指向cody對(duì)象,而getGender函數(shù)可以操作cody對(duì)象。

關(guān)于this的主題可能有點(diǎn)讓人感到困惑,其實(shí)不必如此。僅記住,通常,this指向的對(duì)象正是包含函數(shù)的對(duì)象,而不是函數(shù)本身(當(dāng)然也有例外,例如采用關(guān)鍵字new或者call()和apply())。

重要提示

- 關(guān)鍵字this就像其他的變量,唯一不同就是你不能更改它。

- 不同于傳給函數(shù)的其他參數(shù)和變量,在調(diào)用函數(shù)的對(duì)象中,this是一個(gè)關(guān)鍵字(而不是屬性)。

如何確定this的值?

this傳遞給所有的函數(shù),它的值取決于函數(shù)運(yùn)行時(shí)何時(shí)被調(diào)用。這里請注意,因?yàn)檫@是你需要記住的一個(gè)很特別的地方。

下面的代碼中myObject對(duì)象有個(gè)屬性sayFoo,它指向函數(shù)sayFoo。當(dāng)在全局域中調(diào)用sayFoo函數(shù)時(shí),this指向window對(duì)象。當(dāng)myObject調(diào)用函數(shù)時(shí),this指向的是myObject。

因?yàn)閙yObject有個(gè)叫foo的屬性,在這里被使用。

<!DOCTYPE html><html lang="en"><body><script> 
var foo = 'foo'; 
var myObject = {foo: 'I am myObject.foo'}; 
var sayFoo = function() { 
console.log(this['foo']); 
}; 
// give myObject a sayFoo property and have it point to sayFoo function 
myObject.sayFoo = sayFoo; 
myObject.sayFoo(); // logs 'I am myObject.foo' 12 
sayFoo(); // logs 'foo' 
</script></body></html>

很清楚,this的值取決于函數(shù)什么時(shí)候被調(diào)用。myObject.sayFoo和sayFoo都指向同樣的函數(shù),但sayFoo()調(diào)用的上下文不同,this的值也就不同。下面是類似的代碼,head對(duì)象(window)顯式使用,希望對(duì)你有用。

<!DOCTYPE html><html lang="en"><body><script> 
window.foo = 'foo'; 
window.myObject = {foo: 'I am myObject.foo'}; 
window.sayFoo = function() { ! console.log(this.foo); }; 
window.myObject.sayFoo = window.sayFoo; 
window.myObject.sayFoo(); 
window.sayFoo(); 
</script></body></html>

確保當(dāng)你有多個(gè)引用指向同一個(gè)函數(shù)的時(shí)候,你清楚的知道this的值是隨調(diào)用函數(shù)的上下文的不同而改變。

重要提示

- 除了this以外的所有變量和參數(shù)都屬于靜態(tài)變量范圍(lexical scope)。

在嵌入函數(shù)內(nèi)this指向head對(duì)象

你可能想知道在嵌入在另外一個(gè)函數(shù)的函數(shù)中使用this會(huì)發(fā)生什么事。不幸的是在ECMA 3中,this不遵循規(guī)律,它不指向函數(shù)屬于的對(duì)象,而是指向head對(duì)象(瀏覽器的window對(duì)象)。

在下面的代碼,func2和func3中的this不再指向myObject,而是head對(duì)象。

<!DOCTYPE html><html lang="en"><body><script> 
var myObject = { 
func1:function() { 
console.log(this); //logs myObject 
varfunc2=function() { 
console.log(this); //logs window, and will do so from this point on 
varfunc3=function() { 
console.log(this); //logs window, as it's the head object 
}(); 
}(); 
} 
}; 
myObject.func1(); 
</script></body></html>

然而在ECMAScript 5中,這個(gè)問題將會(huì)得到修正?,F(xiàn)在,你應(yīng)該意識(shí)到這個(gè)問題,尤其是當(dāng)你將一個(gè)函數(shù)的值傳遞到另一個(gè)函數(shù)時(shí)。

看看下面的代碼,將一個(gè)匿名函數(shù)傳給foo.func1,當(dāng)在foo.func1中調(diào)用匿名函數(shù)(函數(shù)嵌套在另一個(gè)函數(shù)中),匿名函數(shù)中this將會(huì)指向是head對(duì)象。

<!DOCTYPE html><html lang="en"><body><script> 
var foo = { 
func1:function(bar){ 
bar(); //logs window, not foo 
console.log(this);//the this keyword here will be a reference to foo object 
} 
}; 
foo.func1(function(){console.log(this)}); 
</script></body></html>

現(xiàn)在你不會(huì)忘了,如果包含this的函數(shù)在另一個(gè)函數(shù)中,或者被另一個(gè)函數(shù)調(diào)用,this的值將會(huì)指向的是head對(duì)象(再說一次,這將在ECMAScript 5中被修正。)

解決嵌套函數(shù)的問題

為了使this的值不丟失,你可以在父函數(shù)中使用一個(gè)作用域鏈(scope chain)來保存對(duì)this進(jìn)行引用。下面的代碼中,使用一個(gè)叫that的變量,利用它的作用域,我們可以更好的保存函數(shù)上下文。

<!DOCTYPE html><html lang="en"><body><script> 
var myObject = { 
myProperty:'Icanseethelight', 
myMethod:function() { 
var that=this; //store a reference to this (i.e.myObject) in myMethod scope varhelperFunctionfunction(){//childfunction 
var helperFunction function() { //childfunction 
//logs 'I can see the light' via scope chain because that=this 
console.log(that.myProperty); //logs 'I can see the light' 
console.log(this); // logs window object, if we don't use "that" 
}(); 
} 
} 
myObject.myMethod(); // invoke myMethod 
</script></body></html>

控制this的值

this的值通常取決于調(diào)用函數(shù)的上下文(除非使用關(guān)鍵字new,稍后會(huì)為你介紹),但是你可以用apply()或call()指定觸發(fā)一個(gè)函數(shù)時(shí)this指向的對(duì)象,以改變/控制this的值。用這兩種方法就好像再說:“嘿,調(diào)用X函數(shù),但讓Z對(duì)象來作this的值?!边@樣做,JavaScript默認(rèn)的this的值將被更改。

下面,我們創(chuàng)建了一個(gè)對(duì)象和一個(gè)函數(shù),然后我們通過call()來觸發(fā)函數(shù),所以函數(shù)中的this指向的是myOjbect。在myFunction函數(shù)中的this會(huì)操作myObject而不是head對(duì)象,這樣我們就改變了在myFunction中this指向的對(duì)象。

<!DOCTYPE html><html lang="en"><body><script> 
var myObject = {}; 
var myFunction = function(param1, param2) { 
//setviacall()'this'points to my Object when function is invoked 
this.foo = param1; 
this.bar = param2; 
console.log(this); //logs Object{foo = 'foo', bar = 'bar'} 
}; 
myFunction.call(myObject, 'foo', 'bar'); // invoke function, set this value to myObject 
console.log(myObject) // logs Object {foo = 'foo', bar = 'bar'} 
</script></body></html>

在上面的例子,我們用了call(),apply()也可適用于同樣用法,二者的不同之處在于參數(shù)如何傳給函數(shù)。用call(),參數(shù)用逗號(hào)分開,而用apply(),參數(shù)放在一個(gè)數(shù)組中傳遞。下面是同樣的代碼,但是用apply()。

<!DOCTYPE html><html lang="en"><body><script> 
var myObject = {}; 
var myFunction = function(param1, param2) { 
//set via apply(), this points to my Object when function is invoked 
this.foo=param1; 
this.bar=param2; 
console.log(this); // logs Object{foo='foo', bar='bar'} 
}; 
myFunction.apply(myObject, ['foo', 'bar']); // invoke function, set this value 
console.log(myObject); // logs Object {foo = 'foo', bar = 'bar'} 
</script></body></html>

在自定義構(gòu)造函數(shù)中用this

當(dāng)函數(shù)用關(guān)鍵字new來觸發(fā),this的值–由于在構(gòu)造函數(shù)中聲明–指向?qū)嵗旧?。換種說法:在構(gòu)造函數(shù)中,我們可以在對(duì)象真正創(chuàng)建之前,就用this來指定對(duì)象。這樣看來,this值的更改和call()或apply()相似。

下面,我們構(gòu)造了一個(gè)構(gòu)造函數(shù)Person,this指向創(chuàng)建的對(duì)象。當(dāng)Person的對(duì)象創(chuàng)建后,this指向這個(gè)對(duì)象,并將屬性name放在對(duì)象內(nèi),值為傳給這個(gè)構(gòu)造函數(shù)的參數(shù)值(name)。

<!DOCTYPE html><html lang="en"><body><script> 
var Person = function(name) { 
this.name = name || 'johndoe'; // this will refer to the instanc ecreated 
} 
var cody = new Person('Cody Lindley'); // create an instance, based on Person constructor 
console.log(cody.name); // logs 'Cody Lindley' 
</script></body></html>

這樣,當(dāng)用關(guān)鍵字new觸發(fā)構(gòu)造函數(shù)時(shí),this指向“要?jiǎng)?chuàng)建的對(duì)象”。那么如果我們沒有用關(guān)鍵字new,this的值將會(huì)指向觸發(fā)Person的上下文——這時(shí)是head對(duì)象。讓我們來看看下面的代碼。

<!DOCTYPE html><html lang="en"><body><script> 
var Person = function(name) { 
this.name=name||'johndoe'; 
} 
var cody = Person('Cody Lindley'); // notice we did not use 'new' 
console.log(cody.name); // undefined, the value is actually set at window.name 
console.log(window.name); // logs 'Cody Lindley' 
</script></body></html>

在prototype方法內(nèi)的this指向構(gòu)造實(shí)例

當(dāng)一個(gè)方法作為一個(gè)構(gòu)造函數(shù)的prototype屬性時(shí),這個(gè)方法中的this指向觸發(fā)方法的實(shí)例。這里,我們有一個(gè)Person()的構(gòu)造函數(shù),它需要person的全名(full name),為了獲得全名(full name),我們在Person.prototype中加入了一個(gè)whatIsMyFullName方法,所有的Person實(shí)例都繼承該方法。這個(gè)方法中的this指向觸發(fā)這個(gè)方法的實(shí)例(以及它的屬性)。

下面我創(chuàng)建了兩個(gè)Person對(duì)象(cody和lisa),繼承的whatIsMyFullName方法包含的this就指向這個(gè)實(shí)例。

<!DOCTYPE html><html lang="en"><body><script> 
var Person = function(x){ 
if(x){this.fullName = x}; 
}; 
Person.prototype.whatIsMyFullName = function() { 
return this.fullName; // 'this' refers to the instance created from Person() 
} 
var cody = new Person('cody lindley'); 
var lisa = new Person('lisa lindley'); 
// call the inherited whatIsMyFullName method, which uses this to refer to the instance 
console.log(cody.whatIsMyFullName(), lisa.whatIsMyFullName()); 
/* The prototype chain is still in effect, so if the instance does not have a 
fullName property, it will look for it in the prototype chain. 
Below, we add a fullName property to both the Person prototype and the Object 
prototype. See notes. */
Object.prototype.fullName = 'John Doe'; 
var john = new Person(); // no argument is passed so fullName is not added to instance 
console.log(john.whatIsMyFullName()); // logs 'John Doe' 
</script></body></html>

在prototype對(duì)象內(nèi)的方法里使用this,this就指向?qū)嵗?。如果?shí)例不包含屬性的話,prototype查找便開始了。

提示

- 如果this指向的對(duì)象不包含想要查找的屬性,那么這時(shí)對(duì)于任何屬性都適用的法則在這里也適用,也就是,屬性會(huì)沿著prototype鏈(prototype chain)上“尋找”。所以在我們的例子中,如果實(shí)例中不包含fullName屬性,那么fullName就會(huì)查找Person.prototype.fullName,然后是Object.prototype.fullName。

查看更多JavaScript的語法,大家可以關(guān)注:《JavaScript 參考教程》、《JavaScript代碼風(fēng)格指南》,也希望大家多多支持腳本之家。

相關(guān)文章

  • HTTP 304錯(cuò)誤的詳細(xì)講解

    HTTP 304錯(cuò)誤的詳細(xì)講解

    以下就是我對(duì)HTTP 304的一個(gè)理解。需要的朋友可以過來參考下,希望對(duì)大家有所幫助
    2013-11-11
  • ES6基礎(chǔ)語法之函數(shù)介紹

    ES6基礎(chǔ)語法之函數(shù)介紹

    這篇文章介紹了ES6中函數(shù)的用法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-05-05
  • 關(guān)于cookie的初識(shí)和運(yùn)用(js和jq)

    關(guān)于cookie的初識(shí)和運(yùn)用(js和jq)

    下面小編就為大家?guī)硪黄P(guān)于cookie的初識(shí)和運(yùn)用(js和jq)。小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧,祝大家游戲愉快哦
    2016-04-04
  • JavaScript數(shù)據(jù)類型詳解

    JavaScript數(shù)據(jù)類型詳解

    這篇文章主要介紹了JavaScript數(shù)據(jù)類型詳解,本文詳細(xì)講解了JavaScript中有5種基本數(shù)據(jù)類型:Undefined、Null、Boolean、Number和String,需要的朋友可以參考下
    2015-04-04
  • 簡介JavaScript中setUTCSeconds()方法的使用

    簡介JavaScript中setUTCSeconds()方法的使用

    這篇文章主要介紹了簡介JavaScript中setUTCSeconds()方法的使用,是JS入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-06-06
  • uniapp父子組件傳值3種方法(props、slot和ref)

    uniapp父子組件傳值3種方法(props、slot和ref)

    這篇文章主要給大家介紹了關(guān)于uniapp父子組件傳值的3種方法,方法包括props、slot和ref,最近看到uniapp組件傳值的方法,這里記錄一下,需要的朋友可以參考下
    2023-07-07
  • 淺析函數(shù)聲明和函數(shù)表達(dá)式——函數(shù)聲明的聲明提前

    淺析函數(shù)聲明和函數(shù)表達(dá)式——函數(shù)聲明的聲明提前

    下面小編就為大家?guī)硪黄獪\析函數(shù)聲明和函數(shù)表達(dá)式——函數(shù)聲明的聲明提前。小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。
    2016-05-05
  • BOM與DOM的區(qū)別分析

    BOM與DOM的區(qū)別分析

    DHTML技術(shù)各項(xiàng)功能的實(shí)現(xiàn)都依賴于使用客戶端腳本與瀏覽器宿主及在宿主中輸出的Web頁面之間的交互,這種交互是通過對(duì)象這個(gè)技術(shù)手段實(shí)現(xiàn)的。
    2010-10-10
  • JavaScript數(shù)據(jù)類型轉(zhuǎn)換

    JavaScript數(shù)據(jù)類型轉(zhuǎn)換

    本文詳細(xì)講解了JavaScript實(shí)現(xiàn)數(shù)據(jù)類型轉(zhuǎn)換的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-03-03
  • JavaScript中的正則表達(dá)式簡明總結(jié)

    JavaScript中的正則表達(dá)式簡明總結(jié)

    這篇文章主要介紹了JavaScript中的正則表達(dá)式,簡明總結(jié)了正則中的語法含義和RegExp對(duì)象,需要的朋友可以參考下
    2014-04-04

最新評(píng)論