虽然JavaScript没有类,但是却有对象,有实例化,有构造函数,抛开这些概念的纠结,复习一下JavaScript中经常容易犯晕的关于原型的问题,原型对象,原型,原型作用域链等 。 JavaScript中的对象定义是无序属性的集合,属性可以包含基本值、对象或者函数。 创建少数对象可以字面量形式 或者构造函数创建。比如像下面这样:
var person = { //字面量形式创建对象
name:"john",
age:25
}
//构造函数形式
var person = new Object();
person.name = "john";
person.age = 25 ;
这两种形式简单易操作,但是如果同意类型的对象需要创建对个,重复代码量很多,这就牵扯到设计模式,比如我们可以使用原型模式,这次主题不是讲设计模式,而是借助原型模式创建对象来讲 原型,原型对象,原型实例之间的关系。
首先,原型(prototype) 是一个属性,我们创建的每一个函数都有一个这样的属性 。这个属性的值是一个指针,该指针指向一个对象,即为该函数的原型对象 。 这个对象包含特定类型的所有实例共享的属性和方法。
比如下面的例子,我们给person添加原型属性name,age 然后调用构造函数创建对象,用for--in 检测实例具有的属性的属性值:
function Person(){
}
Person.prototype.name = "Ann" ;
Person.prototype.age = 25;
var person1 = new Person();
var person2 = new Person() ;
for( key in person1){
console.log("person1 :" + key + person1[key]);
}
for( key in person2) {
console.log("person2 :" + key + person2[key]) ;
}
没有给两个实例添加任何属性,两者都能从原型属性中获取下面的属性,输出结果为下图
其中constructor这个属性,这个是原型对象自动获得的,他是一个指针,指向构造函数。
其次: 创建的实例可以重写原型属性的值,如果属性值是基本值类型,一个实例修改不会影响另一个实例,但是如果属性值是引用类型的值,则会影响所有的实例。例如下面的例子: 实例person1修改了name和friends属性 ,name的改变不会影响其他实例,但是friends却影响了。 但是我们用另一种方式,类似直接改变属性值,而不是通过操作属性值来改变,却不会影响,在下面例子中虽然修改了habits 引用类型的属性值,其他实例没有收到影响。
function Person(){
}
Person.prototype.name = "Ann" ;
Person.prototype.age = 25;
Person.prototype.friends = ["a" ,"b"] ;
Person.prototype.habits = ["reading","sleep"] ;
Person.prototype.sayName = function(){
alert(this.name) ;
}
var person1 = new Person();
var person2 = new Person() ;
person1.name = "john" ;
person1.friends.push("c") ;
person1.habits = ["writing"] ;
for( key in person1){
console.log("person1 :" + key + person1[key]);
}
for( key in person2) {
console.log("person2 :" + key + person2[key]) ;
}
结果为下图:
然后: 用 for --in可以变量 原型对象和实例对象中所有可枚举的属性, hasOwnProperty可判断是否为实例属性,keys()方法可返回调用对象的所有属性。