工厂模式
通过封装一个函数来创建对象,所有的对象都是相同的,缺点是无法赋予一个对象特定的类型
function createObject(name,age,job) {
var o=new Object();
o.name=name;
o.age=age;
o.job=job;
return o;
}
var person=createObject("John","19","teacher");
构造函数模式
这种方法没有显示地创建对象,而是通过this绑定对象。
按照惯例构造函数名以大写字母开头
function Person(name,age,job) {
this.name=name;
this.age=age;
this.job=job;
this.say=function(){
alert("hello");
}//每定义一个Person对象都会实例化一个匿名函数对象
}
var person1=new Person();//通过new来创建对象
alert(person1.constructor==Person);//true
alert(person1 instanceof Object);//true
alert(person1 instanceof Person);//true
这样定义的对象会有一个constructor属性
原型模式
创建的函数都有一个prototype属性,这个属性是一个指针,指向原型对象
function Person() {
Person.prototype.name="John";
Person.prototype.age="18";
Person.prototype.sayName=function () {
alert(this.name);
}
}
var person1=new Person();
alert(person.name);//"John"
alert(Person.prototype.constructor==Person);//true
alert(Person.prototype.isPrototypeOf(person1));//true
person1这个对象会有一个属性{[prototype]}指向Person.prototype,
但person1这个对象和Person函数之间没有直接联系
接下来谈谈关于原型的一些方法
- hasOwnProperty() 实例属性返回true,原型属性返回false;
- in 对象能访问该属性时返回true,无论实例属性还是原型属性都一样
alert("name" in person1);//true
- for in 循环返回能够通过对象访问的可枚举的属性(包括原型中和实例中的),如果实例属性覆盖了原型中不可枚举的属性,该实例属性也会返回,但是在IE8以及更早的版本中,该实例属性不会返回。
不可枚举的属性和方法有:
- hasOwnProperty();
- propertyIsEnumberable( );
- toLocaleString( );
- toString( );
- valueOf( );
- keys( ) 返回对象所有可枚举的实例属性,对象作为参数,返回值是一个可枚举属性的字符串数组,顺序与for in相同
- Object.getOwnPropertyNames( ) 返回所有实例属性,无论能否枚举 (IE9+,Firefox4+,Safari5+,Opera12+,Chrome支持以上两个方法)
原型的其他写法
function Person() {
}
Person.prototype={
name:"John",
age:20,
job:"Doctor"
};
这样写constructor不在指向Person
可以在Person.prototype中显式的声明constructor,但这样这个属性会变成可枚举的,可以用Object.defineProperty( )替代,这个方法适用于兼容ES5及以上的浏览器
Object.defineProperty(Person.prototype,"constructor"
,{
enumberable:false,
value:Person
});
原型的动态性
原型的动态性在于可以在通过原型方法定义对象后,修改原型,此时对象也会相应变化
但是如果重新定义原型,对象与新原型之间则没有联系,原因在于,对象与构造函数之间是没有之间联系的
最后的问题是可以修改对象的原型属性达到修改原型的目的