我的js学习笔记之创建对象
2011-12-19 21:35 尔 阅读(156) 评论(0) 收藏 举报我们创建的每个对象都有一个prototype属性,它是一个指针,它指向一个包含某种类型的所有实例所能共享的属性和方法的对象,我们称这个对象为原型对象。
创建了自定义的构造函数之后,其原型对象会默认具有一个consturctor属性,而这个属性也是一个指针,它会指向构造函数,而当我们创建一个实例后,实例也会具有一个_proto_(除了IE大多数常用游览器都可以访问它)属性,从名字可以看出,它是指向原型对象的指针。
例一:
function Person(){
};
Person.prototype.name='宋峥';//应该为对象独享的属性放在原型对象里其实是不合适的
Person.prototype.age='21';//应该为对象独享的属性放在原型对象里其实是不合适的
Person.prototype.code=function(){
alert(this.name+'在写万恶的代码');
}
var sz=new Person();
sz.code();
当我们调用一个sz的code方法时,会首先在这个对象里查找有无此方法,没有?在从其原型对象里查找,以至于如果其有继承的父类再向上继续查找。
注意点:constructor是原型对象默认的属性,自然可以被它指向的特定的类型的实例所共享。
当我们为对象添加一个同名属性的时候,那个原型对象里面的同名属性会被屏蔽,只是屏蔽,并不是覆盖。
例二:var sz.name='二伯儿';
这样,我们通过sz就无法在访问到原型对象的name属性了,实际上这是符合逻辑的,我们不想让所有的人都叫做宋峥把,每个实例都应该有自己独有的名字(属性),当然如例一注释,把属性放在原型对象里是不合适的。
一种更‘先进’的原型语法
例三:
function Person(){
};
Person.prototype={
constructor:Person,//注意这里!!!!
name:'宋峥',
age:'21',
code:function(){
alert(this.name+'在写万恶的代码');
}
};
这种方式和例一还是不尽相同的,例一是在默认的原型对象进行扩展,而例三是完全重写了原型对象,所以注意注释那里!我们必须把constructor重新指向Person,否则其将指向Object。
我的疑问???
但有一点比较奇怪,即使我们不指定constructor属性为Person,alert(sz instanceof Person),仍然返回true,而实例只能通过_proto_属性指向原型对象,我不知道js是通过何种机制,依然可以判断出sz是Person的实例.
更常用的创建自定义类型的方式---构造函数和原型的组合模式
我们知道属性值常常应该是每个对象的不同的,而方法却可能是所有同类的实例所都应该有的。
如:每个人都会有不同的姓名和爱好,但他们却都有相同的行为(属性)比如都可以跑,都可以说话,尽管跑的快慢,说话的口音可以不同(这时候this就有用武之地了)
例:
function Person(name,age){
this.name=name;
this.age=age;
}
Person.prototype={
constructor:Person,
say:function(){
alert(this.name+'在说话');
}
}
var sz=new Person('宋峥','21');
sz.say();
这已经和java类型的声明非常类似了。
其他几种创建自定意对象的方式
(一)
这种方式,已经不推荐单独使用,创建类似的对象时需要重复很多相似的代码,它没体现出面向对象的优点,也没任何方式可以看出其对象的类型,也毫无封装性可言。
(二)
工厂模式
这种方式很好的解决了(一)的部分问题,但它还是遗留下了(一)的无法判断其对象类型的问题。
(三)
构造函数模式
这种方式创建对象的三个步骤
(1)创建一个新对象
(2)把构造函数的作用域赋给新对象,所以this指向这里的sz对象
(3)执行构造函数中的代码
(4)返回新对象
这种方式和java的构造器有类似点,它们都‘隐性’的返回了一个对象,但js的构造函数和普通函数只是说法不同,并不存在构造函数的特殊语法,任何函数都可以当成构造函数来生成对象,这和java是不同的,java的构造器和普通方法是从jvm处理上是完全不同的
例:普通调用
把Person()当做普通函数调用,因为是在全局作用域调用的函数,所以this对象也就指向了Global对象,在游览器里也就是window.我们也就为window添加了属性和方法。
注:构造函数模式的缺点.
我们在构造函数里定义的函数,在每次创建一个实例的时候,其也会生成一个实例,也就是说,我们每次创建Person对象的时候,每个say函数都是不同的,函数完成的都是类似的工作(还有this呢),所以完全不必创建多个say。所以我们可以把say函数拿出来,放到全局作用域里,问题总是接踵而来,只被某些特定函数使用放在全局作用域里,合适吗?