转载

Object.created浅析

Object.created是ES5出生的,官方给的介绍是 Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__ 对于 __proto__ 的解释请戳这里 简单理解,Object.created是一个继承方法,**返回一个新对象,带着指定的原型对象和属性。**例如:

const person = {
  isHuman: false,
  printIntroduction: function () {
    console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
  }
};

const me = Object.create(person);

me.name = "Matthew"; // "name" is a property set on "me", but not on "person"
me.isHuman = true; // inherited properties can be overwritten

me.printIntroduction();
// "My name is Matthew. Am I human? true"
复制代码

语法

官方特地介绍了语法:

Object.create(proto, [propertiesObject])

参数: proto :新创建对象的原型对象。 propertiesObject :可选。如果没有指定为  undefined ,则是要添加到新创建对象的可枚举属性(即其自身定义的属性,而不是其原型链上的枚举属性)对象的属性描述符以及相应的属性名称。这些属性对应 Object.defineProperties() 的第二个参数。如果 propertiesObject 参数不是  null 或一个对象,则抛出一个 TypeError 异常。

此处对Object.defineProperties()不多加赘述,介绍一个概念和用法不应该引入其他难以理解的部分和概念,Object.defineProperties()后续我可能会追加一篇文章专门介绍

常见用法

我们平时常用的就是使用一个参数的情况,可以实现简单的继承,例如上面的例子,包含一个参数,直接将某一个对象当作原型对象,使新的对象去继承。

包含第二个参数的用法

包含第二个参数的用法可能在大多数场景下用的比较少,尤其是业务代码中会比较少的用到。但是深入探究第二个参数的用法之后,可以给我们带来很多便利: 举例

  1. 创建一个原型为null的空对象
let o
o = Object.create(null)
//得到的结果是这个对象No properties
复制代码
  1. 创建一个空对象的原理
o = {};
// 以字面量方式创建的空对象就相当于:
o = Object.create(Object.prototype);
复制代码
  1. 多个参数
o = Object.create(Object.prototype, {
  // foo会成为所创建对象的数据属性
  foo: { 
    writable:true,
    configurable:true,
    value: "hello" 
  },
  // bar会成为所创建对象的访问器属性
  bar: {
    configurable: false,
    get: function() { return 10 },
    set: function(value) {
      console.log("Setting `o.bar` to", value);
    }
  }
});
复制代码
Object.created浅析

4. 创建一个以另一个空对象为原型,且拥有一个属性的对象

o = Object.create({}, { p: { value: 42 } })

// 省略了的属性特性默认为false,所以属性p是不可写,不可枚举,不可配置的:
o.p = 24
o.p
//42

o.q = 12
for (var prop in o) {
   console.log(prop)
}
//"q"

delete o.p
//false
复制代码
  1. 创建一个可写的,可枚举的,可配置的属性
o2 = Object.create({}, {
  p: {
    value: 42, 
    writable: true,
    enumerable: true,
    configurable: true 
  } 
});
复制代码

现在做有关继承相关的操作,大家更习惯用ES6的`Class xx extends xxx`来实现继承,在ES6出现之前,用的大多是call,apply,bind和Object.create;但是MDN上明确说了Class的语法:

ECMAScript 2015 中引入的 JavaScript 类实质上是 JavaScript 现有的基于原型的继承的语法糖。类语法不会为JavaScript引入新的面向对象的继承模型。

所以最终我们写的代码底层仍然是基于原型来进行继承的。虽然ES6里面涉及到的关键字,例如:super、constructor、extends、static和java中类里面涉及到的关键字相同,但是实际上是完全不同的,不能用看待java中类的眼光去看待JavaScript中的'Class',但是针对Class的用法和基于prototype实现的继承或声明一个'类'在底层其实是相同的。MDN文档后面并没有polyfill相关的代码,我个人的想法是在一定程度上,polyfill是没有必要的存在,这两种写法涉及到的底层是相同的,只不过区别在于使用的浏览器是否能正确识别Class一系列的关键字而已。 如果有兴趣还可以去试一下用typeof 操作符看一下class声明的“类”的具体类型

Object.created浅析

本来是想说一下Object.create的用法和我们平时没注意到的点……结果扯到了ES6中的class上~ 下个周打算写一下symbol的使用:new_moon_with_face:

原文  https://juejin.im/post/5c08bb18e51d451de22a4723
正文到此结束
Loading...