您现在的位置是:网站首页 > 函数声明与函数表达式文章详情
函数声明与函数表达式
陈川
【
JavaScript
】
16558人已围观
3103字
在JavaScript中,函数可以通过声明或表达式的方式定义,两者在语法、作用域和调用时机上存在差异。理解这些差异对编写高效、可维护的代码至关重要。
函数声明的基本语法
函数声明以function
关键字开头,后跟函数名和一对圆括号。函数体包裹在花括号中。例如:
function greet(name) {
return `Hello, ${name}!`;
}
函数声明会被提升(hoisting),这意味着可以在声明之前调用函数:
console.log(greet('Alice')); // 输出: Hello, Alice!
function greet(name) {
return `Hello, ${name}!`;
}
函数表达式的基本语法
函数表达式将函数赋值给变量或属性。它可以是匿名的,也可以有名称:
const greet = function(name) {
return `Hello, ${name}!`;
};
命名函数表达式:
const greet = function sayHello(name) {
return `Hello, ${name}!`;
};
函数表达式不会被提升,必须在定义后才能调用:
console.log(greet('Alice')); // 报错: greet is not defined
const greet = function(name) {
return `Hello, ${name}!`;
};
作用域差异
函数声明的作用域是它所在的函数或全局作用域。函数表达式的作用域取决于它被赋值的位置:
function outer() {
innerDeclared(); // 正常执行
innerExpressed(); // 报错
function innerDeclared() {
console.log('I am hoisted');
}
const innerExpressed = function() {
console.log('I am not hoisted');
};
}
立即调用函数表达式(IIFE)
函数表达式可以立即调用,形成独立作用域:
(function() {
const secret = 'hidden';
console.log(secret); // 输出: hidden
})();
console.log(secret); // 报错: secret is not defined
带参数的IIFE:
(function(message) {
console.log(message); // 输出: Immediately invoked
})('Immediately invoked');
箭头函数表达式
ES6引入的箭头函数是函数表达式的简写形式:
const greet = (name) => {
return `Hello, ${name}!`;
};
// 单行时可省略return和花括号
const square = x => x * x;
箭头函数没有自己的this
绑定,适合用作回调:
const timer = {
seconds: 0,
start() {
setInterval(() => {
this.seconds++;
console.log(this.seconds);
}, 1000);
}
};
作为参数传递
函数表达式常用于高阶函数参数:
const numbers = [1, 2, 3];
const doubled = numbers.map(function(n) {
return n * 2;
});
// 箭头函数更简洁
const tripled = numbers.map(n => n * 3);
构造函数中的差异
函数声明不能直接用作构造函数,除非通过new
调用:
function Person(name) {
this.name = name;
}
const alice = new Person('Alice');
函数表达式赋值给变量后同样可用作构造函数:
const Animal = function(species) {
this.species = species;
};
const cat = new Animal('Felis catus');
递归调用时的区别
命名函数表达式在递归调用时更可靠:
const factorial = function calc(n) {
return n <= 1 ? 1 : n * calc(n - 1);
};
// 即使变量被重新赋值,函数仍能正常工作
const oldFactorial = factorial;
factorial = null;
console.log(oldFactorial(5)); // 输出120
调试时的可读性
命名函数表达式在调试时显示函数名,提高可读性:
const anonymous = function() { /* 调试显示anonymous */ };
const named = function myFunc() { /* 调试显示myFunc */ };
模块模式中的应用
函数表达式常用于创建私有作用域:
const counter = (function() {
let count = 0;
return {
increment() {
count++;
},
get value() {
return count;
}
};
})();
动态函数生成
函数表达式允许运行时动态创建函数:
function createMultiplier(factor) {
return function(x) {
return x * factor;
};
}
const double = createMultiplier(2);
console.log(double(5)); // 输出10
性能考量
现代JavaScript引擎对两种形式的优化差异不大,但函数声明由于提升特性可能略微影响脚本解析速度。实践中应优先考虑代码可读性和维护性。
上一篇: 块级元素与行内元素的区别
下一篇: 函数参数与arguments对象