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" 复制代码
官方特地介绍了语法:
参数: proto
:新创建对象的原型对象。 propertiesObject
:可选。如果没有指定为 undefined
,则是要添加到新创建对象的可枚举属性(即其自身定义的属性,而不是其原型链上的枚举属性)对象的属性描述符以及相应的属性名称。这些属性对应 Object.defineProperties()
的第二个参数。如果 propertiesObject
参数不是 null
或一个对象,则抛出一个 TypeError
异常。
此处对Object.defineProperties()不多加赘述,介绍一个概念和用法不应该引入其他难以理解的部分和概念,Object.defineProperties()后续我可能会追加一篇文章专门介绍
我们平时常用的就是使用一个参数的情况,可以实现简单的继承,例如上面的例子,包含一个参数,直接将某一个对象当作原型对象,使新的对象去继承。
包含第二个参数的用法可能在大多数场景下用的比较少,尤其是业务代码中会比较少的用到。但是深入探究第二个参数的用法之后,可以给我们带来很多便利: 举例
let o o = Object.create(null) //得到的结果是这个对象No properties 复制代码
o = {}; // 以字面量方式创建的空对象就相当于: o = Object.create(Object.prototype); 复制代码
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); } } }); 复制代码
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 复制代码
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.create的用法和我们平时没注意到的点……结果扯到了ES6中的class上~ 下个周打算写一下symbol的使用:new_moon_with_face: