函数声明整体提升且必须有名,可提前调用;函数表达式仅变量名提升(var)或不提升(let/const),须赋值后调用,匿名时调试困难。

函数声明和函数表达式都能定义可调用的函数,但提升(hoisting)行为、语法位置、命名调试支持完全不同——选错可能让你在 undefined 或 ReferenceError 里卡住几分钟。
函数声明:能被提前访问,必须有名字
函数声明会整体被提升到当前作用域顶部,所以可以在定义前调用。它必须带标识符名,不能作为表达式的一部分直接使用。
-
function greet(name) { return 'Hello, ' + name; }是合法声明 -
greet('Alice');在声明前写也不会报错(会被提升) - 不能写成
if (true) { function foo() {} }—— 大多数引擎允许但属非标准行为,不同环境表现不一致 - 在调试器中显示为
greet,堆栈跟踪清晰
函数表达式:只提升变量名,不提升函数体
把函数赋给变量时,属于函数表达式。只有 var 声明的变量名会被提升,函数体不会;let/const 则完全不提升,访问会触发暂时性死区(TDZ)。
-
const add = function(a, b) { return a + b; };——add是变量名,函数是匿名表达式 -
add(2, 3);必须在赋值之后执行,否则TypeError: add is not a function(var下是undefined,let/const下是ReferenceError) - 可以写具名函数表达式:
const factorial = function fact(n) { return n —— 名字fact只在内部可用,利于递归和调试 - 在 Chrome DevTools 堆栈中可能显示为
(anonymous),除非用了具名形式
箭头函数不是替代品,而是不同语义
箭头函数没有自己的 this、arguments、super 或 new.target,也不能用作构造函数。它本质是更紧凑的函数表达式语法,不是声明或表达式的“第三种类型”。
立即学习“Java免费学习笔记(深入)”;
-
const multiply = (x, y) => x * y;等价于const multiply = function(x, y) { return x * y; }; -
obj.method = () => { console.log(this); };中的this指向外层作用域,不是obj - 不能用
new multiply(),会抛TypeError: multiply is not a constructor - 没有
prototype属性,multiply.prototype是undefined
真正容易被忽略的是:函数名是否出现在调用栈、是否能被递归引用、是否参与作用域提升——这些不是风格偏好,而是运行时行为差异。调试时看到 at 却找不到源头?先检查你用的是不是无名函数表达式。











