美文网首页
new运算符的实现机制

new运算符的实现机制

作者: 江平路 | 来源:发表于2020-08-23 21:44 被阅读0次

先来看一个例子,分别用新旧方式创建类,并实例化。

// 传统实现
function Foo(name) {
  this.name = name
}
// 静态属性
Foo.prototype.fn = 'Foo';
// 成员方法
Foo.prototype.sayName = function() {
  console.log(this.name);
}

// 现代实现
class Bar {
  constructor(name) {
    // 静态属性
    Bar.prototype.fn = 'Bar';
    this.name = name;
  }

  sayName() {
    console.log(this.name);
  }
}

分别创建两个类的实例

const foo = new Foo('isaac');
const bar = new Bar('isaac');
image.png

首先,可以看输出结果。很明显两个实例的结构上是基本一致的,类比一下,你可以猜到新语法“class”的实现本质,当然class也确实是传统实现的语法糖。

所以,接下来直接使用Foo的定义方式作为例子讲。

再来看看定义一个类的时候我们做了什么:

定义了一个构造函数,将需要属性赋值给了上下文(context,即上文的this)
定义了构造函数的属性prototype,将方法、属性挂载在这个prototype上。

最后再对比下实例的结构:

你可以发现,传入Foo的实参被初始化到了对象的第一层属性上:

image.png

说不准这就是构造函数做的事情:通过构造函数将传参,经过逻辑处理,然后初始化到实例上。

在看输出结果,在name属性的下面还有一个__proto__属性,他是一个类对象的结构,你可以发现有两个成员是我们自己定义的:

  1. fn
  2. sayName

这两个属性都是我们在定义类的时候挂载到prototype上的。

说不准这就是我们定义在Foo.prototype属性

最后,我们根据上面两个猜想,再进行推断new做了什么事情:

new通过构造函数创建了一个对象foo,并且通过构造函数的逻辑初始化了这个对象的基本成员;
new将foo的原型引用指向了Foo.prototype,从而连接好从foo -> Foo.prototype -> Object.prototype这条原型链。

上面即是猜想也是实质,我不去证明,这不是我的主要想写的,我是想根据这个猜测去实现一个方法达到“new”的功能。

小结一下

javascript的类的实现分成两部分:

Constructor(构造函数)
Proptotype(原型)

实例化一个类的实例的本质是:

创建一个对象,且在访问该对象成员时,可以向它类指向原型回溯;
对象的成员属性(包含方法)通过Constructor进行初始化;

实现一个“new”创建实例

分析

根据上面对new操作符的分析,我们可以这么做:

  1. 创建一个对象;
  2. 将这个对象的原型引用(不是这个对象的原型,是一个内部属性__proto__指向);
  3. 调用构造函数,将上下文(this)绑定到对象。

具体实现

1、使用setPrototypeOf实现原型指向

setPrototypeOf是ES6的新方法,具体实现其实就是对对象__proto__的修改

function setPrototypeOf(_ctx, _proto) {
  _ctx.__proto__ = _proto;
}
复制代码
/**
 * 创建实例
 * @param { Constructor } ctor 构造
 */
function newIns(ctor) {
  const ins = {};
  Object.setPrototypeOf(ins, ctor.prototype);
  ctor.apply(ins, Array.prototype.slice.call(arguments, 1));
  return ins;
}

const ins = newInsOf(Foo, 'isaac')
console.log(ins);
复制代码
image.png
2、通过Object.create“继承”类

Object.create是官方对原型式继承的内部实现,具体逻辑如下:

function objectCreate(prototype) {
  function F() {}
  F.prototype = prototype;
  return new F();
}
//创建一个新对象,将参数赋值给新对象的原型

Object.create不但创建了一个对象,并且设置了这个对象的__proto__指向。

function newInsOf(
  const ins = Object.create(ctor.prototype);
  ctor.apply(ins, Array.prototype.slice.call(arguments, 1));
  return ins;
}
复制代码
image.png

链接:https://juejin.im/post/6844903910897877005

相关文章

  • new运算符的实现机制

    先来看一个例子,分别用新旧方式创建类,并实例化。 分别创建两个类的实例 首先,可以看输出结果。很明显两个实例的结构...

  • js中new操作符做了什么并实现自己的new操作符

    我们通过new运算符的使用,来探寻new操作符在执行的过程中究竟做了哪些操作,并且根据操作实现自己的new运算符。...

  • Java获取反射的三种方法

    1.通过new对象实现反射机制 2.通过路径实现反射机制 3.通过类名实现反射机制 public class Ge...

  • 实现 new 运算符

    new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象类型之一 原理 MDN 对 new 解释的操...

  • Python:Python学习总结(三)

    魔法方法 对象构造相关:new、init、del。 运算符重载:所有运算符都能重载。 属性访问 集合实现 可调用对...

  • 模拟new的实现

    new运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象类型之一 模拟new之前,看看new实现了哪些...

  • new 运算符实现细节

    由上面这个例子可以知道new在执行时做了哪些事情: 创建一个新对象 将传入的参数变为了新对象的属性,这是构造函数内...

  • 第四章 对象和数组

    Object类型 创建方法有两种,字面量和new运算符 1. 使用new运算符 let obj = new Obj...

  • 动态内存分配

    注:以下大部分内容来源于 coursera 课程《C++程序设计》 用new 运算符来实现动态内存分配 new运算...

  • 原型和原型链

    一、new 和 构造函数 1.1 new 运算符 new 运算符用来创建一个新的对象,其后面需紧跟一个函数,该函数...

网友评论

      本文标题:new运算符的实现机制

      本文链接:https://www.haomeiwen.com/subject/vhlyjktx.html