亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

JavaScript高級程序設計(第3版)學習筆記10 再訪js對象

 更新時間:2012年10月11日 15:30:06   作者:  
在ECMAScript中,兩個核心主題就是對象與函數(shù),而這兩個主題也有些互相纏繞的,在前面幾個博文中大略的過了一遍函數(shù)相關的基礎知識,這篇文章再回到對象主題上來

1、對象再認識

(1)對象屬性和特性

  什么是屬性(Property),什么是特性(Attribute),這有什么區(qū)別?我不想也不會從語義學上去區(qū)分,對于這系列文章來說,屬性就是組成對象的一個部分,廣義上也包括對象的方法,而特性則是指被描述主體所具有的特征,換句話說,屬性是我們可以通過編碼來訪問的具體存在,而特性則主要是為了便于理解概念的抽象存在,當然,特性也可以通過相應的屬性來具體外化。這一小節(jié)所講的對象屬性的特性就是對對象屬性特征的一個描述,主要來自于ECMA-262規(guī)范的第5版,該規(guī)范使用兩個中括號的形式來描述不能直接訪問的內部特性。

A、屬性類型(先給屬性分下類):

  • 數(shù)據(jù)屬性:直接訪問屬性值的屬性
  • 訪問器屬性:通過getter/setter方法來訪問屬性值的屬性
  • 內部屬性:不能通過代碼直接訪問的屬性,只是為了規(guī)范說明目的而存在,在規(guī)范中也使用兩個中括號的形式來描述

B、對象內部屬性

  內部屬性不能通過代碼直接訪問,它主要是為了描述規(guī)范,也是給ECMAScript實現(xiàn)者參考的,而對于開發(fā)者來說,了解這些可以便于理解一些內部機制。比如在給一個屬性賦值時,在實現(xiàn)中會調用[[Put]]內部方法,而讀取一個屬性值時,則調用[[Get]]方法。

所有對象公共的內部屬性 個別對象特有的內部屬性
名稱 規(guī)范 名稱 規(guī)范 對象
[[Prototype]] Object/Null [[PrimitiveValue]] primitive Boolean|Date|Number|String
[[Class]] String [[Construct]] SpecOp(a List of any) → Object new
[[Extensible]] Boolean [[Call]] SpecOp(any, a List of any) → any|Reference call
[[Get]] SpecOp (propName) →any [[HasInstance]] SpecOp(any) → Boolean Function
[[GetOwnProperty]] SpecOp (propName) →Undefined|Property Descriptor [[Scope]] Lexical Environment Function
[[GetProperty]] SpecOp (propName) →Undefined|Property Descriptor [[FormalParameters]] List of Strings Function
[[Put]] SpecOp (propName, any, Boolean) [
復制代碼 代碼如下:
]
ECMAScript code Function
[[CanPut]] SpecOp (propName) → Boolean [[TargetFunction]] Object Function.prototype.bind
[[HasProperty]] SpecOp (propName) → Boolean [[BoundThis]] any Function.prototype.bind
[[Delete]] SpecOp (propName, Boolean) → Boolean [[BoundArguments]] List of any Function.prototype.bind
[[DefaultValue]] SpecOp (Hint) → primitive [[Match]] SpecOp(String, index) → MatchResult RegExp
[[DefineOwnProperty]] SpecOp (propName, PropDesc, Boolean) → Boolean [[ParameterMap]] Object  

說明:

  • 每一個對象都有一個原型對象[[Prototype]],一般我們不能在代碼中直接訪問這個內部屬性,但可以通過Object.getPrototypeOf(object)來獲取原型對象(在Firefox中可以通過__proto__來直接訪問)。
  • 在Object.prototype.toString方法中,按照規(guī)范內建對象會返回包含[[Class]]的值“[object class]”,而內建對象的[[Class]]值就是相應的名稱(比如Array對象的[[Class]]值為'Array'),因此可以通過Object.prototype.toString.call(value) == '[object Array]'來判斷value是否是一個Array。
  • 給一個屬性賦值時,后臺調用[[Put]]來實現(xiàn),獲取一個屬性值時,后臺調用[[Get]]來獲取。
  • 使用new操作符調用一個函數(shù)時,后臺調用[[Construct]],而使用call方法來調用函數(shù)時,后臺會調用[[Call]]
  • [[HasInstance]]方法返回給定參數(shù)是否是通過調用函數(shù)來創(chuàng)建的,和Object的方法isPrototypeOf(obj)類似。
  • 當一個函數(shù)被執(zhí)行時,就會創(chuàng)建一個[[Scope]]對象,可以理解為[[Scope]]就是我們前面所說的活動對象,也就是說this、arguments、形參、函數(shù)內部定義的變量和函數(shù)都是的[[Scope]]對象的屬性。

C、屬性特性(用來描述屬性的特性)

內部特性 配置屬性 屬性類型 數(shù)據(jù)類型 默認值 含義 備注
[[Configurable]] configurable

數(shù)據(jù)屬性

訪問器屬性

Boolean

true

能否通過delete刪除屬性從而重新定義屬性

能否修改屬性的特性

能否把屬性修改為訪問器特性

一旦把屬性定義為不可配置的,就不能再變?yōu)榭膳渲玫?/P>

如果為false,不能做刪除、也不能修改屬性特性,但是允許修改屬性值

非嚴格模式下會忽略相應操作,嚴格模式下則拋出異常

[[Enumerable]] enumerable

數(shù)據(jù)屬性

訪問器屬性

Boolean true 能否通過for-in循環(huán)返回屬性 為true時可以通過for-in來枚舉,否則不能通過for-in枚舉
[[Writable]] writable 數(shù)據(jù)屬性 Boolean true 能否修改屬性的值 為false時不能修改屬性值,非嚴格模式下會忽略相應操作,嚴格模式下則拋出異常
[[Value]] value 數(shù)據(jù)屬性 任意類型 undefined 屬性值  
[[Get]] get 訪問器屬性 Undefined/Function undefined 讀取屬性時調用的函數(shù) 為一個函數(shù)時,會無參數(shù)調用這個函數(shù),并將返回值作為屬性值返回
[[Set]] set 訪問器屬性 Undefined/Function undefined 寫入屬性時調用的函數(shù) 為一個函數(shù)時,會將傳入的值作為參數(shù)調用這個函數(shù),賦給屬性

說明:

  • 配置屬性是指使用下面要講的屬性定義方法時用以定義相關特性的配置項名稱。
  • 對于訪問器屬性,[[Get]]、[[Set]]不一定都有,沒有[[Get]]的屬性不能讀(返回undefined,嚴格模式下拋出異常),沒有[[Set]]的屬性不能寫(會忽略,嚴格模式下拋出異常)。
  • 注意區(qū)分對象內部屬性和對象屬性的特性。

D、屬性定義方法(用來定義屬性的方法)

最常見的定義屬性的方法就是直接在對象上添加屬性,比如obj.name = 'linjisong',這種情況下定義的屬性所具有的內部特性都是默認的,如果想定義一個值不能被修改的屬性要怎么做呢?在ES中給我們提供了幾個方法用于實現(xiàn)類似的功能。

方法名 功能說明 參數(shù)和返回值 說明 調用示例
defineProperty() 定義一個屬性

(1)目標對象

(2)屬性的名字

(3)屬性描述符對象

使用屬性定義方法時 
[[Enumerable]]
[[Configurable]]
[[Writable]]
默認值為false

// 創(chuàng)建一個包含一個默認屬性job的對象(job屬性可以修改、刪除、在for-in中枚舉)
var person = {job:'it'};
// 添加一個不能被修改、刪除的name屬性
Object.defineProperty(person, 'name', {
value:'linjisong',//這里的配置屬性和上面特性列表中的配置屬性一致
enumerable:true
});
// 定義多個屬性(數(shù)據(jù)屬性year和訪問器屬性age)
Object.defineProperties(person, {
year:{
value : 2012,
configurable:true,
writable:true
},
age:{
get : function(){
return this.year-1983;
}
}
});

var job = Object.getOwnPropertyDescriptor(person, 'job');
console.info(job.configurable);//true,直接添加屬性時默認為true

var name = Object.getOwnPropertyDescriptor(person, 'name');
console.info(name.configurable);//false,使用屬性定義方法添加屬性時默認為false
console.info(person.name);//linjisong
person.name = 'oulinhai';//由于不能修改,所以值不會改變,在嚴格模式下會拋出異常
console.info(person.name);//linjisong

person.year = 2015;
console.info(person.year);//2015
console.info(person.age);//32,在修改year的同時,也修改了age屬性
defineProperties() 定義一組屬性

(1)目標對象

(2)多個屬性描述符組成的一個對象

getOwnPropertyDescriptor() 獲取屬性的特性

(1)目標對象

(2)屬性的名字

(3)返回一個包括了屬性特性的對象

 

注:這些方法設置或獲取的屬性特殊和屬性的類型有關,比如數(shù)據(jù)屬性只能設置[[Confirurable]]、[[Enumerable]]、[[Writable]]、[[Value]]。

(2)防篡改對象

  所謂防篡改對象,就是給對象一定級別的保護以防止在這個級別上對對象的變更,在ES5規(guī)范中,定義了依次升高的三種保護級別:

保護級別 描述 操作方法 判斷方法 說明
不可擴展 不能給對象添加新屬性和方法,但可以修改已有屬性和方法 preventExtensions() isExtensible():不能擴展時返回false  
密封 不可擴展,并且已有成員的[[Configurable]]設置為false,不能刪除屬性,但可以修改屬性值 seal() isSeal():被密封時返回true isSeal()為true時一定有isExtensible()為false
凍結 密封,其[[Writable]]設置為false,但如果定義了[[Set]],訪問器屬性仍然可寫 freeze() isFrozen():被凍結時返回true isFrozen()為true時一定有isSeal()為true,isExtensible()為false

注:一旦定義成了防篡改對象,就不能撤銷。

(3)對象的其它方法

名稱 描述
create(prototype[,descriptors]) 創(chuàng)建一個具有指定原型且可選擇性地包含指定屬性的對象
getOwnPropertyNames(object) 返回對象的屬性(方法)的名稱
getPrototypeOf(object) 返回對象的原型
keys(object) 返回對象的可枚舉屬性(方法)的名稱

這里的create(prototype[,descriptors])是一個非常有意思的方法,規(guī)范中這樣描述它的行為:

[code]
①如果prototype不是Null或Object,拋出TypeError異常
②var obj = new Object()
③設置obj的內部屬性[[Prototype]]為prototype
④如果descriptors存在且不為undefined,使用Object.defineProperties(obj,descriptors)來添加屬性
⑤返回obj


由于一般對象的[[Prototype]]不能直接訪問,可以使用函數(shù)來進行下面模擬實現(xiàn):
復制代碼 代碼如下:

(function(){
function Base(){};
Object.create = function(prototype, descriptors){
var typeVal = typeof prototype;
if(typeVal !== null && typeVal !== 'object' && typeVal !== 'function'){
throw new TypeError('類型錯誤,請檢查第一個參數(shù)的類型');
}

Base.prototype = prototype;
var result = new Base();
if(descriptors){
Object.defineProperties(result, descriptors);
}
return result;
};
})();

測試一下:
復制代碼 代碼如下:

try{
var one = Object.create(1);//異常
}catch(e){
console.info(e);//TypeError
}
var base = {
name:'linjisong',
getName:function(){
return this.name;
}
};
var two = Object.create(base);
console.info(two.name);//linjisong
console.info(two.getName());//linjisong
var three = Object.create(base, {
name:{value:'oulinhai'},
age:{value:23}
});
console.info(three.getName());//oulinhai
console.info(three.age);//23

這里實現(xiàn)了一個簡單的繼承,這也引出下一個主題。

2、原型對象

(1)原型與原型鏈

  每個對象都有一個原型對象,而原型對象本身也是一個對象,也有自己的原型對象,這樣就形成了一個原型鏈直至null對象。對象的內部屬性[[Prototype]]指向的就是對象的原型對象,而Object.prototype的原型對象為null。

(2)屬性查找

  在訪問一個對象的屬性(方法)時,引擎會先查找對象本身有沒有這個屬性,如果有,返回這個屬性值,如果沒有,則查找對象的原型是否有這個屬性,如果有,返回,如果沒有就繼續(xù)查找原型對象的原型直至最后一個原型對象。

  注意區(qū)分屬性查找和和前面說過的標識符查找的異同。屬性查找是沿著原型鏈,標識符查找是沿著作用域鏈,但都有一個逐級查找的過程。

(3)對象的原型對象[[Prototype]]與函數(shù)的原型屬性prototype

•每一個對象都有一個原型對象,在規(guī)范中使用[[Prototype]]來表示,這個對象一般不能直接訪問,但可以通過getPrototypeOf()這個方法來獲取,而在Firefox中還可以通過__proto__直接訪問,來驗證一下:
復制代碼 代碼如下:

var obj = {};
console.info(obj.__proto__===Object.getPrototypeOf(obj));//true
console.info(obj.__proto__===Object.prototype);//true

•每一個函數(shù)都有一個屬性prototype,這個屬性是在函數(shù)定義過程中添加的,它指向的對象就是所有使用該函數(shù)創(chuàng)建的實例對象的原型對象。
復制代碼 代碼如下:

var fn = function(){};
console.info(typeof fn.prototype);//object,一旦定義了函數(shù),就會添加prototype屬性,指向原型對象
var obj1 = new fn();
console.info(fn.prototype === Object.getPrototypeOf(obj1));//true,所有使用fn創(chuàng)建的實例的原型對象都指向fn.prototype
var obj2 = new fn();
console.info(fn.prototype === Object.getPrototypeOf(obj2));//true
console.info(Object.getPrototypeOf(fn) === Function.prototype);//true

當然,fn本身也是一個對象,也有自己的原型對象,它的原型對象就是Function的屬性prototype了(fn.__proto__===Function.prototype)。

  我們知道,每一個對象都可以訪問一個屬性constructor,指向創(chuàng)建這個對象的函數(shù)(構造函數(shù)),實際上,constructor屬性只不過是構造函數(shù)的原型對象的一個屬性而已,因此通過構造函數(shù)創(chuàng)建的實例都能夠訪問constructor。
復制代碼 代碼如下:

var fn = function fn(){};
var obj1 = new fn();
console.info(fn.constructor);//Function()
console.info(fn.prototype.constructor);//fn(),函數(shù)原型對象的constructor指向函數(shù)本身console.info(obj1.hasOwnProperty('constructor'));//false,實例本身沒有constructor屬性console.info(fn.prototype.constructor === obj1.constructor);//true,實例可以訪問到原型對象中的constructor屬性

•函數(shù)的原型對象具有動態(tài)性,即便先創(chuàng)建實例,后修改原型對象,也還是能夠通過實例訪問到對原型對象所做的變更。
復制代碼 代碼如下:

var fn = function fn(){};
var obj = new fn();
console.info(obj.name);//undefined
fn.prototype.name = 'linjisong';
console.info(obj.name);//linjisong


3、創(chuàng)建對象

創(chuàng)建方式 示例 說明
傳統(tǒng)方式
var person = new Object(); 
person.name = 'linjisong'; 
person.job = 'it';
傳統(tǒng)方式創(chuàng)建對象容易產生大量重復的代碼
對象字面量
var person = { 
name : 'linjisong', 
job : 'it' 
};
使用對象字面量創(chuàng)建簡潔明了,非常適合創(chuàng)建作為函數(shù)實參的對象
工廠模式
function createPerson(name, job){ 
var o = new Object(); 
o.name = name; 
o.job = job; 
return o; 
} 
var person = createPerson('linjisong','it');

1、工廠模式能有效解決重復代碼問題。

2、但是不能判定對象的類型

構造函數(shù)模式
function Person(name, job){ 
this.name = name; 
this.job = job; 
this.getName = function(){ 
return this.name; 
} 
} 
var person = new Person('linjisong','it');

構造函數(shù)模式能解決重復代碼問題,也能夠判定對象的類型

但是這種模式下創(chuàng)建的每個實例都有一份屬性和方法的Copy

對于方法來說,每個實例都保存一份是沒有必要的

使用new調用構造函數(shù)的內部步驟:

(1)創(chuàng)建一個新對象

(2)將構造函數(shù)的作用域賦給新對象(構造函數(shù)內this指向新創(chuàng)建對象)

(3)執(zhí)行構造函數(shù)中的代碼

(4)返回新對象

原型模式
function Person(){} 
Person.prototype.name = 'linjisong'; 
Person.prototype.job = 'it; 
Person.prototype.getName = fucntion(){ 
return this.name; 
}; 
var person = new Person();

原型模式能夠解決構造函數(shù)模式的方法實例有多個副本的問題

但是同時每個實例的屬性也共享了,對于引用類型的屬性來說

這會導致非常嚴重的問題,修改一個實例的屬性會導致另一個實例也修改

而且也不能接受參數(shù)

function Angle(){}; 
Angle.prototype.coordinate = [0,0]; 

var a1 = new Angle(); 
var a2 = new Angle(); 

a1.coordinate[0] = 1; 
console.info(a2.coordinate);//[1,0]修改a1會導致a2變更
組合構造原型模式
function Person(name, job){ 
this.name = name; 
this.job = job; 
} 
Person.prototype.getName = fucntion(){ 
return this.name; 
}; 
var person = new Person('linjisong','it');

結合構造函數(shù)模式和原型模式

使用構造函數(shù)模式創(chuàng)建屬性,每個實例保存一份

使用原型模式共享方法,所有實例共享保存一份

這是目前使用最廣泛的對象創(chuàng)建方式

動態(tài)原型模式
function Person(name, job){ 
this.name = name; 
this.job = job; 
if(!Person.prototype.getName){ 
Person.prototype.getName = fucntion(){ 
return this.name; 
}; 
} 
} 
var person = new Person('linjisong','it');

這種模式實際上是對于不習慣將構造函數(shù)和原型分離而引入的

在判斷的時候,可以只判斷其中一個屬性

寄生構造函數(shù)模式
function Person(name, job){ 
var o = new Object(); 
o.name = name; 
o.job = job; 
o.getName = fucntion(){ 
return this.name; 
}; 
return o; 
} 
var person = new Person('linjisong','it');

工廠模式不使用new,寄生構造函數(shù)模式使用new操作符

構造函數(shù)模式不返回,寄生構造函數(shù)模式返回對象

不能使用instanceof判斷類型

穩(wěn)妥構造函數(shù)模式
function Person(name, job){ 
var o = new Object(); 
o.getName = fucntion(){ 
return name; 
}; 
return o; 
} 
var person = Person('linjisong','it');

穩(wěn)妥對象:不使用this和new

穩(wěn)妥構造模式類似寄生構造模式,但只能通過提供的方法訪問成員

不能使用instanceof判斷類型

各種創(chuàng)建對象的模式需要根據(jù)具體情況來看,最常用的還是對象字面量和組合構造原型方式。

4、繼承

在ECMAScript中,沒有接口繼承,只有實現(xiàn)繼承,這些繼承主要是通過原型鏈來實現(xiàn)的。像對象創(chuàng)建一樣,下面也通過一張表格來瀏覽一下一些實現(xiàn)繼承的方法。

繼承方式 示例 說明
原型鏈
function Square(){//正方形 
this.width = 10;//邊長 
this.coordinate = [0,0];//左上頂點的坐標  
} 
Square.prototype.getArea = function(){//計算面積 
return this.width * this.width; 
}; 

function ColorSquare(){//有顏色的正方形 
this.color = 'red'; 
} 
ColorSquare.prototype = new Square();//實現(xiàn)了繼承 
ColorSquare.prototype.getColor = function(){//獲取顏色 
return this.color; 
} 

var cs = new ColorSquare(); 
console.info(cs.width);//10 
console.info(cs.getArea());//100 
console.info(cs.color);//red 
console.info(cs.getColor());//red

1、通過修改子類型創(chuàng)建函數(shù)的原型實現(xiàn)繼承。

2、通過原型給子類型添加新方法時,一定要在替換子類型原型之后添加,而后也不能通過對象字面量修改子類型的原型。

3、可以通過兩種方法確定原型和實例之間的關系:只要實例原型鏈中出現(xiàn)過構造函數(shù)fn,都返回true

(1)instance instanceof fn

(2)fn.prototype.isPrototype(instance)

4、使用原型鏈繼承時,創(chuàng)建子對象時無法傳遞參數(shù)。

5、引用類型的父類屬性會被所有子類型實例共享從而產生問題:

修改一個子類型實例的引用類型屬性會導致其它所有子類型實例相應的修改

var cs2 = new ColorSquare(); 
console.info(cs2.coordinate);//[0,0] 
cs.coordinate[1] = 1; 
console.info(cs2.coordinate);//[0,1],修改cs會導致cs2也修改
借用構造函數(shù)
function Square(){//正方形 
this.width = 10;//邊長 
this.coordinate = [0,0];//左上頂點的坐標  
} 

Square.prototype.getArea = function(){//計算面積 
return this.width * this.width; 
}; 

function ColorSquare(){//有顏色的正方形 
Square.call(this);//實現(xiàn)繼承 
this.color = 'red'; 
} 

var cs = new ColorSquare(); 
var cs2 = new ColorSquare(); 
console.info(cs.coordinate);//[0,0] 
console.info(cs2.coordinate);//[0,0] 
cs.coordinate[1] = 1; 
console.info(cs.coordinate);//[0,1] 
console.info(cs2.coordinate);//[0,0],互相獨立,修改cs不影響cs2 
try{ 
console.info(cs.getArea());//異常,不能訪問父類原型中方法 
}catch(e){ 
console.info(e);//TypeError 
}

1、使用借用構造函數(shù)時,可以在call調用時傳遞參數(shù)。

2、同時也不存在引用類型共享的問題。

3、借用構造函數(shù)的缺點是,子類不能訪問父類原型中定義的方法

組合繼承
function Square(){//正方形 
this.width = 10;//邊長 
this.coordinate = [0,0];//左上頂點的坐標  
} 

Square.prototype.getArea = function(){//計算面積 
return this.width * this.width; 
}; 

function ColorSquare(){//有顏色的正方形 
Square.call(this);//創(chuàng)建子類實例時,第二次調用父類構造函數(shù) 
this.color = 'red'; 
} 

ColorSquare.prototype = new Square();//第一次調用 
ColorSquare.prototype.getColor = function(){//獲取顏色 
return this.color; 
} 

var cs = new ColorSquare(); 
var cs2 = new ColorSquare(); 
console.info(cs.coordinate);//[0,0] 
console.info(cs2.coordinate);//[0,0] 
cs.coordinate[1] = 1; 
console.info(cs.coordinate);//[0,1] 
console.info(cs2.coordinate);//[0,0],互相獨立,修改cs不影響cs2 
console.info(cs.getArea());//100,可以訪問

1、組合繼承也稱為偽經典繼承,是將原型鏈和借用構造函數(shù)兩種方式結合起來的繼承方式。

2、基本思想是:

(1)使用原型鏈實現(xiàn)對原型屬性和方法的繼承

(2)使用借用構造函數(shù)實現(xiàn)對實例屬性的繼承

3、組合繼承避免了原型鏈和借用構造函數(shù)的缺點,融合了它們的優(yōu)點,是最常用的繼承方式。

4、組合繼承的缺點是需要調用兩次父類的構造函數(shù)

原型式繼承
function create(o){ 
var fn = function(){}; 
fn.prototype = o; 
return new fn(); 
} 

var square = { 
width:10, 
coordinate:[0,0] 
}; 

var cs = create(square); 
var cs2 = create(square); 
console.info(cs.coordinate);//[0,0] 
console.info(cs2.coordinate);//[0,0] 
cs.coordinate[1] = 1; 
console.info(cs.coordinate);//[0,1] 
console.info(cs2.coordinate);//[0,1],和原型鏈一樣,會有共享問題

1、這種方式實際上就是前面說的模擬ES5中create函數(shù)來實現(xiàn)繼承。

2、ES5及前面模擬的create還可以接受另外的屬性描述參數(shù)。

3、和原型鏈與借用構造函數(shù)不同的是,這種方式需要先有一個對象,然后直接創(chuàng)建子對象。

前者是構造函數(shù)的繼承,而后者是對象實例的繼承。

4、和使用原型鏈繼承一樣,也會有引用類型實例屬性的共享問題。

寄生式繼承
function create(o){ 
var fn = function(){}; 
fn.prototype = o; 
return new fn(); 
} 

var square = { 
width:10, 
coordinate:[0,0] 
}; 

function colorSquare(original){ 
var s = create(original); 
s.color = 'red'; 
return s; 
} 

var cs = colorSquare(square); 
console.info(cs.width);//10 
console.info(cs.coordinate);//[0,0]

1、首先,這里的create函數(shù)不是必需的,任何返回新對象的函數(shù)都可以。

2、其次,這種模式也有引用類型實例屬性共享的問題。

3、這種方式,可以看成將上面的對象繼承包裝成構造函數(shù)。

寄生組合式繼承
function create(o){ 
var fn = function(){}; 
fn.prototype = o; 
return new fn(); 
} 

function inherit(sub, sup){ 
var prototype = create(sup.prototype); 
prototype.constructor = sub; 
sub.prototype = prototype; 
} 

function Square(){//正方形 
this.width = 10;//邊長 
this.coordinate = [0,0];//左上頂點的坐標  
} 
Square.prototype.getArea = function(){//計算面積 
return this.width * this.width; 
}; 

function ColorSquare(){//有顏色的正方形 
Square.call(this); 
this.color = 'red'; 
} 
inherit(ColorSquare, Square); 
ColorSquare.prototype.getColor = function(){//獲取顏色 
return this.color; 
} 

var cs = new ColorSquare(); 
console.info(cs.width);//10 
console.info(cs.getArea());//100 
console.info(cs.color);//red 
console.info(cs.getColor());//red 

var cs2 = new ColorSquare(); 
console.info(cs2.coordinate);//[0,0] 
cs.coordinate[1] = 1; 
console.info(cs2.coordinate);//[0,0]

1、這種方式只調用了一次父類構造函數(shù),從而避免了在子類型的原型對象上創(chuàng)建不必要的屬性。

2、能夠保證原型鏈不變,從而可以正常使用instanceof和isPrototypeOf()。

相關文章

  • JavaScript的21條基本知識點

    JavaScript的21條基本知識點

    這篇文章主要介紹了JavaScript的21條基本知識點的相關資料,需要的朋友可以參考下
    2014-03-03
  • 淺談javascript 迭代方法

    淺談javascript 迭代方法

    這篇文章主要介紹了淺談javascript 迭代方法的相關資料,需要的朋友可以參考下
    2015-01-01
  • JavaScript splice()方法詳解

    JavaScript splice()方法詳解

    這篇文章介紹了JavaScript splice()方法,有需要的朋友可以參考一下
    2013-11-11
  • JavaScript語言對Unicode字符集的支持詳解

    JavaScript語言對Unicode字符集的支持詳解

    這篇文章主要介紹了JavaScript語言對Unicode字符集的支持詳解,需要的朋友可以參考下
    2014-12-12
  • JavaScript中setTimeout和setInterval函數(shù)的傳參及調用

    JavaScript中setTimeout和setInterval函數(shù)的傳參及調用

    這篇文章主要介紹了JavaScript中setTimeout和setInterval函數(shù)的傳參及調用,著兩個函數(shù)可以把要執(zhí)行的代碼在設定的一個時間點插入js引擎維護的一個代碼隊列中,需要的朋友可以參考下
    2016-03-03
  • Javascript Throttle & Debounce應用介紹

    Javascript Throttle & Debounce應用介紹

    Throttle:無視一定時間內所有的調用Debounce:一定間隔內沒有調用時,接下來將為大家介紹下Throttle & Debounce的應用,感興趣的朋友可以參考下哈
    2013-03-03
  • Javascript中引用示例介紹

    Javascript中引用示例介紹

    Javascript腳本中,引用的參數(shù)內部可以修改,但參數(shù)對應的引用不能修改,下面為大家詳細介紹下
    2014-02-02
  • Javascript 按位左移運算符使用介紹(<<)

    Javascript 按位左移運算符使用介紹(<<)

    這篇文章主要介紹了Javascript 按位左移運算符 (<<) 將表達式數(shù)字轉換成二進制,之后向左移表達式的位的相關資料,需要的朋友可以參考下
    2014-02-02
  • javascript 注釋代碼的幾種方法總結

    javascript 注釋代碼的幾種方法總結

    為了程序/代碼的易讀性,基本上每一種編程語言都有注釋的功能,javascript也不例外,javascript注釋代碼有多種形式,本文章向大家介紹javascript注釋代碼的兩種方法,需要的朋友可以參考一下
    2017-01-01
  • JavaScript入門教程(6) Window窗口對象

    JavaScript入門教程(6) Window窗口對象

    他是JavaScript中最大的對象,它描述的是一個瀏覽器窗口。一般要引用它的屬性和方法時,不需要用“window.xxx”這種形式,而直接使用“xxx”。一個框架頁面也是一個窗口。
    2009-01-01

最新評論