工厂模式属于建立型模式,它提供了一种建立对象的最佳方式。咱们在函数内部建立一个对象,赋予对象属性和方法,并经过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
复制代码