JavaScript关闭和范围问题

时间:2015-10-06 06:44:31

标签: javascript

有人可以向我解释以下代码:

var person = (function () {
    var locX = 0;
    return {
        "walk": function () {
            locX++;
        },
        "getLocX": function () {
            return locX;
        },
        "locX": locX
    }
})();


person.locX // output 0

person.getLocX() // output 0

person.walk()

person.getLocX() // output 1

person.locX // output 0    <-------- why it is still 0

3 个答案:

答案 0 :(得分:5)

  

person.locX //输出0&lt; --------为什么它仍为0

因为在对象初始值设定项中,这个属性初始值设定项为:

"locX" : locX

获取locX并将其分配给对象上的属性。它不会在您的locX 变量与属性之间建立链接。

就是这样:

var a, b;
a = 1;
b = a;
a = 2;
console.log(b); // 1, of course

a分配给b并未在ab之间创建任何类型的链接。它与对象属性完全相同。

如果您想获取变量的值 locX,您的getLocX功能就是您的功能。

如果您的目标是能够从对象中读取locX而不显式调用函数,但是该值来自您的变量,那么在ES5中,您可以使用 getter 功能:

var person = (function() {
  var locX = 0;
  return {
    walk: function() {
      locX++;
    },
    get locX () {
      return locX;
    }
  };
})();
snippet.log(person.locX); // 0
person.walk();
snippet.log(person.locX); // 1
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

重要的是要意识到使用getter函数意味着person.locX是一个隐藏的函数调用。

答案 1 :(得分:2)

  

person.locX //输出0&lt; --------为什么它仍为0

问题在这里,

"locX" : locX

getLocX不同,只有值0在return语句时被复制,而不是locX的引用。

答案 2 :(得分:1)

因为更改locX变量的值不会更新属性的值,所以它们不会链接在一起。

一种可能的解决方案是使用Object.defineProperty(),如下所示,只要请求locX属性的值,我们就可以返回局部变量的值。

var person = (function() {
  var locX = 0;
  var obj = {
    "walk": function() {
      locX++;
    },
    "getLocX": function() {
      return locX;
    }
  }

  Object.defineProperty(obj, 'locX', {
    enumerable: true,
    get: function() {
      return locX
    }
  });

  return obj;
})();

snippet.log('locX: ' + person.locX);
snippet.log('getLocX: ' + person.getLocX());
person.walk();
snippet.log('walk')
snippet.log('locX: ' + person.locX);
snippet.log('getLocX: ' + person.getLocX());
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

或者正如TJ所说使用getter

var person = (function() {
  var locX = 0;

  return {
    "walk": function() {
      locX++;
    },
    "getLocX": function() {
      return locX;
    },
    get locX() {
      return locX;
    }

  };
})();

snippet.log('locX: ' + person.locX);
snippet.log('getLocX: ' + person.getLocX());
person.walk();
snippet.log('walk')
snippet.log('locX: ' + person.locX);
snippet.log('getLocX: ' + person.getLocX());
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>