每日三问之javascript面向对象之函数

 
所有原型对象都会自动获得一个 constructor (构造函数)属性,这个属性包含一个指向 prototype 属性所在函数的指针。就拿前面的例子来说, Person.prototype.constructor 指向 Person 。而通过这个构造函数,我们还可继续为原型对象添加其他属性和方法。

展示了 Person 构造函数、Person 的原型属性以及 Person 现有的两个实例之间的关系。

在此, Person.prototype 指向了原型对象,而 Person.prototype.constructor 又指回了 Person
原型对象中除了包含 constructor 属性之外,还包括后来添加的其他属性。
原型与 in 操作符
function Person(){ 
} 
Person.prototype.name = "Nicholas"; 
Person.prototype.age = 29; 
Person.prototype.job = "Software Engineer"; 
Person.prototype.sayName = function(){ 
 alert(this.name); 
}; 
var person1 = new Person(); 
var person2 = new Person(); 
alert(person1.hasOwnProperty("name")); //false 
alert("name" in person1); //true 
person1.name = "Greg"; 
alert(person1.name); //"Greg" ——来自实例
alert(person1.hasOwnProperty("name")); //true 
alert("name" in person1); //true 
alert(person2.name); //"Nicholas" ——来自原型
alert(person2.hasOwnProperty("name")); //false 
alert("name" in person2); //true 
delete person1.name; 
alert(person1.name); //"Nicholas" ——来自原型
alert(person1.hasOwnProperty("name")); //false 
alert("name" in person1); //true
因此,调用 "name" in person1 始终都返回 true ,无论该属性存在于实例中还是存在于原型中。 同时使用 hasOwnProperty() 方法和 in 操作符,就可以确定该属性到底是存在于对象中,还是存在于原型中,
function hasPrototypeProperty(object, name){ 
 return !object.hasOwnProperty(name) && (name in object); 
}
要取得对象上所有可枚举的实例属性,可以使用 ECMAScript 5 Object.keys() 方法。
function Person(){ 
} 
Person.prototype.name = "Nicholas"; 
Person.prototype.age = 29; 
Person.prototype.job = "Software Engineer"; 
Person.prototype.sayName = function(){ 
 alert(this.name); 
}; 
var keys = Object.keys(Person.prototype); 
alert(keys); //"name,age,job,sayName" 
var p1 = new Person(); 
p1.name = "Rob"; 
p1.age = 31; 
var p1keys = Object.keys(p1); 
alert(p1keys); //"name,age"
更简单的原型语法
function Person(){ 
} 
Person.prototype = { 
 name : "Nicholas", 
 age : 29, 
 job: "Software Engineer", 
 sayName : function () { 
 alert(this.name); 
 } 
};


var friend = new Person(); 
alert(friend instanceof Object); //true 
alert(friend instanceof Person); //true 
alert(friend.constructor == Person); //false 
alert(friend.constructor == Object); //true
instanceof 操作符测试 Object Person仍然返回 true ,但 constructor 属性则等于 Object 而不等于 Person 了。如果 constructor 的值真的很重要,可以像下面这样特意将它设置回适当的值。
function Person(){ 
} 
Person.prototype = { 
 constructor : Person, 
 name : "Nicholas", 
 age : 29, 
 job: "Software Engineer", 
 sayName : function () { 
 alert(this.name); 
 } 
};
原型的动态性
var friend = new Person(); 
Person.prototype.sayHi = function(){ 
 alert("hi"); 
}; 
friend.sayHi(); //"hi"(没有问题!)
function Person(){ 
} 
var friend = new Person(); 
 
Person.prototype = { 
 constructor: Person, 
 name : "Nicholas", 
 age : 29, 
 job : "Software Engineer", 
 sayName : function () { 
 alert(this.name); 
 } 
}; 
friend.sayName(); //error
调用构造函数时会为实例添加一个指向最初原型的[[Prototype]]指针,而把原型修改为另外一个对象就等于切断了构造函数与最初原型之间的联系。

 原生对象的原型

所有原生引用类型( Object Array String ,等等)都在其构造函数的原型上定义了方法。
Array.prototype 中可以找到 sort() 方法,而在 String.prototype 中可以找到substring()方法,如下所示。
alert(typeof Array.prototype.sort); //"function" 
alert(typeof String.prototype.substring); //"function"
通过原生对象的原型,不仅可以取得所有默认方法的引用,而且也可以定义新方法。
下面的代码就给基本包装类型String 添加了一个名为 startsWith() 的方法。
String.prototype.startsWith = function (text) { 
 return this.indexOf(text) == 0; 
}; 
var msg = "Hello world!"; 
alert(msg.startsWith("Hello")); //true
原型对象的问题
原型模式的最大问题是由其共享的本性所导致的。
person2.friends(与 person1.friends 指向同一个数组)反映出来,  此时发现person2.friends也被添加了“Van”值。这样会被污染风险
function Person(){ 
} 
Person.prototype = { 
 constructor: Person, 
 name : "Nicholas", 
 age : 29, 
 job : "Software Engineer", 
 friends : ["Shelby", "Court"], 
 sayName : function () { 
 alert(this.name); 
 } 
}; 
var person1 = new Person(); 
var person2 = new Person(); 
person1.friends.push("Van"); 
alert(person1.friends); //"Shelby,Court,Van" 
alert(person2.friends); //"Shelby,Court,Van" 
alert(person1.friends === person2.friends); //true
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值