Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

面试题解JavaScript(二): new的实现原理是什么 #3

Closed
campcc opened this issue Jul 26, 2019 · 0 comments
Closed

面试题解JavaScript(二): new的实现原理是什么 #3

campcc opened this issue Jul 26, 2019 · 0 comments
Labels
interview interview new new

Comments

@campcc
Copy link
Owner

campcc commented Jul 26, 2019

new 的实现原理是什么?

什么是 new

new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。MDN

有点晦涩难懂,简单来说就是:

  • new 是一个运算符
  • new 的作用,就是执行构造函数,返回一个实例对象

实现原理

使用 new 命令时,它后面的构造函数会执行以下操作:

  1. 创建一个空的简单的 JavaScript 对象
  2. 将空对象的原型,指向构造函数的 prototype 属性
  3. 将当前函数内部的 this 绑定到空对象
  4. 执行构造函数,如果没有返回对象,则返回 this,即新创建的对象

步骤 3 中,将新创建的对象作为了当前函数 this 的上下文,这也是为什么通过 new 创建实例时,构造函数内部的 this 指向创建的实例对象的原因。

Tips: 构造函数之所以叫 “构造函数”,可能也是因为这个函数的目的,就是操作一个空对象(this),然后将它 “构造” 成我们想要的样子吧。 -- 阮一峰

模拟实现一个 new

由于 new 是保留字,我们没有办法直接覆盖,所以我们创建一个函数 _new,来模拟 new 的实现,调用时,new Foo(args) 等同于 _new(Foo, args)

function _new() {
  let constructor = [].shift.call(arguments);
  let context = Object.create(constructor.prototype);
  let result = constructor.apply(context, arguments);
  return (typeof result === 'object' && typeof result !== null) ? result : context;
}

上面的实现中,

  1. 首先取出构造函数
  2. 创建一个空对象,继承构造函数的 prototype 属性,相当于将空对象的原型指向构造函数的原型:
context.__proto__ = constructor.prototype
  1. 执行构造函数,获取返回值
  2. 判断返回值类型,如果没有返回对象,返回 context ,即当前的 this

判断返回值的类型是有必要的,因为如果构造函数返回一个对象,new 命令也会返回这个对象

function foo(name) {
  this.name = name
  return { name: 'foo' }
}

(new foo('bar')).name // foo

Reflect.construct

新的语法中,还有一个和 new 操作符行为相似的方法:Reflect.construct

区别在于,Reflect.construct 允许使用可变参数来调用构造函数:

let obj = Reflect.construct(Foo, args)

上面的代码和 new 搭配展开运算符是等价的:

let obj = new Foo(...args)

此外,Reflect.construct 还可以替代 Object.create 来创建一个对象 Reflect.construct

下一篇文章

面试题解JavaScript(三):call,apply 及 bind 函数的内部实现是什么样的

勘误与提问

如果有疑问或者发现错误,可以在相应的 issues 进行提问或勘误

如果喜欢或者有所启发,欢迎 star,对作者也是一种鼓励

(完)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
interview interview new new
Projects
None yet
Development

No branches or pull requests

1 participant