Могу ли я передать N count params в .bind ()

Вот быстрый и грязный пример того, как класс может запускать разные версии метода сохранения, в зависимости от того, какую операционную систему он выполняет при использовании getattr().

import os

class Log(object):
    def __init__(self):
        self.os = os.name
    def __getattr__(self, name):
        """ look for a 'save' attribute, or just 
          return whatever attribute was specified """
        if name == 'save':
            try:
                # try to dynamically return a save 
                # method appropriate for the user's system
                return getattr(self, self.os)
            except:
                # bail and try to return 
                # a default save method
                return getattr(self, '_save')
        else:
            return getattr(self, name)

    # each of these methods could have save logic specific to 
    # the system on which the script is executed
    def posix(self): print 'saving on a posix machine'
    def nt(self): print 'saving on an nt machine'
    def os2(self): print 'saving on an os2 machine'
    def ce(self): print 'saving on a ce machine'
    def java(self): print 'saving on a java machine'
    def riscos(self): print 'saving on a riscos machine'
    def _save(self): print 'saving on an unknown operating system'

    def which_os(self): print os.name

Теперь давайте использовать этот класс в примере:

logger = Log()

# Now you can do one of two things:
save_func = logger.save
# and execute it, or pass it along 
# somewhere else as 1st class:
save_func()

# or you can just call it directly:
logger.save()

# other attributes will hit the else 
# statement and still work as expected
logger.which_os()
0
задан Joseph Cho 13 July 2018 в 20:34
поделиться

2 ответа

Если я сейчас правильно понимаю, вы можете использовать Object.values и Spread Syntax , чтобы выполнить это:

var myFunction = function(param1, param2) {
  console.log(param1);
  console.log(param2);
}

var functionParameters = {
  data1: "test",
  data2: "another test"
};

var run = myFunction.bind(null, ...Object.values(functionParameters))
run();


Старый ответ

Я бы предположил, что самым простым решением будет просто передать массив ...

var myFunction = function(args) {
  args.forEach((i) => console.log(i));
}

var functionParameters = {
  1: "test",
  2: "another test",
  3: "another one"
};

var run = myFunction.bind(null, Object.values(functionParameters)) //Get array of values from the object
run();


Если вы планируете отправлять только определенные значения объекта, как у вас в вашем примере, вы можете использовать Rest Parameters ]:

var myFunction = function(...args) {
  args.forEach((i) => console.log(i));
}

var functionParameters = {
  data1: "test",
  data2: "another test",
  data3: "another one"
};

var run = myFunction.bind(null, functionParameters.data1, functionParameters.data2, functionParameters.data3) //Get array of values from the object
run();

//myFunction("This", "function", "will", "now", "take", "unlimited", "parameters");

0
ответ дан Tyler Roper 17 August 2018 в 12:15
поделиться
  • 1
    значение object.value было бы действительно отличным решением, если бы оно поддерживалось хорошо – Cheese 13 July 2018 в 19:21
  • 2
    Чтобы добавить совместимую поддержку Object.values в старых средах, которые ее не поддерживают, вы можете найти Polyfill в tc39 / items-objects-values-entries или в es-shims / Object.values ​​ репозитории. – Tyler Roper 13 July 2018 в 19:22
  • 3
    Хотя, если вам неудобно использовать Object.values, вы определенно не должны использовать синтаксис распространения, который использует оба текущих ответа. – Tyler Roper 13 July 2018 в 19:28
  • 4
    Мне больше нравится синтаксис распространения, как если бы функция вызывала любые параметры, синтаксис распространения задает пустой массив [], и он может работать с более легким в функциональной части. Также не упоминается, но вы можете попробовать аргументы Object функции – Angel 13 July 2018 в 19:34
  • 5
    Что касается синтаксиса распространения, я просто говорю, что если OP обеспокоен отсутствием поддержки для Object.values (все браузеры, кроме IE), то он не должен также рассматривать использование синтаксиса распространения, поскольку он намного более новый и менее поддерживаемый. – Tyler Roper 13 July 2018 в 19:39

Вам может понравиться попробовать операцию распространения

function fn(a,b,c){
    console.log(a,b,c)
}

, и вы могли бы сделать

const paras = [1,2,3];
const myFun = fn.bind(null, ...paras)

Он выведет 1,2,3, когда вы вызываете myFun()

Однако он работает только для массива.

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

Например, у вас есть тип объекта

const paras = {b:1, a:2, c:3};

, вы можете преобразовать его в массив с помощью

const arrayParas = ['a','b','c'].map(field => paras[field])

И затем вы можете связать свою функцию

const myFun = fn.bind(null, ...arrayParas)

Редактировать: если вы не знаете, как подавать / как получить имя параметра из функции

Js имеет свою toString, которая преобразует функцию в строку, которая содержит входной параметр этой функции.

Но вам нужно убедиться, что имя входных параметров в функции точно совпадает с именами полей в объекте.

// get function parameter name
function getParameterNames(func) {
  const STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
  const ARGUMENT_NAMES = /([^\s,]+)/g;
  const fnStr = func.toString().replace(STRIP_COMMENTS, '');
  const result = fnStr.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')')).match(ARGUMENT_NAMES);
  if (result === null)
    result = [];
  return result;
}
//
function fn(a, b, c) {
  console.log(a, b, c)
}

const paraObjs = {
  c: 3,
  a: 1,
  b: 2
};
const fields = getParameterNames(fn);
const paraArray = fields.map(field => paraObjs[field]);
const myFun = fn.bind(null, ...paraArray)

myFun();

0
ответ дан user3003238 17 August 2018 в 12:15
поделиться
  • 1
    этот звук как решение – Cheese 13 July 2018 в 19:00
  • 2
    любые идеи, если я не знаю названия полей и их счет? – Cheese 13 July 2018 в 19:03
  • 3
    @Cheese да, вы можете попробовать toString () и разобрать текстовое содержимое, чтобы получить параметр (см. Обновление). НО следует считать, что имя параметра функции ДОЛЖНО БЫТЬ ТОЧНО ИМЕЮТСЯ ТОЛЬКО, что и для параметра paramObject – user3003238 13 July 2018 в 20:15
Другие вопросы по тегам:

Похожие вопросы: