我正在尝试编写一个有点通用的模式对话框处理函数,因此我可以将控件传递给它来处理不同的操作。听起来很简单,我也这么认为。我试图在一个对象中传递按钮处理程序函数,该对象循环通过 ID 将每个函数注册到按钮单击处理程序。它有效,但不是以我期望的方式。这是代码(需要 bootstrap 3):
function confirmation(question){
var modalTitle = 'Confirmation';
var modalContents = question;
var modalControls = '<button type="button" class="btn btn-primary" id="confirmYes">Confirm</button> <button type="button" class="btn btn-default" id="confirmNo">Cancel</button>';
var modalButtons = {
confirmNo: function(){
console.log('really, no!');
},
confirmYes: function(){
console.log('really, yes!');
}
}
standardModal(modalTitle,modalContents,modalControls,modalButtons);
}
function standardModal(modalTitle,modalContents,modalControls,modalButtons){
$('#standardModalTitle').html(modalTitle);
$('#standardModalBody').html(modalContents);
$('#standardModalControls').html(modalControls);
for (var prop in modalButtons){
if(!modalButtons.hasOwnProperty(prop)) continue;
$('#'+prop).click(function(e){
e.preventDefault();
modalButtons[prop]();
});
}
$('#standardModal').modal('show');
}
这是 HTML:
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
<div class='modal fade' tabindex='-1' role='dialog' id='standardModal'>
<div class='modal-dialog'>
<div class='modal-content'>
<div class='modal-header'>
<button type='button' class='close' data-dismiss='modal' aria-label='Close'><span aria-hidden='true'>×</span></button>
<h4 class='modal-title' id='standardModalTitle'></h4>
</div>
<div class='modal-body' id='standardModalBody'>
</div>
<div class='modal-footer' id='standardModalControls'>
<button type='button' class='btn btn-default' data-dismiss='modal'>Close</button>
</div>
</div>
</div>
</div>
当我运行确认时('这是一个问题?');对话框中应该有两个按钮:确认和取消。我希望确认运行 modalButtons.confirmYes 函数,而取消应该运行 modalButtons.confirmNo。实际发生的情况是,两个按钮都调用了 modalButtons 中定义的最后一个函数。如果confirmYes 是最后定义的函数,则它会针对两个按钮运行。
当我在那里抛出console.log语句时,变量输出是我每次所期望的......但实际的函数调用是错误的。
我做错了什么?
最佳答案
当您单击按钮并调用 modalButtons[prop]()
时,prop
的计算结果是什么?记住 javascript 如何查找变量名称:
- 如果变量是本地定义的,则使用该值
- 否则,一次走出 1 个作用域,直到到达全局(窗口)作用域,并查看那里是否定义了具有给定名称的变量
- 否则,解析为
未定义
在我们的例子中,您单击按钮,然后执行 click
回调,并且 javascript 尝试查找 prop
的值:
prop
未在回调的作用域中定义,因此它会查看下一个外部作用域prop
在回调的直接父作用域中定义!prop
的值是多少?嗯,这是您循环的最后一个值(数组的最后一个元素)。
您想要做的是定义一个始终指向 prop
预期值的变量。最简单的方法是用函数迭代器替换 for
循环:
Object.keys(modalButtons).forEach(function (prop) {
// same loop code as before
})
不同之处在于,我们在父作用域中声明一个名为 prop
的新变量,而不是声明一次 prop
并在每次滚动时更改其值循环。这是一个微妙的错误,但您会经常遇到,因此了解其工作原理非常重要。
这有帮助吗?
或者查看我对此的回答 similar question ,如果有帮助请告诉我!
关于javascript - 调用对象中设置的匿名函数,未得到预期结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36751503/