虽然创建对象可以通过构造函数和对象字面量来创建,但要是创建多个对象的话,就比较麻烦,所以有如下几种模式创建对象
工厂模式
function Person(name){
var obj = {}
obj.name = name
obj.eat = function(){
console.log(this.name)
}
return obj
}
var a = new Person('美丽')
var b = new Person('漂亮')
console.log(a.constructor == Person) // false
console.log(b.constructor == Person) // false
构造函数模式
function Person(name){
this.name = name
this.eat = function(){
console.log(this.name) }
}
var xiaomei = new Person('美丽')
xiaomei.eat() // '美丽'
var a = new Person('美丽')
var b = new Person('漂亮')
console.log(a.constructor == Person) // true
console.log(b.constructor == Person) // true
上面模式的变化,也正是说明了一个面试中常问到的一个题,new的过程发生了什么
答案:
1. 创建一个新对象
2. 将构造函数的作用域赋给新对象(this指向这个新对象)
3. 执行构造函数的代码(新对象会拥有构造函数的属性和方法)
4. 返回这个新对象
构造函数模式相对工厂模式的优势
工厂模式不知道实例化出来的对象的类型,但是构造函数可以用constructor属性检测对象类型
构造函数模式弊端
function Person(name){
this.name = name
this.eat = new Function("console.log(this.name)")
}function eat(){
console.log(this.name)
}
var a = new Person('美丽')
var b = new Person('漂亮')
a.eat() == b.eat(). // false
上面这种的可以看到实例化的两个对象指向了两个不同的函数,开辟了不同的空间,但是下面这种方式由于把函数放在了全局环境里面,实例会共享这个方法,但这样会因为兼顾这个原因,造成创建很多的全局函数,可能会造成空间污染,所以请看下面的原型模式
function Person(name){
this.name = name
this.eat = eat
}
function eat(){
console.log(this.name)
}
var a = new Person('美丽')
var b = new Person('漂亮')
a.eat === b.eat. // true
原型模式
最大的好处就是:所有的实例对象共享属性和方法,换句话说,不需要在构造函数中定义对象的信息,而是直接添加在原型对象中
function Person(name){
this.name = name
}
Person.prototype.eat = function(){
console.log(this.name)
}
var a = new Person('美丽')
var b = new Person('漂亮')
console.log(a.eat() == b.eat()) // true
小彩蛋:
1. hasOwnproperty查找的是属性是不是实例对象的属性还是原型对象的属性,返回true,表示是实例对象的属性
2. 构造函数的实例对象的constructor指向原构造函数