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

时间:2017-08-02 15:20:17

标签: javascript scope closures javascript-objects

increment可以value更改value并且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 ,而不是同一对象的属性。

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

import shapeless.Generic

object FooBar {

  case class Foo(a: String, b: Int, c: String)
  case class Bar(x: String, y: Int, z: String)

  def main(args: Array[String]): Unit = {
    val genFoo = Generic[Foo]
    val genBar = Generic[Bar]

    println(genBar.from(genFoo.to(Foo("foobar", 5, "barfoo"))))
  }

}

2 个答案:

答案 0 :(得分:2)

var foo创建一个变量,其范围限定为声明的函数。它可以作为foo在该函数内的任何位置或在其中声明的其他函数中访问第一个功能。

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

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

当您创建对象时,您说:

value: value,

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

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

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

答案 1 :(得分:1)

@Quentin's等其他答案已经解释了问题的彻底性。通过最低限度地修改当前的方法来纠正问题,这是一种正确的方法:



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




但是,此功能将是使用ES6 class

的一个很好的示例



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




As was pointed out in comments,封闭和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