Javascript执行上下文,鼠标处理程序中的反直观作用域链
这是一个有趣的范围链案例,在我发现很难理解的很多文档中都没有解释。如果有人能花时间阅读下面注释良好的代码,并解释如何解析变量,那将非常好 我在一个文档上有两个矩形(div)。我在mousedown上注册mousedown的事件侦听器,并在mousedown侦听器中注册mouseup。在穆塞普的听者中发生了奇怪的事情 通过使用不同的参数值调用testfunc两次,可以创建两个执行上下文:Javascript执行上下文,鼠标处理程序中的反直观作用域链,javascript,scope,closures,Javascript,Scope,Closures,这是一个有趣的范围链案例,在我发现很难理解的很多文档中都没有解释。如果有人能花时间阅读下面注释良好的代码,并解释如何解析变量,那将非常好 我在一个文档上有两个矩形(div)。我在mousedown上注册mousedown的事件侦听器,并在mousedown侦听器中注册mouseup。在穆塞普的听者中发生了奇怪的事情 通过使用不同的参数值调用testfunc两次,可以创建两个执行上下文: window.onload = function() { test_func("horizontal
window.onload = function() {
test_func("horizontal"); // First Execution context
test_func("vertical"); // Second Execution Context
}
在第一个矩形(水平)的mouseup侦听器中,正在使用第二个执行上下文(垂直),这是违反直觉的:
function test_func(dir) {
var X = 9; // variable which helps to track the execution contexts
if(dir === "horizontal")
X = 1; // leave at 9 if vertical
mouseup_vert = function() {}
mouseup_horiz = function() {
// Here the value of X I am getting is 9 whereas I am expecting 11
// QUESTION: Why I am getting the second execution context??
}
mousedown_vert = function() {
// As expected the value of X here is 9
X=99;
// set X to 99 to check if during mouseup same exec context is picked
document.addEventListener("mouseup", mouseup_vert, false);
}
mousedown_horiz = function() {
// As expected value of X is 1, so using first execution context
X=11;
// set this to check if during mouseup I get a value of 11
document.addEventListener("mouseup", mouseup_horiz, false);
}
if (dir === "horizontal") {
e = document.getElementById("horiz");
e.addEventListener("mousedown", mousedown_horiz, false);
} else {
e = document.getElementById("vert");
e.addEventListener("mousedown", mousedown_vert, false);
}
}
这是因为引用函数的变量不是用
var
声明的,所以它们是全局变量
它们将被第二个调用覆盖,该调用将在X
附近关闭,值为9
编辑:以下是实际发生的情况。为简单起见,我在同一范围内创建所有变量 …或使代码更具体一点:
确切地那些“mouseup_foo”变量都是全局变量。它们必须用
var
关键字声明!!另外,从事件处理程序内部设置事件处理程序将是一个大问题。如果它是全局的,那么在mousedown_horiz中X将被设置为11,这是我应该在mouseup_horiz中看到的值,而不是我看到的值,因此我的question@Raks符号“mouseup_vert”、“mousedown_vert”、“mouseup_horiz”和“mousedown_horiz“它们是全球性的。毫无疑问。@Raks:它没有显示更新的值的原因是,在下一次调用覆盖该函数实例之前,您正在引用该函数实例。mouseup\u-vert/\u-horiz
函数在mousedown事件发生之前不会被引用,因此它们会获得全局变量的最新版本,该变量现在引用第二次test\u-func
调用中的函数……换句话说,您立即引用了存储在mousedown\u-horiz/\u-vert
中的函数,因此,在它们有机会被覆盖之前,它们是安全的。由于您对存储在mouseup\u vert/\u horiz
中的函数的引用被延迟,因此在引用它们之前,它们有可能被覆盖。
// "a" is referencing a function.
var a = function() { alert( 'a' ); };
// "b" is referencing the same function that "a" is referencing.
var b = a;
// The reference "a" holds to the function is being overwritten with a
// reference to a new function.
a = function() { alert( "I'm a new function" ); };
// "c" is referencing the same function that "a" is referencing (the new one).
var c = a;
// So what is "b" referencing? It is still the original function, because it
// picked up that reference *before* the original reference "a" held was
// overwritten.
b(); // alerts 'a'
// reference a function
var mouseup_vert = function() { alert( "I'm a mouseup function." ); };
// reference a function
var mousedown_vert = function() {
// When this function is invoked, add a listener using
// whatever function is referenced by mouseup_vert
document.addEventListener( "mouseup", mouseup_vert, false);
};
// The function currently referenced by "mousedown_vert" is passed here
// as the event handler.
document.addEventListener("mousedown", mousedown_vert, false);
// Overwrite "mouseup_vert" just for kicks.
mouseup_vert = function() { alert( "I'm a completely different function." ); };
// NOW trigger a "mousedown" event. What happens? The function passed as the
// handler is invoked.
// What does that function do? It adds a "mouseup" handler.
// Which variable is referenced? "mouseup_vert".
// What is the current value of "mouseup_vert"? The new function, since we
// overwrote the reference to the original.