Object.create与new操作符

发布时间 2023-04-18 12:34:41作者: 风行者夜色

前言

Object.create与new都可以用来生成一个对象,那么它们之间有什么区别和联系呢

分析

  1. 先看一下用法,很明显可以看出,new是生成一个基于构造函数生成一个新对象,而Object.create是基于某个对象,将这个对象作为原型链实现的一个新的空对象。
function O(a) {
  this.a = a;
}
const obj = new O(1); // { a: 1, [[Prototype]]: { constructor: f O(a), ... } }
const obj_new = Object.create(obj); // { [[Prototype]]: { a: 1, [[Prototype]]: { constructor: f O(a), ... } } }
  1. 从原理上来看,他们都存在一个原型链的继承,但是使用的场景和接受的对象是不太一致的。new是作用于一个构造函数,Object.create接受一个将要被当做原型链的函数,最终得到的结果前者是一个已经初始化过后可能存在值的对象,但是后者肯定是个空对象。

  2. 接下来来模拟一下这两个方法的实现。

const my_new = function(fn, ...args) {
    const obj = {}; // 创建一个空对象
    const result = fn.apply(obj, args); // 把空对象当做this执行构造函数
    obj.__proto__ = fn.prototype; // 把空对象的原型链指向构造函数
    if (result) { // 判断是否构造函数已经有返回值,有就返回该构造函数的返回值
        return result;
    } 
    return obj; // 没有就把新生成的对象返回
}
const my_create = function (obj) {
    const F = function() {}; // 构建一个空的构造函数
    F.prototype = obj; // 将构造函数的原型链指向目标对象
    return my_new(F); // 返回该构造函数生成的新对象
}
const obj = my_new(O, 1); // { a: 1, [[Prototype]]: { constructor: f O(a), ... } }
const obj_new = my_create(obj); // { [[Prototype]]: { a: 1, [[Prototype]]: { constructor: f O(a), ... } } }

小结

两者都体现了js的原型链继承的特点,只不过分别继承的对象不太一致,一个是原型链继承构造函数,一个是原型链继承目标对象,仅此而已。