模块中的可变范围

时间:2018-02-19 17:30:25

标签: javascript

我正在编写我的第一个javascript模块,并且我不了解范围变量。这是我的模块:

var Module = (function () {

    var myString ='a';

    var changeString = function () {
        myString ='b';
        console.log(myString);
    };

    return {
      changeString: changeString,
      myString:myString
    };

  })();

现在,如果我这样做:

Module.myString;             // returns 'a'
Module.changeString();       // returns 'b'
Module.myString;             // returns 'a'

对我来说,最后一个命令应该返回' b'因为我用changeString方法改变了myString。我不明白为什么,因为myString是在changeString方法之外声明的,所以范围似乎没问​​题。我想了解为什么它的行为如此,以及如何创建一个覆盖我的变量值的方法。 提前谢谢。

4 个答案:

答案 0 :(得分:4)

这会在创建对象时生成myString的副本:

return {
  changeString: changeString,
  myString:myString
}

您可以使用getter动态返回本地变量,这将为您提供所需的行为:

return {
  changeString: changeString,
  get myString() { 
    return myString;
  }
}

完整示例:



var Module = (function () {

    var myString ='a';

    var changeString = function () {
        myString ='b';
        console.log(myString);
    };

    return {
      changeString: changeString,
      get myString() { 
        return myString;
      }
    }

})();

console.log( Module.myString );
Module.changeString();
console.log( Module.myString );




答案 1 :(得分:3)

匿名函数只执行一次,因此它返回的对象也只被评估一次:它是一个具有字符串属性myString的对象,它是一个原始值 - 如果是变量myString稍后会更改。

如果你想要你想要的行为,那么你应该在Module中保留一个引用你返回的对象,然后当string属性需要改变时 mutate 该对象:

var Module = (function () {    
    var changeString = function () {
        obj.myString = 'b'; // mutation of obj!
        console.log(obj.myString);
    };
    var obj = {
         changeString: changeString,
         myString: 'a';
    };
    return obj; // we have a reference to this object
})();

答案 2 :(得分:3)

正如在其他答案中所说,因为myString是一个原语,所以它的值从作用域复制到返回的匿名对象的成员值。要从myString方法访问外部可用的changeString()副本,您可以使用Module关键字引用分配给this的匿名对象:



var Module = (function() {

  var myString = 'a';

  var changeString = function() {
    // `Module.changeString()` causes `this === Module` inside here
    this.myString = 'b';
  };

  return {
    changeString: changeString,
    myString: myString
  };
})();

console.log(Module.myString);             // returns 'a'
Module.changeString();
console.log(Module.myString);             // returns 'b'




使用ES6语法,您可以使用一些快捷方式来简化此方法:



var Module = (() => {

  let myString = 'a';

  return {
    // ES6 for `myString: myString,`
    myString,
    // ES6 for `changeString: function () {`
    changeString () {
      this.myString = 'b';
    }
  };
})();

console.log(Module.myString); // returns 'a'
Module.changeString();
console.log(Module.myString); // returns 'b'




答案 3 :(得分:1)

您会看到此行为,因为您return是一个新对象。

字符串myString被复制,因为它是原始值。

您可以通过一些调整来实现目标:

var Module = function() {
    var myString = 'a';

    this.changeString = function() {
        myString = 'b';
    };

    this.getString = function() {
        return myString;
    };
};

var mod = new Module;

console.log(mod.getString()); // a
mod.changeString();
console.log(mod.getString()); // b