首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >JavaScript new 操作符

JavaScript new 操作符

作者头像
用户1065635
发布2019-03-21 11:13:57
发布2019-03-21 11:13:57
5970
举报
文章被收录于专栏:前端社区前端社区

new 原理

我们可以在 ES5 官方文档中看到其对 new 创建对象过程的定义与约束:

13.2.2 [[Construct]] When the [[Construct]] internal method for a Function object F is called with a possibly empty list of arguments, the following steps are taken:

  1. Let obj be a newly created native ECMAScript object.
  2. Set all the internal methods of obj as specified in 8.12.
  3. Set the [[Class]] internal property of obj to "Object".
  4. Set the [[Extensible]] internal property of obj to true.
  5. Let proto be the value of calling the [[Get]] internal property of F with argument "prototype".
  6. If Type(_proto_) is Object, set the [[Prototype]] internal property of obj toproto.
  7. If Type(_proto_) is not Object, set the [[Prototype]] internal property of obj to the standard built-in Object prototype object as described in 15.2.4.
  8. Let result be the result of calling the [[Call]] internal property of F_, providing _obj as the this value and providing the argument list passed into [[Construct]] as _args_.
  9. If Type(_result_) is Object then return _result_.
  10. Return _obj_.

若执行 new Foo() ,其过程可简单描述为:

  1. 创建新对象 o
  2. 给新对象的内部属性赋值,关键是给 [[Prototype]] 属性赋值,构造原型链。若构造函数的原型为 Object 类型,则指向构造函数的原型,否则执行 Object 对象的原型;
  3. 内部 this 指向 o ,执行构造函数;
  4. 若构造函数显式返回对象,则返回该对象,否则返回 o

new 实现

根据上两节的内容,我们可以尝试自己实现 new

代码语言:javascript
复制
function my_new() {
  // 创建一个空的对象
  let o = {};
  // 获得构造函数
  let constructor = [].shift.call(arguments);
  // 链接到原型
  let prototype =
    typeof constructor.prototype === "object"
      ? constructor.prototype
      : Object.prototype;
  o.__proto__ = prototype;
  // 绑定 this,执行构造函数
  let result = constructor.apply(o, arguments);
  // 确保 new 出来的是个对象
  return typeof result === "object" ? result : o;
}

function Foo(name) {
  this.name = name;
}

const obj = my_new(Foo, "Jiahonzheng");
console.log(obj); // {name: "Jiahonzheng"}

instanceof 原理

我们可以通过 instanceof 判断某个对象的类型,其内部机制是通过判断对象的原型链中是否能找到类型的 prototype

值得注意的是,null instanceof Object 返回 false ,所以 null 不是 Object 类型,尽管 typeof null 返回 "Object"

PS:typeof null 返回 "Object" 情况的出现是因为:在 JS 的最初版本中,使用的是 32 位系统,为了性能考虑使用低位存储变量的类型信息,000 开头代表的是对象,而 null 所有数据位为零,故 typeof 错误地将它判断为 object 。虽然现在内部类型判断代码已经改变,但是这个 Bug 仍在流传。

instanceof 实现

代码语言:javascript
复制
function instanceOf(left, right) {
  // 获得类型的原型
  let prototype = right.prototype;
  // 获得对象的原型
  left = left.__proto__;
  // 判断对象的类型是否等于类型的原型
  while (true) {
    if (left === null) return false;
    if (prototype === left) return true;
    left = left.__proto__;
  }
}

const Foo = function() {};
const o = new Foo();

console.log(instanceOf(o, Foo)); // true

// 重写 Foo 原型
Foo.prototype = {};
console.log(instanceOf(o, Foo)); // false

注意

  • 当构造函数为箭头函数时,无法使用 new 调用,原因是箭头函数无 [[Construct]] 方法。
  • 对于实例对象来说,都是通过 new 生成的。
  • 推荐使用字面量的方式创建对象,因为在使用 new Object() 的方式创建对象,需要通过作用域链层层查找到 Object ,而在使用字面量时,则无此问题。
  • new 运算符优先级问题: function Foo() { return this; } Foo.func = function() { console.log("1"); }; Foo.prototype.func = function() { console.log("2"); }; new Foo.func(); // new (Foo.func()); -> 1 new Foo().func(); // (new Foo()).func(); -> 2
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • new 原理
  • new 实现
  • instanceof 原理
  • instanceof 实现
  • 注意
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档