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

JavaScript高級程序設(shè)計(jì)(第3版)學(xué)習(xí)筆記6 初識js對象

 更新時(shí)間:2012年10月11日 14:33:06   作者:  
砌好墻,下面出場的就是房子了,在ECMAScript中,對象就是我們所說的房子,至于你所寫的整個(gè)應(yīng)用程序,那就是一整套建筑群了
在房子里面可以放你想放的任意事物——如果你有足夠的美學(xué)造詣,你甚至可以弄一個(gè)房中房試試——當(dāng)然,為了方便管理,我們會(huì)給房子里存放的所有事物都會(huì)取上一個(gè)不重復(fù)的名字,比如醫(yī)藥房間里的各種藥品名稱。在ECMAScript中,你可以在對象中存放任意你想放的數(shù)據(jù),同樣,我們需要給存放的數(shù)據(jù)取一個(gè)名字——也就是對象的屬性名,再存放各種數(shù)據(jù)。再看看ECMA-262中對象的定義:無序?qū)傩缘募?,其屬性可以包含簡單?shù)據(jù)類型值、對象或者函數(shù)。

  進(jìn)入對象,我開始有些激動(dòng)了,說實(shí)話,讓我想起做這系列學(xué)習(xí)筆記的最初原因,就是因?yàn)樵摃鴮ο蟮纳羁陶撌?,讓我對JavaScript的認(rèn)知從客戶端驗(yàn)證小工具轉(zhuǎn)變成一門強(qiáng)大的面向?qū)ο竽_本語言,但我現(xiàn)在也有點(diǎn)犯難了,因?yàn)殛P(guān)于對象,有太多太多的東西需要去細(xì)化,一時(shí)也不知該從哪個(gè)點(diǎn)切入,比如要想深入理解對象,作用域、執(zhí)行環(huán)境、閉包這些概念是肯定離不開的,但如果連對象的概念都沒說就開始執(zhí)行環(huán)境和閉包,又感覺像是空中樓閣。不過又一想,也就釋然了,這畢竟只是自己的個(gè)人學(xué)習(xí)筆記,又不是什么教科書,我大可以使用自己喜歡的方式來做自己的筆記(事實(shí)上,在前面的篇章中,我就有意識的重復(fù)那些我認(rèn)為有意思的地方,這就是我喜歡的一種方式),當(dāng)然,我還是會(huì)盡量以一種易于理解的方式來做這些筆記。

對象類型

  和5種簡單數(shù)據(jù)類型(Undefined、Null、Boolean、Number、String)相對應(yīng),對象(Object)也是一種數(shù)據(jù)類型,只是這種數(shù)據(jù)類型比較特別,它不但可以像簡單數(shù)據(jù)類型一樣存取通常的數(shù)據(jù),而且可以將動(dòng)作行為作為一種特殊的數(shù)據(jù)加以存取。

1、對象實(shí)例

  每種數(shù)據(jù)類型都有相應(yīng)的值,比如Undefined類型只有一個(gè)值undefined,而數(shù)字5是Number類型的一個(gè)值。對于對象類型,我們把值稱為對象實(shí)例,那么對象類型都可以有哪些(值)實(shí)例呢?任意一個(gè)對象都是對象類型的值(實(shí)例),比如簡單類型包裝對象(Boolean、Number、String)就是對象類型的值(實(shí)例)。

2、對象字面量

  既然任意一個(gè)對象都是對象類型的實(shí)例,那么對象實(shí)例怎么表示呢?或者說我們在交流過程中怎么書寫出對象實(shí)例呢?簡單數(shù)據(jù)類型的值很好表示,比如用符號“5”表示數(shù)字5,符號“true”表示Boolean值true,這些被稱為字面量,那么,有沒有對象字面量呢?答案是肯定的,對象字面量就是通過一對大括號({})來表示的。比如:
復(fù)制代碼 代碼如下:

{
name:'linjisong',
getName:function(){
return this.name;
}
}

這里最外層的一對大括號({})就表示這是一個(gè)對象字面量。另外,還有數(shù)組字面量的概念,在ECMAScript中,數(shù)組Array是一個(gè)繼承了Object的對象實(shí)例,通過這個(gè)對象實(shí)例可以創(chuàng)建數(shù)組類型的實(shí)例,數(shù)組類型的實(shí)例也可以直接通過數(shù)組字面量來表示,方法如下:
復(fù)制代碼 代碼如下:

[{
name:'linjisong',
age:29
},{
name:'oulinhai',
age:23
}]

這里一對中括號([])用于表示數(shù)組,這是一個(gè)包含了兩個(gè)對象的數(shù)組。通過對象字面量和數(shù)組字面量,形成了難以想象的強(qiáng)大表現(xiàn)力,事實(shí)上,流行的JSON數(shù)據(jù)格式就是基于此。

3、創(chuàng)建對象實(shí)例

  熟悉一般面向?qū)ο蟮呐笥讯贾?,要?jiǎng)?chuàng)建一個(gè)類的實(shí)例,首先要定義這個(gè)類,然后用new關(guān)鍵字來創(chuàng)建這個(gè)類的實(shí)例(別和我說還可以使用反射,我的Java可學(xué)的不好……)。但是在ECMAScript中,根本沒有類的概念,那么,對象實(shí)例要怎么創(chuàng)建呢?

  在ECMAScript中盡管沒有類,但是也有某種程度上類似的概念,承擔(dān)這個(gè)角色的就是函數(shù),可以通過new操作符和函數(shù)來創(chuàng)建對象實(shí)例——每一個(gè)對象實(shí)例都有一個(gè)用于創(chuàng)建這個(gè)實(shí)例的函數(shù)。最基本的函數(shù)就是Object(),它是用來創(chuàng)建最一般對象的函數(shù),其它的諸如Number()函數(shù),可以用來創(chuàng)建Number對象的實(shí)例,Boolean()函數(shù),可以用來創(chuàng)建Boolean對象的實(shí)例:
復(fù)制代碼 代碼如下:

var obj = new Object();//Object()函數(shù),創(chuàng)建最一般的對象實(shí)例
var num = new Number(1);//Number()函數(shù),創(chuàng)建Number對象的實(shí)例
var boo = new Boolean(true);//Boolean()函數(shù),創(chuàng)建Boolean對象的實(shí)例
console.info(typeof num);//object
console.info(typeof Number(1));//number
console.info(typeof boo);//object
console.info(typeof Boolean(true));//boolean

(1)可以看到,要?jiǎng)?chuàng)建一個(gè)對象實(shí)例,首先需要有一個(gè)函數(shù)(稱為構(gòu)造函數(shù)),這個(gè)函數(shù)使用new調(diào)用時(shí)就是創(chuàng)建對象實(shí)例,不使用new時(shí)只是通常意義上的函數(shù)調(diào)用(如果這個(gè)函數(shù)在內(nèi)部返回實(shí)例了,函數(shù)調(diào)用也可以創(chuàng)建對象)。

(2)所謂的內(nèi)置對象實(shí)際上也就是內(nèi)置了一些創(chuàng)建對象實(shí)例的函數(shù)而已,不同的函數(shù)創(chuàng)建不同的內(nèi)置對象。

(3)關(guān)于要不要使用new操作符,我的建議是使用,如果不使用new操作符,有些情況下結(jié)果會(huì)出乎你的意料之外,像上例中的第5、7行,實(shí)際上并沒有創(chuàng)建對象,而只是普通的函數(shù)調(diào)用,這個(gè)調(diào)用的作用就是轉(zhuǎn)換數(shù)據(jù)類型。

(4)使用new創(chuàng)建對象實(shí)例時(shí),如果調(diào)用構(gòu)造函數(shù)不需要傳入?yún)?shù),也可以省略后面的函數(shù)調(diào)用操作符(()),當(dāng)然,這種特性也不是什么值得宣揚(yáng)的事情。

(5)如果需要?jiǎng)?chuàng)建自定義對象的實(shí)例,那么首先也需要定義一個(gè)構(gòu)造函數(shù),然后使用new操作符調(diào)用創(chuàng)建實(shí)例。這里需要注意,如果忘了new的話,可能會(huì)污染全局環(huán)境:
復(fù)制代碼 代碼如下:

function Person(){//首先定義一個(gè)用于創(chuàng)建對象實(shí)例的(構(gòu)造)函數(shù)
this.name = 'linjisong';
this.age = 29;
}

var person = new Person();//調(diào)用(構(gòu)造)函數(shù)創(chuàng)建對象實(shí)例
console.info(person.age);//29

try{
console.info(age);//為了演示忘記使用new的情況,這里先輸出全局的age,由于未定義,拋出異常
}catch(e){
console.info(e);//ReferenceError
}
var person2 = Person();//忘記使用new的情況下,只是普通的函數(shù)調(diào)用,由于函數(shù)沒有返回,這里person2就是undefined了
console.info(person2);//undefined
console.info(age);//29,沒有使用new,內(nèi)部的this指向了全局作用域,因?yàn)榭梢栽谌衷L問age了

要避免這種問題,可以修改一下構(gòu)造函數(shù):
復(fù)制代碼 代碼如下:

function Person(){
if(this instanceof Person)
{
this.name = 'linjisong';
this.age = 29;
}else{
return new Person();
}
}
var person2 = Person();
console.info(person2.age);//29,可以訪問person2的age了
console.info(age);//全局環(huán)境中沒有age的定義了,拋出異常


這個(gè)構(gòu)造函數(shù)首先判斷this值是否為Person類型,如果不是,就在內(nèi)部使用new調(diào)用,以確保返回的值一定是Person類型實(shí)例。這種方式使得重構(gòu)構(gòu)造函數(shù)成為了可能,也許Boolean()、Number()、String()在實(shí)現(xiàn)上就是使用了這種方式來區(qū)分是構(gòu)造函數(shù)還是轉(zhuǎn)換函數(shù)。如果你在調(diào)用Object()時(shí)省略new的話,結(jié)果也能返回對象,估計(jì)也是在后臺(tái)做了類似處理,同樣的情況還有本文后部分要講的函數(shù)類型構(gòu)造函數(shù)Function()。

(5)可能有人會(huì)問,既然有對象字面量,何必要用這么復(fù)雜的方式來創(chuàng)建對象實(shí)例呢,直接寫對象字面量不就完了?用對象字面量創(chuàng)建對象實(shí)例,根本沒有使用什么函數(shù),看來,上面的“每一個(gè)對象實(shí)例都有一個(gè)用于創(chuàng)建這個(gè)實(shí)例的函數(shù)”的說法并不正確。

  首先第一個(gè)問題,的確,可以使用對象字面量來創(chuàng)建函數(shù),而且也非常簡潔,這甚至也是我首先推薦的一種創(chuàng)建方式,但是用這種方式創(chuàng)建對象實(shí)例,只能創(chuàng)建單例的實(shí)例,對于需要?jiǎng)?chuàng)建多個(gè)相同類型的對象實(shí)例來說并不適用,然后第二個(gè)問題,用對象字面量創(chuàng)建對象,實(shí)際上并不是沒有相應(yīng)的構(gòu)造函數(shù),只是構(gòu)造函數(shù)為Object(),使用對象字面量,后臺(tái)可能不會(huì)去調(diào)用new Object(),但創(chuàng)建出的對象仍然有指向這個(gè)函數(shù)的屬性,這可以從下面代碼輸出中得到驗(yàn)證:
復(fù)制代碼 代碼如下:

var person = {};
console.info(person.constructor===Object);//true

這里的constructor是每個(gè)實(shí)例對象都有的一個(gè)屬性,用于保存創(chuàng)建這個(gè)對象實(shí)例的函數(shù),這就是下面要講的。

4、對象屬性和方法

  每一種數(shù)據(jù)類型都有各自的共性,比如Number類型值都有可以和另外一個(gè)Number類型值相加的特性,同樣,對象類型的實(shí)例也有一些相同的特性,這些特性就體現(xiàn)在它們都包含下面的屬性和方法(方法實(shí)際上也是一種屬性,只是屬性的值類型是函數(shù)的話,我們也稱之為方法):

類別 屬性/方法 說明
屬性 constructor 指向用于創(chuàng)建當(dāng)前對象的函數(shù)
方法 hasOwnProperty(propertyName) 檢查給定的屬性是否在當(dāng)前對象實(shí)例中
propertyIsEnumerable(propertyName) 檢查給定的屬性是否能夠是使用for-in語句來枚舉
isPrototype(object) 檢查傳入的對象是否是另一個(gè)對象的原型
toLocalString() 返回對象的字符串表示,該字符串與執(zhí)行環(huán)境的地區(qū)相對應(yīng)
toString() 返回對象的字符串表示
valueOf() 返回對象的字符串、數(shù)值或布爾值表示,通常與toString()方法返回值相同

注:在《JavaScript高級程序設(shè)計(jì)(第3版)》第35頁中的Constructor將首字母大寫了,應(yīng)該是一個(gè)印刷錯(cuò)誤。

屬性和方法的訪問有兩種方式:

(1)使用點(diǎn)號(.):如person.name。

(2)使用方括號([]):如person[name],使用這種方式,方括號內(nèi)部可以是一個(gè)變量或者表達(dá)式,這使得可以訪問名稱包含特殊符號的屬性和方法。

  通過結(jié)合for-in和這里的hasOwnProperty (propertyName),我們就可以遍歷對象實(shí)例自身的屬性而不包括從原型鏈繼承而來的屬性了:
復(fù)制代碼 代碼如下:

for(var propertyName in object){
  if(object.hasOwnPorperty(propertyName)){
    //循環(huán)處理
  }
}

相關(guān)文章

最新評論