js new一个对象的过程,实现一个简单的new方法

对于大部分前端开发者而言,new一个构造函数或类得到对应实例,是非常普遍的操作了。下面的例子中分别通过构造函数与class类实现了一个简单的创建实例的过程。
// ES5构造函数
let Parent = function (name, age) {
this.name = name;
this.age = age;
};
Parent.prototype.sayName = function () {
console.log(this.name);
};
const child = new Parent('听风是风', 26);
child.sayName() //'听风是风' //ES6 class类
class Parent {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayName() {
console.log(this.name);
}
};
const child = new Parent('echo', 26);
child.sayName() //echo
但new不应该像一个黑盒,我们除了知道结果,更应该明白过程究竟如何。那么那么这篇文章主要围绕两点展开,第一,js中new一个对象时到底发生了什么,第二,知道了原理后我们通过js来实现一个简单的new方法。
一、new操作中发生了什么?
比较直观的感觉,当我们new一个构造函数,得到的实例继承了构造器的构造属性(this.name这些)以及原型上的属性。
在《JavaScript模式》这本书中,new的过程说的比较直白,当我们new一个构造器,主要有三步:
• 创建一个空对象,将它的引用赋给 this,继承函数的原型。
• 通过 this 将属性和方法添加至这个对象
• 最后返回 this 指向的新对象,也就是实例(如果没有手动返回其他的对象)
我们改写上面的例子,大概就是这样:
// ES5构造函数
let Parent = function (name, age) {
//1.创建一个新对象,赋予this,这一步是隐性的,
// let this = {};
//2.给this指向的对象赋予构造属性
this.name = name;
this.age = age;
//3.如果没有手动返回对象,则默认返回this指向的这个对象,也是隐性的
// return this;
};
const child = new Parent();
这应该不难理解,你应该在工作中看过类似下述代码中的操作,将this赋予一个新的变量(例如that),最后返回这个变量:
// ES5构造函数
let Parent = function (name, age) {
let that = this;
that.name = name;
that.age = age;
return that;
};
const child = new Parent('听风是风', '26');
为什么要这么写呢?我在前面说this的创建与返回是隐性的,但在工作中为了让构造过程更易可见与更易维护,所以才有了上述使用that代替this,同时手动返回that的做法;这也验证了隐性的这两步确实是存在的。
但上述这个解释我觉得不够完美,它只描述了构造器属性是如何塞给实例,没说原型上的属性是如何给实例继承的。
我在winter大神的重学前端专栏中,看到了比较符合我心意的,同时也是符合原理的描述:
• 以构造器的prototype属性为原型,创建新对象;• 将this(也就是上一句中的新对象)和调用参数传给构造器,执行;• 如果构造器没有手动返回对象,则返回第一步创建的新对象,如果有,则舍弃掉第一步创建的新对象,返回手动return的对象。
到这里不管怎么说,你都应该大概知道了new过程中会新建对象,此对象会继承构造器的原型与原型上的属性,最后它会被作为实例返回这样一个过程。知道了原理,我们来手动实现一个简单的new方法。
二、实现一个简单的new方法
// 构造器函数
let Parent = function (name, age) {
this.name = name;
this.age = age;
};
Parent.prototype.sayName = function () {
console.log(this.name);
};
//自己定义的new方法
let newMethod = function (Parent, ...rest) {
// 1.以构造器的prototype属性为原型,创建新对象;
let child = Object.create(Parent.prototype);
// 2.将this和调用参数传给构造器执行
let result = Parent.apply(child, rest);
// 3.如果构造器没有手动返回对象,则返回第一步的对象
return typeof result === 'object' ? result : child;
};
//创建实例,将构造函数Parent与形参作为参数传入
const child = newMethod(Parent, 'echo', 26);
child.sayName() //'echo'; //最后检验,与使用new的效果相同
child instanceof Parent//true
child.hasOwnProperty('name')//true
child.hasOwnProperty('age')//true
child.hasOwnProperty('sayName')//false
那么到这里就介绍完毕了。
new一个构造函数默认返回什么?调用构造函数不使用new能得到实例吗?如果你对这些有兴趣,可以阅读博主这篇博客:
精读JavaScript模式(三),new一个构造函数究竟发生了什么?
实例为什么能使用构造器prototype上的方法?继承之间的关系又是怎么样的?如果你对这些有兴趣,可以阅读博主这篇博客:
ES6新增的class类怎么用?与传统构造函数写法有哪些区别?如何快速上手class类?那你可以阅读博主这篇博客:
最后模拟实现new方法中,...rest是个什么参数?如果你对这个存疑,那怕是得了解下ES6中的取代arguments的rest参数,欢迎阅读这篇:
原谅我的厚颜无耻,如果你觉得本文对你有所帮助,欢迎评论,点赞与关注。
js new一个对象的过程,实现一个简单的new方法的更多相关文章
- 只是一个用EF写的一个简单的分页方法而已
只是一个用EF写的一个简单的分页方法而已 慢慢的写吧.比如,第一步,先把所有数据查询出来吧. //第一步. public IQueryable<UserInfo> LoadPagesFor ...
- 通过Knockout.js + ASP.NET Web API构建一个简单的CRUD应用
REFERENCE FROM : http://www.cnblogs.com/artech/archive/2012/07/04/Knockout-web-api.html 较之面向最终消费者的网站 ...
- 【 D3.js 入门系列 --- 3 】 做一个简单的图表!
前面说了几节,都是对文字进行处理,这一节中将用 D3.js 做一个简单的柱形图. 做柱形图有很多种方法,比如用 HTML 的 div 标签,或用 svg . 推荐用 SVG 来做各种图形.SVG 意为 ...
- 【 D3.js 入门系列 — 3 】 做一个简单的图表!
图1. 柱形图 1. 柱形图 前几章的例子,都是对文字进行处理.本章中将用 D3 做一个简单的柱形图.制作柱形图有很多种方法,比如用 HTML 的 <div> 标签,或在 SVG 上绘制 ...
- 从一个简单的main方法执行谈谈JVM工作机制
本来JVM的工作原理浅到可以泛泛而谈,但如果真的想把JVM工作机制弄清楚,实在是很难,涉及到的知识领域太多.所以,本文通过简单的mian方法执行,浅谈JVM工作原理,看看JVM里面都发生了什么. 先上 ...
- Java实现一个简单的缓存方法
缓存是在web开发中经常用到的,将程序经常使用到或调用到的对象存在内存中,或者是耗时较长但又不具有实时性的查询数据放入内存中,在一定程度上可以提高性能和效率.下面我实现了一个简单的缓存,步骤如下. 创 ...
- js利用点击事件做一个简单的计算器
先放一个样式图: 源代码如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"&g ...
- 一个简单的解决方法:word文档打不开,错误提示mso.dll模块错误。
最近电脑Word无故出现故障,无法打开,提示错误信息如下: 问题事件名称: APPCRASH应用程序名: WINWORD.EXE应用程序版本: 11.0.8328.0应用程序时间戳: 4c717ed1 ...
- Vue.js如何在一个页面调用另一个同级页面的方法
使用场景: 页面分为header.home.footer三部分,需要在home中调用header中的方法,这两个没有相互引入 官方给出方法: 需要在展示页里调用顶部导航栏页里的方法,两者之间没有引用关 ...
随机推荐
- python map函数 reduce函数
Python中map()函数浅析 函数式编程: 更好的描述问题 map函数 怎么理解当传入多个参数list时,map如何运作: abc函数第一次传入的数据时 (11,44,77),然后(22,5 ...
- 用nginx搭建http/rtmp/hls协议的MP4/FLV流媒体服务器
前前后后搭建了两三个星期,终于可以告一段落,nginx实在是有点强大.写一篇笔记来记录一下这个过程中的思路和解决方案. 一.搭建nginx平台: 基本是基于http://blog.csdn.net/x ...
- HNOI2008玩具装箱 斜率优化
题目描述 P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具, ...
- Link-cut-tree 学习记录 & hdu4010
网上的lct一抓一大把,所以我也不再写什么讲解了,只写一写自己的看法. Link-cut-tree 是用于维护动态树的一种数据结构 所谓动态树就是一片存在边的添加与删除的森林中的一棵树 所以我们要快速 ...
- DSP基础
CCS V5的使用 CCS安装与设置
- uboot 命令使用教程(uboot参数设置)
1. Printenv 打印环境变量. uboot> printenv baudrate=115200 ipaddr=192.168.0.111 ethaddr=32:34:46:78:9A:D ...
- 四种生成和解析XML文档的方法介绍
解析XML的方法越来越多,但主流的方法也就四种,即:DOM.SAX.JDOM和DOM4J 1.DOM(Document Object Model) DOM是用与平台和语言无关的方式表示XML文档的官方 ...
- js拼的onclick调用方法需要注意的地方 之二
那如果之前的方法不行,想传递json对象怎么办呢? 使用下面这种方法, getA = function(){ var obj = {'projectId':123,'projectName':'aac ...
- net.sf.json-lib maven依赖问题.
<dependency> <groupId>net.sf.json-lib</groupId> <artifactId>json-lib</art ...
- PopupWindow-----listview item的点击出现PopupWindow
/** * 设置listview item的点击事件 */ lv_app_manager.setOnItemClickListener(new OnItemClickListener() { @Ove ...