Двузначные правила для запоминания:
Если поля касаются, они рушатся. Вложенные элементы «прижимают», если только маржа отделяет их. Элементы вне «Потока» ведут себя по-разному. То есть, это поведение не применяется одинаково для плавающего или позиционного: фиксированное или положение: абсолютные элементы.
blockquote>Брок Адамс прав, но я также хотел добавить, что «переполнение: hidden "также может предотвратить срыв вложенных полей.
Не используйте eval
, если у вас абсолютно, положительно нет другого выбора.
Как уже упоминалось, использование чего-то подобного было бы лучшим способом сделать это:
window["functionName"](arguments);
Это, однако, не будет работать с функцией пространства имен:
window["My.Namespace.functionName"](arguments); // fail
Вот как вы это сделаете:
window["My"]["Namespace"]["functionName"](arguments); // succeeds
Чтобы упростить это и обеспечить некоторую гибкость, вот удобная функция:
function executeFunctionByName(functionName, context /*, args */) {
var args = Array.prototype.slice.call(arguments, 2);
var namespaces = functionName.split(".");
var func = namespaces.pop();
for(var i = 0; i < namespaces.length; i++) {
context = context[namespaces[i]];
}
return context[func].apply(context, args);
}
Вы бы назвали это вот так:
executeFunctionByName("My.Namespace.functionName", window, arguments);
Обратите внимание, вы можете передать в любом контексте, который вы хотите, так что это будет делать то же, что и выше:
executeFunctionByName("Namespace.functionName", My, arguments);
Я не могу не упомянуть еще один прием, который помогает, если у вас есть неизвестное количество аргументов, которые также передаются как часть строки , содержащей имя функции. Например:
var annoyingstring = 'call_my_func(123, true, "blah")';
Если ваш Javascript работает на HTML-странице, все, что вам нужно, это невидимая ссылка; Вы можете передать строку в атрибут onclick
и вызвать метод click
.
<a href="#" id="link_secret"><!-- invisible --></a>
$('#link_secret').attr('onclick', annoyingstring);
$('#link_secret').click();
Или создайте элемент <a>
во время выполнения.
Все ответы предполагают, что к функциям можно получить доступ через глобальную область видимости (также известное как окно). Тем не менее, ФП не сделал этого предположения.
Если функции находятся в локальной области видимости (или закрытии) и на них не ссылается какой-либо другой локальный объект, неудача: вам нужно использовать eval () AFAIK, см. , динамически вызывать local функция в JavaScript
Две вещи:
избегать Eval, это очень опасно и медленно
во-вторых, не имеет значения, где ваша функция существует, " глобальное "-несущество" не имеет значения. x.y.foo()
можно активировать через x.y['foo']()
, x['y']['foo']()
или даже window['x']['y']['foo']()
. Вы можете цепляться бесконечно, как это.
С ES6 вы можете получить доступ к методам класса по имени:
class X {
method1(){
console.log("1");
}
method2(){
this['method1']();
console.log("2");
}
}
let x = new X();
x['method2']();
вывод будет:
1
2
Просто подумал, что выложу слегка измененную версию очень полезной функции Джейсона Бантинга .
Во-первых, я упростил первое утверждение, указав второй параметр для slice () . Оригинальная версия работала нормально во всех браузерах, кроме IE.
Во-вторых, я заменил этот на контекст в операторе возврата; в противном случае этот всегда указывал на окно , когда выполнялась целевая функция.
function executeFunctionByName(functionName, context /*, args */) {
var args = Array.prototype.slice.call(arguments, 2);
var namespaces = functionName.split(".");
var func = namespaces.pop();
for (var i = 0; i < namespaces.length; i++) {
context = context[namespaces[i]];
}
return context[func].apply(context, args);
}
Итак, как и другие говорили, определенно лучший вариант:
window['myfunction'](arguments)
И, как сказал Джейсон Бантинг , он не будет работать, если имя вашей функции включает объект :
window['myobject.myfunction'](arguments); // won't work
window['myobject']['myfunction'](arguments); // will work
Итак, вот моя версия функции, которая будет выполнять все функции по имени (включая объект или нет):
my = {
code : {
is : {
nice : function(a, b){ alert(a + "," + b); }
}
}
};
guy = function(){ alert('awesome'); }
function executeFunctionByName(str, args)
{
var arr = str.split('.');
var fn = window[ arr[0] ];
for (var i = 1; i < arr.length; i++)
{ fn = fn[ arr[i] ]; }
fn.apply(window, args);
}
executeFunctionByName('my.code.is.nice', ['arg1', 'arg2']);
executeFunctionByName('guy');
Ответ на этот другой вопрос показывает Вам, как сделать это: JavaScript, эквивалентный из Python' s местные жители ()?
В основном, можно сказать
window["foo"](arg1, arg2);
или как многие другие предположили, можно просто использовать оценку:
eval(fname)(arg1, arg2);
, хотя это чрезвычайно небезопасно, если Вы не абсолютно уверены в том, что Вы - луг оценки.
Люди продолжают говорить, что eval
является опасным и злым, потому что это может выполнить любой произвольный код. Однако при использовании оценки с белый список подход, предполагая знание всех возможных имен функций, которые, возможно, должны быть выполнены заранее, затем оценка больше не является проблемой безопасности, потому что вход больше не произволен . Белый список является хорошим и частым шаблоном безопасности. Вот пример:
function runDynamicFn(fnName, ...args) {
// can also be fed from a tightly controlled config
const allowedFnNames = ['fn1', 'ns1.ns2.fn3', 'ns4.fn4'];
return allowedFnNames.includes(fnName) ? eval(fnName)(...args) : undefined;
}
// test function:
function fn1(a) {
console.log('fn1 called with', a)
}
runDynamicFn('alert("got you!")')
runDynamicFn('fn1', 'foo')