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

