你真的会用Object.create?

我心飞翔 分类:javascript

说起Object.create,我们经常会在es5实现原生继承时被经常用到,但对于整个api却显得并不是那么熟悉,让我们再来好好看一下这个api

Object.create定义

创建一个新对象,使用现有的对象来提供新创建的对象的__proto__

基本语法

Object.create(proto, [propertiesObject])

  • proto: 新创建对象的原型对象
  • propertiesObject:(可选参数) ,传入一个对象,对象的某一个属性值为属性描述对象,可参考Object.defineProperties()的第二个参数,该传入对象的自有可枚举属性(即其自身定义的属性,而不是其原型链上的枚举属性)将为新创建的对象添加指定的属性值和对应的属性描述符。

上面的propertiesObject,即第二个参数传参是一个比较难理解的点,我们通过下面这一个例子来瞧瞧,
顺便把属性描述对象中的enumerable属性再做一个总结。

示例

var person = {
    address: "world"
}

var son = Object.create(person, {
    name: {
        value: "min",
        writable: true,
        enumerable: true
    },
    sex: {
        value: "men",
        enumerable: false,
        writable: true
    },
    age: {
        value: 23
    }
});

console.log(son);  // node: { name: 'min' }   chrome: {name: "min", sex: "men", age: 23}
console.log(son.__proto__);  // person
console.log(son.address);    // world
console.log(son.age);  // 23
 

上面的例子中可以看到:

  1. 通过Object.create创建的对象son, 存在自身属性name,sex,age,当然这些自身属性在node和chrome下,对象展示略有不同
  2. 新创建对象son的原型指向person

enumerable

这是一个很奇特的属性,我们要再来认识一下这个属性
同样来看一个例子

/* enumerable */
var person = {
    name: "min"
}

Object.defineProperty(person,"age",{
    value: 23,
    enumerable: false
})

console.log(person);  // node: { name: 'min' }   chrome: {name: "min", age: 23}
console.log(Object.keys(person));  // [ 'name' ]
for(var i in person){
    console.log(i)
}               // name
console.log(Object.getOwnPropertyNames(person))  // [ 'name', 'age' ]
console.log(person.age);  // 23
 

总结下几点:

  1. 在打印person时,node, chrome下有不同,chrome会把不可枚举属性也打印,而node则不会
  2. 属性key值非Symbol下:Object.keys,for...in 会打印出所有可枚举属性,getOwnPropertyNames会打印所有属性
  3. 不管是在node还是chrome环境下,person.age的方式同样可以取出不可枚举属性值

应用

  • 实现继承
function Super(name, age){
    this.name = name;
    this.age = age;
    this.sayHello = function(){
        console.log("hello,"+ this.name)
    }
}

function Sub(name,age,habit){
    this.habit = habit;
    Super.call(this, name, age);
}

Sub.prototype = Object.create(Super.prototype, {
    constructor:{   // 构造函数修复
        value: Sub    // 无需枚举
    }
})
var sub = new Sub("min", 23, "sleep");
console.log(sub instanceof Sub); // true
console.log(sub instanceof Super); // true
console.log(sub.constructor);  // Sub
 

可以看到使用Object.create可以轻松实现原型的继承以及constructor的回指。


谢谢你读完本篇文章,希望对你能有所帮助,如有问题欢迎各位指正。

我是him8(✿◡‿◡),如果觉得写得可以的话,请点个赞吧❤。

回复

我来回复
  • 暂无回复内容