手写实现JS中的new


Posted in Javascript onNovember 07, 2021

⚠ 预备知识:

  • 了解原型和原型链
  • 了解this绑定

1 new 运算符简介

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

class Person {
    constructor(name) {
        this.name = name;
    }
}
// 创建自定义对象类型的实例
const person = new Person('小明')
// 创建具有构造函数的内置对象的实例
const date = new Date()

new的作用:创建对象的实例

2 new 究竟干了什么事

上面说了new的作用是创建对象的实例,那么它究竟是怎么创建实例的,内部干了哪几件事?

以new Person()为例,当它执行时,会发生以下事情:

创建一个空的简单JS对象

const obj = {}

给这个对象添加属性__proto__,并将该属性链接到构造函数的原型对象

obj.__proto__ = Person.prototype

调用构造函数Person,并将this绑定到新创建的对象obj

Person.apply(obj)

如果构造函数没有显式返回一个对象,则返回新创建的对象,即obj

3 模拟实现 new 运算符

如上所述,new运算符就干了这么4件事,下面我们就根据这4个步骤用函数来模拟实现new(面试手写代码)

const _new = function(constructor, ...args) {
    const obj = {}
    obj.__proto__ = constructor.prototype
    const res = constructor.apply(obj, args)
    // 这一步在"补充"中会详细解释
    return res instanceof Object ? res : obj
}

代码非常简单,就是按照上面4步,一步一步写就可以了

4 补充

ES5提供了Object.create方法,该方法可以创建一个对象,并让新对象的__proto__属性指向已经存在的对象。

所以我们可以使用这个方法合并1、2两步

const obj = Object.create(constructor.prototype)
// 等价于
const obj = {}
obj.__proto__ = constructor.prototype

对于第4步,再解释一下

  • 如果构造函数没有显式return(通常情况)那么person就是新创建的对象obj
  • 如果构造函数返回的不是一个对象,比如1、"abc" 那么person还是新创建的对象obj
function Person() {
    ...
   return 1
}

如果构造函数显式返回了一个对象,比如{}function() {}

那么person就不是新创建的对象obj了,而是显式return的这个对象

function Person() {
  // 函数也是对象
  return function() {}
}

所以我们在_new函数最后一句代码是:

return res instanceof Object ? res : obj

注意:模拟实现的函数_new传入的参数只能是构造函数,不能是类

class Animal {  ...}_new(Animal)// 会报错:Class constructor Animal cannot be invoked without 'new'// 类只能通过new来创建

到此这篇关于手写实现JS中的new的文章就介绍到这了,更多相关JS中的new内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
js原生appendChild的bug解决心得分享
Jul 01 Javascript
div模拟选择框示例代码
Nov 03 Javascript
基于jquery实现ajax无刷新评论
Aug 19 Javascript
canvas 实现中国象棋
Feb 17 Javascript
JavaScript编写的网页小游戏,很给力
Aug 18 Javascript
浅谈angular4 ng-content 中隐藏的内容
Aug 18 Javascript
Angular使用动态加载组件方法实现Dialog的示例
May 11 Javascript
jQuery实现百度图片移入移出内容提示框上下左右移动的效果
Jun 05 jQuery
Vue项目报错:Uncaught SyntaxError: Unexpected token
Nov 10 Javascript
vue中使用[provide/inject]实现页面reload的方法
Sep 30 Javascript
基于javascript处理nginx请求过程详解
Jul 07 Javascript
8个非常实用的Vue自定义指令
Dec 15 Vue.js
用JS写一个发布订阅模式
Nov 07 #Javascript
浅谈JavaScript浅拷贝和深拷贝
JavaScript严格模式不支持八进制的问题讲解
Javascript使用integrity属性进行安全验证
Nov 07 #Javascript
JavaScript中时间格式化新思路toLocaleString()
Nov 07 #Javascript
JavaScript中isPrototypeOf函数
JavaScript原型链详解
You might like
PHP 模拟$_PUT实现代码
2010/03/15 PHP
关于UEditor编辑器远程图片上传失败的解决办法
2012/08/31 PHP
PHP执行批量mysql语句的解决方法
2013/05/02 PHP
根据当前时间在jsp页面上显示上午或下午
2014/08/18 Javascript
javascript判断css3动画结束 css3动画结束的回调函数
2015/03/10 Javascript
Javascript编写俄罗斯方块思路及实例
2015/07/07 Javascript
Node.js实现JS文件合并小工具
2016/02/02 Javascript
浅谈JavaScript中变量和函数声明的提升
2016/08/09 Javascript
angular实现图片懒加载实例代码
2017/06/08 Javascript
微信小程序之电影影评小程序制作代码
2017/08/03 Javascript
checkbox:click事件触发span元素内容改变的方法
2017/09/11 Javascript
Nodejs 和 Electron ubuntu下快速安装过程
2018/05/04 NodeJs
微信小程序scroll-view实现滚动穿透和阻止滚动的方法
2018/08/20 Javascript
详解如何用VUE写一个多用模态框组件模版
2018/09/27 Javascript
JavaScript代码调试方法实例小结
2019/01/05 Javascript
js嵌套的数组扁平化:将多维数组变成一维数组以及push()与concat()区别的讲解
2019/01/19 Javascript
NodeJs操作MongoDB教程之分页功能以及常见问题
2019/04/09 NodeJs
Javascript 关于基本类型和引用类型的个人理解
2019/11/01 Javascript
vue v-for 点击当前行,获取当前行数据及event当前事件对象的操作
2020/09/10 Javascript
[48:28]完美世界DOTA2联赛循环赛FTD vs Magma第二场 10月30日
2020/10/31 DOTA
ptyhon实现sitemap生成示例
2014/03/30 Python
python实现定制交互式命令行的方法
2014/07/03 Python
学习python 之编写简单乘法运算题
2016/02/27 Python
详解python多线程、锁、event事件机制的简单使用
2018/04/27 Python
使用urllib库的urlretrieve()方法下载网络文件到本地的方法
2018/12/19 Python
如何使用Python标准库进行性能测试
2019/06/25 Python
在cmd中查看python的安装路径方法
2019/07/03 Python
python ETL工具 pyetl
2020/06/07 Python
Python中使用Selenium环境安装的方法步骤
2021/02/22 Python
洛杉矶生活休闲而精致的基础品牌:Mika Jaymes
2018/01/07 全球购物
服务生自我鉴定
2014/01/22 职场文书
九年级英语教学反思
2014/01/31 职场文书
邀请函范文
2015/02/02 职场文书
简爱电影观后感
2015/06/10 职场文书
Python实现位图分割的效果
2021/11/20 Python
分享7个 Python 实战项目练习
2022/03/03 Python