JavaScript 對象與傳統的面向對象中的對象幾乎沒有相似之處,傳統的面向對象語言中,創建一個對象必須先有對象的模板:類,類中定義了對象的屬性和操作這些屬性的方法。通過實例化來構筑一個對象,然后使用對象間的協作來完成一項功能,通過功能的集合來完成整個工程。而Javascript 中是沒有類的概念的,借助JavaScript 的動態性,我們完全可以創建一個空的對象( 而不是類) ,通過像對象動態的添加屬性來完善對象的功能。
JSON 是JavaScript 中對象的字面量,是對象的表示方法,通過使用JSON ,可以減少中間變量,使代碼的結構更加清晰,也更加直觀。使用JSON ,可以動態的構建對象,而不必通過類來進行實例化,大大的提高了編碼的效率。
3.1 Javascript 對象
JavaScript 對象其實就是屬性的集合,這里的集合與數學上的集合是等價的,即具有確定性,無序性和互異性,也就是說,給定一個JavaScript 對象,我們可以明確的知道一個屬性是不是這個對象的屬性,對象中的屬性是無序的,并且是各不相同的( 如果有同名的,則后聲明的覆蓋先聲明的) 。
一般來說,我們聲明對象的時候對象往往只是一個空的集合,不包含任何的屬性,通過不斷的添加屬性,使得該對象成為一個有完整功能的對象,而不用通過創建一個類,然后實例化該類這種模式,這樣我們的代碼具有更高的靈活性,我們可以任意的增刪對象的屬性。
如果讀者有python 或其他類似的動態語言的經驗, 就可以更好的理解JavaScript 的對象,JavaScript 對象的本身就是一個字典(dictionary) ,或者Java 語言中的Map ,或者稱為關聯數組,即通過鍵來關聯一個對象,這個對象本身又可以是一個對象,根據此定義,我們可以知道JavaScript 對象可以表示任意復雜的數據結構。
3.1.1 對象的屬性
屬性是由鍵值對組成的,即屬性的名字和屬性的值。屬性的名字是一個字符串,而值可以為任意的JavaScript 對象(JavaScript 中的一切皆對象,包括函數) 。比如,聲明一個對象:
?
Js代碼
?? var ?jack?=?new ?Object(); ??jack.name?=?"jack" ; ?? jack.age?=?26; ?? jack.birthday?=?new ?Date(1984,?4,?5); ?? ? ?? ?? var ?address?=?new ?Object(); ??address.street?=?"Huang?Quan?Road" ; ?? address.xno?=?"135" ; ?? ? ?? ?? jack.addr?=?address;??
//聲明一個對象
var jack = new Object();
jack.name = "jack";
jack.age = 26;
jack.birthday = new Date(1984, 4, 5);//聲明另一個對象
var address = new Object();
address.street = "Huang Quan Road";
address.xno = "135";//將addr屬性賦值為對象address
jack.addr = address;
?
?
?
這種聲明對象的方式與傳統的OO 語言是截然不同的,它給了我們極大的靈活性來定制一個對象的行為。
?
對象屬性的讀取方式是通過點操作符(.) 來進行的,比如上例中jack 對象的addr 屬性,可以通過下列方式取得:
?
?
?
?
后者是為了避免這種情況,設想對象有一個屬性本身包含一個點(.) ,這在JavaScript 中是合法的,比如說名字為foo.bar ,當使用jack.foo.bar 的時候,解釋器會誤以為foo 屬性下有一個bar 的字段,因此可以使用jack[foo.bar] 來進行訪問。通常來說,我們在開發通用的工具包時,應該對用戶可能的輸入不做任何假設,通過[ 屬性名] 這種形式則總是可以保證正確性的。
3.1.2 屬性與變量
在第二章,我們講解了變量的概念,在本章中,讀者可能已經注意到,這二者的行為非常相似,事實上,對象的屬性和我們之前所說的變量其實是一回事。
JavaScript 引擎在初始化時,會構建一個全局對象,在客戶端環境中,這個全局對象即為window 。如果在其他的JavaScript 環境中需要引用這個全局對象,只需要在頂級作用域( 即所有函數聲明之外的作用域) 中聲明:
?
?
?
?
我們在頂級作用域中聲明的變量將作為全局對象的屬性被保存,從這一點上來看,變量其實就是屬性。比如,在客戶端,經常會出現這樣的代碼:
?
?
?
?
事實上相當于:
?
Js代碼
window.v?=?"global" ; ?? ? ?? window.array?=?["hello" ,?"world" ]; ?? ? ?? window.func?=?function (id){ ?? ????var ?element?=?document.getElementById(id); ?? ?????? }??
window.v = "global";window.array = ["hello", "world"];window.func = function(id){var element = document.getElementById(id);//對elemen做一些操作
}
?
?
?
3.1.3 原型對象
原型(prototype) ,是JavaScript 特有的一個概念,通過使用原型,JavaScript 可以建立其傳統OO 語言中的繼承,從而體現對象的層次關系。JavaScript 本身是基于原型的,每個對象都有一個prototype 的屬性來,這個prototype 本身也是一個對象,因此它本身也可以有自己的原型,這樣就構成了一個鏈結構。
訪問一個屬性的時候,解析器需要從下向上的遍歷這個鏈結構,直到遇到該屬性,則返回屬性對應的值,或者遇到原型為null 的對象(JavaScript 的基對象Object 的prototype 屬性即為null) ,如果此對象仍沒有該屬性,則返回undefined.
下面我們看一個具體的例子:
?
Js代碼
?? function ?Base(name){ ??????this .name?=?name; ?? ????this .getName?=?function (){ ?? ???????return ?this .name; ?? ????} ?? } ?? ? ?? ?? function ?Child(id){ ??????this .id?=?id; ?? ????this .getId?=?function (){ ?? ???????return ?this .id;?? ?? ????} ?? } ?? ? ?? ?? Child.prototype?=?new ?Base("base" ); ?? ? ?? ?? var ?c1?=?new ?Child("child" ); ??? ?? ?? print(c1.getId()); ?? ?? print(c1.getName());??
//聲明一個對象base
function Base(name){this.name = name;this.getName = function(){return this.name;}
}//聲明一個對象child
function Child(id){this.id = id;this.getId = function(){return this.id; }
}//將child的原型指向一個新的base對象
Child.prototype = new Base("base");//實例化一個child對象
var c1 = new Child("child");//c1本身具有getId方法
print(c1.getId());
//由于c1從原型鏈上"繼承"到了getName方法,因此可以訪問
print(c1.getName());
?
?
?
得出結果:
?
child
base
?
?
?
由于遍歷原型鏈的時候,是有下而上的,所以最先遇到的屬性值最先返回,通過這種機制可以完成重載的機制。
?
3.1.4 this 指針
???????? JavaScript 中最容易使人迷惑的恐怕就數this 指針了,this 指針在傳統OO 語言中,是在類中聲明的,表示對象本身,而在JavaScript 中,this 表示當前上下文,即調用者的引用。這里我們可以來看一個常見的例子:
?
Js代碼
?? var ?jack?=?{ ??????name?:?"jack" , ?? ????age?:?26 ?? } ?? ? ?? ?? var ?abruzzi?=?{ ??????name?:?"abruzzi" , ?? ????age?:?26 ?? } ?? ? ?? ?? function ?printName(){ ??????return ?this .name; ?? } ?? ? ?? ?? print(printName.call(jack)); ?? ?? print(printName.call(abruzzi));??
//定義一個人,名字為jack
var jack = {name : "jack",age : 26
}//定義另一個人,名字為abruzzi
var abruzzi = {name : "abruzzi",age : 26
}//定義一個全局的函數對象
function printName(){return this.name;
}//設置printName的上下文為jack, 此時的this為jack
print(printName.call(jack));
//設置printName的上下文為abruzzi,此時的this為abruzzi
print(printName.call(abruzzi));
?
?
?
運行結果:
?
jack
Abruzzi
?
?
?
應該注意的是,this 的值并非函數如何被聲明而確定,而是被函數如何被調用而確定,這一點與傳統的面向對象語言截然不同,call 是Function 上的一個函數,詳細描述在第四章。
3.2 使用對象
對象是JavaScript 的基礎,我們使用JavaScript 來完成編程工作就是通過使用對象來體現的,這一小節通過一些例子來學習如何使用JavaScript 對象:
對象的聲明有三種方式:
?
?? 通過new 操作符作用域Object 對象,構造一個新的對象,然后動態的添加屬性,從無到有的構筑一個對象。
?? 定義對象的“類”: 原型,然后使用new 操作符來批量的構筑新的對象。
?? 使用JSON ,這個在下一節來進行詳細說明
?
這一節我們詳細說明第二種方式,如:
?
Js代碼
?? function ?Address(street,?xno){ ??????this .street?=?street?||?'Huang?Quan?Road' ; ?? ????this .xno?=?xno?||?135; ?? ????this .toString?=?function (){ ?? ???????return ?"street?:?" ?+?this .street?+?",?No?:?" ?+?this .xno;??? ?? ????} ?? } ?? ? ?? ?? function ?Person?(name,?age,?addr)?{ ????this .name?=?name?||?'unknown' ; ?? ??this .age?=?age; ?? ??this .addr?=?addr?||?new ?Address(null ,?null ); ?? ??this .getName?=?function ?()?{return ?this .name;} ?? ??this .getAge?=?function (){return ?this .age;} ?? ??this .getAddr?=?function (){return ?this .addr.toString();} ?? } ?? ? ?? ?? var ?jack?=?new ?Person('jack' ,?26,?new ?Address('Qing?Hai?Road' ,?123)); ??var ?abruzzi?=?new ?Person('abruzzi' ,?26); ??? ?? ?? print(jack.getName()); ?? print(jack.getAge()); ?? print(jack.getAddr()); ?? ? ?? print(abruzzi.getName()); ?? print(abruzzi.getAge()); ?? print(abruzzi.getAddr());??
//定義一個"類",Address
function Address(street, xno){this.street = street || 'Huang Quan Road';this.xno = xno || 135;this.toString = function(){return "street : " + this.street + ", No : " + this.xno; }
}//定義另一個"類",Person
function Person (name, age, addr) {this.name = name || 'unknown';this.age = age;this.addr = addr || new Address(null, null);this.getName = function () {return this.name;}this.getAge = function(){return this.age;}this.getAddr = function(){return this.addr.toString();}
}//通過new操作符來創建兩個對象,注意,這兩個對象是相互獨立的實體
var jack = new Person('jack', 26, new Address('Qing Hai Road', 123));
var abruzzi = new Person('abruzzi', 26);//查看結果
print(jack.getName());
print(jack.getAge());
print(jack.getAddr());print(abruzzi.getName());
print(abruzzi.getAge());
print(abruzzi.getAddr());
?
?
?
運行結果如下:
?
jack
26
street : Qing Hai Road, No : 123
abruzzi
26
street : Huang Quan Road, No : 135
?
?
3.3 JSON 及其使用
JSON 全稱為JavaScript 對象表示法(JavaScript Object Notation) ,即通過字面量來表示一個對象,從簡單到復雜均可使用此方式。比如:
?
?
?
?
這種方式,顯然比上邊的例子簡潔多了,沒有冗余的中間變量,很清晰的表達了obj 這樣一個對象的結構。事實上,大多數有經驗的JavaScript 程序員更傾向與使用這種表示法,包括很多JavaScript 的工具包如jQuery ,ExtJS 等都大量的使用了JSON 。JSON 事實上已經作為一種前端與服務器端的數據交換格式,前端程序通過Ajax 發送JSON 對象到后端,服務器端腳本對JSON 進行解析,還原成服務器端對象,然后做一些處理,反饋給前端的仍然是JSON 對象,使用同一的數據格式,可以降低出錯的概率。
???????? 而且,JSON 格式的數據本身是可以遞歸的,也就是說,可以表達任意復雜的數據形式。JSON 的寫法很簡單,即用花括號括起來的鍵值對,鍵值對通過冒號隔開,而值可以是任意的JavaScript 對象,如簡單對象String ,Boolean ,Number ,Null ,或者復雜對象如Date ,Object ,其他自定義的對象等。
???????? JSON 的另一個應用場景是:當一個函數擁有多個返回值時,在傳統的面向對象語言中,我們需要組織一個對象,然后返回,而JavaScript 則完全不需要這么麻煩,比如:
?
?
?
?
直接動態的構建一個新的匿名對象返回即可:
?
?
?
?
使用JSON 返回對象,這個對象可以有任意復雜的結構,甚至可以包括函數對象。
在實際的編程中,我們通常需要遍歷一個JavaScript 對象,事先我們對對象的內容一無所知。怎么做呢?JavaScript 提供了for..in 形式的語法糖:
?
?
?
?
這種模式十分有用,比如,在實際的WEB 應用中,對一個頁面元素需要設置一些屬性,這些屬性是事先不知道的,比如:
?
?
?
?
然后,我們給一個DOM 元素動態的添加這些屬性:
?
?
?
?
當然,jQuery 有更好的辦法來做這樣一件事,這里只是舉例子,應該注意的是,我們在給$("div#element") 添加屬性的時候,我們對style 的結構是不清楚的。
?
另外比如我們需要收集一些用戶的自定義設置,也可以通過公開一個JSON 對象,用戶將需要設置的內容填入這個JSON ,然后我們的程序對其進行處理。
?
Js代碼
function ?customize(options){ ??????this .settings?=?$.extend(default ,?options); ?? }??
function customize(options){this.settings = $.extend(default, options);
}
?
Js代碼
for (var ?item?in ?style){ ???????? ????$("div#element" ).css(item,?style[item]); ?? }??
for(var item in style){//使用jQuery的選擇器$("div#element").css(item, style[item]);
}
?
Js代碼
var ?style?=?{ ??????border:"1px?solid?#ccc" , ?? ????color:"blue" ?? };??
var style = {border:"1px solid #ccc",color:"blue"
};
?
Js代碼
for (var ?item?in ?json){ ???????? ?????? }??
for(var item in json){//item為鍵//json[item]為值
}
?
Js代碼
var ?pos?=?point(3,?4); ???? ??
var pos = point(3, 4);
//pos.x = 3;
//pos.y = 4;
?
Js代碼
function ?point(left,?top){ ??????this .left?=?left; ?? ????this .top?=?top; ?? ?????? ????return ?{x:?this .left,?y:this .top}; ?? }??
function point(left, top){this.left = left;this.top = top;//handle the left and topreturn {x: this.left, y:this.top};
}
?
Js代碼
var ?obj?=?{ ??????name?:?"abruzzi" , ?? ????age?:?26, ?? ????birthday?:?new ?Date(1984,?4,?5), ?? ????addr?:?{ ?? ???????street?:?"Huang?Quan?Road" , ?? ???????xno?:?"135" ?? ????} ?? }??
var obj = {name : "abruzzi",age : 26,birthday : new Date(1984, 4, 5),addr : {street : "Huang Quan Road",xno : "135"}
}
?
Js代碼
var ?v?=?"global" ; ??? ?? var ?array?=?["hello" ,?"world" ]; ??? ?? function ?func(id){ ??????var ?element?=?document.getElementById(id); ?? ?????? }??
var v = "global";var array = ["hello", "world"];function func(id){var element = document.getElementById(id);//對elemen做一些操作
}
?
Js代碼
var ?global?=?this ;??
var global = this;
?
Js代碼
var ?ja?=?jack.addr; ??? ?? ja?=?jack[addr];??
var ja = jack.addr;ja = jack[addr];
?
總結
以上是生活随笔 為你收集整理的第三章 对象与JSON 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。