js创建对象方案

111 阅读2分钟

1.字面量

直接申明一个对象

let p = {
   name:'zb',
   age:18,
   height:10,
   address:'jjj'
   eating:function(){
      ....
   },
}

上面的方式在申明对象的时候,有很多冗余的代码,下面我们利用工厂模式来进行改进。

2.工厂模式

工厂模式是在原来的字面量的基础上进行封装,由于函数在new 的过程中是返回一个对象,所以我们在内部申明一个对象的变量,并且返回出去

function createPerson(name,age,height,address) {
    // 返回一个对象,那么内部肯定需要一个对象
    let p = {}
    p.name = name
    p.age = age
    p.height = height
    p.address = address
    p.eating = function() {
        console.log('...');
    }
    return p
}
let p1 = new createPerson('zb', 18, 10, 'hhhh')
let p2 = new createPerson('zb1', 18, 10, 'hhhh')
let p3 = new createPerson('zb2', 18, 10, 'hhhh')

但是工厂模式也有缺陷,就是这样创建的p1,p2,p3的对象,获取不到对象最真实的类型。因为对象的类型都是Object类型了,但是从某种角度来说,这些对象应该有一个他们共同的类型。

下面我们来看一下另一种模式:构造函数模式

3.构造函数模式

构造函数也是一个函数,从表现形式来看,和千千万万的普通函数没啥区别;

如果一个函数被new 操作符来调用了,那么这个函数就是构造函数。

function foo(name,age,height){
    this.name = name
    this.age = age
    this.height = height
}
new foo()

此时foo就是构造函数了(必须是通过new操作符来调用才能是构造函数)

那么我们通过new来调用函数与普通函数有什么区别?

new 的时候会执行以下操作:

new的时候执行以下的五步

(1)先创建一个对象,

(2)这个对象内部的prototype赋值为该构造函数的prototype属性

(3)构造函数的内部的this指向创建出来的新对象

(4)执行函数的内部代码

(5)如果构造函数没有返回非空对象,则返回创建出来的新对象

那我们来模拟实现一个new操作符

function _new(fn, ...args) {
//(1)先创建一个对象,

//(2)这个对象内部的prototype赋值为该构造函数的prototype属性

    const obj = Object.create(fn.prototype)
    //利用apply函数来将this指向obj对象,并且指向函数的内部代码
    let res = fn.apply(this, args)
    //(5)如果构造函数没有返回非空对象,则返回创建出来的新对象
    return typeof res === 'Object' ? Object(res) : obj
}

所以当我们new 的时候,

实例对象的隐式原型会指向构造函数的原型 也就是 f1.proto === foo.prototype 构造函数的缺点:

当创建太多对象的时候,会重复开辟内存空间