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

 更新时间:2022年10月25日 15:55:59   作者:来碗盐焗星球  
你知道new吗?你知道new的实现原理吗?你能手写new方法吗?不要担心,这篇文件就来带大家深入了解一下JavaScript中的new操作符,感兴趣的小伙伴可以学习一下

一、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);

由以上代码可以看出,

第一:在构造函数内部有一个空的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 }

以上就是JavaScript中new操作符的原理与实现详解的详细内容,更多关于JavaScript new操作符的资料请关注脚本之家其它相关文章!

相关文章

  • JS组件Bootstrap实现图片轮播效果

    JS组件Bootstrap实现图片轮播效果

    这篇文章主要为大家详细介绍了JS组件Bootstrap实现图片轮播效果的具体代码,对图片轮播效果感兴趣的小伙伴们可以参考一下
    2016-05-05
  • 创建一般js对象的几种方式

    创建一般js对象的几种方式

    本文主要介绍了创建一般js对象的几种方式。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-01-01
  • 轻松5句话解决JavaScript的作用域

    轻松5句话解决JavaScript的作用域

    作用域(scope)是javascript语言的基石之一,在构建复杂程序时可能是最头痛的东西,所以这里罗列了五句话轻松搞定并且附上了示例。给需要的朋友参考学习。
    2016-07-07
  • 实例讲解避免javascript冲突的方法

    实例讲解避免javascript冲突的方法

    这篇文章主要以实例的方式讲解了避免javascript冲突的方法,具有一定的参考价值,感兴趣的朋友可以参考一下
    2016-01-01
  • javascript的动态加载、缓存、更新以及复用(一)

    javascript的动态加载、缓存、更新以及复用(一)

    在做OA、MIS、ERP等信息管理类的项目,经常会遇到引用很多js文件,这就需要用到动态加载、缓存、更新以及复用等技术,下面我们来讨论下
    2014-06-06
  • JavaScript实现异步图像上传功能

    JavaScript实现异步图像上传功能

    这篇文章主要介绍了JavaScript实现异步图像上传功能,本文展示了一种使用代码示例立即显示图像的方法(使用图像的Base64编码版本),同时将其上载到服务器,而无需等待操作完成。需要的朋友可以参考下
    2018-07-07
  • js函数的引用, 关于内存的开销

    js函数的引用, 关于内存的开销

    函数的引用, 对于内存的开销分析,需要的朋友可以参考下
    2012-09-09
  • javascript数据结构中栈的应用之符号平衡问题

    javascript数据结构中栈的应用之符号平衡问题

    这篇文章主要介绍了javascript数据结构中栈的应用之符号平衡问题,结合实例形式分析了javascript基于栈的形式实现对各种括号如<> {} [] ()等的匹配验证操作相关应用技巧,需要的朋友可以参考下
    2017-04-04
  • javascript利用控件对windows的操作实现原理与应用

    javascript利用控件对windows的操作实现原理与应用

    假如要发送汉字的聊天框的内容的话,我们也要从windows消息机制下手,先找到聊天消息的句柄(可以利用findwindow函数或者用spy工具哈),然后在找到上面的聊天框的句柄,接着我们就可以想这个句柄发送WM_SETTEXT的消息了
    2012-12-12
  • Javascript异步编程模型Promise模式详细介绍

    Javascript异步编程模型Promise模式详细介绍

    异步模式在 Web 编程中变得越来越重要,如何处理异步请求后的操作是一件麻烦事。Promise 是一种异步编程模型,术语称作 Deferred 模式,它通过一组API来规范化异步操作,让异步操作的流程控制更加容易。
    2014-05-05

最新评论