JavaScript 范围和闭包:value 属性不返回递增的值



increment如何更改value以及更改valuegetValue可以访问,但不能访问同一对象的属性感到困惑。

这是否与增量和 getValue 方法是定义值的匿名函数的内部函数这一事实有关?

var myObject = function() {
var value = 0;
return {
increment: function(inc){
value += typeof inc === 'number' ? inc : 1;
},
getValue: function(){
return value;
},
value: value,
};
}();
console.log(myObject.getValue()); // 0
myObject.increment(2);
console.log(myObject.getValue()); // 2
console.log(myObject.value); // 0
myObject.increment(2); 
console.log(myObject.getValue()); // 4

var foo创建一个变量,该变量的作用域为声明它的函数。它可以作为foo在该函数中的任何位置访问,也可以在第一个函数内声明的另一个函数进行访问。

myObject.foo创建一个附加到对象的属性。它可以作为???.foo进行访问,其中???是对myObject引用的对象的引用。您可以在任何可以找到对象引用的地方执行此操作。

属性不是变量。变量不是属性。(例外情况是全局变量是全局(window在浏览器中(对象的属性。


创建对象时,您说:

value: value,

但这会将value变量的当前值复制到value属性。

这是一个数字,不是参考。

更新value变量时,value属性保持不变。

像@Quentin这样的其他答案已经非常彻底地解释了这个问题是什么。不过,这是一种正确的方法,通过最少地修改您当前的方法来纠正问题:

var myObject = function() {
return {
increment: function(inc) {
this.value += typeof inc === 'number' ? inc : 1;
},
getValue: function() {
return this.value;
},
value: 0
};
}();
console.log(myObject.getValue()); // 0
myObject.increment(2);
console.log(myObject.getValue()); // 2
console.log(myObject.value); // 2
myObject.increment(2);
console.log(myObject.getValue()); // 4
console.log(myObject.value); // 4

但是,此功能将是使用 ES6class的一个很好的例子:

class Counter {
constructor (value = 0) {
this.value = value
}

increment (amount = 1) {
this.value += amount
}

getValue () {
return this.value
}
}
let myObject = new Counter()
console.log(myObject.getValue()) // 0
myObject.increment(2)
console.log(myObject.getValue()) // 2
console.log(myObject.value) // 2
myObject.increment(2)
console.log(myObject.getValue()) // 4
console.log(myObject.value) // 4

正如评论中指出的那样,关闭和getValue()似乎毫无意义。如果要允许value访问作用域变量,并禁用对其进行修改,可以通过以下方式实现它:

var myObject = function() {
var value = 0;
return {
increment: function(inc) {
value += typeof inc === 'number' ? inc : 1;
},
getValue: function() {
return value;
},
get value() {
return value;
},
// disable setting it without throwing
set value(newValue) {
return value;
}
};
}();
console.log(myObject.getValue()); // 0
myObject.increment(2);
console.log(myObject.getValue()); // 2
console.log(myObject.value); // 2
// won't work
myObject.value = 4
// still 2
console.log(myObject.getValue()); // 2
console.log(myObject.value); // 2

最新更新