Javascript繼承(上)——對(duì)象構(gòu)建介紹
更新時(shí)間:2012年11月08日 10:48:35 作者:
Javascript中除了基本數(shù)據(jù)(Undefined、Null、Boolean、Number、String),其他都是對(duì)象(Object)
Javascript中存在“類”么?
萬(wàn)物皆對(duì)象
Javascript中除了基本數(shù)據(jù)(Undefined、Null、Boolean、Number、String),其他都是對(duì)象(Object)。
實(shí)際上,Javascript中的對(duì)象是數(shù)據(jù)與功能的集合。例如我們知道:
var foo = new Function("alert('hello world!')");
foo();
可見(jiàn)foo是一個(gè)函數(shù),也是一種對(duì)象。再比如說(shuō):
function foo(){
//do something
}
foo.data = 123;
foo["data2"] = "hello";
alert(foo.data);
alert(foo.data2);
函數(shù)也可以像對(duì)象一樣添加屬性。
對(duì)象的構(gòu)建
一般我們用構(gòu)造函數(shù)來(lái)構(gòu)建對(duì)象,但如果沒(méi)有構(gòu)造函數(shù),我們也有辦法構(gòu)建我們想要的對(duì)象:
function creatPerson(__name, __sex, __age){
return {
name: __name,
sex: __sex,
age: __age,
get: function(__key){
alert(this[__key]);
}
};
}
var Bob = creatPerson("Bob", "male", 18);
Bob.get("name"); //Bob
Bob.get("sex"); //male
Bob.get("age"); //18
但是這不夠,我希望方法是可以共享的。比如我再用該函數(shù)創(chuàng)建一個(gè)Tom對(duì)象,get函數(shù)就又被創(chuàng)建了一次,這明顯地浪費(fèi)了我的內(nèi)存。
導(dǎo)入共享資源
因?yàn)槲覀冎篮瘮?shù)也是對(duì)象,所以我們可以把需要共享的方法或?qū)傩苑旁诜旁谒吧砩稀保?
function creatPerson(__name, __sex, __age){
var common = arguments.callee.common;
return {
//自身的屬性
name: __name,
sex: __sex,
age: __age,
//自身的方法
sayhi: function(){alert("hi");},
//共享的方法
get: common.get,
getType: common.getType,
//共享的屬性
type: common.type
};
}
creatPerson.common = {
get:function(__key){
alert(this[__key]);
},
getType: function(){
alert(this.type);
},
type: "Person"
};
var Bob = creatPerson("Bob", "male", 18);
Bob.get("name"); //Bob
Bob.get("sex"); //male
Bob.getType(); //Person
于是我們就用蹩腳的方法,成功的創(chuàng)建了一個(gè)擁有自有屬性方法和共享屬性方法的對(duì)象。但實(shí)際上,Javascript就是這么蹩腳地創(chuàng)建對(duì)象的。
其實(shí)共享屬性沒(méi)有真正實(shí)現(xiàn),因?yàn)檫@個(gè)共享屬性,依然只是一個(gè)副本。這并不是我們真正希望的共享屬性。
new關(guān)鍵字
和上面的“對(duì)象的構(gòu)建”相同,new的目的是創(chuàng)建對(duì)象的自有屬性和方法。例如:
function Person(__name, __sex, __age){
this.name = __name;
this.sex = __sex;
this.age = __age;
this.get = function(__key){
alert(this[__key]);
};
}
var Bob = new Person("Bob", "male", 18);
Bob.get("name"); //Bob
Bob.get("sex"); //male
Bob.get("age"); //18
原型(Prototype)
Javascript的作者用了和上面“導(dǎo)入共享資源”的方法差不多。既然函數(shù)也是對(duì)象,那么把需要共享的“東東”放在他“身上”吧:
function Person(__name, __sex, __age){
this.name = __name;
this.sex = __sex;
this.age = __age;
this.sayhi = function(__key){
alert("hi");
};
}
Person.prototype = {
constructor: Person,
get: function(__key){
alert(this[__key]);
}
};
var Bob = new Person("Bob", "male", 18);
Bob.get("name"); //Bob
Bob.get("sex"); //male
alert(Bob.constructor); //function Person
Javascript創(chuàng)建對(duì)象的模型是簡(jiǎn)潔的,new來(lái)處理自身問(wèn)題,prototype來(lái)處理共享問(wèn)題。
如果說(shuō)Java的對(duì)象(實(shí)例)產(chǎn)生方式是將原材料丟到模子里(類)熔煉而成;那么Javascript的對(duì)象產(chǎn)生方式就是給材料給建筑工(構(gòu)造函數(shù))讓他按圖紙搭建而成。
實(shí)際流程
當(dāng)然實(shí)際流程并不是這樣的,新建一個(gè)對(duì)象先做的是處理共享資源,例如:
function A(){
console.dir(this);
alert(this.type); //A
}
A.prototype.type = "A";
var a = new A();
通過(guò)console.dir將a打印出來(lái)我們可以看到:
構(gòu)造函數(shù)新建一個(gè)對(duì)象以后,立刻將其prototype的引用賦給新建對(duì)象的內(nèi)部屬性__proto__,然后再運(yùn)行構(gòu)造函數(shù)里面的構(gòu)造語(yǔ)句。
并沒(méi)有覆蓋
function A(){
this.type = "B"
}
A.prototype.type = "A";
var a = new A();
alert(a.type); //B
當(dāng)我們想得到a.type時(shí),引擎會(huì)先去在a對(duì)象中查看是否有屬性type,如果有則返回該屬性,沒(méi)有則試圖在__proto__中查找是否有type屬性,如果有則返回該屬性。
__proto__并不是標(biāo)準(zhǔn)的,比如IE上沒(méi)有,但I(xiàn)E上也有類似的內(nèi)部屬性,但我們也無(wú)法使用它。
基于這個(gè)原因,我們刪掉a.type時(shí)依然可以返回a.type:
function A(){
this.type = "B"
}
A.prototype.type = "A";
var a = new A();
alert(a.type); //B
delete a.type;
alert(a.type); //A
到底有沒(méi)有類?
嚴(yán)格地講,Javascript并沒(méi)有類(class)這種東西。
但有時(shí)候我們會(huì)用構(gòu)造函數(shù)的名字作為利用該構(gòu)造函數(shù)創(chuàng)建的對(duì)象們的“類型(type not class)名”,以方便我們用Javascript進(jìn)行面向?qū)ο缶幊虝r(shí)的交流。
名字只是一個(gè)代號(hào),一個(gè)方便理解的工具罷了。
參考文獻(xiàn)
Javascript繼承機(jī)制的設(shè)計(jì)思想
萬(wàn)物皆對(duì)象
Javascript中除了基本數(shù)據(jù)(Undefined、Null、Boolean、Number、String),其他都是對(duì)象(Object)。
實(shí)際上,Javascript中的對(duì)象是數(shù)據(jù)與功能的集合。例如我們知道:
復(fù)制代碼 代碼如下:
var foo = new Function("alert('hello world!')");
foo();
可見(jiàn)foo是一個(gè)函數(shù),也是一種對(duì)象。再比如說(shuō):
復(fù)制代碼 代碼如下:
function foo(){
//do something
}
foo.data = 123;
foo["data2"] = "hello";
alert(foo.data);
alert(foo.data2);
函數(shù)也可以像對(duì)象一樣添加屬性。
對(duì)象的構(gòu)建
一般我們用構(gòu)造函數(shù)來(lái)構(gòu)建對(duì)象,但如果沒(méi)有構(gòu)造函數(shù),我們也有辦法構(gòu)建我們想要的對(duì)象:
復(fù)制代碼 代碼如下:
function creatPerson(__name, __sex, __age){
return {
name: __name,
sex: __sex,
age: __age,
get: function(__key){
alert(this[__key]);
}
};
}
var Bob = creatPerson("Bob", "male", 18);
Bob.get("name"); //Bob
Bob.get("sex"); //male
Bob.get("age"); //18
但是這不夠,我希望方法是可以共享的。比如我再用該函數(shù)創(chuàng)建一個(gè)Tom對(duì)象,get函數(shù)就又被創(chuàng)建了一次,這明顯地浪費(fèi)了我的內(nèi)存。
導(dǎo)入共享資源
因?yàn)槲覀冎篮瘮?shù)也是對(duì)象,所以我們可以把需要共享的方法或?qū)傩苑旁诜旁谒吧砩稀保?
復(fù)制代碼 代碼如下:
function creatPerson(__name, __sex, __age){
var common = arguments.callee.common;
return {
//自身的屬性
name: __name,
sex: __sex,
age: __age,
//自身的方法
sayhi: function(){alert("hi");},
//共享的方法
get: common.get,
getType: common.getType,
//共享的屬性
type: common.type
};
}
creatPerson.common = {
get:function(__key){
alert(this[__key]);
},
getType: function(){
alert(this.type);
},
type: "Person"
};
var Bob = creatPerson("Bob", "male", 18);
Bob.get("name"); //Bob
Bob.get("sex"); //male
Bob.getType(); //Person
于是我們就用蹩腳的方法,成功的創(chuàng)建了一個(gè)擁有自有屬性方法和共享屬性方法的對(duì)象。但實(shí)際上,Javascript就是這么蹩腳地創(chuàng)建對(duì)象的。
其實(shí)共享屬性沒(méi)有真正實(shí)現(xiàn),因?yàn)檫@個(gè)共享屬性,依然只是一個(gè)副本。這并不是我們真正希望的共享屬性。
new關(guān)鍵字
和上面的“對(duì)象的構(gòu)建”相同,new的目的是創(chuàng)建對(duì)象的自有屬性和方法。例如:
復(fù)制代碼 代碼如下:
function Person(__name, __sex, __age){
this.name = __name;
this.sex = __sex;
this.age = __age;
this.get = function(__key){
alert(this[__key]);
};
}
var Bob = new Person("Bob", "male", 18);
Bob.get("name"); //Bob
Bob.get("sex"); //male
Bob.get("age"); //18
原型(Prototype)
Javascript的作者用了和上面“導(dǎo)入共享資源”的方法差不多。既然函數(shù)也是對(duì)象,那么把需要共享的“東東”放在他“身上”吧:
復(fù)制代碼 代碼如下:
function Person(__name, __sex, __age){
this.name = __name;
this.sex = __sex;
this.age = __age;
this.sayhi = function(__key){
alert("hi");
};
}
Person.prototype = {
constructor: Person,
get: function(__key){
alert(this[__key]);
}
};
var Bob = new Person("Bob", "male", 18);
Bob.get("name"); //Bob
Bob.get("sex"); //male
alert(Bob.constructor); //function Person
Javascript創(chuàng)建對(duì)象的模型是簡(jiǎn)潔的,new來(lái)處理自身問(wèn)題,prototype來(lái)處理共享問(wèn)題。
如果說(shuō)Java的對(duì)象(實(shí)例)產(chǎn)生方式是將原材料丟到模子里(類)熔煉而成;那么Javascript的對(duì)象產(chǎn)生方式就是給材料給建筑工(構(gòu)造函數(shù))讓他按圖紙搭建而成。
實(shí)際流程
當(dāng)然實(shí)際流程并不是這樣的,新建一個(gè)對(duì)象先做的是處理共享資源,例如:
復(fù)制代碼 代碼如下:
function A(){
console.dir(this);
alert(this.type); //A
}
A.prototype.type = "A";
var a = new A();
通過(guò)console.dir將a打印出來(lái)我們可以看到:
type | "A" |
__proto__ | A {type = "A"} |
type | "A" |
constructor | A() |
構(gòu)造函數(shù)新建一個(gè)對(duì)象以后,立刻將其prototype的引用賦給新建對(duì)象的內(nèi)部屬性__proto__,然后再運(yùn)行構(gòu)造函數(shù)里面的構(gòu)造語(yǔ)句。
并沒(méi)有覆蓋
復(fù)制代碼 代碼如下:
function A(){
this.type = "B"
}
A.prototype.type = "A";
var a = new A();
alert(a.type); //B
當(dāng)我們想得到a.type時(shí),引擎會(huì)先去在a對(duì)象中查看是否有屬性type,如果有則返回該屬性,沒(méi)有則試圖在__proto__中查找是否有type屬性,如果有則返回該屬性。
__proto__并不是標(biāo)準(zhǔn)的,比如IE上沒(méi)有,但I(xiàn)E上也有類似的內(nèi)部屬性,但我們也無(wú)法使用它。
基于這個(gè)原因,我們刪掉a.type時(shí)依然可以返回a.type:
復(fù)制代碼 代碼如下:
function A(){
this.type = "B"
}
A.prototype.type = "A";
var a = new A();
alert(a.type); //B
delete a.type;
alert(a.type); //A
到底有沒(méi)有類?
嚴(yán)格地講,Javascript并沒(méi)有類(class)這種東西。
但有時(shí)候我們會(huì)用構(gòu)造函數(shù)的名字作為利用該構(gòu)造函數(shù)創(chuàng)建的對(duì)象們的“類型(type not class)名”,以方便我們用Javascript進(jìn)行面向?qū)ο缶幊虝r(shí)的交流。
名字只是一個(gè)代號(hào),一個(gè)方便理解的工具罷了。
參考文獻(xiàn)
Javascript繼承機(jī)制的設(shè)計(jì)思想
相關(guān)文章
Zod進(jìn)行TypeScript類型驗(yàn)證使用詳解
這篇文章主要為大家介紹了Zod進(jìn)行TypeScript類型驗(yàn)證使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09ChatGPT用于OA聊天助手導(dǎo)致訪問(wèn)量服務(wù)宕機(jī)
這篇文章主要為大家介紹了ChatGPT用于OA聊天助手導(dǎo)致訪問(wèn)量服務(wù)宕機(jī),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03electron渲染進(jìn)程主進(jìn)程相互傳值示例解析
這篇文章主要為大家介紹了electron渲染進(jìn)程主進(jìn)程相互傳值示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02