创建对象的方式

218 阅读2分钟

虽然创建对象可以通过构造函数和对象字面量来创建,但要是创建多个对象的话,就比较麻烦,所以有如下几种模式创建对象

工厂模式

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指向原构造函数