之前提到,构造函数方法创建对象存在着方法不共享的问题,因此引申出了原型模式创建对象
原型模式
原型模式旨在创建一个模版对象,该对象的所有属性和方法被其实例所共享。
原型的概念
不同于构造函数模式创建对象只能单级即成,得益于原型链的概念,原型模式可实现类似其他OOP语言的多级继承。
原型链:一系列有继承关系的函数(对象)中[[prototype]]属性自底向上的指向
先给一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function Person() { }
Person.prototype = { constructor: Person, name: "Jonathan", age: 23, job: developer, sayName: function() { console.log(this.name); } }
person1 = new Person(); person2 = new Person();
|
该例子中各对象的关系如下
//
每一个函数(对象)都可以视为一个模版,向上看,该对象的[[prototype]]
创建原型对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| function Person() { }
Person.prototype = { constructor: Person, name: "Jonathan", age: 23, job: developer, sayName: function() { console.log(this.name); } }
var person1 = new Person(); person1.sayName();
var person2 = new Person(); person2.sayName();
console.log(person1.sayName == person2.sayName);
|
要点
- 先命名一个空函数
- 用对象字面量方式,为该函数的.prototype属性添加原型属性及方法
- 为了constructor属性的正确指向,应先把constructor指向该对象
原型对象的问题
由于众多实例共享原型的属性,因此改变其中某个实例的属性会影响到全局,造成属性污染,例子如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| function Person(){ }
Person.prototype = { constructor: Person, name : "Nicholas", age : 29, job : "Software Engineer", friends : ["Shelby", "Court"], sayName : function () { alert(this.name); } };
var person1 = new Person(); var person2 = new Person();
person1.friends.push("Van");
alert(person1.friends); alert(person2.friends); alert(person1.friends === person2.friends);
|
可见,person1的friends属性污染了person2的friends属性。为避免这种情况,引入组合构造函数与原型模式。
组合使用构造函数与原型模式
单一使用原型对象的问题在于所有属性皆共享,若不想共享某属性,则可放入构造函数中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.friends = ["Boy next door", "Deep dark fantasy"]; }
Person.prototype = { constructor: Person, sayName : function () { alert(this.name); } };
var person1 = new Person("Nicholas", 29, "Software Engineer"); var person2 = new Person("Greg", 27, "Doctor");
person1.friends.push("Van");
alert(person1.friends); alert(person2.friends); alert(person1.friends === person2.friends); alert(person1.sayName === person2.sayName);
|