js 的 new 和原型链一个问题请教,感谢!!!!

2018-01-26 14:11:35 +08:00
 xuecat
function Super() {
    this.val = 1;
    this.arr = [1];
}
function Sub() {...}

Sub.prototype = new Super();
var sub1 = new Sub();
var sub2 = new Sub();

sub1.val = 2;//不会影响 sub2
sub1.arr.push(2);//会影响 sub2

上面的代码有点我无法理解,想请教下!!!

先讲下我的理解:

new Super后,导致Sub.prototype通过call得到了valarr
new Sub后的实质变化也只是sub1__proto__指向了Sub.prototype

也就是说,sub1.val,sub1.arr这都是访问Sub.prototype上的。
这特么访问就都是一个链上的东西了。
为何sub1.arr能影响,而sub1.val却不影响呢?
不能因为一个是值类型,一个是引用类型就有区别吧!!!!

是 new 的时候对值类型复制了吗?可是我翻了下没这描述。。。。。求解答

4344 次点击
所在节点    JavaScript
22 条回复
xilixjd
2018-01-26 23:39:30 +08:00
7 楼完美解释
yunfeihe
2018-02-15 01:11:50 +08:00
## 关于 sub1.arr.push(2);//会影响 sub2 的问题
Sub.prototype = new Super();
这一句,创建了一个新的 Super 实例,并且让 Sub.prototype 指向(并非复制)这个 Super 实例。
var sub1 = new Sub();
var sub2 = new Sub();
new 只是一个语法糖,等同于在一个构造函数里加了两段代码
var yourFunction = function(){
this = Object.create(yourFunction.prototype); //new 后隐性执行的代码
.....
实际代码
.....
return this; //new 后隐性执行的代码
}
假如楼主没有在 Sub()函数里写入自定义代码(只是为了便于理解,实际上不可能)则
var sub1 = new Sub() 等价于 var sub1 = Object.create(Sub.prototype)
var sub2 = new Sub() 等价于 var sub2 = Object.create(Sub.prototype)
这样就很容易解释关于 array 的问题了,当执行 arr.push 时,编译器先查找 sub1 本身,然后根据原型链查询由 Object.create(Sub.prototype)创建的对象(也就是 Sub.__proto__所指的对象),这个对象也就是刚开始创建的 Super 实例,而 sub1 和 sub2 指向同一个 Super 实例,所以可以相互影响。

## 关于 sub1.val = 2;//不会影响 sub2 这个问题
楼主应该很容易判断出来,对于一个双层函数,外层函数执行了 var a = 1,当内层函数对 a 这个变量进行操作时,有无在内层函数里同样声明 var a,a 的值可能大不相同(声明了即是内层函数变量,否则是外层)。
但是对象是没有 var sub1.val 这样的声明语句的,所以当你执行 sub1.val=2 时,不仅仅是赋值,可以理解为是声明且赋值。声明了 sub1 的私有属性 val,并且赋值为 2,覆盖掉了原型的 val。事实上如果楼主尝试 delete sub1.val 并且再次执行 sub1.val 会发现值又等于 1 了。
ps:楼主要是写过 python3 的闭包函数,上面的话应该很容易理解。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/426144

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX