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

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. ES6 快速开始

    Refs 现代框架 Vue React 都使用到了 ES6 (包括D3js) [常量] // ES5 中常量的写法 Object.defineProperty(window, "PI2&qu ...

  2. Spring 快速开始 配置Spring Framework

    [配置Spring Framework] 1.XML配置依赖关系 bean是由Springframework管理,我们自己编写bean,Spring也内建了bean,比如ApplicationCont ...

  3. 20155324 2016-2017-2 《Java程序设计》第2周学习总结

    20155324 2016-2017-2 <Java程序设计>第2周学习总结 教材学习内容总结 Java可区分为基本类型(Primitive Type)和类类型(Class Type)两大 ...

  4. tensorflow/core/kernels/conv_ops.cc:659] check failed: stream->parent()->getc

    tensorflow版本与cudnn版本不对应,如tensorflow-gpu==1.1.0,cudnn==6.0 升级tensorflow-gpu到更高版本

  5. echarts 导出图片,并将图片导出pdf格式

    1.官方下载echarts 包. 2.实例案例: 1)页面: <h2>Index</h2> <div id="main" style="he ...

  6. pyqt5-QWidget坐标系统和大小

    获取坐标和尺寸: 坐标的获取视频教程:https://v.qq.com/x/page/t085892mzh9.html  x()    y()   返回控件的坐标 相对于父控件的坐标(窗口框架左上角) ...

  7. css flex布局详解

    来源:https://blog.csdn.net/liveinmylife/article/details/51838939 1,flex布局是个什么东西? 官方说法:Flex是Flexible Bo ...

  8. 第19月第20天 UITableView:改变 TableHeaderView 的高度 获取目录大小

    1.UITableView:改变 TableHeaderView 的高度 CGRect newFrame = headerView.frame; newFrame.size.height = newF ...

  9. vue之简单的todoList(一)

    <!-- 根组件 --> <!-- vue的模板内,所有内容要被一个根节点包含起来 --> <template> <div id="app" ...

  10. java 基础 浮点类型

    1.浮点类型用于表示小数的数据类型. 2.浮点数原理:也就是二进制科学计数法. 3.Java的浮点类型有float和double两种. 4.Java默认浮点类型计算的结果是double类型,字面量也是 ...