JavaScript中new操作符的原理与实现详解

作者:来碗盐焗星球 时间:2024-05-22 10:31:07 

一、new做了哪些事

先看看new的使用场景:

// 1、创建一个构造函数
function Vehicle(name, price) {
   this.name = name
   this.price = price
}
?
// 2、new一个实例对象
let truck = new Vehicle()
console.log(truck); //Vehicle { name: undefined, price: undefined }
console.log(Object.prototype.toString.call(truck)); //[object Object]
?
// 传入参数
let car = new Vehicle('car', '¥9999999')
console.log(car);
//Vehicle { name: 'car', price: '¥9999999' }

司空见惯的代码,烂熟于心的写法,那你知道new具体做了哪些事情嘛?从上述代码可以看出,一个构造函数使用new操作符调用的时候,会生成一个具有构造函数相同属性的新对象。是不是很奇怪?明明Vehicle是构造函数:

console.log(typeof Vehicle); //function

然而,经过new的一番操作后,它的实例化是一个对象!!!new到底做了哪些事情呢?对于这个例子,我们可以概括为以下事情:

?
   // 第一件:在构造函数内部,创建一个this对象
   let this = {
       name = name,
       price = price
   }
?
   // 第二件:返回this对象
   return this;
?
   // 第三件:给this对象的属性赋值
   this.name = name
   this.price = price

很抽象,看不懂。。。进一步剖析如下:

function Person(name, gender) {
   console.log('赋值前的this=', this); //赋值前的this= Person {}
   this.name = name
   this.gender = gender
   console.log('赋值后的this=', this); //赋值后的this= Person { name: '小灰灰', gender: 'boy' }
}
?
let child = new Person('小灰灰', 'boy')//Person { name: '小灰灰', gender: 'boy' }
console.log(child);

JavaScript中new操作符的原理与实现详解

由以上代码可以看出,

第一:在构造函数内部有一个空的this对象,通过new操作符,会创建生成一个全新的对象(实例对象)。

第二:实例对象会执行[[Prototype]]( .proto)链接,并且实例对象的this会指向构造函数的this(实例对象会绑定函数调用的this)。通过new创建的实例对象最终被[[Prototype]]( .proto)链接到构造函数的Prototype对象上。也就是说,实例对象的隐式原型===构造函数的显示原型

二、返回不同类型时有哪些表现

创建一个构造函数X,通过new操作符,实例化X得到实例化对象x,打印x,一定会是X{...}这个对象嘛?当构造函数内部有返回值,并且返回的是不同类型的值,打印的结果又会是怎么样呢?

function Student(id, name) {
   this.id = id
   this.name = name
?
   // 返回基本类型的值时:返回的结果依然是对象Student {name:xxx,age:xxx}
   // return null   //Student { id: '1001', name: 'cat' }
   // return undefined //Student { id: '1001', name: 'cat' }
   // return 123        //Student { id: '1001', name: 'cat' }
   // return 'hello world'   //Student { id: '1001', name: 'cat' }
   // return true  //Student { id: '1001', name: 'cat' }
   // return false  //Student { id: '1001', name: 'cat' }
   //return Symbol('abc')  //Student { id: '1001', name: 'cat' }
?
   // 返回引用类型时:
   //返回空对象时:返回的结果是空对象
   // return {}  //{}
   //返回函数时,返回的结果是函数
   return function() {} //[Function (anonymous)]
   // return [] //[]
   // return new Date() //2022-10-24T04:44:18.581Z
   // return new Error() //Error...
}
?
let student = new Student('1001', 'cat')
console.log(student); //构造函数内部返回不同类型的值时,这里的打印结果是一样的吗?

三、手写new的实现原理

思路:new的实现原理核心是new做了哪些事情。

总结:

(1)通过new操作符调用构造函数,会返回一个全新的对象,这个对象的属性是构造函数的参数。

若构造函数内部有返回值,且返回值是基本数据类型(number|string|null|undefined|Symbol|boolean),则实例对象的返回结果是原本的对象;

若返回值是引用数据类型(Object|Array|Function|Date|RegExp|Error),则实例对象的返回的结果就是引用类型对应的值。

(2)通过new操作符创建的实例对象的隐式原型会挂载到构造函数的显示原型上。实例对象.proto==构造函数.prototype。

(3)通过new操作符创建的实例对象的this会绑定调用函数的this 请看如下代码:

// new的实现原理
function newPerson() {
   // 先return一个对象
   var obj = {};

var constructor = Array.prototype.shift.call(arguments); //把数组的shift方法借给constructor使用

// 实例对象的隐式原型===构造函数的显示原型
   obj._proto_ = constructor.prototype;
   var result = constructor.apply(obj, arguments);
   return typeof result === 'object' && result != 'null' ? result : obj;
}
?
let p = newPerson(Person, 'hunny')
console.log(p); //{ _proto_: {}, name: 'hunny', age: undefined }

来源:https://juejin.cn/post/7158073689408274463

标签:JavaScript,new
0
投稿

猜你喜欢

  • Python用模块pytz来转换时区

    2021-05-27 20:09:32
  • Python2与Python3关于字符串编码处理的差别总结

    2022-05-21 19:09:51
  • Python操作SQLite数据库过程解析

    2024-01-26 08:16:38
  • 深入了解Hybrid App技术的相关知识

    2023-08-10 09:36:02
  • OpenCV结合selenium实现滑块验证码

    2022-06-29 14:18:57
  • Sql Server2005对现有数据进行分区具体步骤

    2008-06-26 13:18:00
  • javascript 实现的完全兼容鼠标滚轴缩放图片的代码

    2024-04-10 16:09:43
  • python安装cxOracle避坑总结不要直接pip install

    2023-12-07 09:13:11
  • 使用Abot中文分词组件来开发ASP站内搜索引擎

    2007-10-18 13:36:00
  • Oracle 数据库中创建合理的数据库索引

    2024-01-24 12:37:05
  • Python中unittest用法实例

    2023-09-02 13:13:45
  • Git 的基本操作、开发流程、实用技巧总结(陈彦贝)

    2022-05-10 03:03:35
  • MySQL用truncate命令快速清空一个数据库中的所有表

    2024-01-18 16:05:29
  • python使用递归的方式建立二叉树

    2021-07-07 23:47:18
  • 使用Python脚本实现批量网站存活检测遇到问题及解决方法

    2022-04-12 00:50:03
  • sqlserver巧用row_number和partition by分组取top数据

    2024-01-28 12:33:39
  • 自然选择:自然界的颜色与界面设计[译]

    2009-09-19 17:17:00
  • 精巧支付宝导航条制作教程

    2010-03-20 21:25:00
  • php全局变量和类配合使用深刻理解

    2023-11-18 19:50:17
  • python中可以声明变量类型吗

    2022-02-13 19:44:05
  • asp之家 网络编程 m.aspxhome.com