工厂模式
(1). 用函数封装以特定接口创建对象的细节,解决了相似对象的问题,没有解决对象识别的问题
(2).
function createPerson(name,age,job){
var o=new Object();
o.name='name';
o.age=age;
o.job=job;
o.sayName=function(){
alert(this.name);
};
return o;
}.构造 函数模式
(1). ECMAScript中的构造函数可以用来创建特定类型的对象,向Object和Array这样的原生构造函数,在运行时会自动出现在执行环境中;此外也可以创建自定义的构造函数从而创建自定义对象类型的属性和方法
(2)`function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
this.sayName=function(){
alert(this.name);
}
}(3).与上面工厂模式不同的是,没有显式创建对象,将属性和方法直接给了this,没有return语句
(4). 创建Person的实例必须使用new 操作符,调用后经历:创建一个新对象;将构造函数的作用域赋值给新对象,此时this指向新对象;执行构造函数中的代码;返回新对象;
(5). 创建自定义的构造函数意味着可以将它的实例标识为一种特定的类型,解决对象识别的问题,任何函数使用new操作符都可以成为构造函数;
但是带来的问题是,当构造函数创建了多个实时,构造函数中的方法会在每个实例上创建一遍;
`
3. 原型模式
(1). 每个函数都有一个prototype(原型)属性,是个指针,指向一个对象,该对象包含可有特定类型的实例共享的属性和方法.即prototye是通过构造函数创建的对象的原型对象
(2). 理解原型对象
只要创建了一个新函数,就会创建一个prototype的指针指向其原型对象;
所有原型对象自动获取一个constructor(构造函数)属性,指向prototype所在函数即构造函数;
当构造函数创建以个新实例时,该实例内部的[[prototype]]指向其构造函数的原型对象;
function Person(){
}
Person.prototype={
name:'nicholas',
age:29,
job:'software engineer',
sayName:function(){
alert(this.name);
};
}
//以这种对象字面量的方法创建原型时,原型中的constructor属性不再指向其构造函数,所以可以在name属性前加上constructor:Person,
var person1=new Person();
var person2=new Person();
person1.name='greg';
alert(person1.name); //'greg',来自实例
alert(person2.name); //'greg',来自原型
为实例添加一个与原型同名的属性会屏蔽原型中的属性,原因是每当代码读取到某个对象的属性时,现在其实例对象上查找,当没有找到时会沿着原型链向上查找,直到找到该属性并返回其值。不过使用delete可以完全删除实例属性,这样原型属性就可以访问了
(3). 确定原型和实例关系:
Person.prototype.isPrototypeOf(person1);确定person1的原型是 Person.prototype,是则返回true
确定属性存在于实例中: person1.hasOwnProperty(“name”);
(4). 当重写原型对象时会切断现有原型(重写后的原型)和已经存在的对象实例间的联系,已存在的实例引用的是最初的原型。
(5). 原型模式的问题:首先,省略了为构造函数传入参数初始化环节,所有实例在默认情况下取得相同的属性值;其次由于实例共享原型属性和方法,对于方法合适,但当一个实例用来原型中的属性,给其属性进行修改时也会反应在该原型的其他实例上。
1. 构造函数与原型模式公用
(1). 构造函数用于定义实例属性,原型模式用于定义方法和共享属性这样每份实例都有自己的实例属性副本并且共享原型对象上的属性和方法,这样节省了内存解决了构造函数和原型模式的问题,还支持向构造函数传递参数。
function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
}
}
Person.prototype={
sayName:function(){
alert(this.name);
}
}
};
- 动态原型
function Person(name,age,job){
this.name=name;
......
//注意:初次调用构造函数才会在原型上创建此方法实现方法共享,下一次调用不会再创建,其他的实例会调用原型上的sayName方法
if(typeof this.sayName !="function"){
Person.prototype.sayName=function(){...};
}
}
这里将原型模式封装进构造函数里面,保留上一种方法的优点,又实现了封装。
使用动态原型模式时不能使用对象字面量的方法重写原型,原因是会切断现有原型和已经有的实例之间的联系
- 寄生构造函数模式
- 稳妥构造函数模式