1. 程式人生 > >JavaScript prototype 屬性和 物件屬性、類屬性的區別

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
--------------------------------------------------------
第一條虛線上為非原型屬性,第一條虛線下為所有的屬性。