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 相关文章推荐
基于jquery的滚动鼠标放大缩小图片效果
Oct 27 Javascript
JavaScript子类用Object.getPrototypeOf去调用父类方法解析
Dec 05 Javascript
浅谈javascript 迭代方法
Jan 21 Javascript
jquery+ajax实现注册实时验证实例详解
Dec 08 Javascript
第一章之初识Bootstrap
Apr 25 Javascript
全面解析JavaScript中“&&”和“||”操作符(总结篇)
Jul 18 Javascript
jQuery中animate()的使用方法及解决$(”body“).animate({“scrollTop”:top})不被Firefox支持的问题
Apr 04 jQuery
详解node中创建服务进程
May 09 Javascript
JSON字符串操作移除空串更改key/value的介绍
Jan 05 Javascript
webpack 最佳配置指北(推荐)
Jan 07 Javascript
js模拟实现百度搜索
Jun 28 Javascript
五句话帮你轻松搞定js原型链
Dec 09 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 magic_quotes_gpc的一点认识与分析
2008/08/18 PHP
PHP 面向对象程序设计(oop)学习笔记 (四) - 异常处理类Exception
2014/06/12 PHP
js类型检查实现代码
2010/10/29 Javascript
Chrome中JSON.parse的特殊实现
2011/01/12 Javascript
js中的this关键字详解
2013/09/25 Javascript
JavaScript调用客户端的可执行文件(示例代码)
2013/11/28 Javascript
为开发者准备的10款最好的jQuery日历插件
2014/02/04 Javascript
jQuery插件Elastislide实现响应式的焦点图无缝滚动切换特效
2015/04/12 Javascript
js注入 黑客之路必备!
2016/09/14 Javascript
Jquery Easyui菜单组件Menu使用详解(15)
2016/12/18 Javascript
老生常谈combobox和combotree模糊查询
2017/04/17 Javascript
JS jQuery使用正则表达式去空字符的简单实现代码
2017/05/20 jQuery
基于AngularJS的简单使用详解
2017/09/10 Javascript
jQuery轻量级表单模型验证插件
2018/10/15 jQuery
vue 内置过滤器的使用总结(附加自定义过滤器)
2018/12/11 Javascript
微信小程序如何实现全局重新加载
2019/06/05 Javascript
vue实现表格合并功能
2020/12/01 Vue.js
[03:22]DSPL第一期精彩集锦:酷炫到底!
2014/11/07 DOTA
解析Python中while true的使用
2015/10/13 Python
Python的Flask站点中集成xhEditor文本编辑器的教程
2016/06/13 Python
Python实现发送QQ邮件的封装
2017/07/14 Python
tensorflow实现tensor中满足某一条件的数值取出组成新的tensor
2020/01/04 Python
Android Q之气泡弹窗的实现示例
2020/06/23 Python
CSS实现圆形放大镜狙击镜效果 只有圆圈里的放大
2012/12/10 HTML / CSS
浅析rem和em和px vh vw和% 移动端长度单位
2016/04/28 HTML / CSS
Speedo澳大利亚官网:全球领先游泳品牌
2018/02/04 全球购物
Hanky Panky官方网站:内衣和睡衣
2019/07/25 全球购物
如何打印出当前源文件的文件名以及源文件的当前行号
2015/04/05 面试题
银行会计财务工作个人的自我评价
2013/10/29 职场文书
大学生毕业求职自荐书范文
2014/02/04 职场文书
酒店保安领班职务说明书
2014/03/04 职场文书
商场租赁意向书
2014/07/30 职场文书
安全伴我行演讲稿
2014/09/04 职场文书
家庭暴力离婚起诉书
2015/05/18 职场文书
2015年街道办事处工作总结
2015/05/22 职场文书
利用javaScript处理常用事件详解
2021/04/14 Javascript