扫码关注官方订阅号
说getSuperValue is not a function。麻烦指点下,谢谢
光阴似箭催人老,日月如移越少年。
因为此时的instance.__proto__和SubType.prototype指向两个不同的对象。
这里需要注意的是我们通常认为instance.__proto__==SubType.prototype//true,是因为他们的值相同,即他们保存的对象指针相同。当一个函数被创建是内存就会有一块区域作为原型对象,在函数中prototype属性指向它,在函数的实例对象中[prototype](也就是我们常用的__proto__,注:这是浏览器方便测试引入的并不是规范属性)指向它。为SubType.prototype直接赋值会使他它的变量值也就是对象指针发生变化,SubType.prototype会指向一个全新的对象。但原来的原型对象并没有销毁,在生成实例时[prototype]还是会指向它。
你可以在你的代码后加console.log(instance.__proto__==SubType.prototype)加以验证,注释掉SubType.prototype返回true,不注销返回false。 到这里应该清楚了,如果还有疑问可以查阅《权威指南》原型部分或《js高程》构造函数部分。 希望对你有所帮助
虽然 已经完结了,但是我还是想补上一份我的答案。
题主的希望 :instance.__proto__ = new SuperType();
实际的情况 :instance.__proto__ = SubType.oldPrototype;
function SuperType() { this.property = true; SuperType.prototype.getSuperValue = function () { return this.property; } } function SubType() { this.prototype = false; SubType.prototype = new SuperType(); //1 } SubType.prototype.old = 'oldPrototype'; //oldPrototype var instance = new SubType(); console.log(instance.old); console.log(instance.getSuperValue());
因为在new的时候
var o = new Object();
o.__proto__ = A.prototype; 绑定原型
A.call(o); 绑定this, 并执行构造函数里面的代码
把这个o返回给a;//完成var a = new A()的过程.由上面看出
我们的原型在 构造函数内的函数运行时已经完成了绑定。
这也是如果我们写在外面为什么会生效的原因。但是这里还需要注意一个问题:
SubType.prototype = new SuperType();
这句话 改变了原型的引用地址,如果在构造函数中写上这句话,就会造成instance的实例已经附上SubType.prototype,而不是这个new SuperType(); 此时intance不会因为你对Subtype.prototype而改变,因为instance.__proto__的引用的是oldPrototype的内存地址。
如果你再加一段代码
var instance2 = new SubType(); console.log(instance2.getSuperValue());
这个时候 你就可以输出,这个时候原型链就是正常的,因为已经改变过一次。!~!~
重点就是:1. new做了什么,2. 对prototype的直接赋值对象会造成引用地址改变 3.instance.__proto__的引用地址不会跟着prototype的引用地址改变而改变
我来搬运一下,看了应该很明白了,为什么写在外面就可以,写在里面就不可以。另外推荐看这个blog写的挺不错的,不过要很好的理解还是要不断的写代码实践。
原型对象才有原型,实例没有原型。
你在这里把SubType的原型赋值成了一个实例,而一个对象的实例本身是没有原型的方法的,它是基于__proto__属性往原型链上去找的。
而由于你给SubType.prototype赋值的不是一个原型对象,所以实际上原型链在这里已经断掉了,所以也不可能找到那个函数。
微信扫码关注PHP中文网服务号
QQ扫码加入技术交流群
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
PHP学习
技术支持
返回顶部
这里需要注意的是我们通常认为instance.__proto__==SubType.prototype//true,是因为他们的值相同,即他们保存的对象指针相同。当一个函数被创建是内存就会有一块区域作为原型对象,在函数中prototype属性指向它,在函数的实例对象中[prototype](也就是我们常用的__proto__,注:这是浏览器方便测试引入的并不是规范属性)指向它。为SubType.prototype直接赋值会使他它的变量值也就是对象指针发生变化,SubType.prototype会指向一个全新的对象。但原来的原型对象并没有销毁,在生成实例时[prototype]还是会指向它。
虽然 已经完结了,但是我还是想补上一份我的答案。
题主的希望 :instance.__proto__ = new SuperType();
实际的情况 :instance.__proto__ = SubType.oldPrototype;
因为在new的时候
var o = new Object();
o.__proto__ = A.prototype; 绑定原型
A.call(o); 绑定this, 并执行构造函数里面的代码
把这个o返回给a;//完成var a = new A()的过程.
由上面看出
我们的原型在 构造函数内的函数运行时已经完成了绑定。
这也是如果我们写在外面为什么会生效的原因。
但是这里还需要注意一个问题:
这句话 改变了原型的引用地址,如果在构造函数中写上这句话,就会造成instance的实例已经附上SubType.prototype,而不是这个new SuperType(); 此时intance不会因为你对Subtype.prototype而改变,因为instance.__proto__的引用的是oldPrototype的内存地址。
如果你再加一段代码
这个时候 你就可以输出,这个时候原型链就是正常的,因为已经改变过一次。!~!~
重点就是:1. new做了什么,2. 对prototype的直接赋值对象会造成引用地址改变 3.instance.__proto__的引用地址不会跟着prototype的引用地址改变而改变
我来搬运一下,看了应该很明白了,为什么写在外面就可以,写在里面就不可以。
另外推荐看这个blog
写的挺不错的,不过要很好的理解还是要不断的写代码实践。
原型对象才有原型,实例没有原型。
你在这里把SubType的原型赋值成了一个实例,而一个对象的实例本身是没有原型的方法的,它是基于__proto__属性往原型链上去找的。
而由于你给SubType.prototype赋值的不是一个原型对象,所以实际上原型链在这里已经断掉了,所以也不可能找到那个函数。