最小化JS getter / setter样板

时间:2015-08-25 19:55:40

标签: javascript closures encapsulation getter-setter

我正在进行面向闭包的对象创建,其对象具有围绕getter / setter方法的大量样板。有没有办法在没有那么多重复的情况下将这些属性声明为getter / setter?

目前我有:

var test = function(){
    var width = 10;    
    var height = 10;    
    return {
        width: {get: function(){return width;}, set: function(_){width=_;}},
        height: {get: function(){return height;}, set: function(_){height=_;}},
    }
}

但我想要更像的东西:

var test = function(){
    var width = 10;    
    var height = 10;    
    return {
        width: getset(width)
        height: getset(height),
    }
}

我想写一个像:

这样的函数
var test = function(){

    var getset = function(val){
        return {
            get: function(){
                console.log('getting');
                return val
            },
            set: function(_){
                console.log('besetted');
                param=_
            },
        }
    }
    var width = 10;    
    var height = 10;    

    return {
        width: getset(width),
        height: getset(height),
    }
}

但这不起作用;变量未被正确覆盖。什么是最好的方法?这有语言功能吗?

4 个答案:

答案 0 :(得分:1)

你想要的是这个:

var test = function()
{
    var
        width = 10,
        height = 10;

    this.setWidth = function(_w)
    {
        width = _w;
    };

    this.getWidth = function()
    {
        return width;
    };

    // etc.
}

现在你有一个"班级"您可以实例化:

var testObj = new test();
console.log(testObj.getWidth()); // 10
testObj.setWidth(20);
console.log(testObj.getWidth()); // 20

解释:JS没有"私人"或"公共"属性/方法。相反,公共对象属性/方法附加到this,而私有"属性"声明为函数变量,如上所示。

由于JS的 closure 逻辑,函数变量总是可以被类方法访问,而其他组件则看不到它们。

答案 1 :(得分:1)

你走了:

<% cache "script_code" do %>
   <script type="text/javascript">
    -- javascript code here --
   </script>
<% end %>

使用闭包记住的事情 - 您需要一个可在内部函数内部以及外部函数中访问的变量。

答案 2 :(得分:1)

How about something like this:

function GetSet(value) = {
  this.myValue = value;
  var that = this;

  this.getset = function(setter){
    if (setter === undefined){
      return that.myValue;
    } else {
      that.myValue = setter;
    }
  }
}

So you replace:

return {
    width: getset(width),
    height: getset(height),
}

With:

return {
  width: new GetSet(width),
  height: new GetSet(height)
}

答案 3 :(得分:0)

  

...变量未被正确覆盖。 ......这是否有语言功能?

语言本身并不直接提供功能。但是,一如既往,可以利用各种基于功能的模式,例如作为穷人帮手和工厂模块的闭包。

出于代码重用的原因,我个人会模块化一个辅助函数,它通常会解决基于键值配置的getter和setter的创建问题。 然后,我们可以专注于实现必须解决主要任务的工厂/构造函数。

除了大多数怀疑架构,有时偏执狂试图封装每个对象状态没有充分理由我在此提供概念性解决方案... [paranoid][Paranoiac],种类 { {1}} ...

test

...

var paranoid = (function () {


  var
    module,


    firstCharToUpperCase = function (str) {
      var
        list = str.split(""),
        char = list.shift()
      ;
      list.unshift(char.toUpperCase());

      return list.join("");
    },
    createKeyForSetter = function (key) {
      return ["set", firstCharToUpperCase(key)].join("");
    },
    createKeyForGetter = function (key) {
      return ["get", firstCharToUpperCase(key)].join("");
    },


    setTargetValue = function (target, key, value) {
      return (target[key] = value);
    },
    getTargetValue = function (target, key) {
      return target[key];
    },


    createAndAggregateGetterAndSetterForEachKeyValueAndTarget = function (collector, key) {

      collector.target[createKeyForSetter(key)] = function (value) {

      //return setTargetValue(collector.config, key, value);
        setTargetValue(collector.config, key, value);

      //return collector.target;
        return this;
      };
      collector.target[createKeyForGetter(key)] = function () {

        return getTargetValue(collector.config, key);
      };

      return collector;
    }
  ;


  module = {
    aggregateGettersAndSetters: createAndAggregateGetterAndSetterForEachKeyValueAndTarget
  };


  return module;


}());

...

var Paranoiac = (function (global) {


  var
    Constructor,
    factory,


    object_keys = global.Object.keys,


    createAndAggregateGetterAndSetterForEachKeyValueAndTarget = global.paranoid.aggregateGettersAndSetters,


    createInstanceFromConfig = function (config) {
      var instance = null;
      if ((config != null) && (object_keys(config).length >= 1))  {

        instance = new Constructor(config);
      }
      return instance;
    },
    isInstance = function (type) {
      return (
           (type != null)
        && (type instanceof Constructor)
      );
    }
  ;


  Constructor = function Paranoiac (config) {
    var
      instance = this
    ;
    object_keys(config).reduce(createAndAggregateGetterAndSetterForEachKeyValueAndTarget, {

      config: config,
      target: instance
    });
    return instance;
  };


  factory = {
    create      : createInstanceFromConfig,
    isParanoiac : isInstance
  };


  return factory;


}(window || this));