刚学 JavaScript 的时候,我曾被一个看似简单的问题卡住过:

const counter = createCounter(); 
console.log(counter);    // 输出 [Function (anonymous)]  
console.log(counter());  // 输出 1  

明明 counter 是个变量,为啥有时候要加括号 (),有时候不用?这俩到底有什么区别?

今天咱们就用最生活化的例子,把这个事儿掰扯清楚。

一、先搞清楚:变量里存的是“啥”?

想象你有一个抽屉,里面可以放各种东西:一本书、一把钥匙、甚至一张“使用说明书”。

在 JavaScript 里,变量就像这个抽屉——它可以存任何东西:数字、字符串、对象,甚至是“函数”。

比如,你可以这样存一个数字:

const age = 20; // 抽屉里存的是数字 20  

也可以存一个函数(后面会重点说):

const greet = function() { 
  console.log("你好呀~"); 
}; // 抽屉里存的是一个“函数说明书”  

二、counter 是啥?它存的是“函数说明书”

回到之前的例子:

function createCounter() { 
  let count = 0; 
  return function() {  // 这里返回了一个“匿名函数”  
    count++; 
    return count; 
  }; 
} 

const counter = createCounter(); // 执行 createCounter,得到返回的函数  

这里的 counter 变量,存的其实是 createCounter 函数返回的那个匿名函数

打个比方:

  • createCounter 就像一个“函数工厂”,输入“生产指令”(调用它),它会给你吐出一个“小工具”(匿名函数)。
  • counter 就是你把这“小工具”从工厂里拿回来,放进自己的抽屉里——抽屉里存的是“小工具的使用说明书”(函数本身),而不是小工具做出来的东西(函数的返回值)。

三、counter() 是啥?它是“使用这个小工具”

现在问题来了:抽屉里存着“小工具的使用说明书”(counter 变量),那怎么用这个小工具?

答案很简单:按照说明书上的步骤操作——也就是用 () 调用它。

比如:

counter(); // 相当于说:“喂,小工具,按你的说明书干活!”  

这时候,JavaScript 引擎会打开抽屉(找到 counter 变量),取出里面的“小工具”(匿名函数),然后执行它的代码:

// 匿名函数的代码开始执行  
let count = 0; // 注意:这里的 count 是函数内部的“私有变量”,外面看不到  
count++; // 第一次执行时,count 从 0 变成 1  
return count; // 把 1 返还给调用者  

所以 counter() 的结果就是 1,而 counter 本身只是“小工具的说明书”,不是小工具做出来的结果。

四、不加括号的 counter,到底在干啥?

如果你直接打印 counter

console.log(counter); 

控制台会输出类似 [Function (anonymous)] 的信息——这其实是在告诉你:“counter 变量里存的是一个函数对象,它的代码大概是这样的……”

这就像你打开抽屉,直接展示里面的“小工具说明书”,而不是用它干活——你只是在“描述”这个小工具,而不是“使用”它。

五、总结:一句话搞懂区别

  • counter:变量里存的是“函数对象”(类似“小工具的说明书”),不执行任何操作。
  • counter():通过 () 调用函数,触发函数内部的代码执行(类似“按说明书用小工具干活”),最终返回函数执行的结果。

小提醒:新手常踩的坑

刚开始学的时候,很容易犯一个错误:明明想调用函数,却忘了加括号。比如:

// 错误示例:想获取计数器的值,却打印了函数本身  
console.log("当前计数:" + counter); // 输出“当前计数:[Function (anonymous)]”  

正确的做法是加括号调用:

console.log("当前计数:" + counter()); // 输出“当前计数:1”(第一次调用后)  

下次再遇到 counter()counter 的困惑,不妨想想“抽屉里的说明书”和“用说明书干活”的关系——搞懂了这个,函数调用的小秘密就再也不会难倒你啦! 😊