在闭包作用域中设置变量

6

我认为我理解了变量存在于声明它们的函数之外的原因,因为你正在返回另一个函数:

myFunction = function() {
    var closure = 'closure scope'
    return function() {
        return closure;
    }
}
A = myFunction(); // myFunction returns a function, not a value
B = A(); // A is a function, which when run, returns:
console.log(B); // 'closure scope'

现在的写法中,调用A()就像是一个getter。

问:我该如何编写myFunction,以便调用A(123)成为一个setter?


说“不是一个值”有点误导,一个函数就是一个值。 - icktoofay
6个回答

9

请尝试以下方法:

myFunction = function() {
    var closure = 'closure scope'

    // value is optional
    return function(value) {
        // if it will be omitted
        if(arguments.length == 0) {
            // the method is a getter
            return closure;
        } else {
            // otherwise a setter
            closure = value;
            // with fluid interface ;)
            return this;
        }
    }
}
A = myFunction(); // myFunction returns a function, not a value
A(123); // set value
B = A(); // A is a function, which when run, returns:
console.log(B); // '123'

谢谢Thorsten!我没有想到可以使用长度属性来确定是否有参数。这很好。 - Phillip Senn
使用它,您也可以将属性设置为“null”或“false”。很长一段时间以来,我并没有真正编写js代码,但是记得有些东西 :) - hek2mgl

3
如果你想同时拥有getter和setter,可以像这样做:
var func = function() {
  var closure = 'foo';

  return {
    get: function() { return closure; },
    set: function(value) { closure = value; }
  }
};

var A = func();

A.set('foobar');
console.log(A.get()); //=> "foobar"

谢谢elclanrs。我看了JavaScript getters和setters,但是我想要使用jQuery样式的getters和setters,其中调用没有参数的函数被认为是getter,而调用带参数的函数被认为是setter。 - Phillip Senn

2
应该尽可能简单:
myFunction = function() {
    var closure = 'closure scope'
    return function(setTo) {
        if (typeof setTo !== "undefined") {
            closure = setTo;
            return this; //support call chaining, good idea hek2mgl
        } else {
            return closure;
        }
    }
}

由于闭包变量位于函数范围的闭包中,您应该可以像读取它一样对其进行赋值。

请参见 jsFiddle:http://jsfiddle.net/WF4VT/1/


如果 setTo0 呢?;) - Felix Kling

2
另一个选择是使用类并定义getter和setter:
function MyClass(p){
    this._prop = p;
}
MyClass.prototype = {
    constructor: MyClass,
    get prop(){
        return this._prop;
    },
    set prop(p){
        this._prop = p;
    }
}

var myObject = new MyClass("TEST");
console.log(myObject.prop);
myObject.prop = "test";
console.log(myObject.prop);

演示: http://jsfiddle.net/louisbros/bMkbE/

1

jsFiddle 演示

让你的返回函数接受一个参数,并将其用作setter:

myFunction = function() {
 var closure = 'closure scope';
 return function(val) {
    closure = val;
    return closure;
 }
}
A = myFunction(); // myFunction returns a function, not a value
B = A(123); // A is a function, which when run, returns:
console.log(B); // 'closure scope'

0
重新审视这个问题,我发现我可以这样做:

    function outside() {
     var result = 'initialized'
     return inside
     function inside(argVariable) {
      if(arguments.length) {
       result = argVariable
       return this
      } else {
       return result
      }
     }
    }
    myFunction = outside() // outside returns a function
    X = myFunction() // returns: 'initialized'
    $('body').append(X + '<br>')
    myFunction(123) // setter
    X = myFunction() // returns: 123
    $('body').append(X)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接