假设我有一个类和一些静态辅助方法,如下所示:
function MyClass (myVar) {
this.myVar = myVar;
this.replaceMe = function (value) {
// this will fail
this = MyClass.staticHelper( value );
return this;
}
this.revealVar = function () {
alert( this.myVar );
}
}
MyClass.staticHelper = function (instance, value) {
return new MyClass( instance.myVar + value );
}
我想做的是这样的事情:
var instance = new MyClass( 2 );
instance.revealVar(); // alerts 2
instance.replaceMe( 40 ).revealVar(); // alerts 42
原因是我的类有一个稍微复杂的结构,我不想每次手动分配所有内部变量,而是替换整个对象。有一种简单的方法吗?
答案 0 :(得分:1)
instance.replaceMe( 40 ).revealVar();
提醒42
好的,因为return MyClass.staticHelper(this, value);
就足够了。问题是,下次调用instance.revealVar()
现在应该警告2还是42 - 如果您希望将instance
更改为42,则会更复杂:
this = MyClass.staticHelper( value ); // this will fail
...因为this
不是常见变量,而是关键字和evaluates to the value of the ThisBinding of the current execution context is set depending on how the function is entered - 你无法分配给它,你只能设置它在调用函数时。
我不希望每次手动分配所有内部变量,而是替换整个对象。
不幸的是,您必须这样做,而不更改instance
对象(以及闭包隐藏变量)的属性,您不会更改instance
,而revealVar()
将保持2。
有一种简单的方法吗?
是的,可以通过编程方式完成。最简单的方法是call构造函数(再次) on 当前实例,就像使用new
keyword调用时一样:
MyClass.call( instance, instance.myVar + value );
然而,你不能像创建一个全新实例的静态函数那样使用它。您可以将其置于静态方法中,并使用replaceMe
从this
调用该方法,或者直接将其放在replaceMe
中。
如果您需要一个静态方法,它首先返回一个全新的实例,您也可以通过复制旧实例上的新属性来使用它:
….replaceMe = function(val) {
var newInst = MyClass.staticHelper(this, val); // new MyClass(this.myVar+val);
for (var prop in newInst)
if (newInst.hasOwnProperty(prop))
this[prop] = newInst[prop];
return this;
};
这意味着要覆盖旧的属性,而旧的闭包现在可以被垃圾收集了,因为没有任何东西可以引用它们。
是的,我建议put your methods on the prototype instead of assigning them in the constructor。答案 1 :(得分:0)
如何返回新实例:
function MyClass(myVar) {
// ...
this.replaceMe = function (value) {
return MyClass.staticHelper(this, value);
}
// ...
}
MyClass.staticHelper = function (instance, value) {
return new MyClass( instance.myVar += value );
}
答案 2 :(得分:0)
有两个原因导致这种情况无法在Javascript中运行。
首先,尽管它看起来像一个变量,this
实际上是一个函数调用*,因此无法分配。 this=foo
与bar()=baz
相同。所以不可能有这样的代码:
a = 5
a.change(10)
alert(a == 10) // nope
其次,即使this=z
成为可能,这种方法仍然会失败,因为Javascript按值传递,因此不可能有一个更改其参数值的函数:
a = 5
change(a)
alert(a == 10) // nope
*
“是”意味着“在各方面完全相同”
答案 3 :(得分:0)
我想做一些非常相似的事情。遗憾的是,无法为this
分配值 - this
指针是只读变量。然而,接下来最好的事情是使用getter和setter对象来更改保存实例本身的变量。
请注意,这只会更新对实例的单个引用。您可以在此处详细了解:Is there a better way to simulate pointers in JavaScript?
这就是它的工作原理:
function MyClass(pointer, myVar) {
this.myVar = myVar;
this.replaceMe = function (value) {
pointer.value = MyClass.staticHelper(this, pointer, value);
return pointer.value;
};
this.revealVar = function () {
alert(this.myVar);
};
}
MyClass.staticHelper = function (instance, pointer, value) {
return new MyClass(pointer, instance.myVar + value);
};
这是创建pointer
并使用它的方法:
var instance = new MyClass({
get value() { return instance; },
set value(newValue) { instance = newValue; }
}, 2);
instance.revealVar(); // alerts 2
instance.replaceMe(40).revealVar(); // alerts 42
这不是最优雅的解决方案,但它可以完成工作。您可以在行动中看到此代码:http://jsfiddle.net/fpxXL/1/