工厂模式
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;
}
var p1 = createPerson('zed', 18, 'Doctor');
var p2 = createPerson('ls', 19, 'Engineer');
p1.sayName()
p2.sayName()
console.log(p1)
console.log(p2)
这个模式虽然能够很方便的创建多个相似的对象,但却有个很大的问题,即对象无法识别类型,这就引出了构造函数模式。
构造函数模式
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function () {
alert(this.name);
}
}
var p1 = new Person('zed', 18, 'Doctor');
var p2 = new Person('ls', 19, 'Engineer');
p1.sayName()
p2.sayName()
console.log(p1)
console.log(p2)
以此模式创建对象,必须使用new操作符。p1和p2中分别保存着Person的两个实例对象。这两个对象都有一个属性constructor
,指向Person。
console.log(p1.constructor)//ƒ Person(name, age, job) {...}
console.log(p1.constructor === p2.constructor)//true
此模式创建的对象类型,是可识别的。
console.log(typeof p1)//object
console.log(p1 instanceof Person)//true
console.log(p2 instanceof Person)//true
此模式大大补足了工厂模式的弊端,但是也不是完美的。
console.log(p1.sayName===p2.sayName)//false
以此模式创建的对象,所有对象中的公共方法并不是真正意义上的共享。别忘了函数也是对象,构造函数会为每个对象分别创建一个同名函数,即使他们的作用完全相同。
这么做的话,每个函数都要在每个实例对象上重新创建一遍,会浪费很多内存空间。这可不是我们想要的。这也就引出了接下来的原型模式。
原型模式
function Person() {
}
Person.prototype.name = 'zed';
Person.prototype.age = 18;
Person.prototype.job = 'Doctor';
Person.prototype.sayName = function () {
alert(this.name);
}
var p1 = new Person();
var p2 = new Person();
console.log(p1)
console.log(p2)
如果把属性和函数,挂载到对象的原型对象上,那么就可实现真正意义的共享。
console.log(p1.sayName===p2.sayName)//true
- 原型对象。我们创建的每个对象,都有一个
prototype
属性,这个属性会指向一个对象,这个对象包含着特定类型的所有实例对象共享的属性和方法。这个对象就叫做原型对象。 - 原型对象都会自动获得一个
constructor
属性,这个属性指向prototyoe
所在的函数。 - 在使用构造函数创建一个实例后,每个实例都会有一个
__proto__
属性,它指向原型对象。 - 创建的实例本身没有属性和方法,但是是可以调用,访问的。这是通过查找对象属性的过程实现的。
- 查找对象属性
- 当我们访问某个属性时,会先寻找实例对象本身开始。如果在实例对象中找到指定的属性,则会返回;如果没有,会继续搜索
__proto__
指向的原型对象,有则返回。
- 当我们访问某个属性时,会先寻找实例对象本身开始。如果在实例对象中找到指定的属性,则会返回;如果没有,会继续搜索
- 更简单地原型语法
function Person() {
}
Person.prototype = {
constructor: Person,
name: 'zed',
age: 18,
job: 'Doctor',
sayName: function () {
alert(this.name);
}
};
var p1 = new Person();
var p2 = new Person();
console.log(p1)
console.log(p2)