js创建对象的方式以及各方式的优缺点

123 阅读2分钟

1,对象字面量的方式

const obj = {
    name: 'jxh',
    age: 16
  }

2,new Object()方式

 const obj = new Object({
     name: 'xhh',
     age: 16
   })

以上两种方式优缺点:

  • 优点:简单方便, 易于理解
  • 缺点:代码重用性低, 创建多个对象会产生大量重复代码

3,工厂模式

  function person (name, age,say) {
    const obj = new Object()
    obj.name = name
    obj.age = age
    obj.say=say
    obj.fun=function(){
        console.log(this.say)
        }
    return obj
  }
  const obj = person('zhh', 16,'hello world')
   console.log(obj instanceof person)  //false
  console.log(obj.constructor)  //Object
  • 优点:可以重复创建大量相似的对象,代码可复用
  • 缺点:无法确定创建的对象类型

4,构造函数方式

  function Person (name, age, say) {
    this.name = name
    this.age = age
    this.say = say
    this.fun = function () {
      console.log(this.say)
    }
  }
  • 优点:代码可重用, 对象类型确定
  • 缺点:在创建多个person对象实例的时候, 会产生多个fun的方法副本,造成内存浪费

5,原型对象方式

  function Person () {}
  Person.prototype.name = 'xhh'
  Person.prototype.age = 16
  Person.prototype.sayName = function () {
    console.log(this.name)
  }
  const person = new Person()
  person.sayName() //xhh
   function Person(){}
   Person.prototype.name = '123'
   Person.prototype.age = 18
   Person.prototype.friends = ['a', 'b'] // 值为引用类型的属性
   Person.prototype.sayName = function() {
      console.log(this.name)
   }
   const o1 = new Person(1,11)
   const o2 = new Person(2,22)
   o1.friends.push('c')
   console.log(o2.friends) // ['a', 'b', 'c']
  • 优点:解决了实例共享属性值和方法的问题
  • 缺点:因为实例共享属性值的原因,对于值为引用类型的属性来说,一个实例的修改会导致其他实例访问值更改

6,混合模式(构造函数+原型)

  function Person (name, age) {
    this.name = name
    this.age = age
    this.friends = ['a']
  }
  Person.prototype.sayName = function () {
    console.log(this.name)
  }
  const person = new Person('xhh', 16)
  const person1 = new Person('xhh', 16)
  person1.friends.push('b')
  person.sayName() //xhh
  console.log(person1.friends) //['a', 'b']
  console.log(person.friends) //['a']
  • 优点:每个实例有自己的属性,同时又共享着方法的引用,还支持传参数

7,动态混合(构造函数中通过if判断的方式为原型对象添加方法)

  function Person (name, age) {
    this.name = name
    this.age = age
    this.friends = ['a']
    if (typeof this.sayName !== 'function') {
      Person.prototype.sayName = function () {
        console.log(this.name)
      }
    }
  }
  const person = new Person('xhh', 16)
  person.sayName = function () {
    console.log(this.age)
  }
  const person1 = new Person('xhh', 16)
  person.sayName() //16
  person1.sayName() //xhh
  • 优点:仅在方法不存在的时候创建一次,避免重复创建

8,寄生构造模式

  function Person (name, age) {
    this.name = name
    this.age = age
  }
  function Female (name, age, sex) {
    const person = new Person(name, age)
    person.sex = sex
    person.say = function () {
      console.log(`姓名是${name},性别是${sex},年龄是${age}`)
    }
    return person
  }
  const female = new Female('xhh', 16, '女')
  female.say() //姓名是xhh,性别是女,年龄是16
  console.log(female instanceof Object) //true
  console.log(female instanceof Female) //false
  • 优点:在不更改原始构造函数的情况下为对象添加特殊方法
  • 优点:返回的对象与构造函数以及构造函数的原型没有任何关系,该方法与在构造函数外部创建的对象没有什么不同

9,基于闭包的原理方式创建

function Person(name) {
    const obj = new Object()
    // 添加方法
    obj.sayName = function(){
      return name
    }
    return obj
  }
  const obj = new Person('xhh')
  obj.sayName() // xhh
  • 优点:除了使用Person暴露出的sayName方法外没有任何其他的方法能够访问name,可以保护对象内部的变量
  • 缺点:与工厂模式相似,无法识别对象所属类型,使用闭包容易造成内存泄漏

10,class的方式(构造函数+原型模式的语法糖)

  class Person {
    constructor(name, age) {
      this.name = name
      this.age = age
    }
    fun () {
      console.log(this.name)
    }
  }
  const person = new Person('xhh', 16)
  person.fun()  //xhh