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
这样的技巧