这是我在公众号(高级前端进阶)看到的文章,现在做笔记

https://github.com/yygmind/blog/issues/24

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

举个例子:

function Car(color) {
this.color = color;
}
Car.prototype.start = function() {
console.log(this.color + " car start");
} var car = new Car("black");
car.color; // 访问构造函数里的属性
// black car.start(); // 访问原型里的属性
// black car start

可以看出 new 创建的实例有以下 2 个特性

  • 1、访问到构造函数里的属性
  • 2、访问到原型里的属性

注意点

ES6新增 symbol 类型,不可以使用 new Symbol(),因为 symbol 是基本数据类型,每个从Symbol()返回的 symbol 值都是唯一的。

Number(""); //
String(); // "123"
Boolean(); // true
Symbol(); // Symbol(123) new Number(""); // Number {123}
new String(); // String {"123"}
new Boolean(true); // Boolean {true}
new Symbol(); // Symbol is not a constructor

模拟实现

当代码 new Foo(...) 执行时,会发生以下事情:

  1. 一个继承自 Foo.prototype 的新对象被创建。
  2. 使用指定的参数调用构造函数 Foo ,并将 this 绑定到新创建的对象。new Foo 等同于 new Foo(),也就是没有指定参数列表,Foo 不带任何参数调用的情况。
  3. 由构造函数返回的对象就是 new 表达式的结果。如果构造函数没有显式返回一个对象,则使用步骤1创建的对象。
模拟实现第一步

new 是关键词,不可以直接覆盖。这里使用 create 来模拟实现 new 的效果。

new 返回一个新对象,通过 obj.__proto__ = Con.prototype 继承构造函数的原型,同时通过 Con.apply(obj, arguments)调用父构造函数实现继承,获取构造函数上的属性(【进阶3-3期】)。

实现代码如下:

  // 第一版
function create() {
// 创建一个空的对象
var obj = new Object(),
// 获得构造函数,arguments中去除第一个参数
Con = [].shift.call(arguments);
// 链接到原型,obj 可以访问到构造函数原型中的属性
obj.__proto__ = Con.prototype;
// 绑定 this 实现继承,obj 可以访问到构造函数中的属性
Con.apply(obj, arguments);
// 返回对象
return obj;
};

测试一下

// 测试用例
function Car(color) {
this.color = color;
}
Car.prototype.start = function() {
console.log(this.color + " car start");
} var car = create(Car, "black");
car.color;
// black car.start();
// black car start

完美!

不熟悉 apply / call 的点击查看:【进阶3-3期】深度解析 call 和 apply 原理、使用场景及实现

不熟悉继承的点击查看:JavaScript常用八种继承方案

模拟实现第二步

上面的代码已经实现了 80%,现在继续优化。

构造函数返回值有如下三种情况:

  • 1、返回一个对象
  • 2、没有 return,即返回 undefined
  • 3、返回undefined 以外的基本类型

情况1:返回一个对象

function Car(color, name) {
this.color = color;
return {
name: name
}
} var car = new Car("black", "BMW");
car.color;
// undefined car.name;
// "BMW"

实例 car 中只能访问到返回对象中的属性。

情况2:没有 return,即返回 undefined

function Car(color, name) {
this.color = color;
} var car = new Car("black", "BMW");
car.color;
// black car.name;
// undefined

实例 car 中只能访问到构造函数中的属性,和情况1完全相反。

情况3:返回undefined 以外的基本类型

function Car(color, name) {
this.color = color;
return "new car";
} var car = new Car("black", "BMW");
car.color;
// black car.name;
// undefined

实例 car 中只能访问到构造函数中的属性,和情况1完全相反,结果相当于没有返回值。

所以需要判断下返回的值是不是一个对象,如果是对象则返回这个对象,不然返回新创建的 obj对象。

所以实现代码如下:

// 第二版
function create() {
// 创建一个空的对象
var obj = new Object(),
// 获得构造函数,arguments中去除第一个参数
Con = [].shift.call(arguments);
// 链接到原型,obj 可以访问到构造函数原型中的属性
obj.__proto__ = Con.prototype;
// 绑定 this 实现继承,obj 可以访问到构造函数中的属性
var ret = Con.apply(obj, arguments);
// 优先返回构造函数返回的对象
return typeof ret === 'object' ? ret : obj;
};

【进阶3-5期】深度解析 new 原理及模拟实现(转)的更多相关文章

  1. 【进阶3-4期】深度解析bind原理、使用场景及模拟实现(转)

    这是我在公众号(高级前端进阶)看到的文章,现在做笔记  https://github.com/yygmind/blog/issues/23 bind() bind() 方法会创建一个新函数,当这个新函 ...

  2. 深度解析 Vue 响应式原理

    深度解析 Vue 响应式原理 该文章内容节选自团队的开源项目 InterviewMap.项目目前内容包含了 JS.网络.浏览器相关.性能优化.安全.框架.Git.数据结构.算法等内容,无论是基础还是进 ...

  3. mysql索引原理深度解析

    mysql索引原理深度解析 一.总结 一句话总结: mysql索引是b+树,因为b+树在范围查找.节点查找等方面优化 hash索引,完全平衡二叉树,b树等 1.数据库中最常见的慢查询优化方式是什么? ...

  4. java8Stream原理深度解析

    Java8 Stream原理深度解析 Author:Dorae Date:2017年11月2日19:10:39 转载请注明出处 上一篇文章中简要介绍了Java8的函数式编程,而在Java8中另外一个比 ...

  5. 并发编程(十五)——定时器 ScheduledThreadPoolExecutor 实现原理与源码深度解析

    在上一篇线程池的文章<并发编程(十一)—— Java 线程池 实现原理与源码深度解析(一)>中从ThreadPoolExecutor源码分析了其运行机制.限于篇幅,留下了Scheduled ...

  6. 并发编程(十二)—— Java 线程池 实现原理与源码深度解析 之 submit 方法 (二)

    在上一篇<并发编程(十一)—— Java 线程池 实现原理与源码深度解析(一)>中提到了线程池ThreadPoolExecutor的原理以及它的execute方法.这篇文章是接着上一篇文章 ...

  7. spring5 源码深度解析----- 被面试官给虐懵了,竟然是因为我不懂@Configuration配置类及@Bean的原理

    @Configuration注解提供了全新的bean创建方式.最初spring通过xml配置文件初始化bean并完成依赖注入工作.从spring3.0开始,在spring framework模块中提供 ...

  8. VueRouter 源码深度解析

    VueRouter 源码深度解析 该文章内容节选自团队的开源项目 InterviewMap.项目目前内容包含了 JS.网络.浏览器相关.性能优化.安全.框架.Git.数据结构.算法等内容,无论是基础还 ...

  9. 《SEO深度解析——全面挖掘搜索引擎优化的核心秘密》

    <SEO深度解析——全面挖掘搜索引擎优化的核心秘密> 基本信息 作者: 痞子瑞 出版社:电子工业出版社 ISBN:9787121224041 上架时间:2014-2-28 出版日期:201 ...

随机推荐

  1. getservbyname和getservbyport

    一.getservbyname函数原型 #include <netdb.h> struct servent *getservbyname(const char *servname, con ...

  2. 移动端300ms延迟解决方法在vue 里面的一些小坑

    话不多说上图: 至于import为什么会报错,瞅下面这个图: 总结:要搞懂个必须了解下es6的解构赋值才能在这方面装逼,网上资料一大堆自行百度.

  3. Maven项目配置logback

    首先,在pom.xml中加入maven依赖 <!-- log start --> <dependency> <groupId>org.slf4j</group ...

  4. 【try..catch..】【判断输入是否为空】【onchange事件】【onmouseover和onmouseout事件】【onmousedown和onmouseup事件】

    1.try..catch.. <body><script>function myFunction(){try{ var x=document.getElementById(&q ...

  5. 常用linux命令总结

    Linux 版本 centos 1.查看Linux版本 uname -a 2.查看 ip 地址 ip addr 3.查看端口应用程序 netstat -lanp 如果输入上述命令,显示“-bash: ...

  6. (4)java数据结构--集合类及其数据结构归纳-有大图

    Java集合类及其数据结构归纳 - s小小的我 - 博客园http://www.cnblogs.com/shidejia/p/6433788.html ---------大图可以 在新标签中打开图片 ...

  7. 虚拟机克隆后无法上网的解决(Centos7为例)

    说明:我的虚拟机之前配置的为静态ip 解决步骤: (1)更换mac地址 (2)删除 etc/udev/rules.d/70-persistent-net.rules 删除后重启机器,系统会自动生成一个 ...

  8. Django入门------基础(1)

    基础 Django 是用 Python 写的一个自由和开放源码 web 应用程序框架.web框架是一套组件,能帮助你更快.更容易地开发web站点.当你开始构建一个web站点时,你总需要一些相似的组件: ...

  9. Springboot实体类转JSON报错Could not find acceptable representation & 设置访问项目根路径的默认欢迎页面

    =================实体类转JSON报错的解决办法============= 之前在springmvc的时候也报过这个错,原因以及springmvc中解决办法参考:https://www ...

  10. Hibernate学习(三)

    Hibernate的查询方法(五种) 一.OID查询:按主键查询 --get( ) --load( ) 二.对象导航查询:通过已经查询到的联系人,得到起关联的对象 三.SQL查询 四.HQL查询(** ...