Object.create() 作用和原理

218 阅读2分钟

作用

  • 创建一个新对象,该对象继承自指定的原型对象,可实现基于原型的继承

原理

  • 基于原型链机制,调用ceate()时,会创建一个新对象,该对象内部的prototype属性会被设置为传入的proto对象,
  • 这意味着新对象会自动继承proto传入对象的所有属性和方法

优点

精准控制原型
便捷简单
纯原型继承:不依赖类和构造函数的概念

缺点

IE8以下不兼容

运用场景

const a = Object.create(null) // 创建一个没有原型的干净对象
a.toString // undefined
const b = Object.create({}) // 普通使用场景
b.toString // function

使用语法

  • Object.create(proto, [propertiesObject])

    • proto:必需参数,指定新对象的原型对象。
    • propertiesObject:可选参数,用于为新对象定义额外的属性。
      • 数据描述属性
        • value: 属性值,默认为undefined
        • writable: 是否可被赋值,默认是false
      • 存取描述属性
        • get: 函数,访问该属性时回调这个函数并返回返回值,默认是undefined
        • set:函数,给该属性赋值时会回调这个函数并传入新值,默认undefined
      • 通用描述属性
        • configurable: 布尔值,是否可以被删除,默认false
        • enumerable: 布尔值,是否可被枚举,默认false
      • 需要注意:
        • 数据描述属性 和 存取描述属性不可同时定义,否则报错
      var a = Object.create({}, {
          name: {
              value: 'name1',
              get () {
                  console.log('test value')
              }
          }
      })
      // 报错
      

    使用示范

    // 数据描述属性
    const a = Object.create({}, {
        name: {
            value: 'name1',
            writable: true
        }
    })
    console.log(a) // {name: 'name1'}
    a.name = 1
    console.log(a.name) // name1  赋值修改被禁止
    
    // 存取描述属性
    const a = Object.create({}, {
        name: {
            get() {
                return `${this.nameA} ${this.nameB}`
            },
            set(value) {
                this.nameA = value
                this.nameB = value
            },
            enumerable: true,
            configurable: true
        }
    })
    console.log(a.name) // 'undefined undefined'
    a.nameA = 'nameA'
    a.nameB  = 'nameB'
    console.log(a.name) // 'nameA nameB'
    a.name = 'nameC'
    console.log(a.nanme) // 'nameC nameC'
    

直接赋值对象 和 Object.create创建对象的区别

  • 直接赋值
    • 直接赋值b1和a1之间的关系是引用赋值,在内存中是同一个内容,修改其中一方会影响另外一方
var a1 = {a:1}
var b1 = a1
  • create创建
    • Object.create 会在内存中创建一个新的对象b2,其原型为a2,继承a2的所有属性和方法,它们是不同对象 修改b2自身属性不影响a2的属性
// Object.create
var a2 = {a:1}
var b2 = Object.create(a2)

console.log(b2) // {} 在内存中创建一个新对象,其__proto__指向了a2
console.log(b2.a) // 1 ,首先在b2上找不到a属性,然后沿着原型找到a2上面的a并返回出来

b2.a = 2
console.log(b2) // {a: 2},在自身创建了a属性
console.log(a2.a) // 1 ,由于b2自身已经有了a属性,所以获取和设置a属性的时候都是获取设置b2自身的,a2上面的不受影响

b2.__proto__.a = 3
console.log(b2) // {a: 2}
console.log(a2.a) // 3 ,被b2找到原型修改到了a2上的a属性