函数与 this
this、bind/call/apply、闭包、IIFE、recursion。
35 分钟
函数与 this
javascript-core 讲过闭包入门;本课系统讲解 this 绑定规则、bind/call/apply、IIFE 与递归。React 类组件与 nodejs-essentials 事件回调里,this 丢失是经典 bug 来源。
学习目标
- 说出
this的四种绑定规则(默认、隐式、显式、new) - 使用 bind/call/apply 固定
this - 理解闭包在模块模式与递归中的应用
this 绑定规则
// 1. 默认绑定(非 strict 下指向 global/window)
function show() {
console.log(this);
}
show();
// 2. 隐式绑定:obj.method() 中 this 指向 obj
const page = {
title: '首页',
getTitle() { return this.title; },
};
page.getTitle(); // '首页'
// 3. 显式绑定
show.call({ id: 1 });
show.apply({ id: 2 });
// 4. new 绑定
function User(name) {
this.name = name;
}
const u = new User('Lee');
丢失 this 的经典场景
const page = {
title: '首页',
getTitle() { return this.title; },
};
const fn = page.getTitle;
fn(); // undefined(独立调用,默认绑定)
// 修复
const bound = page.getTitle.bind(page);
bound(); // '首页'
React 类组件曾需 this.handleClick = this.handleClick.bind(this);函数组件 + 箭头回调已规避多数场景。
bind / call / apply
function greet(greeting, punct) {
return `${greeting}, ${this.name}${punct}`;
}
const person = { name: 'Lee' };
greet.call(person, '你好', '!'); // '你好, Lee!'
greet.apply(person, ['Hi', '.']); // 'Hi, Lee.'
const hi = greet.bind(person, '你好');
hi('~'); // '你好, Lee~'
apply 适合参数已是数组;bind 返回新函数,适合事件监听。
箭头函数与 this
const timer = {
seconds: 0,
start() {
setInterval(() => {
this.seconds++; // 箭头函数不绑定自己的 this,继承 start 的 this
}, 1000);
},
};
箭头函数不能用作构造函数,也没有 arguments 对象。
IIFE 与模块模式
const counter = (function () {
let n = 0;
return {
inc() { return ++n; },
get() { return n; },
};
})();
counter.inc(); // 1
IIFE 创建私有作用域,现代项目多用 ESM 替代。
递归
function flatten(arr) {
return arr.reduce((acc, item) => {
return acc.concat(Array.isArray(item) ? flatten(item) : item);
}, []);
}
flatten([1, [2, [3]]]); // [1, 2, 3]