JS深入理解—详解Object.create(null)、new实现过程以及手写实现
前言在阅读Vue框架源码的时候,会发现作者大量使用Object.create(null)来创建空对象。我们常常使用字面量{}的方式创建,他们之间有什么区别?为啥这么做呢?带着这些疑问,我们来探索其原因。其标准定义请看Object.create。Object.create(null)与{}的区别我们通过例子来直观的认识下两者:let obj = {};let jbo = Object.cr...
·
前言
在阅读Vue
框架源码的时候,会发现作者大量使用Object.create(null)
来创建空对象。我们常常使用字面量{}
的方式创建,他们之间有什么区别?为啥这么做呢?带着这些疑问,我们来探索其原因。其标准定义请看Object.create。
Object.create(null)与{}的区别
我们通过例子来直观的认识下两者:
let obj = {};
let jbo = Object.create(null, {
name: {
writable: true, // 可写
enumerable: true, // 可枚举
value: "yu"
}
});
前者输出的结果是这样:
后者输出的结果是这样:
- 通过字面量的方式定义对象,其原型指向
Object.prototype
,也就是obj.__proto__ === Object.prototype
,同时包含了toString,hasOwnProperty
等方法。 - 通过Object.create(null)创建出来的对象是一个
干净对象
,除自身属性之外,没有附加其他属性。
使用Object.create(null)的原因
很多框架源码作者使用它来初始化一个新的对象,难道是最佳实践?
- 通过
Object.create(null)
创建出来的对象,没有任何属性,显示No properties
。我们可以将其当成一个干净的map
来使用,自主定义toString
,hasOwnProperty
等方法,并且不必担心将原型链上的同名方法被覆盖。 {...}
创建的对象,使用for in
遍历对象的时候,会遍历原型链上的属性,带来性能上的损耗。使用Object.create(null)
则不必再对其进行遍历了。
框架源码对性能的要求,哪怕是一点点,都值得关注。
手写Object.create
// create并不是在原型上的,直接判断是否有这个方法
if (typeof Object.create !== "function") {
Object.create = function(proto, properties) {
// 判断类型,第一个参数传入的必须是 object, function
if (typeof proto !== "object" && typeof proto !== "function") {
throw new TypeError("Object prototype may only be an Object: " + proto);
}
// 这个判断可有可无,至少在chrome中是允许传入null的
// else if (proto === null) {
// throw new Error(
// "This browser's implementation of Object.create is a shim and doesn't support 'null' as the first argument."
// );
// }
// 简单的实现的过程,忽略了properties
var func = function() {};
func.prototype = proto; // 将fn的原型指向传入的proto
return new func(); // 返回创建的新对象,这里思考下,new func() 又做了什么事情呢?且往下看!
};
}
new func()做了什么
new func()
的作用是创建一个新的对象,其中func是一个构造函数,在这个过程中,主要包含了如下步骤:
- 创建空对象obj;
- 将obj的原型设置为构造函数的原型,
obj.__proto__= func.prototype
; - 以obj为上下文执行构造函数,
func.call(obj)
; - 返回obj对象。
根据上面的过程,我们通过代码来模仿new的实现原理:
因为new是关键字,无法像 bind,call,apply 等函数一样直接覆盖,我们写一个函数,命名为 objectCreator。使用的时候是这样的:
function Person() {
...
}
// 使用new
var f = new Person();
//使用 objectCreator
var f = objectCreator(Person[,args]);
实现方案如下:
function objectCreator(func) {
// 创建一个空对象,并将空对象的原型设置为构造函数的原型
var obj = Object.create(func.prototype);
// 以obj为上下文执行构造函数
var newObj = func.call(obj);
// 如果构造函数有返回结果,则返回,若无直接返回obj
if (typeof newObj == "object") {
return newObj;
} else {
return obj;
}
}
至此,我们已经了解Object.create的原理以及new对象的过程,通过模拟实现其原理达到深刻记忆。
更多推荐
已为社区贡献2条内容
所有评论(0)