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 相关文章推荐
Chrome Form多次提交表单问题的解决方法
May 09 Javascript
jQuery选择器的工作原理和优化分析
Jul 25 Javascript
javascript实现tabs选项卡切换效果(扩展版)
Mar 19 Javascript
js自动生成对象的属性示例代码
Oct 28 Javascript
Javascript中的call()方法介绍
Mar 15 Javascript
JavaScript的Date()方法使用详解
Jun 09 Javascript
JavaScript语言精粹经典实例(整理篇)
Jun 07 Javascript
AngularJS入门教程之表格实例详解
Jul 27 Javascript
JS如何设置cookie有效期为当天24点并弹出欢迎登陆界面
Aug 04 Javascript
js防阻塞加载的实现方法
Sep 09 Javascript
gulp加批处理(.bat)实现ng多应用一键自动化构建
Feb 16 Javascript
微信小程序自定义modal弹窗组件的方法详解
Dec 20 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学习教程之第1天
2008/06/15 PHP
Laravel框架源码解析之模型Model原理与用法解析
2020/05/14 PHP
刷新页面实现方式总结(HTML,ASP,JS)
2008/11/13 Javascript
jquery自动完成插件(autocomplete)应用之PHP版
2009/12/15 Javascript
jquery 学习之二 属性 文本与值(text,val)
2010/11/25 Javascript
js实现点击注册按钮开始读秒倒计时的小例子
2013/05/11 Javascript
JavaScript包装对象使用介绍
2013/08/29 Javascript
如何在node的express中使用socket.io
2014/12/15 Javascript
Jquery结合HTML5实现文件上传
2015/06/25 Javascript
Jquery-1.9.1源码分析系列(十一)之DOM操作
2015/11/25 Javascript
Angular2入门教程之模块和组件详解
2017/05/28 Javascript
详解ionic本地相册、拍照、裁剪、上传(单图完全版)
2017/10/10 Javascript
基于匀速运动的实例讲解(侧边栏,淡入淡出)
2017/10/17 Javascript
详解mpvue小程序中怎么引入iconfont字体图标
2018/10/01 Javascript
JS闭包原理与应用经典示例
2018/12/20 Javascript
用Python编程实现语音控制电脑
2014/04/01 Python
python基于socket实现网络广播的方法
2015/04/29 Python
浅谈Python中用datetime包进行对时间的一些操作
2016/06/23 Python
python输出决策树图形的例子
2019/08/09 Python
详解Python图像处理库Pillow常用使用方法
2019/09/02 Python
Python读取实时数据流示例
2019/12/02 Python
python opencv如何实现图片绘制
2020/01/19 Python
使用placeholder属性设置input文本框的提示信息
2020/02/19 HTML / CSS
如何使用amaze ui的分页样式封装一个通用的JS分页控件
2020/08/21 HTML / CSS
PacSun官网:加州生活方式服装、鞋子和配饰
2018/03/10 全球购物
彪马荷兰官网:PUMA荷兰
2019/05/08 全球购物
Nike意大利官网:Nike.com IT
2020/01/19 全球购物
应届毕业生简历自我评价
2014/01/31 职场文书
社区学习雷锋活动总结
2014/04/25 职场文书
公司授权委托书样本
2014/09/15 职场文书
信访维稳承诺书
2015/05/04 职场文书
教学反思怎么写
2016/02/24 职场文书
小学运动会开幕词
2016/03/04 职场文书
2016个人廉洁自律承诺书
2016/03/25 职场文书
创业计划书之餐饮馄饨店
2019/07/18 职场文书
jQuery实现广告显示和隐藏动画
2021/07/04 jQuery