在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
--------------------------------------------------------
第一条虚线上为非原型属性,第一条虚线下为所有的属性。