深入理解new运算符

在 JavaScript 中,new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。创建一个对象很简单,为什么我们还要多此一举使用 new 运算符呢?它到底有什么样的魔力?

认识 new 运算符

通过下面的例子理解 new 运算符:

function Person (name) {
  this.name = name
}

Person.prototype.getName = function () {
  console.log(this.name)
}

var joe = new Person('joe')

joe.sayHello = function () {
  console.log('Hello!')
}

joe.getName() // joe
joe.sayHello() // Hello!

Person.sayHello() // Uncaught TypeError: Person.sayHello is not a function

Person 是一个普通的函数,当它与 new 运算符一起使用时,Person 就是一个构造函数。通过 new Person('joe') 得到的新对象 joe 继承了 Person 的属性,同时,this 也指向 joe 实例。为 joe 添加的属性 sayHello 不会影响 Person,即 joe 是区别与 Person 的一个新对象。

因此,通过 new 创建的实例对象和构造函数之间建立了一条原型链,并通过原型链赋予实例对象继承属性的能力

new 的原理和实现

通过上面的分析,new 运算符内部做了如下四个操作:

  • 创建一个空的简单 JavaScript 对象(即{});
  • 链接新对象(即设置该新对象的构造函数)到函数对象;
  • 将新创建的对象作为 this 的上下文;
  • 如果该函数没有返回对象,返回新创建的对象。

new 的实现如下:

function newOperator (ctor, ...args) {
  var obj = {};
  obj.__proto__ = ctor.prototype
  var res = ctor.apply(obj, args)
  return res || obj;
}

优化一下代码:

function newOperator (ctor, ...args) {
  var o = Object.create(ctor.prototype) // 合并第一和第二步:创建一个空的简单 JavaScript 对象(即{}),链接新对象(即设置该新对象的构造函数)到函数对象
  return fn.apply(o, args) || o
}

使用 newOperator 函数测试上面 Person 的例子:

function Person(name) {
  this.name = name
}

Person.prototype.getName = function () {
  console.log(this.name)
}

var joe = newOperator(Person, 'joe')

joe.sayHello = function () {
  console.log('Hello!')
}

joe.getName() // joe
joe.sayHello() // Hello!

Person.sayHello() // Uncaught TypeError: Person.sayHello is not a function

结果是一致的。

更好的检查方式是:

function Person(name) {
  this.name = name
}

console.log(new Person('joe')) // @1
console.log(newOperator(Person, 'joe')) // @2

@1 和 @2 在控制台的显示信息是一模一样的。

判断是否使用 new 关键字

在 JavaScript 中,一个实例对象的创建必须使用 new 关键字。但是限于 JavaScript 的语法特征,实际上构造函数同样可以像普通函数那样直接执行。那么构造函数内部如何判断是否使用了 new 关键字?

使用 instanceof 检测

通过理解 new 操作符的原理,可知,在执行 new 操作时,构造函数的 prototype 赋值给了实例的 proto 属性。在 JavaScript 中 instanceof 可以用来检测对象的原型链,如:a instanceof A 用来检测 a 是否是 A 的实例(即 a 的原型链中存在原型对象 A)。

function Person () {
  if (this instanceof Person) {
    console.log('new 调用')
  } else {
    console.log('普通函数调用')
  }
}

const foo = new Person() // new 调用
const bar = Person()     // 普通函数调用

使用 new.target 属性

在 ES6 中引入了 new.target 属性,new.target 属性允许你检测函数或构造方法是否是通过 new 运算符被调用的。在通过 new 运算符被初始化的函数或构造方法中,new.target 返回一个指向构造方法或函数的引用。在普通的函数调用中,new.target 的值是 undefined。

function Person () {
  console.log(new.target)
}

const foo = new Person() // ƒ Person () { console.log(new.target) }
const bar = Person()     // undefined
(0)

相关推荐

  • JavaScript – 继承

      课程大纲  一.继承 1.继承和UML图 2.构造函数继承 3.原型链继承 4.混合继承 二.闭包 1.什么是闭包 2.闭包的原理 3.闭包的应用   继承和UML图  首先来看类的继承 1.父类 ...

  • 利用构造函数创建对象

    我们为什么要使用构造函数? 1:普通的字面量方式和new Object创建的对象方式一次只能创建一个对象,而里面的 属性和方法大多是重复使用的.当我们想创建多个相同属性和方法的对象并重复使用,就需要使 ...

  • 什么是原型链

    对象原型 相信大家都这样用过 map : let arr = [0, 1, 2]let doubleArr = arr.map(c => c * 2)console.log(doubleArr) ...

  • C++核心编程

    时间:2021-03-09 13:17:24                        主要针对C++面向对象编程技术做详细讲解,探讨C++中的核心和精髓. 1.内存分区模型 C++程序在执行时, ...

  • 全国人大常委会关于《中华人民共和国刑法》第九章渎职罪主体适用问题的解释(附:理解与适用)

    ☞[招募律师站长]☜ 全国人民代表大会常务委员会关于<中华人民共和国刑法>第九章渎职罪主体适用问题的解释 (2002年12月28日通过) 全国人大常委会根据司法实践中遇到的情况,讨论了刑法 ...

  • 体谅与理解

    人生的路上,如果懂得体谅,懂得理解,懂得宽容,日子就会很温馨,也会很安宁. 人生的路上,如果缺少体谅,不能理解,没有谦让,日子就会很糟糕,越过越烦恼. 生活中的很多烦恼,就是源于我们不能够体谅,过分在 ...

  • 色盲患者看到的世界永远黑白的,他们是无法理解世界的真实色彩的

    哲学那点事(五)--我能认知什么?色盲患者看到的世界永远黑白的,他们是无法理解世界的真实色彩的色盲是由于视网膜视锥细胞中的光敏色素异常或不全所导致的色觉紊乱,从而缺乏辨别一种或多种颜色的能力.色盲又分 ...

  • 特级教师:初中阅读理解33个答题公式 60篇训练题,挑战1分不扣

    语文考试中,同学们普遍认为最难的不是作文,而是阅读理解.初中语文阅读理解篇幅大,内容深奥.要么不知道怎么作答,要么答了很多,却不在踩分点上,自我感觉良好,但得分却少得可怜. 而且在考试中,因为阅读理解 ...

  • 古人是这样藏锋的,大多数人理解错了!

    对于书法的初学者,想必在书店市场上应该看到许多关于书法笔法的论述,很多教材都在强调藏锋的重要性,起笔要逆锋藏锋,收笔也要回锋一下,特别是初学颜真卿楷书的人,老师一般会让学生逆锋起笔,如下图所示: 这种 ...

  • 电路模拟器如何帮助您理解任何电路

    电路模拟器是一种"观察"电路功能的工具.电子设备不容易用肉眼检查,如果你打开一个音频放大器,如果你没有设计和建造电子电路的经验,就很难判断它是做什么的. 模拟理解电路 电路模拟器使 ...

  • 法考过关经验贴|六字箴言“基础”、“理解”与“计划”

    法考并不是高考,分数高低对个人来说影响并不大,因此怎样用最少的时间与精力达到目标就是最重要的课题.我的法考经历可以总结为每天学一点,一学小半年:主要经验是"基础"."理解 ...

  • “本是青灯不归客,却因浊酒留风尘,星光不问赶路人,岁月不负有心人”,你是怎么理解的?

    这是网络爆火的诗句,很多人都喜欢它!它是人生逆旅中默默赶路人的心境,留给世人无限况味的的人生禅意.或许有些人不以为然,而当你仔细品味诗中的意境和禅意时,突然就蓦然释怀了,人活一世,一生境况概莫如是. ...

  • 怎么理解单点对焦和多点对焦?9点、21点、39点对焦有什么区别?

    相机中的单点对焦.9点.21点.39点对焦这一块内容,属于自动对焦区域的内容,初学者对这块内容不理解,主要是因为没有把自动对焦区域和自动对焦模式这两块内容结合起来看.在实际拍摄过程中,一般是先根据拍摄 ...