当从Object内部访问时,变量变为0

Variable becomes 0 when accessing from within Object

本文关键字:变量 Object 内部 访问 当从      更新时间:2023-09-26

我已经创建了一个像这样的对象:

var Object = function() {
    var value = 0;
    function do() {
        console.log(value);
    }
    return {
        do : do,
        value : value
    }
};
exports.Object = Object;

我从这个对象的外部调用do函数:

function call(object) {
    console.log(object.value);
    object.update();
}

我在玩家类之外将值设置为等于2.5。奇怪的是,当我执行代码时,控制台记录如下:

2.5
0
2.5
0

所以,似乎值是0从类内,但2.5当我从外部访问它。这里的问题是什么?

我的背景主要是Java,我对Javascript相当陌生,所以也许我错过了一些微不足道的东西。

您已经创建了一个闭包:您正在返回一个具有属性value的对象,但是当您更改返回对象的value属性时,闭包中的var value不会更改

换一种方式解释,当你说new Object时,你会得到两个value,一个作为对象的属性返回,另一个是隐藏在闭包中的var object

尝试以下操作:

var Object = function() {
    this.value = 0;
    function do() {
        console.log(this.value);
    }
    return {
        do : do
    }
};
exports.Object = new Object;

另外:

var Object = function() {
    var value = 0;
    function do() {
        console.log(value);
    }
    return {
        do : do,
        getValue : function(){ return value; },
        setValue : function(val){ value = val; }
    }
};
exports.Object = Object;

正如Josh所提到的,这是一个value vs reference的问题,通常通过返回一个对象(所以它是通过引用)或包括getValuesetValue这样的函数来解决。

对于第二个选项,您实际上可以重写函数并使用getters,如下所示:
var Object = function() {
    var value = 0;
    function _do() {
        console.log(value);
    }
    function update(val) {
        value = val * .5;
    }
    return {
        do: _do,
        update: update,
        // Our fancy getter!
        get value() {
            return value;
        }
    }
};
exports.Object = Object;

此时,Object.value的行为与getValue相似。

因为今天是星期五,让我们疯狂地添加我们的setter:

var Object = function() {
    var value = 0;
    function _do() {
        console.log(value);
    }
    return {
        do: _do,
        // Our fancy getters/setters!
        get value() {
            return value;
        },
        set value(val) {
            value = val * .5;
        }
    }
};
exports.Object = Object;

那么你在做这样的事情:

Object.value; // Returns 0
Object.value = 5;
Object.value; // Returns 2.5
Object.do(); // Logs 2.5

定义getter和setter

Getter/Setter兼容性

实际上,您的代码相当于

var Object = function() {
  var value = 0;
  function do() {
    console.log(value);
  }
  var res= {
    do : do,
    value : value
  }
  return res;
 };
exports.Object = Object; 

功能do()将不记录res.value。相反,它记录了Object函数的一个局部变量,这意味着你不能改变do返回的值。

如果您想记录res.value,可以尝试如下:

function do(){
    console.log(this.value);
}

然而,我必须提到别的事情。如果value是一个对象而不是文字。你可以很容易地访问它。当对象通过ref.

传递时,闭包无法保护对象不被更改。

试试这个:

var Object = function() {
    var value = [0];
    function doSth() {
        console.log(value[0]);
    }
    var res= {
        do : doSth,
        value : value
    }
    return res;
};
exports.Object = Object;