一道面试题引发的思考:理解 new 运算符

栏目: JavaScript · 发布时间: 5年前

内容简介:今天看到一道面试题,如下,问: 实例化说实话,第一反应我以为值为很显然,输出的结果是

今天看到一道面试题,如下,问: 实例化 Person 过程中, Person 返回什么(或者 p 等于什么)?

function Person(name) {
    this.name = name
    return name;
}
let p = new Person('Tom');
复制代码

说实话,第一反应我以为值为 'Tom' ,等到我把代码丢到控制台一输出,才明白我错了。天呐, new 运算符给无视掉了吗??? 撇开 new 的存在,我们修改下代码

function Person(name) {
    this.name = name
    return name;
}
let p = Person('Tom');
console.log(p);
复制代码

很显然,输出的结果是 'Tom' , 但是有 new 存在呢?接下去,我们来捋一捋。 首先,我先去MDN上搜索了 new 的定义

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

emmmm,相当晦涩难懂。

那我们试着写几个栗子看看结果吧

function Person1(name) {
  this.name = name;
  // 没有返回值
}

function Person2(name) {
  this.name = name;
  return name;
  // 返回非对象
}

function Person3(name) {
  this.name = name;
  return { a: 1 };
  // 返回对象
}

function Person4(name) {
  this.name = name;
  return null;
  // 返回null
}

var p1 = new Person1("aa");
var p2 = new Person2("bb");
var p3 = new Person3("cc");
var p4 = new Person4("dd");

console.log(p1); // Person1 {name: "aa"}
console.log(p2); // Person2 {name: "bb"}
console.log(p3); // {a: 1}
console.log(p4); // Person4 {name: "dd"}
复制代码

根据上面几个栗子,我们能得出结论:当使用 new 来创建对象||调用构造函数时,如果函数没有返回值|| 返回值是非对象,那么返回的就是构造函数实例后的对象;如果函数return对象,那么返回这个对象(特例: return null ,返回的也是构造函数实例后的对象而非 null )

我们接着看MDN 文档的解释,毕竟光光看这几个demo没有说服力。

一道面试题引发的思考:理解 new 运算符

一起来理解下 new 到底做了什么工作吧~ 就拿下面这个 demo 分析

function Person(name) {
  this.name = name;
  return {a: 1}
}
var p = new Person('fefeng')
复制代码

当调用 new Person(...) 时,会进行以下几步:

  • 首先是 继承自 Person.prototype 的新对象会被创建
  • 使用参数 'fefeng' 调用构造函数 Person , 并将 this 绑定到新创建的对象
  • Person 返回的对象就是 new 表达式的结果 =》 Person 返回的对象是 {a: 1} 所以 new 表达式的结果为 {a:1} ; 如果 Person 没有返回值(一般构造函数都不返回值)那么使用步骤1创建的对象,即==》 继承自 Person.prototype 的新对象

貌似照着文档能够些许理解了,倘若模拟实现 new 运算符更能深入理解 new 以下是 new 的模拟实现,代码来源 : JavaScript深入之new的模拟实现

function objectFactory() {
  var obj = new Object(),
  cons = [].shift.call(arguments)
  obj.__proto__ = cons.prototype
  var ret = cons.apply(obj, arguments)
  return typeof ret === 'object' ? ret|| obj : obj
}
function Person(name) {
  this.name = name;
  return {a: 1}
}
var p = objectFactory(Person, 'fefeng')
复制代码

当然了,学习别人的代码不能仅仅只是照搬过来,起码得理解这个代码吧。 使用

  • 首先是创建一个对象
  • cons 是调用 objectFactory 方法的第一个参数,即构造函数; 因为 shift 会改变原数组,所以改变后的 argument 即为调用构造函数的参数 (这里补充说明下: arguments 是一个对应于传递给函数的参数的类数组对象。)
  • obj 的原型指向构造函数, 这样 obj 就能访问到构造函数原型上的属性
  • 将构造函数 consthis 指向 obj ,这样 obj 能访问构造函数里的属性
  • 判断返回的值是不是一个对象,如果是对象即返回它(当然这里要处理 return null 的特例);如果不是对象就返回 obj (注意:这里的 obj 已经不是一个空对象)

如果你耐心看到了这里,那么十分感谢。如文章有错误,望给予指正~


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

C陷阱与缺陷

C陷阱与缺陷

凯尼格 / 高巍 / 人民邮电出版社 / 2008-2-1 / 30.00元

作者以自己1985年在Bell实验室时发表的一篇论文为基础,结合自己的工作经验扩展成为这本对C程序员具有珍贵价值的经典著作。写作本书的出发点不是要批判C语言,而是要帮助C程序员绕过编程过程中的陷阱和障碍。.. 全书分为8章,分别从词法分析、语法语义、连接、库函数、预处理器、可移植性缺陷等几个方面分析了C编程中可能遇到的问题。最后,作者用一章的篇幅给出了若干具有实用价值的建议。.. 本书......一起来看看 《C陷阱与缺陷》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试