Javascript 将对象分配给;这";
假设我有一个类和一些静态助手方法,如下所示:Javascript 将对象分配给;这";,javascript,Javascript,假设我有一个类和一些静态助手方法,如下所示: function MyClass (myVar) { this.myVar = myVar; this.replaceMe = function (value) { // this will fail this = MyClass.staticHelper( value ); return this; } this.revealVar = function () {
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
a = 5
a.change(10)
alert(a == 10) // nope
我想做的是这样的:
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
a = 5
a.change(10)
alert(a == 10) // nope
原因是我的类有一个稍微复杂的结构,我不想每次都手动分配所有内部变量,而是替换整个对象。有简单的方法吗?只返回新实例如何:
function MyClass(myVar) {
// ...
this.replaceMe = function (value) {
return MyClass.staticHelper(this, value);
}
// ...
}
MyClass.staticHelper = function (instance, value) {
return new MyClass( instance.myVar += value );
}
….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;
};
这在Javascript中不起作用有两个原因 首先,尽管它看起来像一个变量,
这个
实际上是一个函数调用*,因此不能分配给this=foo
与bar()=baz
相同。所以不可能有这样的代码:
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
a = 5
a.change(10)
alert(a == 10) // nope
其次,即使this=z
是可能的,这种方法也会失败,因为Javascript通过值传递,因此不可能有一个函数来更改其参数的值:
a = 5
change(a)
alert(a == 10) // nope
*
“是”表示“在各个方面完全相同”
instance.replaceMe(40.revealVar()代码>警报42
好的,对于这个返回MyClass.staticHelper(这个值)代码>就足够了。问题只是对instance.revealVar()
的下一次调用现在是否应向2或42发出警报-如果希望instance
更改为42,则会变得更复杂:
this = MyClass.staticHelper( value ); // this will fail
…因为它不是一个公共变量,而是一个关键字,并且-您无法分配给它,所以只能在调用函数时设置它
我不想每次都手动分配所有内部变量,而是替换整个对象
不幸的是,如果不更改实例
对象(以及闭包隐藏变量)的属性,您将无法更改实例
,revealVar()
将保持为2
有没有一个简单的方法可以做到这一点
是的,它可以通过编程实现。最简单的方法是(再次)调用当前实例上的构造函数,就像使用以下函数调用时发生的情况:
但是你不能像静态函数那样使用它来创建一个全新的实例。您可以将它放在一个静态方法中,并使用this
从replaceMe
调用它,或者直接将它放在replaceMe
中
如果需要一个首先返回全新实例的静态方法,也可以通过复制旧实例上的新属性来使用该方法:
function MyClass(myVar) {
// ...
this.replaceMe = function (value) {
return MyClass.staticHelper(this, value);
}
// ...
}
MyClass.staticHelper = function (instance, value) {
return new MyClass( instance.myVar += value );
}
….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;
};
这意味着覆盖旧属性,而且旧闭包现在可以被垃圾收集,因为不再有任何东西引用它们
顺便说一句,我建议你去。不久前我想做一些非常类似的事情。不幸的是,无法为此
赋值-此
指针是只读变量。但是,下一个最好的方法是使用getter和setter对象来更改保存实例本身的变量
请注意,这仅更新对实例的单个引用。您可以在此处阅读更多信息:
这就是它的工作原理:
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);
};
以下是如何创建并使用指针的方法:
var instance = new MyClass({
get value() { return instance; },
set value(newValue) { instance = newValue; }
}, 2);
instance.revealVar(); // alerts 2
instance.replaceMe(40).revealVar(); // alerts 42
这不是最优雅的解决方案,但它可以完成任务。您可以看到这段代码的作用:看起来您只想返回MyClass.staticHelper(这个值)代码>。您不能替换此
,但可以返回一个新的类似对象。这只会返回调用链中的新对象,而不会实际替换实例。是的,这是不可能的。您可以为整个类创建一个包装器,并保留对实际实例的内部引用。那就太好了。我将只更改我的设计,不覆盖对象,而是返回它们以启用调用链。对于实际的覆盖,我仍然可以重新分配变量,或者使用静态函数。谢谢如果要通过使当前引用成为不同的对象来“替换”对象,则需要更改其所有属性。您不能分配到范围链之外的任何内容。正如问题的注释所述,这实际上不会替换实例,即调用链之外的对象将不会被触及。@IngoBürk我还添加了+=
,而不是=
,这样会改变对象属性。哦,我没有看到这一点。但这与我问题的目的背道而驰:我的类需要在发生变化时更新几个变量。我一直在寻找一种不必手动操作的方法。@IngoBürk您不能更改这个,因为它是一个常量对象。我认为您可以使用模块模式来实现这一点。我很快会更新的。是的,我现在明白了。我只是想也许有一种方法,毕竟Javascript是一种具有很多“特性”的语言:)规范并没有说它是一个函数调用。它被描述为“与此执行上下文关联的ECMAScript代码中的this
关键字关联的值。”(,)。函数中的this
指针是只读值,而不是函数调用。这就是分配给这个不起作用的原因。@AaditMShah:“只读值”在某种程度上是一个矛盾修饰法,因为所有值都是只读的(5=x
也不起作用)。如果您的意思是“只读变量”,这也不正确,因为变量保留它们的值,而这个没有。@thg435-Oops,我确实是指只读变量。也就是说,内存保留与只读或读写变量有什么关系?这个
指针确实保留了它的值,它的值是对内存中某个对象的引用(地址)。@AaditMShah:对于一个正则变量,一旦我们给它赋值,这个值就会一直存在,直到我们重新赋值为止。当我们进入一个新的函数范围时,this
的值“自行”改变(不过还有另一个具有相同属性的“变量”)。这就是为什么需要像var me=this
这样的技巧