?
?
| Quiz1 |
?
Javascript中存在“類”么?
?
萬物皆對象
Javascript中除了基本數據(Undefined、Null、Boolean、Number、String),其他都是對象(Object)。
實際上,Javascript中的對象是數據與功能的集合。例如我們知道:
var
foo =
new
Function("alert('hello world!')"
);
foo();
可見foo是一個函數,也是一種對象。再比如說:
function
foo(){
//
do something
}
foo.data
= 123
;
foo[
"data2"] = "hello"
;
alert(foo.data);
alert(foo.data2);
函數也可以像對象一樣添加屬性。
?
對象的構建
一般我們用構造函數來構建對象,但如果沒有構造函數,我們也有辦法構建我們想要的對象:
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
但是這不夠,我希望方法是可以共享的。比如我再用該函數創建一個Tom對象,get函數就又被創建了一次,這明顯地浪費了我的內存。
?
導入共享資源
因為我們知道函數也是對象,所以我們可以把需要共享的方法或屬性放在放在他“身上”:
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
于是我們就用蹩腳的方法,成功的創建了一個擁有自有屬性方法和共享屬性方法的對象。但實際上,Javascript就是這么蹩腳地創建對象的。
其實共享屬性沒有真正實現,因為這個共享屬性,依然只是一個副本。這并不是我們真正希望的共享屬性。
?
new關鍵字
和上面的“對象的構建”相同,new的目的是創建對象的自有屬性和方法。例如:
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的作者用了和上面“導入共享資源”的方法差不多。既然函數也是對象,那么把需要共享的“東東”放在他“身上”吧:
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創建對象的模型是簡潔的,new來處理自身問題,prototype來處理共享問題。
如果說Java的對象(實例)產生方式是將原材料丟到模子里(類)熔煉而成;那么Javascript的對象產生方式就是給材料給建筑工(構造函數)讓他按圖紙搭建而成。
?
實際流程
當然實際流程并稍稍有些變化,新建一個對象先做的是處理共享資源,例如:
function
A(){
console.dir(
this
);
alert(
this
.type);
//
A
}
A.prototype.type
= "A"
;
var
a =
new
A();
通過console.dir將a打印出來我們可以看到:
type "A" __proto__ A {type = "A"} type "A" constructor A() ?
?
?
構造函數新建一個對象以后,立刻將其prototype的引用賦給新建對象的內部屬性__proto__,然后再運行構造函數里面的構造語句。
?
并沒有覆蓋
function
A(){
this
.type = "B"
}
A.prototype.type
= "A"
;
var
a =
new
A();
alert(a.type);
//
B
當我們想得到a.type時,引擎會先去在a對象中查看是否有屬性type,如果有則返回該屬性,沒有則試圖在__proto__中查找是否有type屬性,如果有則返回該屬性。
__proto__并不是標準的,比如IE上沒有,但IE上也有類似的內部屬性,但我們也無法使用它。
基于這個原因,我們刪掉a.type時依然可以返回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
?
到底有沒有類?
- 嚴格地講,Javascript并沒有類(class)這種東西。
- 但有時候我們會用構造函數的名字作為利用該構造函數創建的對象們的“類型(type not class)名”,以方便我們用Javascript進行面向對象編程時的交流。
名字只是一個代號,一個方便理解的工具罷了。
?
?
參考文獻
Javascript繼承機制的設計思想 . 阮一峰?.?2011年6月5日
?
補充閱讀
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

