以前提到,構造函數方法建立對象存在着方法不共享的問題,所以引伸出了原型模式建立對象javascript
原型模式旨在建立一個模版對象,該對象的全部屬性和方法被其實例所共享。java
不一樣於構造函數模式建立對象只能單級即成,得益於原型鏈的概念,原型模式可實現相似其餘OOP語言的多級繼承。函數
原型鏈:一系列有繼承關係的函數(對象)中[[prototype]]屬性自底向上的指向this
先給一個例子:prototype
function Person() { } Person.prototype = { constructor: Person, name: "Jonathan", age: 23, job: developer, sayName: function() { console.log(this.name); } } person1 = new Person(); person2 = new Person();
該例子中各對象的關係以下code
//對象
每個函數(對象)均可以視爲一個模版,向上看,該對象的[[prototype]]繼承
function Person() { } Person.prototype = { constructor: Person, name: "Jonathan", age: 23, job: developer, sayName: function() { console.log(this.name); } } var person1 = new Person(); person1.sayName(); //"Jonathan" var person2 = new Person(); person2.sayName(); //"Jonathan" console.log(person1.sayName == person2.sayName); //true
要點ip
因爲衆多實例共享原型的屬性,所以改變其中某個實例的屬性會影響到全局,形成屬性污染,例子以下:原型鏈
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); //"Shelby,Court,Van" alert(person2.friends); //"Shelby,Court,Van" alert(person1.friends === person2.friends); //true
可見,person1的friends屬性污染了person2的friends屬性。爲避免這種狀況,引入組合構造函數與原型模式。
單一使用原型對象的問題在於全部屬性皆共享,若不想共享某屬性,則可放入構造函數中。
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); //"Shelby,Court,Van" alert(person2.friends); //"Shelby,Court" alert(person1.friends === person2.friends); //false alert(person1.sayName === person2.sayName); //true