重学 JS 系列:聊聊 new 操作符
admin
2023-02-13 21:00:05
0

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
}
复制代码

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

  1. 首先函数接受不定量的参数,第一个参数为构造函数,接下来的参数被构造函数使用
  2. 然后内部创建一个空对象 obj
  3. 因为 obj 对象需要访问到构造函数原型链上的属性,所以我们通过 setPrototypeOf 将两者联系起来。这段代码等同于 obj.__proto__ = Con.prototype
  4. obj 绑定到构造函数上,并且传入剩余的参数
  5. 判断构造函数返回值是否为对象,如果为对象就使用构造函数返回的值,否则使用 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'
复制代码

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

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

最后

我们通过这篇文章重学了 new 操作符,如果你还有什么疑问欢迎在评论区与我互动。

相关内容

热门资讯

深度专访|网易智企段毓铮:不敢... 企业AI的商业化,难点在于让客户敢用、会用、用得有效果。在WAIC现场,搜狐AI邀请到网易智企副总经...
来论|从“菲尔兹奖”,看见科技... 王虹、邓煜分别凭借在调和分析与几何测度论、偏微分方程与数学物理领域的突破性工作,共同荣获2026年菲...
当清洁机器人爬上窗户,能否开启... 过去十年,清洁机器人的故事,几乎都发生在地面上。 扫地、拖地、洗地,从随机碰撞到激光导航,从人工洗抹...
冰箱通电发烫压缩不启动不制冷什... 1、很有可能是因为冰箱的压缩机内高压输出缓冲管出现了断裂,造成高压管不排气,低压管不吸气的这种状况,...
冰箱能通电但是不制冷什么问题 1、电源问题先检查冰箱的电源,看电源的连接是否正常,插头是否通电,插稳。插好插头之后,可以看一下冰箱...
洗衣机通电为什么不转动 导致这类问题一般有这几种情况:可能是进水电磁阀故障导致,若电磁阀已得电还不进水,就是电磁阀的阀芯被卡...
海尔洗衣机不转动了但是会流水 洗衣机可以进水说明电磁阀工作正常;能排水,说明排水泵是正常。洗衣机电源是没有问题的,但是不转动说明洗...
全球首个5G鲁班工坊莫斯科结硕... 【原标题】全球首个5G鲁班工坊莫斯科结硕果 文/本报记者 黄河 刘恺 李鲲 宋瑞 从渤海之滨到莫斯科...
西门子滚筒洗衣机不启动嗒嗒响 1、可能是因为启动电容器的问题导致的不启动;2、可能是因为皮带松弛和打滑的原因;3、可能是因为棘爪和...
重庆一地发生危岩垮塌,巨石掉落... 7月23日,重庆黔江区,有网友称,金溪镇一路段发生塌方,图片显示,一居民房边有巨石落在路上阻断了道路...