• js 构造函数 return 非空对象,其实例化的对象在原型上的差异


    一、构造函数

    先看下构造函数的定义

    ECMAScript 中的构造函数是用于创建特定类型对象的。构造函数也是函数,只是使用 new 操作符调用构造函数会执行如下操作:

    (1) 在内存中创建一个新对象
    (2) 这个新对象内部的 [[Prototype]] 特性被赋值为构造函数的 prototype 属性
    (3) 构造函数内部的 this 被赋值为这个新对象(即 this 指向新对象)
    (4) 执行构造函数内部的代码(给新对象添加属性)
    (5) 如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象

    二、分析

    如果不清楚构造函数的定义,就没有必要看这部分了

    根据定义,这里将构造函数分为两种:有无返回非空对象。具体区别在哪儿,之前从未细想过

    示例1:实例在原型上的不同

    function Foo(name) {
      this.name = name
    }
    function Bar(name) {
      this.age = 27
      return { name }
    }
    let foo = new Foo('Tom'), bar = new Bar('Tom')
    
    console.log(foo.__proto__ === Foo.prototype) // true
    console.log(bar.__proto__ === Bar.prototype) // false
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述
    上图中也可以看出,foo的原型指向Foo的原型,而bar的原型指向Object的原型

    示例2

    通过这个例子更明显的对比构造函数中的 thisreturn 的实例

    function Foo(name) {
      const _this = this
      this.name = name
      function test(){
        console.log(this, _this)
      }
      return {
        name: 'Tom',
        test
      }
    }
    let foo = new Foo('Anne')
    console.log(foo)
    foo.test()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    执行 foo.test()
    this 打印的是foo,即,实例化时return出来的对象
    _this 打印的是实例化过程中创建的新对象,根据定义,该对象原型指向构造函数的原型。相比之下,前者是对象字面量,其原型指向Object的原型

    在这里插入图片描述
    原型上的区别,意味着,上例中,foo的原型也不指向 Foo的原型,原型的构造函数也并非 Foo。

    因此,foo无法访问Foo的原型属性与方法:

    function Foo(name) {
      const _this = this
      this.name = name
      function test(){
        return _this
      }
      return {
        name: 'Tom',
        test
      }
    }
    
    let foo = new Foo('Anne'), _this = foo.test()
    
    Foo.prototype.age = 18
    Foo.prototype.func = function() {
        console.log(this.name, this.age)
    }
    
    console.log(!!foo.func, !!_this.func)  // false true
    _this.func()                           // Anne 18
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    针对这点,可以在构造函数内手动将返回的对象原型指向构造函数的原型
    如果用不上原型链的话,可以直接忽视这点

    function Foo(name) {
      let res = {}
      res.__proto__ = Foo.prototype
      return Object.assign(res, { name })
    }
    let foo = new Foo('Anne')
    Foo.prototype.age = 20
    console.log(foo.age) // 20
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 相关阅读:
    Kotlin协程最佳实践
    代码随想录算法训练营day57|647. 回文子串|516.最长回文子序列
    低代码开发平台的五大优势
    数据治理项目成功的要点,企业培养数据要把握好关键环节
    查看 SSH 登录失败日志
    [附源码]计算机毕业设计疫情期间小学生作业线上管理系统Springboot程序
    【SA8295P 源码分析】112 - QNX AIS Camera 出图代码过程详解 之 VFEDriver 源码分析(本文未完,待更新...)
    信息论之从熵、惊奇到交叉熵、KL散度和互信息
    C++面向对象程序设计(第2版)第六章(多态性与虚函数)知识点总结
    python中如何打印日志信息
  • 原文地址:https://blog.csdn.net/ymzhaobth/article/details/126051273