工廠模式屬於建立型模式,它提供了一種建立對象的最佳方式。咱們在函數內部建立一個對象,賦予對象屬性和方法,並經過return返回這個對象數組
function createPerson(name, age, job) {
var o = new Object()
o.name = name
o.age = age
o.job = job
o.sayName = function() {
console.log(this.name)
}
return o
}
var person1 = createPerson('caoyuan', 25, 'Software engineer')
var person2 = createPerson('neil', 23, 'Software engineer')
console.log(person1) // {name: "caoyuan", age: 25, job: "Software engineer", sayName: ƒ}
console.log(person2) // {name: "neil", age: 23, job: "Software engineer", sayName: ƒ}
複製代碼
構造模式和工廠模式建立對象的不一樣點在於;安全
function Person(name, age, job) {
this.name = name
this.age = age
this.job = job
this.sayName = function() {
console.log(this.name)
}
}
let person1 = new Person('caoyuan', 25, 'Software Engineer')
let person2 = new Person('neil', 23, 'Software engineer')
person1.sayName()
person2.sayName()
複製代碼
以這種方式調用構造函數實際會經歷一下四個步驟markdown
這種模式的基本思想是建立一個函數,該函數的做用僅僅是封裝對象的代碼,而後再返回新建立的對象。app
function Person(name, age, job) {
var o = new Object()
o.name = name
o.age = age
o.job = job
o.sayName = function() {
console.log(this.name)
}
return o
}
let friend = new Person('neil', 25, 'software Engineer')
friend.sayName() // neil
複製代碼
以上就是例子,把new操做符拋去,這個模式和工廠模式如出一轍。構造函數在不返回值的狀況下,默認會返回新對象實例,而經過構造函數的末尾添加一個return語句,能夠重寫調用給構造函數時返回的值。 以下例子ide
function SpecialArray () {
// 建立數組
var values = new Array()
// 添加值
values.push.apply(values, arguments)
// 添加方法
values.toPipedString = function() {
return this.join('|')
}
// 返回數組
return values
}
var color = new SpecialArray('1','2','3')
console.log(color.toPipedString()) // 1|2|3
複製代碼
穩妥構造函數模式 穩妥對象是指沒有公共屬性, 方法也不引用this的對象。適合在安全的環境中,或者防止數據被其餘應該改動時使用函數
穩妥模式遵循與寄生構造函數相似的模式,但 有兩點不一樣;post
function Person(name, age, job) {
var o = new Object()
o.sayName = function() {
console.log(name)
}
return o
}
let person = Person('neil', 25, 'software Engineer')
person.sayName() // neil
複製代碼
經過代碼介紹下做用域安全的構造函數
function Person(name, age, job) {
this.name = name
this.age = age
this.job = job
}
var person = Person('neil', 25, 'Softwate Engineer')
console.log(window.age) // 25
複製代碼
假設用上述這種方式調用,this指向window,那麼值也就在window上了,那麼怎麼才能解決這種問題呢, 修改代碼以下ui
function Person(name, age, job) {
if (this instanceof Person) {
this.name = name
this.age = age
this.job = job
} else {
return new Person(name, age, job)
}
}
var person = Person('neil', 25, 'software Engineer')
console.log(window.age) // undefined
console.log(person.age) // 25
複製代碼
經過instanceof來判斷當前this是不是person實例上的,如今看上去好像沒有什麼問題了,那麼假設用了構造函數竊取模式的繼承且不使用原型鏈,這個繼承可能就被破壞了this
function Polygon(sides) {
if (this instanceof Polygon) {
this.sides = sides
this.getArea = function() {
return 0
}
} else {
return new Polygon(sides)
}
}
function Rectangle(width, heigth) {
Polygon.call(this, 2)
this.width = width
this.heigth = heigth
this.getArea = function () {
return this.width * this.heigth
}
}
let rect = new Rectangle(5, 10)
console.log(rect.sides) // undefined
複製代碼
你會發現,rect.sides爲undefined,爲啥呢,Polygon這個實例是安全的,可是,Rectangle中是經過call來繼承Polygon的sides屬性,這是由於this對象不是Polygon的實例,因此建立了一個新的Polygon對象,Rectangle中並無sides屬性。若是構造函數竊取結合使用原型鏈和寄生模式就能夠解決這個問題了,代碼以下spa
function Polygon(sides) {
if (this instanceof Polygon) {
this.sides = sides
this.getArea = function() {
return 0
}
} else {
return new Polygon(sides)
}
}
function Rectangle(width, heigth) {
Polygon.call(this, 2)
this.width = width
this.heigth = heigth
this.getArea = function () {
return this.width * this.heigth
}
}
Rectangle.prototype = new Polygon()
let rect = new Rectangle(5, 10)
console.log(rect.sides) // 2
複製代碼
咱們建立的每一個函數都有prototype屬性,這個屬性是一個指針,指向對象,而這個對象包含能夠由特定類型的全部實列共享的屬性和方法。prototype就是經過調用構造函數而建立的那個實例對象的原型對象。
function Person() {
}
Person.prototype.name = 'caoyuan'
Person.prototype.age = '25'
Person.prototype.sayName = function() {
console.log(this.name)
}
let person1 = new Person()
let person2 = new Person()
person2.sayName()
person1.sayName()
console.log(person1.sayName == person2.sayName)
複製代碼
它把全部信息都封裝在了構造函數中,而經過在構造函數中初始化原型,也保持了同時使用構造函數和原型的優勢
function Person(name, age, job) {
this.name = name
this.age = age
this.job = job
// 方法
if (typeof this.sayName != 'function') {
Person.prototype.sayName = function() {
console.log(this.name)
}
}
}
let person = new Person('neil', 25, 'Software Engineer')
person.sayName()
複製代碼
建立自定義對象最多見的方式,就是組合使用構造函數模式和原型模式。
function Person(name, age, job) {
this.name = name
this.age = age
this.children = ['1', '2']
}
Person.prototype.sayName = function() {
console.log(this.name)
}
let person1 = new Person('caoyuan', 25, 'Software Engineer')
let person2 = new Person('neil', 23, 'Software Engineer')
person1.children.push('3')
console.log(person1.children) // Array [1,2,3]
console.log(person2.children) // Array [1,2]
console.log(person1.children === person2.children) // false
console.log(person1.sayName === person2.sayName) // true
複製代碼