var a = 0, b = 0; function A(a) { A = function(b) { alert(a + b++) } alert(a++) } A(1); A(2);
上面A(1)和A(2)输出为多少?为什么?
认证高级PHP讲师
1 var a = 0, b = 0; 2 function A(a) { 3 A = function(b) { 4 alert(a + b++) 5 } 6 alert(a++) 7 } 8 A(1); // 1 9 A(2); // 4
浏览器执行Js程序的时候,分两步:
(1)预解析 在代码解读之前发生,相当于一个"仓库",放一些东西,比如var、function、参数等。 预解析时变量都是未定义的,函数则是整个函数块。 预解析时遇到重名的,会覆盖。变量与函数,留函数;函数与函数,留后面解析的。 当代码在一个环境中执行时,会创建变量对象的一个作用域链。是域就要预解析。 (2)执行代码 代码自上而下,从左往右的执行,读到表达式时,预解析仓库中的东西发生改变。
我们来分析题目:
先预解析,预解析仓库里有:
a = undefind, b = undefind, function A(a) { A = function(b) { alert(a + b++) } alert(a++) }
执行代码:
第1行:遇到表达式,预解析仓库发生变化 a = 0, b = 0, function A(a) { A = function(b) { alert(a + b++) } alert(a++) } 2-7行为函数声明 第8行: 调用A A内部发生预解析: 形参a = undefind 执行A: 实参1传给a,函数局部变量a=1, 执行第3行,将值赋给A,外部预解析仓库变化: A = function(b) { alert(a + b++) } 执行第6行,先弹出a(为1),再自增 第9行:调用A 此时 A = function(b) { alert(a + b++) } A内部发生预解析: 形参b = undefind 执行A: 实参2传给b,函数局部变量b=2, 执行第4行,变量a在局部作用域中没找到,顺着环境往外找,在外层函数中找到, 第3行赋给A的函数因为调用了变量a,所以执行完后不会销毁,会留在内存中 此时: a = 2, b = 2,+的优先级高于后置自增,所以先加,和为4,弹出4
第一次执行A(1),最后alert(1);第二次执行A(2),最后alert(4);
在第一次执行的时候,先是重定义了A这个方法(并不执行),然后alert(a++),其中先输出a然后自加1,于是结果是1。这个时侯A方法变成alert(a+b++),a=2。
第二次执行的时候,执行alert(a+b++),其中a是2,b也是2,先输出了4然后b自加1成了3。
全局下的a,b没有改变,改变的是闭包的a。所以说,第二次执行取的a也不是全局的,而是A内的a。
为什么总是爱 讨论 这种奇怪的东西, 老老实实写可读性好的代码不行吗?
function A() 内部重定义了 function A()第一次,传参 a=1,重定义A(), 然后执行 alert(a++) //alert(1), 然后 a+1 = 2第二次 A() 已经重定义了, 参数b=2, a是第一次的结果2, 执行alert(a+b++) //alert(4), b+1 = 3
ps: F12 自己在控制台 走一遍, 看看 A 执行一次后,已经变化了
浏览器执行Js程序的时候,分两步:
我们来分析题目:
先预解析,预解析仓库里有:
执行代码:
第一次执行A(1),最后alert(1);
第二次执行A(2),最后alert(4);
在第一次执行的时候,先是重定义了A这个方法(并不执行),然后alert(a++),其中先输出a然后自加1,于是结果是1。这个时侯A方法变成alert(a+b++),a=2。
第二次执行的时候,执行alert(a+b++),其中a是2,b也是2,先输出了4然后b自加1成了3。
全局下的a,b没有改变,改变的是闭包的a。所以说,第二次执行取的a也不是全局的,而是A内的a。
为什么总是爱 讨论 这种奇怪的东西, 老老实实写可读性好的代码不行吗?
function A() 内部重定义了 function A()
第一次,传参 a=1,重定义A(), 然后执行 alert(a++) //alert(1), 然后 a+1 = 2
第二次 A() 已经重定义了, 参数b=2, a是第一次的结果2, 执行alert(a+b++) //alert(4), b+1 = 3
ps: F12 自己在控制台 走一遍, 看看 A 执行一次后,已经变化了