JavaScript. Каков наилучший способ создания цепочки функций?

РЕДАКТИРОВАТЬ
Вот попытка упростить мой вопрос.

return this.someFunc(); == return { XXX:this.someFunc() };

Что мне нужно сделать для XXX, чтобы сделать это утверждение истинным?


Я пытаюсь создать функцию, которая может быть скована. Позвольте мне написать некоторый гипотетический код. (Любые ошибки синтаксиса просто игнорируются, я набираю это быстро, и это всего лишь код концепции.) Предположим, что все функции либо определены локально, либо глобально.:)
test = function(){
  this.someFunc = function(){
    this.retest = function(){
      //...code
    }
    //...code
  }
  this.someFunc2 = function(){
    //...code
  }
  return this.someFunc();
}

Эта функция позволяет мне цепочка: test().retest();
Но то, что я хочу сделать, это вернуть более одного элемента.

test = function(){
  this.someFunc = function(){
    this.retest = function(){
      //...code
    }
    //...code
  }
  this.someFunc2 = function(){
    //...code
  }
  return { XXX:this.someFunc(), //What do I put for XXX
           next:this };
}

Я хочу сделать это для доступа к другой функции, которую предлагает test(): test().next.someFunc2();

Итак, моя проблема заключается в следующем:
Я все еще хочу иметь возможность так цепляться: test().retest();
Но я должен сделать это вот так: test().XXX.retest();

В моем коде, какое имя я могу поставить вместо XXX, чтобы выполнить это? И возможно ли это? Я уже пробовал 0 и default. Спасибо за помощь.

Ответ 1

Вы можете сделать связанные функции следующим образом:

var test = function(){

    var self = {};
    console.log('test called')

    function someFunc() {
        console.log('someFunc')
        return self;
    }

    function someOtherFunc() {
        console.log('someOtherFunc')
        return self;
    }   

    self.someFunc = someFunc;
    self.someOtherFunc = someOtherFunc;
    return self;

}

test().someFunc().someOtherFunc();

Надеюсь, что это поможет

Ответ 2

function test() {
   // when test() is called as a regular function
   // it `this` will be `undefined` (in strict mode) or will refer to a global object
   // when test() is called with `new` operator
   // it `this` will be an instance of `test` object
   if(!(this instanceof test)) {
      // create a new object
      return new test();
   }
   else {
      // this is a `new object` creation              
      console.log('new Test created');
   }
}

// declare functions which will be accessible on test object
test.prototype.someFunc = function() {
    console.log('someFunc');
    return this;
};

test.prototype.someFunc2 = function() {
    console.log('someFunc2');
    return this;
};

// declare a `chaining` function - will create a new `test` object
test.prototype.test = function() {
    return new test(); // new instance will be created
};

С помощью этого кода вы можете запустить следующий код

test().someFunc().someFunc2().test().someFunc().someFunc().test().test()

Следующая строка будет записана на консоли

new Test created
someFunc
someFunc2
new Test created
someFunc
someFunc
new Test created
new Test created

Ответ 3

у вас проблема с областью - вы не можете ссылаться на _NAME "тест" в функции, потому что вы не знаете, как она называется.

если вы сделаете это статически, вы просто можете сделать:

test = function(){

    this.someFunc = function(){ // blaaa
    };

    //...code 
    return { 
        OUTPUT: this.someFunc(), //What do I put for XXX
        test: this
    };
}

приведет к:

test().test().test().test().OUTPUT (or something like this)

Ответ 4

test = function(){

  var someFunc = function(){
      //...code
  }

  return {
      someFunc:someFunc,
      next:this
  }
}

EDIT - Обновлено, чтобы отразить ваше обновление вопроса, для ясности.

Ответ 5

Сделайте это

test = function(){
  this.someFunc = function(){
    this.retest = function(){
      //...code
    }
    //...code
  }
  this.someFunc2 = function(){
    //...code
  }

  var ret = this.somefunc();
  ret.next = this;

  return ret;
}

EDIT: здесь лучше, работает, версия

test = function(){
  var ret;

  var func = function() {
    console.log("test func");
  }

  ret = function(){
    func();
    return ret;
  }

  ret.test = ret;
  ret.next = ret; // You can define an arbitrary number of members here
  ret.XXX = func(); // Like this, and you can still chain it like your question

  return ret;
}

Ответ 6

Не уверен, каково ваше намерение, но это будет цепная функция Test:

function Test(){
  Test.retest = Test.retest || function(){console.log('retested'); return Test;}
  return Test;
}
Test().retest().retest().retest().retest();
/* => result
 retested
 retested
 retested 
 retested
*/
// and
log(Test() === Test); //=> true

Ответ 7

Хорошо, поэтому я думаю, что я понимаю ваш вопрос, но я не уверен (и здесь очень поздно ночью, так что дайте мне немного по этому поводу). Я думаю, что вы хотите иметь такое поведение:

test(); //is ["result1"]
test().retest(); //is ["result1", "result2"]
test().retest().retest(); //is ["result1", "result2", "result3"]

Возможно, вы захотите вернуть объекты вместо строк, но это же общая идея. И код оказывается довольно простым:

var test = (function() {
    var results = ["result1"], 
        i = 1;

    results.retest = (function() {
        results.push("result" + (++i));
        return results;
    });

    return results;
});

test(); //is ["result1"]
test().retest(); //is ["result1", "result2"]
test().retest().retest(); //is ["result1", "result2", "result3"]

Не уверен, что это то, что вы ищете, но, может быть, вы попадете на правильный путь.

Ответ 8

Поскольку ваш пример не работает так, как вы его разместили, я полагаю, вы имели в виду следующее:

test = function(){
  this.someFunc = function(){
    this.retest = function(){
      //...code
    }
    //...code
  }
  this.someFunc2 = function(){
    //...code
  }
  return new this.someFunc();
}

Обратите внимание на новый в возврате. Теперь, чтобы все еще иметь возможность связывать свои функции, вы должны вернуть это:

return {retest: new this.someFunc().retest, next:this};

Таким образом, вы сможете называть test().retest(); Надеюсь, это поможет.