• 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
  • 相关阅读:
    [小技巧]C# 反射
    Win7安装nvme协议的SSD硬盘方法
    Ubuntu18.04下载安装基于使用QT的pcl1.13+vtk8.2,以及卸载
    java基础Object转String的四种方式
    Kafka - 消息队列的两种模式
    23种设计模式之享元模式
    你知道如何科学的学习吗?-关于个人成长的思考
    Diverse Branch Block论文中对于串联卷积的融合中的一些理解点
    10 个神奇的网站,助力带薪摸鱼
    浏览器中location详解
  • 原文地址:https://blog.csdn.net/ymzhaobth/article/details/126051273