You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Javascript Prototype Inheritance计数器输出差异原因求解

执行结果差异原因解释

核心原因是JavaScript原型链继承中,引用类型和基础类型的读写规则存在本质差异,具体拆解如下:

  • 先理清实例与原型的关联关系
    代码中Bar.prototype被显式赋值为foo(Foo构造函数的实例),因此bar1、bar2两个Bar实例的原型链都指向同一个foo对象,所有实例默认会共享原型上的属性。
  • 两个计数器的类型差异是问题根源
    • counter是引用类型(普通对象),存储的是内存地址,所有访问都指向同一个{i: 0}对象
    • counter2是基础类型(数字),存储的是直接值
  • 逐次调用的执行逻辑拆解:
    1. 第一次调用foo.sayHello()
      直接操作foo自身的属性,执行后foo.counter.i = 1、foo.counter2 = 1,对应第一行输出结果。
    2. 第二次调用bar1.sayHello()
      读取阶段:bar1自身没有counter和counter2属性,顺着原型链找到foo上的属性,读到counter.i=1、counter2=1,对应第二行输出。
      赋值阶段:
      • this.counter.i += 1是修改引用类型的内部属性,不会在bar1上创建新属性,直接修改原型上foo的counter.i为2
      • this.counter2 += 1是对基础类型赋值,JS会直接在当前实例bar1上创建一个私有counter2属性,赋值为2,不会修改原型上foo的counter2
    3. 第三次调用bar2.sayHello()
      读取阶段:bar2自身没有counter,找原型foo的counter.i=2;bar2自身也没有counter2,找原型foo的counter2仍然是1,对应第三行输出。
      赋值阶段:修改原型的counter.i为3,同时在bar2自身创建私有counter2属性赋值为2。
    4. 第四次调用foo.sayHello()
      直接读取foo自身的属性,counter.i已经被累加到3,counter2还是第一次调用后的值1,对应第四行输出。

内容的提问来源于stack exchange,提问作者blueblast

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 10:15:00