分配对象“这个”
说我有一个类和一些静态辅助方法是这样的:分配对象“这个”
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
的原因是,我的类有一个稍微复杂的结构,我不想每次手动分配所有内部变量,而是替换整个对象。有没有简单的方法来做到这一点?
如何只返回新的实例:
function MyClass(myVar) {
// ...
this.replaceMe = function (value) {
return MyClass.staticHelper(this, value);
}
// ...
}
MyClass.staticHelper = function (instance, value) {
return new MyClass(instance.myVar += value);
}
正如问题的评论所述,这实际上不会取代实例,即在调用链之外,对象将不会被触及。 – 2013-03-24 12:45:10
@IngoBürk我还添加了'+ ='而不是'=',以便改变对象属性。 – 0x499602D2 2013-03-24 12:45:38
哦,我没有看到。但是这打破了我的问题的目的:我的课程需要在变化时对几个变量进行更新。我正在寻找一种不必手动执行此操作的方法。 – 2013-03-24 12:46:24
有两个原因,这是不打算在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
*
“是” 是指
你如何看待'this'会是一个函数调用? – Bergi 2013-03-24 12:51:41
该规范没有说它是一个函数调用。 [只提到'ThisBinding'](http://es5.github.com/#x10.4.3),它被描述为*“在与这个执行上下文相关的ECMAScript代码内与'this'关联的值。”* (http://es5.github.com/#x10.3,http://es5.github.com/#x11.1.1)。 – 2013-03-24 12:56:53
函数内的'this'指针是只读值,不是函数调用。这就是'this'的分配不起作用的原因。 – 2013-03-24 14:17:59
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构造上(再次)当前实例一样,当与调用它发生的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。
我想做一些非常相似的事情。不幸的是,没有办法为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/
看起来你只是想'返回MyClass.staticHelper(this,value);'。你不能替换'this',但你可以返回一个新的类似的对象。 – 2013-03-24 12:41:10
这只会返回调用链中的新对象,但不会实际替换该实例。 – 2013-03-24 12:41:57
是的,那是不可能的。你可以为整个类创建一个包装器,并保留对实际实例的内部引用。 – 2013-03-24 12:42:47