JS重学系列之聊聊new操作符


Posted in Javascript onMarch 04, 2019

new操作符的基本过程:

1.创建一个新的空对象。

2.将构造函数的作用域赋给它(即this指向它)。

3.新对象增加构造函数的基本方法和属性。

4.返回新对象

上面的过程大家应该都熟悉,本文是重学 JS 系列的第一篇文章,写这个系列的初衷也是为了夯实自己的 JS 基础。既然是重学,肯定不会从零开始介绍一个知识点,如有遇到不会的内容请自行查找资料。

new 的作用

我们先来通过两个例子来了解 new 的作用

function Test(name) {
 this.name = name
}
Test.prototype.sayName = function () {
 console.log(this.name)
}
const t = new Test('yck')
console.log(t.name) // 'yck'
t.sayName() // 'yck'

从上面一个例子中我们可以得出这些结论:

  • new 通过构造函数 Test 创建出来的实例可以访问到构造函数中的属性
  • new 通过构造函数 Test 创建出来的实例可以访问到构造函数原型链中的属性,也就是说通过 new 操作符,实例与构造函数通过原型链连接了起来

但是当下的构造函数 Test 并没有显式 return 任何值(默认返回 undefined),如果我们让它返回值会发生什么事情呢?

function Test(name) {
 this.name = name
 return 1
}
const t = new Test('yck')
console.log(t.name) // 'yck'

虽然上述例子中的构造函数中返回了 1,但是这个返回值并没有任何的用处,得到的结果还是和之前的例子完全一样。

那么通过这个例子,我们又可以得出一个结论:

  • 构造函数如果返回原始值(虽然例子中只有返回了 1,但是你可以试试其他的原始值,结果还是一样的),那么这个返回值毫无意义

试完了返回原始值,我们再来试试返回对象会发生什么事情吧

function Test(name) {
 this.name = name
 console.log(this) // Test { name: 'yck' }
 return { age: 26 }
}
const t = new Test('yck')
console.log(t) // { age: 26 }
console.log(t.name) // 'undefined'

通过这个例子我们可以发现,虽然构造函数内部的 this 还是依旧正常工作的,但是当返回值为对象时,这个返回值就会被正常的返回出去。

那么通过这个例子,我们再次得出了一个结论:

  • 构造函数如果返回值为对象,那么这个返回值会被正常使用

这两个例子告诉了我们一点,构造函数尽量不要返回值。因为返回原始值不会生效,返回对象会导致 new 操作符没有作用。

通过以上几个例子,相信大家也大致了解了 new 操作符的作用了,接下来我们就来尝试自己实现 new 操作符。

自己实现 new 操作符

首先我们再来回顾下 new 操作符的几个作用

  • new 操作符会返回一个对象,所以我们需要在内部创建一个对象
  • 这个对象,也就是构造函数中的 this,可以访问到挂载在 this 上的任意属性
  • 这个对象可以访问到构造函数原型上的属性,所以需要将对象与构造函数链接起来
  • 返回原始值需要忽略,返回对象需要正常处理

回顾了这些作用,我们就可以着手来实现功能了

function create(Con, ...args) {
 let obj = {}
 Object.setPrototypeOf(obj, Con.prototype)
 let result = Con.apply(obj, args)
 return result instanceof Object ? result : obj
}

这就是一个完整的实现代码,我们通过以下几个步骤实现了它:

  • 首先函数接受不定量的参数,第一个参数为构造函数,接下来的参数被构造函数使用
  • 然后内部创建一个空对象 obj
  • 因为 obj 对象需要访问到构造函数原型链上的属性,所以我们通过 setPrototypeOf 将两者联系起来。这段代码等同于 obj.__proto__ = Con.prototype
  • 将 obj 绑定到构造函数上,并且传入剩余的参数
  • 判断构造函数返回值是否为对象,如果为对象就使用构造函数返回的值,否则使用 obj,这样就实现了忽略构造函数返回的原始值

接下来我们来使用下该函数,看看行为是否和 new 操作符一致

function Test(name, age) {
 this.name = name
 this.age = age
}
Test.prototype.sayName = function () {
 console.log(this.name)
}
const a = create(Test, 'yck', 26)
console.log(a.name) // 'yck'
console.log(a.age) // 26
a.sayName() // 'yck'

虽然实现代码只有寥寥几行,但是结果很完美

最后

我们通过这篇文章重学了 new 操作符,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
短信提示使用 特效
Jan 19 Javascript
用javascript实现给图片加链接
Aug 15 Javascript
JavaScript 常见对象类创建代码与优缺点分析
Dec 07 Javascript
jQuery代码优化 遍历篇
Nov 01 Javascript
Jquery easyui 下loaing效果示例代码
Aug 12 Javascript
js中的preventDefault与stopPropagation详解
Jan 29 Javascript
一个JavaScript处理textarea中的字符成每一行实例
Sep 22 Javascript
判断字符串的长度(优化版)中文占两个字符
Oct 30 Javascript
实现easyui的datagrid导出为excel的示例代码
Nov 10 Javascript
vue组件父子间通信之综合练习(聊天室)
Nov 07 Javascript
React-native桥接Android原生开发详解
Jan 17 Javascript
koa2使用ejs和nunjucks作为模板引擎的使用
Nov 27 Javascript
jQuery实现的导航条点击后高亮显示功能示例
Mar 04 #jQuery
ES10 特性的完整指南小结
Mar 04 #Javascript
node.js使用express框架进行文件上传详解
Mar 03 #Javascript
微信小程序新手教程之启动页的重要性
Mar 03 #Javascript
微信小程序新手教程之页面打开数量限制
Mar 03 #Javascript
JS实现的冒泡排序,快速排序,插入排序算法示例
Mar 02 #Javascript
JS+php后台实现文件上传功能详解
Mar 02 #Javascript
You might like
在php和MySql中计算时间差的方法
2011/04/22 PHP
注册页面之前先验证用户名是否存在的php代码
2012/07/14 PHP
PHP实现UTF-8文件BOM自动检测与移除实例
2014/11/05 PHP
详解PHP中instanceof关键字及instanceof关键字有什么作用
2015/11/05 PHP
web页面数据展示新想法(json)
2010/06/08 Javascript
JQuery 选择和过滤方法代码总结
2010/11/19 Javascript
JavaScript中两种链式调用实现代码
2011/01/12 Javascript
Javascript 浮点运算的问题分析与解决方法
2013/08/27 Javascript
页面加载完毕后滚动条自动滚动一定位置
2014/02/20 Javascript
jquery插件pagination实现无刷新ajax分页
2015/09/30 Javascript
js验证真实姓名与身份证号是否匹配
2015/10/13 Javascript
使用ReactJS实现tab页切换、菜单栏切换、手风琴切换和进度条效果
2016/10/17 Javascript
bootstrap table小案例
2016/10/21 Javascript
一篇看懂vuejs的状态管理神器 vuex状态管理模式
2017/04/20 Javascript
详解Vue2.X的路由管理记录之 钩子函数(切割流水线)
2017/05/02 Javascript
es6函数之尾调用优化实例分析
2020/04/25 Javascript
Electron实现应用打包、自动升级过程解析
2020/07/07 Javascript
vue 解决mintui弹窗弹起来,底部页面滚动bug问题
2020/11/12 Javascript
JQuery+drag.js上传图片并且实现图片拖曳
2020/11/18 jQuery
[01:07:19]2018DOTA2亚洲邀请赛 4.5 淘汰赛 Mineski vs VG 第一场
2018/04/06 DOTA
Python中处理字符串之islower()方法的使用简介
2015/05/19 Python
python在Windows下安装setuptools(easy_install工具)步骤详解
2016/07/01 Python
Python用zip函数同时遍历多个迭代器示例详解
2016/11/14 Python
Python中第三方库Requests库的高级用法详解
2017/03/12 Python
通过python+selenium3实现浏览器刷简书文章阅读量
2017/12/26 Python
教你用 Python 实现微信跳一跳(Mac+iOS版)
2018/01/04 Python
python绘制多个子图的实例
2019/07/07 Python
美国高端婴童品牌:Hanna Andersson
2016/10/30 全球购物
采购员岗位职责
2013/11/15 职场文书
药品促销活动方案
2014/02/14 职场文书
机关作风建设自查报告
2014/10/22 职场文书
一年级数学下册复习计划
2015/01/17 职场文书
2016母亲节感恩话语
2015/12/09 职场文书
Mysql基础之常见函数
2021/04/22 MySQL
MySQL 8.0 之不可见列的基本操作
2021/05/20 MySQL
根德5570型九灯四波段立体声收音机是电子管收音机的楷模 ? 再论5570
2022/04/05 无线电