我开始错误地问这个问题,所以我重新开始,从我正在努力解决的问题的细节开始,而不是 比问题的一般特征。
我有一个对象,其中的值是字符串。它们几乎需要是字符串,因为它们是从HTML5自定义data-*
属性中提取的,我真的不想像1999年那样开始在HTML属性中编写javascript。
下面是其中一个自定义data-*
属性的示例:
data-event="{«eventListener» : «transitionend», «eventAction» : «showText»}"
如您所见,它基本上是一个 JSON 字符串,稍作修改,因此它可以采用 HTML 属性值的形式。
我希望能够解析该自定义data-*
属性并将其转换为以下 javascript:
parentElement.addEventListener('transitionend', showText, false);
为此,我需要:
- 将
«
和»
字符替换为"
字符 - 将结果值
JSON.parse
到对象中 - 如果
useCapture
参数不存在,请创建该参数(如本例所示( - 然后对我来说,创建
addEventListener
语句很简单(几乎(
事实上 - 当然 - 我最终会得到这个声明:
parentElement.addEventListener('transitionend', 'showText', false);
这不起作用,因为我无法调用'showText'
- 它只是一个字符串,它不指向函数。
解决此问题的最简单方法是创建此语句:
parentElement.addEventListener('transitionend', eval('showText'), false);
相当于:
parentElement.addEventListener('transitionend', showText, false);
唯一阻碍我的是我不确定是否真的不应该使用eval()
,或者是否应该简单地避免它 - 而且,尽管有正常的警告,但这种不寻常的情况是可以接受的部署eval()
。
问题:在 Javascript 中,获取一个恰好是函数名称的字符串并通过对字符串使用eval()
来访问和执行该函数是错误的还是不可取的?
如果不可取,当我知道函数的名称并希望将其插入事件处理程序时,还有什么替代方法?
如果我最好避免这种情况:
parentElement.addEventListener('transitionend', eval('showText'), false);
我应该改用什么?
或者......在某些情况下使用eval()
是完全可以接受的 - 这是其中之一?
为了响应更新,最好将所有事件处理程序放在对象而不是全局命名空间中,即:
以前:
function showText(event) {
...
}
function anotherHandler(event) {
...
}
后:
const myActions = {
showText(event) {
...
},
anotherHandler(event) {
...
}
}
然后,在你解析了data
属性并得到如下内容之后:
data = {"eventListener" : "transitionend", "eventAction" : "showText"}
以这种方式绑定处理程序:
parentElement.addEventListener(
data.eventListener,
myActions[data.eventAction],
false)
这不仅摆脱了eval
,而且还有助于以更简洁的方式组织代码。
如果您的函数在全局范围内,则可以执行此操作:
myElement.addEventListener('click', window[myObject.function1], false);
方括号只是.
的替代语法 - 但它们允许变量属性名称。
检查这个:
const obj = { a: 'Hello this is obj.a' };
const key = 'a';
console.log(obj.a);
console.log(obj['a']);
console.log(obj[key]);