Node.js 函数
函数是一等公民:参数默认值、箭头函数的 this、闭包、高阶用法。
Key Points箭头函数没有自己的 `this`,在对象方法和回调里混用是 Node 最常见的坑。
三种定义
JavaScript
// 函数声明(会提升)
function add(a, b) { return a + b; }
// 函数表达式(不提升)
const sub = function (a, b) { return a - b; };
// 箭头函数
const mul = (a, b) => a * b;
console.log(add(1, 2), sub(5, 3), mul(4, 5));Output
3 2 20参数
JavaScript
function greet(name, greeting = '你好', ...rest) {
console.log(`${greeting}, ${name}`);
console.log('额外参数', rest);
}
greet('小明');
greet('小明', 'Hello', 1, 2, 3);
// arguments 在箭头函数里不存在,用 rest
const sum = (...nums) => nums.reduce((a, b) => a + b, 0);
console.log(sum(1, 2, 3, 4));Output
你好, 小明
额外参数 []
Hello, 小明
额外参数 [ 1, 2, 3 ]
10this 的差别
JavaScript
const timer = {
seconds: 0,
startBroken() {
setInterval(function () {
this.seconds++; // this 是 Timeout 对象,不是 timer
}, 1000);
},
startOk() {
setInterval(() => {
this.seconds++; // 箭头函数沿用外层 this
}, 1000);
},
};Arrow functions have no
arguments, this, super or new.target, and cannot be called with new. Use them as callbacks to setTimeout or .map(); avoid them as object methods.闭包
JavaScript
function createCounter() {
let n = 0;
return {
inc: () => ++n,
get: () => n,
};
}
const c = createCounter();
c.inc();
c.inc();
console.log(c.get());
// 经典坑:var 循环
for (var i = 0; i < 3; i++) setTimeout(() => console.log('var', i)); // 3 3 3
for (let j = 0; j < 3; j++) setTimeout(() => console.log('let', j)); // 0 1 2Output
2
var 3
var 3
var 3
let 0
let 1
let 2高阶函数
JavaScript
// 柯里化
const add = (a) => (b) => a + b;
console.log(add(1)(2));
// 防抖
function debounce(fn, ms) {
let t;
return (...args) => {
clearTimeout(t);
t = setTimeout(() => fn(...args), ms);
};
}
// 只执行一次
function once(fn) {
let done = false, result;
return (...args) => {
if (!done) { done = true; result = fn(...args); }
return result;
};
}debounce suits search inputs and window resize; once suits initialization. Both hide state in a closure instead of polluting the outer scope.
三种定义
JavaScript
// 函数声明(会提升)
function add(a, b) { return a + b; }
// 函数表达式(不提升)
const sub = function (a, b) { return a - b; };
// 箭头函数
const mul = (a, b) => a * b;
console.log(add(1, 2), sub(5, 3), mul(4, 5));Output
3 2 20参数
JavaScript
function greet(name, greeting = '你好', ...rest) {
console.log(`${greeting}, ${name}`);
console.log('额外参数', rest);
}
greet('小明');
greet('小明', 'Hello', 1, 2, 3);
// arguments 在箭头函数里不存在,用 rest
const sum = (...nums) => nums.reduce((a, b) => a + b, 0);
console.log(sum(1, 2, 3, 4));Output
你好, 小明
额外参数 []
Hello, 小明
额外参数 [ 1, 2, 3 ]
10this 的差别
JavaScript
const timer = {
seconds: 0,
startBroken() {
setInterval(function () {
this.seconds++; // this 是 Timeout 对象,不是 timer
}, 1000);
},
startOk() {
setInterval(() => {
this.seconds++; // 箭头函数沿用外层 this
}, 1000);
},
};箭头函数没有
arguments、this、super、new.target,也不能用 new 调用。作为回调传进 setTimeout、Array.prototype.map 时用它,作为对象方法时不要用。闭包
JavaScript
function createCounter() {
let n = 0;
return {
inc: () => ++n,
get: () => n,
};
}
const c = createCounter();
c.inc();
c.inc();
console.log(c.get());
// 经典坑:var 循环
for (var i = 0; i < 3; i++) setTimeout(() => console.log('var', i)); // 3 3 3
for (let j = 0; j < 3; j++) setTimeout(() => console.log('let', j)); // 0 1 2Output
2
var 3
var 3
var 3
let 0
let 1
let 2高阶函数
JavaScript
// 柯里化
const add = (a) => (b) => a + b;
console.log(add(1)(2));
// 防抖
function debounce(fn, ms) {
let t;
return (...args) => {
clearTimeout(t);
t = setTimeout(() => fn(...args), ms);
};
}
// 只执行一次
function once(fn) {
let done = false, result;
return (...args) => {
if (!done) { done = true; result = fn(...args); }
return result;
};
}debounce 用于搜索框输入、窗口 resize;once 用于初始化逻辑。两者都是把「状态」藏在闭包里,不污染外部。