Javascript函数就像对象和函数一样

时间:2015-07-20 06:29:20

标签: javascript

通过API设计我需要这样的东西:

Store = function(fn, args) {
     return this[fn](args); 
}
Store.getOptions() { return this.options}
Store.setLog(args) { this.options.log = args}

使用单独的选项从商店创建对象实例,例如:

option1 = {save:false, log: true}
Store1 = new -->  Store(option1)  //pseudo code object creation

let opt1 = Store1('getOptions');   //Store acting like a function

Store1('setLogs', false);          //same call
Store1.setLogs(false);

将act表示为对象(创建新对象)并可以调用。

我正在尝试使用Store.bind(选项),但已定义的属性getOptionssetLog会丢失它。

3 个答案:

答案 0 :(得分:0)

您要定位哪个EcmaScript版本:EcmaScript 5或EcmaScript 6(EcmaScript 2015)?

创建EcmaScript 5课程:

// Declare constructor for class Store:
var Store = function(){ /* This code will be executed when you call 'new Store()' */ }; 

注意:类的实例的所有属性和函数都被添加到类构造函数的prototype属性中。 * /

// Add properties for each instance of class Store:
Store.prototype.options = {Hi:'World'}; // Each instance of Store will have object with property Hi:'World'

// Add functions for each instance of class Store:
Store.prototype.SayHello = function(name){
    console.log('Hello ', name);
};

用法:

var store1 = new Store();
store1.SayHello('Phillip'); //Will output: Hello Phillip

EcmaScript 6(EcmaScript 2015)

Mozilla Developer Network

中查看有关课程用法的文章

答案 1 :(得分:0)

你为什么要这样做?

let opt1 = Store1('getOptions');   //Store acting like a function
Store1('setLogs', false);          //same call

只需定义方法或组合它们。

我可以在这里看到你有2个不同的用例:

  1. 获取/设置选项
  2. 获取/设置与日志相关的内容?
  3. 为什么不呢:

    var optionsProto = function() {
      var options = [];
    
      var getOption = function getOption(key) {
        if(options[key]) {
          return options[key];
        }
    
        //Handle error or return undefined..
      };
    
      var setOption = function setOption(key, val) {
        if(!options[key]) {
          options[key] = val;
        }
    
        //It already exists? Handle it somehow
      };
    
      return {
        getOption: getOption,
        setOption: setOption
      };
    }();
    
    var debuggerProto = function() {
      var level = 'DEBUG';
    
      var getLevel = function getLevel() {
        return level;
      };
    
      var setLevel = function setLevel(_level) {
        level = _level;
      };
    
      return {
        getLevel: getLevel,
        setLevel: setLevel
      };
    }();
    
    
    var mixedUpStoreProto = _.extend({}, optionsProto, debuggerProto);
    
    var store = Object.create(mixedUpStoreProto);
    
    store.setLevel('INFO');
    store.getLevel(); //INFO
    
    store.addOption('somekey', 'someval');
    store.getOption('somekey'); // someval
    

    通过这种方式,您可以通过重用原型来组合很多对象。

答案 2 :(得分:0)

首先,感谢@ Epsil0neR和@ gor181获得答案,但可能比我没有正确提问。 实际上我再次询问Ramda Github问题,因为我需要使用curry函数实现API。 最后,我迟到了几个小时。

以下是代码,可能对某人有用:https://github.com/ramda/ramda/issues/1291

//return 'fn' with all 'obj' props
function functionize(obj, fn)
{
    let fn = fn;
    for( let i in obj ){ fn[i] = obj[i] };
    return fn;
}


SubStore = function(options) {
    this.options = options;
}
SubStore.prototype.getOptions = function() { return this.options }
SubStore.prototype.setOptions = function(options) { this.options = options }
SubStore.prototype.insert = function(doc) { return doc }
SubStore.prototype.find = function(selector, options) { return selector }

SubStore.create = function(options) {
    let sub = functionize(new SubStore(options), R.curry(function (args, fn) {
        let self = sub;         //reference to new SubStore obj
        return self[fn](args);
    }))
    return sub;
}

Store = function(options) {
    this.options = options;
}
Store.prototype.insert = function(args) {
    for (let i = 0, len = args.length; i < len; i++) {
        if ( R.is(Function, args[i]) ) { args[i] = args[i]('insert') }
        console.log(args[i]);
    }
}
Store.prototype.find = function(args) {
    for (let i = 0, len = args.length; i < len; i++) {
        if ( R.is(Function, args[i]) ) { args[i] = args[i]('find') }
        console.log(args[i]);
    }
}

测试代码

store = new Store();

sub1 = SubStore.create({path:'perfil'});
sub2 = SubStore.create({path:'rol'});

// test#1
store.insert([ sub1({name: "Foo"}), sub2({age: 18}) ]);

// test#2
store.insert([ sub1.insert({name: "Foo"}), sub2.insert({age: 18}) ]);

您是否需要Javascript ES5版本只需将let替换为var,并且您还必须添加Ramda库以用于咖喱功能。

由于