JavaScript prototype 屬性和 物件屬性、類屬性的區別
在JavaScript中, 物件可以帶屬性,物件的原型(pototype)也可以帶屬性,類(Function物件)也可以帶屬性,那麼這些屬性有什麼區別呢?
1、實驗條件
首先宣告一個類
var my fun = function(){}
(1)類的屬性
myfun.name = 'Zhangsan';
(2)原型的屬性
myfun.prototype.address = '北京東路88號';
(3)物件的屬性
建立一個物件:
var myfun1 = new myfun();
myfun1.name2='Wangwu';
2、測試指令碼
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <title>hasOwnProperty and in</title> </head> <body> <script lang="javascript"> //建立一個類(class) var myfun = function(){ } //設定prototype方法 myfun.prototype.companyname = '3COM'; myfun.prototype.address='北京東路88號'; myfun.prototype.postcode='210000'; myfun.prototype.sayhello = function(name){ alert('Hello '+ name + ' !'); } //設定類的屬性(放置在物件的constructor屬性中) myfun.name = 'Zhangsan'; //例項化 var myfun1 = new myfun(); //非物件屬性,故訪問不到 alert('myfun1.name:' + myfun1.name); //通過構造器屬性,可以訪問到 alert('myfun1.constructor.name:' + myfun1.constructor.name); //設定物件的屬性 myfun1.name2 = 'Wangwu'; myfun1.address2 = '湖北路168號'; myfun1.department ={ code: '001', name:'研發中心' }; //設定物件的方法(依然視作物件的屬性) myfun1.func = function(){ alert('test is ok!'); } //實用函式 function print(str){ document.writeln(str + "<br>"); } //列印物件非原型的屬性 function test(){ var obj = myfun1; for(var n in obj) { if(Object.prototype.hasOwnProperty.call(obj, n)){ print(n); } } print("--------------------------------------------------------"); } //列印物件所有屬性 function test2(){ var obj = myfun1; for(var n in obj) { print(n); } print("--------------------------------------------------------"); } test(); test2(); </script> </body> </html>
3、分析總結
通過以上測試案例,可知三者之間區別如下:
a. 類屬性:在其例項化物件中,只能通過構造器物件來訪問。例子:
//非物件屬性,故訪問不到
alert('myfun1.name:' + myfun1.name);
//通過構造器屬性,可以訪問到
alert('myfun1.constructor.name:' + myfun1.constructor.name);
b. 原型屬性;原型屬性在記憶體中只會存在一份拷貝,物件例項化後並不能修改其值。
通過偵錯程式觀察物件,原型屬性存在於物件的__proto__屬性中,值不受外界影響。類似下面的賦值語句,實際上是給物件增加了新的屬性,並未修改原型中的屬性值。
myfun1.address='新的地址';
物件原型中的屬性不能通過myfun1.__proto__.address來進行訪問,因為__proto__屬性對呼叫者不可見,只能通過物件的“類”來訪問:
alert('myfun.prototype.address:' + myfun.prototype.address);
c.物件屬性:在類被例項化後,給物件賦值,即為物件屬性。物件屬性時運用得最為廣泛的一種屬性,可以動態設定和獲取。
4、prototype 屬性和物件屬性區分的實際應用
在某些場景下,需要區分出,哪些屬性是原型所有,哪些屬性時物件所有。使用的方法:
for(var n in obj) {
if(Object.prototype.hasOwnProperty.call(obj, n)){
print(n);
}
}
打印出非原型屬性。
for(var n in obj) {
if(!Object.prototype.hasOwnProperty.call(obj, n)){
print(n);
}
}
而使用for...in可以打印出所有的屬性。實驗結果如下:
name2
address2
department
func
--------------------------------------------------------
name2
address2
department
func
companyname
address
postcode
sayhello
--------------------------------------------------------
第一條虛線上為非原型屬性,第一條虛線下為所有的屬性。