You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 15:38:17