2016-09-14 3 views
0

Я хотел бы, чтобы обернуть некоторые динамически создаваемые JavaScript функции, аналогичные принятым ответом Даниила здесь: How do I store javascript functions in a queue for them to be executed eventuallyКак обернуть функцию javascript динамическими аргументами?

// Function wrapping code. 
// fn - reference to function. 
// context - what you want "this" to be. 
// params - array of parameters to pass to function. 
var wrapFunction = function(fn, context, params) { 
    return function() { 
     fn.apply(context, params); 
    }; 
} 

Разница в том, я хотел бы значения аргументов, чтобы быть динамичным во время исполнения - это можно передать ссылку на переменную в аргументах, которая может быть обновлена ​​после ее обертывания?

Вот что я хотел бы сделать:

// I have a function to be wrapped 
var sayStuff = function(a,b) { 
    console.log(a); 
    console.log(b); 
} 

// Variables I'd like to pass 
var randomNumberA = 0; 
var randomNumberB = 0; 

// Wrap the function 
var fun = wrapFunction(sayStuff, this, [*reference randomNumberA*,*reference randomNumberB*]); 

// variables get changed 
randomNumberA = Math.random()*100; 
randomNumberB = Math.random()*100; 

// Execute the function using current values of randomNumberA & randomNumberB 
fun(); 

Если возможно, я хотел бы сделать это без изменения sayStuff, у меня есть много существующих функций, как это я надеюсь обернуть, что также можно использовать вне оболочки, поэтому в идеале я бы не хотел заменять аргументы на объект. Надеюсь, что имеет смысл, спасибо!

+1

Хотя возможно, я бы вообще сказал «нет» в контексте «этого», и я точно не знаю, почему вы хотели бы это сделать? – Xotic750

+0

Вы должны внимательно посмотреть, что примитивы всегда передаются по значению и разнице между функциями и методами. Функция становится методом, когда это зависит от 'this', которое ни одна из ваших функций не делает. – ftor

+0

@ Xotic750 Итак, функции, которые я обертываю, - это набор звуковых фильтров. Они выполняются последовательно. Но я хотел бы рандомизировать их порядок и настройки, поэтому я хотел их обернуть в нечто общее. Однако некоторые из их аргументов должны быть динамичными. Я надеюсь, что каждый объект будет помещен в объект, так что объект будет контекстом, который я думаю. – WilliamAmateur

ответ

1

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

var wrapFunction = function(fn, context) { 
 
    var xArg = arguments; 
 
    return function() { 
 
    var argsArray = []; 
 
    for (var i = 2; i < xArg.length; i++) { 
 
     argsArray.push(context[xArg[i]]); 
 
    } 
 
    fn.apply(context, argsArray); 
 
    }; 
 
} 
 

 
var sayStuff = function() { 
 
    for (var i = 0; i < arguments.length; i++) { 
 
    console.log('sayStuff func: ' + arguments[i]); 
 
    } 
 
} 
 

 
var randomNumber1 = 0; 
 
var randomNumber2 = 0; 
 

 
var fun = wrapFunction(sayStuff, this, 'randomNumber1', 'randomNumber2'); 
 

 
randomNumber1 = Math.random()*100; 
 
randomNumber2 = Math.random()*100; 
 

 
console.log('randomNumber1: ' + randomNumber1); 
 
console.log('randomNumber2: ' + randomNumber2); 
 

 
fun();

+0

Я не верю, что это будет работать во всех случаях. – Xotic750

+0

@ Xotic750 Извините за мой английский, не могли бы вы упростить свою идею? Я уверен, что вы говорите что-то полезное. Поэтому мне интересно учиться. Огромное спасибо. – gaetanoM

+0

'' '' '' '' может быть 'undefined' пытаться обернуть код в [' (function() {...}()); '] (https://jsfiddle.net/r159866L/) потребуется дополнительная работа, поэтому на самом деле это не общее решение вопроса ОП, а работает для их конкретного примера. – Xotic750

1

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

var randomNumber = 0; 
var fun = function(){ alert(randomNumber); } 

randomNumber = 10; 

// Now this will alert 10, because when fun is executed 
// JS looks in his scope to find what randomNumber is. 
fun(); 

Thi s происходит потому, что функции в javascript работают как Closures, они несут с собой свою среду. См. Так: https://en.wikipedia.org/wiki/Closure_(computer_programming)

Так что если randomNumber будет изменено вне области, в которой вы связываете эту функцию, вам нужно использовать объект, это связано с тем, что в javascript у нас нет указателей или ссылок на прохождение. Один из способов - использовать объект.

function giveMeAFunction(){ 
    var params = { randomNumber: 0 } 
    var fun = function(){ alert(scope.randomNumber); } 
    return {fun: fun, scope: scope}; 
} 

var paramsAndFun = giveMeAFunction() 
// Now you can change the variables in the scope and call the function 
paramsAndFun.params.randomNumber = 10; 
paramsAndFun.fun(); // Will alert 10 

// Now if you replace the entire params object it will not work 
// This is because you will replacing it with a new object while 
// The one that is referenced in the scope where fun was created is 
// the old one. 
paramsAndFun.params = { randomNumber: 15 }; 
paramsAndFun.fun(); // will still alert 10 

Теперь давайте перейдем к связующей части проблемы.

Функция Function.prototype.bind, которая поможет вам в этом.

Например:

var sayStuff = function(opts) { 
    alert(otions.randomNumber); 
} 

var options = { randomNumber: 0 }; 
var fun = sayStuff.bind(this, options); 

options.randomNumber = 10; 

fun(); // Will print 10 

Там будет много здесь происходит. Извините, если я все запутал.

+0

Ах спасибо, нет, что имеет смысл. Я понимаю, что я должен был упомянуть, что в идеале я бы сказал sayStuff то же самое (только что обновил вопрос), поскольку это уже существующая функция, и, если возможно, я хотел бы сохранить ее аргументы неповрежденными. Если это невозможно, то использование такого объекта, безусловно, будет работать - спасибо! – WilliamAmateur

Смежные вопросы