我想对this old question发表评论,但似乎已被锁定。
这是我的用例:
obj
创建对象Base
。 obj instanceof Base
返回true。obj
的原型,使其看起来好像obj
是从Derived
构建的。那就是我想要的
obj
可以访问Derived
obj instanceof Derived
返回true 原因是obj
在层次结构中有一个类型,它在创建时是未知的,并由之后发生的事情决定。我希望能够将其移到层次结构中。
我相信我可以用
做到这一点
obj.__proto__ = Derived.prototype;
但__proto__
将在下一版本的JavaScript中弃用。 proxies API自上面提到的问题以来发生了变化,但似乎不支持我的用例。
我的用例是否有替代实现,现在或计划在将来使用?
我现在能看到的唯一选择是使用
obj2 = Object.create(Derived.prototype);
obj2.extend(obj);
并且永远不会存储多个对obj的引用,但是这个成本非常不方便。
以下是展示此问题的fiddle。
答案 0 :(得分:3)
我认为不可能这样做。正如RobG所演示的那样,你可以通过更改使类false
属性返回prototype
。
看到这一点,我认为你可以通过一个额外的课程来完成它,就像来自普通F
垫片的Object.create
一样:
Object.newChangeable = function create(b) {
function F(){b.call(this);}
F.prototype = b.prototype;
var f = new F();
f.change = function change(n) {
F.prototype = n.prototype;
};
return f;
}
var obj = Object.newChangeable(Base);
obj instanceof Base; // true
obj.change(Derived);
但没有:
obj instanceof Derived; // still false
obj instanceof Base; // still true
因为obj
的内部[[原型]]仍指向与Base.prototype
相同。您可以做的是Derived
新Base
:
var obj = new Base;
obj instanceof Base; // true
Derived.prototype = Base.prototype;
Base.prototype = {}; // something else
alert(obj instanceof Derived); // true
alert(obj instanceof Base); // false
但我认为这不是你想要的,操纵表达的右边而不是改变obj
处的东西: - )
答案 1 :(得分:1)
instanceof 运算符只检查构造函数的public prototype
属性是否在对象的[[Prototype]]
链上。打破链的一种方法是更改构造函数的原型:
function Base() {}
var base = new Base();
alert( base instanceof Base); // true
Base.prototype = {};
alert( base instanceof Base); // false
alert( base instanceof Object); // true
第二个提醒是错误的,因为新的Base.prototype
不再位于[[Prototype]]
base
链上(原来的那个仍然存在)。请注意,Object.protoyype
仍然是。以上是instanceof
运算符不被视为特别有用的一个原因。
要执行您要执行的操作,您必须在构造对象时创建[[Prototype]]
链,因为您以后无法更改它:
Derived.prototype = new Base();
var base = new Derived();
alert(base instanceof Base); // true
alert(base instanceof Derived); // true
要求是:
- 使用构造函数Base创建对象obj。 obj instanceof Base返回true。
醇>
如图所示,这不一定是真的。如果您的策略依赖于instanceof
返回特定值,那么您将在设计上放置(可能是不合理的)约束而没有明显的好处。
2
。我想改变obj的原型,好像obj是从Derived构造的。也就是说,我想要•obj可以访问Derived方法
你可以通过使Base.prototype成为Derived的实例(如图所示)或将属性复制到Base.prototype来实现。
•obj instanceof Derived返回true
您可以在创建 Base 的任何实例之前,通过Base.prototype
派生 的实例来实现这一目标。
创建实例后无法修改链。如果您放弃instanceof
约束,则只需将Derived.prototype
复制到Base.prototype
即可添加Derived.prototype.someMethod.call(base, ...);
方法。另一种方法是使用调用或应用:
{{1}}
但我怀疑你正在尝试做一些不可能的事情。
答案 2 :(得分:0)
你的意思是这个(对这个问题有点困惑,我还是学习者)
function vehicle(name, color)
{
if(this instanceof arguments.callee)
{
this.name = name;
this.color = color;
}
else return new arguments.callee(arguments);
}
vehicle.prototype = {
getName : function()
{
alert(this.name);
}
}
function Car(name, color, speed)
{
this.name = name;
this.color = color;
this.speed = speed;
}
Car.prototype = vehicle();
var obj = new Car("Ford", "Red", "200mph");
obj.getName(); // alerts `Ford` using vehicle's/parent's method
alert(obj instanceof vehicle); alerts `True` instanceof vehicle's/parent's constructor
小提琴是here。
John Resig的文章。