前端面试手写代码——模拟实现new运算符
预备知识:
- 了解原型和原型链
- 了解
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来创建实例
公众号【前端嘛】获取更多优质内容
前端面试手写代码——模拟实现new运算符的更多相关文章
- 前端面试手写代码——call、apply、bind
1 call.apply.bind 用法及对比 1.1 Function.prototype 三者都是Function原型上的方法,所有函数都能调用它们 Function.prototype.call ...
- 前端面试手写代码——JS函数柯里化
目录 1 什么是函数柯里化 2 柯里化的作用和特点 2.1 参数复用 2.2 提前返回 2.3 延迟执行 3 封装通用柯里化工具函数 4 总结和补充 1 什么是函数柯里化 在计算机科学中,柯里化(Cu ...
- 前端面试手写代码——JS数组去重
目录 1 测试用例 2 JS 数组去重4大类型 2.1 元素比较型 2.1.1 双层 for 循环逐一比较(es5常用) 2.1.2 排序相邻比较 2.2 查找元素位置型 2.2.1 indexOf ...
- 3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖
本次博客的目标 1. 手写spring循环依赖的整个过程 2. spring怎么解决循环依赖 3. 为什么要二级缓存和三级缓存 4. spring有没有解决构造函数的循环依赖 5. spring有没有 ...
- zen-coding for notepad++,前端最佳手写代码编辑器
zen-Coding是一款快速编写HTML,CSS(或其他格式化语言)代码的编辑器插件,这个插件可以用缩写方式完成大量重复的编码工作,是web前端从业者的利器. zen-Coding插件支持多种编辑器 ...
- js面试-手写代码实现new操作符的功能
我们要搞清楚new操作符到底做了一些什么事情? 1.创建一个新的对象 2.将构造函数的作用域赋给新对象(因此this指向了这个新对象) 3.执行构造函数中的代码(为这个新对象添加属性) 4.返回新对象 ...
- Java面试手写代码题
1.栈实现 2.Iterator实现 3.单例 4.多线和控制(暂停,恢复,停止) 5.生产者消费者
- 2019前端面试系列——JS高频手写代码题
实现 new 方法 /* * 1.创建一个空对象 * 2.链接到原型 * 3.绑定this值 * 4.返回新对象 */ // 第一种实现 function createNew() { let obj ...
- .netER的未来路,关于基础是否重要和应该自己手写代码吗?
http://www.cnblogs.com/onepiece_wang/p/5558341.html#!comments 引用"基础知识的学习,一开始可能是背书,但是在后续若干年的工作过程 ...
随机推荐
- Consul+Ocelot+Polly在.NetCore中使用(.NET5)-网关Ocelot+Consul
相关文章 Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Consul服务注册,服务发现 Consul+Ocelot+Polly在.NetCore中使用(.NET5)-网 ...
- 在PHP中灵活使用foreach+list处理多维数组
先抛出问题,有时候我们接收到的参数是多维数组,我们需要将他们转成普通的数组,比如: $arr = [ [1, 2, [3, 4]], [5, 6, [7, 8]], ]; 我们需要的结果是元素1变成1 ...
- html 随笔-水平控件不对齐的解决办法
分别在左右两个控件的css代码中加上 vertical-align:top. 便可对齐:(推荐使用,因为这样可以避免脱标流). 来源: https://www.jianshu.com/p/f00d51 ...
- CentOS Linux 简单安装 clickhouse
本文只是仅仅的介绍安装 至于更多介绍请自信百度 1.本人 linux版本 [root@localhost /]# cat /etc/redhat-releaseCentOS Linux release ...
- 深入xLua实现原理之C#如何调用Lua
本文主要是探讨xLua下C#调用Lua的实现原理,有关Lua如何调用C#的介绍可以查看深入xLua实现原理之Lua如何调用C# C#与Lua数据通信机制 无论是Lua调用C#,还是C#调用Lua,都需 ...
- Django边学边记——中间件
特点 Django中的中间件是一个轻量级.底层的插件系统,可以介入Django的请求和响应处理过程,用于全局修改Django的输入或输出. 每个中间件组件负责做一些特定的功能.中间件全部注册在sett ...
- CF1556E-Equilibrium【栈,树状数组】
正题 题目连接:https://codeforces.com/contest/1556/problem/E 题目大意 两个长度为\(n\)的序列\(a,b\),\(q\)次询问一个区间\([l,r]\ ...
- P3190-[HNOI2007]神奇游乐园【插头dp】
正题 题目链接:https://www.luogu.com.cn/problem/P3190 题目大意 \(n*m\)的网格上有权值,求一条权值和最大的不交回路. \(1\leq n\leq 100, ...
- P6076-[JSOI2015]染色问题【组合数学,容斥】
正题 题目链接:https://www.luogu.com.cn/problem/P6076 题目大意 给出\(n*m\)的网格,\(c\)种颜色涂色要求 每个格子可以染色也可以不染 每一行每一列至少 ...
- C++面向行输入:get()与getline()
面向行的输入:get()与getline() 引入: char a = 's';//这样的语句合法 char b = "s";//不合法 /* "S"不是字符常 ...