JavaScript函数引用赋值逻辑困惑:Shell游戏代码结果解析
《Head First JavaScript》Shell游戏代码执行逻辑解析
我在通过《Head First JavaScript》学习时,遇到书中440页的Shell游戏代码,热身部分执行符合预期,但从步骤[3]开始,变量赋值的实际控制台输出和我对=赋值运算符的预期不符,比如[3]中b = c我预期结果是'LOSER',实际却是'WINNER';[4]中c = a我预期为'WINNER',实际为'LOSER'。下面是相关代码和控制台输出,以及详细的执行逻辑解析。
原代码
var winner = function() { console.log("WINNER!") }; var loser = function() { console.log("LOSER!") }; // let's test as a warm up winner(); // let's assign to other variables for practice var a = winner; var b = loser; var c = loser; a(); b(); // now let's try your luck with a shell game c = a; //[1] console.log("c is: " + c);// winner a = b; //[2] console.log("a is: " + a);// loser b = c; //[3] console.log("b is: " + b);// loser c = a; //[4] console.log("c is: " + c);// winner a = c; //[5] console.log("a is: " + a);// loser a = b; //[6] console.log("a is: " + a);// loser b = c; //[7] console.log("b is: " + b);// loser a();
控制台实际输出
WINNER! WINNER! LOSER! --------from here ---------------- c is: function() { console.log("WINNER!") } a is: function() { console.log("LOSER!") } b is: function() { console.log("WINNER!") } c is: function() { console.log("LOSER!") } a is: function() { console.log("LOSER!") } a is: function() { console.log("WINNER!") } b is: function() { console.log("LOSER!") } WINNER!
执行逻辑解析
首先要明确:这里的变量a、b、c存储的是函数的引用,不是函数执行的结果。每次赋值x = y,都是让x指向y当前引用的那个函数,而非固定初始值。
先确认热身结束后的初始状态(Shell游戏开始前):
a→ 引用winner函数(输出"WINNER!")b→ 引用loser函数(输出"LOSER!")c→ 引用loser函数(输出"LOSER!")
步骤[1]:c = a
此时a引用的是winner函数,赋值后:
c→ 引用winner函数
控制台输出c is: function() { console.log("WINNER!") },符合实际结果。
步骤[2]:a = b
此时b引用的是loser函数,赋值后:
a→ 引用loser函数
控制台输出a is: function() { console.log("LOSER!") },符合实际结果。
步骤[3]:b = c
注意此时c已经在步骤[1]中被改成引用winner函数(不再是初始的loser),赋值后:
b→ 引用winner函数
所以控制台输出b is: function() { console.log("WINNER!") },你预期错误是因为误以为c还是初始的loser。
步骤[4]:c = a
此时a在步骤[2]中被改成引用loser函数,赋值后:
c→ 引用loser函数
控制台输出c is: function() { console.log("LOSER!") },你预期错误是没注意a已经变成loser。
步骤[5]:a = c
此时c在步骤[4]中引用loser函数,赋值后:
a→ 引用loser函数(和之前状态一致)
控制台输出a is: function() { console.log("LOSER!") },符合实际结果。
步骤[6]:a = b
此时b在步骤[3]中引用winner函数,赋值后:
a→ 引用winner函数
控制台输出a is: function() { console.log("WINNER!") },符合实际结果。
步骤[7]:b = c
此时c在步骤[4]中引用loser函数,赋值后:
b→ 引用loser函数
控制台输出b is: function() { console.log("LOSER!") },符合实际结果。
最后执行a()
此时a在步骤[6]中引用winner函数,所以执行后控制台输出WINNER!。
内容的提问来源于stack exchange,提问作者Samuel Gachuhi
相关产品推荐
相关产品推荐

