參考資料
JavaScript高級程序設(shè)計(第3版)
一、理解對象
( 一)對象屬性的分類
JS對象屬性有兩種類型:數(shù)據(jù)屬性和訪問器屬性
1、數(shù)據(jù)屬性
數(shù)據(jù)類型有四個描述其行為的特性:
- [[Configurable]] : 表示能否通過delete刪除屬性、能否修改屬性的特性(改為訪問器屬性),默認值為true。
- [[Enumerable]]:是否可(通過for-in)枚舉,默認值為true。
- [[Writable]]:表示能否修改屬性的值,默認值為true。
- [[Value]]:包含這個屬性的數(shù)據(jù)值,默認值為undefined。
2、訪問器屬性
訪問器屬性有如下4個特性:
- [[Configurable]]:同上。
- [[Enumerable]]:同上。
- [[Get]:在讀取屬性時調(diào)用的函數(shù),默認值為undefined。
- [[Set]:在寫入屬性時調(diào)用的函數(shù),默認值為undefined。
(二)定義或修改對象屬性
1、定義或修改數(shù)據(jù)屬性
- [[Value]]可直接定義,而[[Configurable]] 、 [[Enumerable]]和[[Writable]]只能利用方法Object.definedProperty( )或Object.definedProperties( )修改默認的特性。
- 一旦調(diào)用方法Object.definedProperty( )或Object.definedProperties( ),若不指定,[[Configurable]] 、 [[Enumerable]]和[[Writable]]的值都改為false。
Object.definedProperty()和Object.definedProperties()是 ES5(ECMAScript5)特有的,部分瀏覽器不兼容。
2、定義或修改訪問器屬性
訪問器屬性不能直接定義,必須使用Object.definedProperty( )來定義。
(三)讀取屬性的特性
利用Object.getOwnPropertyDescriptor(obj,property)讀取指定對象obj的屬性property的值。
二、創(chuàng)建對象
JavaScript中可以使用以下7種模式來創(chuàng)建對象,其中“組合使用構(gòu)造函數(shù)模式和原型模式”使用最廣泛、認同度最高。
(一) 工廠模式
function createStudent(name,country){
var o=new Object();
o.name=name;
o.country=country;
o.sayName=function(){
alert(this.name);
};
return o;
}
var student1=createStudent("evelyn","China");
缺點:沒有解決對象識別的問題。
(二)構(gòu)造函數(shù)模式
function Student(name,country){
this.name=name;
this.country=country;
this.sayName=sayName;
}
function sayName{
alert(this.name);
}
var student1=new Student("evelyn","China");//student1既是Student的實例,也是Object的實例
1、關(guān)于構(gòu)造函數(shù)
構(gòu)造函數(shù)命名必須首字母大寫,而非構(gòu)造函數(shù)應(yīng)該以一個小寫字母開頭。
2、缺點
對象的方法是全局的函數(shù),但卻只被某個對象調(diào)用。另外,如果某個對象有很多方法,就要定義許多全局函數(shù),毫無封裝性可言。
(三) 原型模式
function Student(){
}
Student.prototype={
constructor:Student,
name:"evelyn",
country:"China",
sayName:function(){
alert(this.name);
}
};
var student1=new Student();
1、關(guān)于原型
- hasOwnProperty()用于檢測一個屬性是否存在于實例中,可用于區(qū)分實例屬性和繼承原型的屬性。
- ES5的Object.getOwnPropertyDescriptor()方法只能用于讀取實例屬性的描述符。
- "property in obj"通過返回布爾值檢測對象是否有某個屬性(不區(qū)分實例屬性和原型屬性)
- hasPrototypeProperty()用于檢測一個屬性是否存在于原型中
- ES5中object.defineProperty()用于定義屬性。
- 以對象字面量形式創(chuàng)建的對象原型相當于重寫原型。
2、關(guān)于枚舉
- ES5中的constructor和prototype屬性的[[Enumerable]]特性默認為false,因此for in不會枚舉這兩個屬性。
- for in循環(huán)返回可枚舉的原型對象和實例對象;object.keys()返回可枚舉的實例對象的對應(yīng)數(shù)組;object.getOwnPropertyNames()返回所有的實例屬性(無論是否可枚舉)。
3、缺點
- 省略傳參環(huán)節(jié),所有實例在默認情況下取得相同屬性值。
- 單獨使用原型模式的最大缺點在于,原型屬性共享導(dǎo)致實例之間相互影響。
(四)組合使用構(gòu)造函數(shù)模式和原型模式(最常用)
function Student(name,country){
this.name=name;
this.country=country;
}
Student.prototype={
constructor:Person, //重寫了默認的prototype對象,constructor不再指向Person(而是指向Object),因而重新設(shè)置指向Person
sayName:function(){
alert(this.name);
}
};
var student1=new Student("evelyn","China");
特點:實例共享的屬性和方法在原型中定義,除此之外的實例屬性在構(gòu)造函數(shù)中定義。
(五)動態(tài)原型模式
function Student(name,country){
this.name=name;
this.country=country;
if(typeof this.sayName!="function"){
Student.prototype.sayName=function(){
alert(this.name);
};
}
};
var student1=new Student("evelyn","China");
(六)寄生構(gòu)造函數(shù)模式
function Student(name,country){
var o=new Object();
o.name=name;
o.country=country;
o.sayName=function(){
alert(this.name);
};
return o;
}
var student1=new Student("evelyn","China");
(七)穩(wěn)妥構(gòu)造函數(shù)模式
function Student(name,country){
var o=new Object();
o.sayName=function(){
alert(name);
}; //只能通過sayName方法訪問name的值
return o;
}
var student1=Student("evelyn","China");