Можете ли вы динамически построить цепочку вызовов методов? - PullRequest
0 голосов
/ 26 июня 2018

Я наткнулся на некоторый код, который я пытаюсь реорганизовать, где они писали JavaScript в виде строки и помещали его в теги HTML-сценария, а затем записывали его в DOM. Очень некрасиво и не ремонтопригодно. Но одна из вещей, которая позволила им это сделать, - создать вызов функции, добавив строку.

var methods = '';
for (key in obj) {
  methods += 'func1("'+key+'", "'+obj[key]+'").';
}    
var scriptString = '<script>func2().' + methods + 'func3();</script>'

Результат может быть:

'<script>func2().func1("key1", "value1").func1("key2", "value2").func3();</script>'

Итак, поскольку я действительно не одобряю написание JavaScript внутри строки HTML внутри JavaScript ... Кто-нибудь знает, как добиться того же результата с помощью чистого JavaScript? Есть ли способ непрерывного добавления методов к вызову функции путем итерации по объекту?

Ответы [ 2 ]

0 голосов
/ 26 июня 2018

Array.reduce() должен делать то, что вам нужно.

Сложная часть - это цепочка вызовов метода .func1(), где вы зависите от пар ключ / значение объекта. Если вы не привыкли работать с методом Array.reduce(), я бы посоветовал прочитать документацию MDN , но в основном он проходит по массиву, выполняя преобразование предыдущего результата, пока не достигнет конца где он возвращает окончательный результат. Это может быть использовано для нашего преимущества, поскольку цепочка методов - это просто вызов метода для возвращаемого значения предыдущего вызова метода. Но, поскольку это метод массива, нам нужно сначала получить записи Объекта в массив ... и вот тут появляется Object.entries().

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

См. Пример ниже:

const wrapperFunc = (obj) => {

    // Start with func2()
    const func2Result = func2()
  
    // Chain to func1() for each entry in obj (the tricky part)
    const func1Result = Object.entries(obj).reduce(

        // Call func1 method on previous result to get the next result
        (prevResult, [ key, val ]) => prevResult.func1(key, val),

        // Initial "prevResult" value used above
        func2Result
    )
  
    // Chain to func3()
    return func1Result.func3()
}

// Inject object to be used for func1() calls
wrapperFunc({
    key1: 'value1',
    key2: 'value2'
})

Кроме того, вот второй, более сложный пример с некоторыми реализованными методами. В отличие от приведенного выше примера, этот на самом деле работает.

class MyObject {
  constructor() {
    this.innerString = ''
  }

  // Chainable method (returns this)
  func1(key, val) {
    this.innerString += `${key}, ${val} `
    return this
  }

  func3() {
    return this.innerString.trim()
  }
}


const func2 = function () {
  return new MyObject()
}

const wrapperFunc = (obj) => {

  // Start with func2()
  const func2Result = func2()

  // Chain to func1() for each entry in obj (the tricky part)
  const func1Result = Object.entries(obj).reduce(

    // Call func1 method on previous result to get the next result
    (prevResult, [ key, val ]) => prevResult.func1(key, val),

    // Initial "prevResult" value used above
    func2Result
  )

  // Chain to func3()
  return func1Result.func3()
}

// Inject object to be used for func1() calls
console.log(wrapperFunc({
  key1: 'value1',
  key2: 'value2'
}))
0 голосов
/ 26 июня 2018

Вы можете создать функцию, которая неоднократно вызывает метод func1 для всех пар ключ / значение в объекте.

var script = function(obj) {
    var value = func2();
    for (var key in obj) {
        value = value.func1(key, obj[key]);
    }
    value.func3();
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...