JavaScript 基础
Document
运算符
深入数据和类型
函数进阶
原型、继承
类
浏览器存储
Web API
事件
错误处理
异步编程
网络请求
模块
练习
实例
工具与规范
软件架构模式
设计模式
call、apply、bind
call
、 apply
、 bind
的作用都是修改函数的 this
指向,只是使用的方式略有不同。
$$jsdemo$$
$$edit$$
function sayHello() {
alert(this.word)
}
const mingren = {
word: "你好,我是鸣人。",
}
const kenan = {
word: "你好,我是柯南。",
}
sayHello.call(mingren) // 你好,我是鸣人。
sayHello.call(kenan) // 你好,我是柯南。
sayHello.apply(mingren) // 你好,我是鸣人。
sayHello.apply(kenan) // 你好,我是柯南。
const hiMr = sayHello.bind(mingren)
const hiKn = sayHello.bind(kenan)
hiMr() // 你好,我是鸣人。
hiKn() // 你好,我是柯南。
call
、 apply
是在修改 this
指向的同时直接调用函数,而 bind
是返回了一个修改 this
指向后的函数。
传递参数
当函数有参数时,这三者的传递方法也略有不同。
$$jsdemo$$
$$edit$$
function sayHello(name1, name2) {
alert(`${name1}、${name2}。${this.word}`)
}
const mingren = {
word: "你好,我是鸣人。",
}
sayHello.call(mingren, "小明", "小红") // 小明、小红。你好,我是鸣人。
sayHello.apply(mingren, ["小明", "小红"]) // 小明、小红。你好,我是鸣人。
const hiMr = sayHello.bind(mingren)
hiMr("小明", "小红") // 小明、小红。你好,我是鸣人。
实例
装饰器的 this
装饰器是我们常用的设计模式之一,但一不小心容易“丢失” this
。
$$jsdemo$$
$$edit$$
function decorator(func) {
return function (...args) {
alert("开始运行")
return func(...args)
}
}
const work = {
base: 10,
sum(x, y) {
alert(this.base + x + y)
},
}
// 13
work.sum(1, 2)
work.sum = decorator(work.sum)
// 你好
// NaN,因为此时 sum 函数中的 this “丢失”
work.sum(1, 2)
此时,我们就可以用 call、apply、bind
绑定 this
。
function decorator(func) {
return function (...args) {
alert("开始运行")
// return func.call(this, ...args)
// return func.apply(this, args)
return func.bind(this)(...args)
}
}
const work = {
base: 10,
sum(x, y) {
alert(this.base + x + y)
},
}
// 13
work.sum(1, 2)
work.sum = decorator(work.sum)
// 你好
// 13
work.sum(1, 2)
练习
- 补全以下代码。
const obj = {
x: 100,
}
function sum(n) {
return this.x + n
}
// 分别使用 call、apply、bind
// 三种方法绑定 obj 并执行 sum
$$answer
$$jsdemo$$
$$edit$$
const obj = {
x: 100,
}
function sum(n) {
return this.x + n
}
alert(sum.call(obj, 50)) // 150
alert(sum.apply(obj, [50])) // 150
alert(sum.bind(obj)(50)) // 150
$$
- 以下代码的执行结果偏离了预期,尝试修改一下,看看你能想到几种方法?
$$jsdemo$$
$$edit$$
const mingren = {
name: "鸣人",
sayHello() {
console.log(`你好,我叫${this.name}`)
},
}
// 修改以下代码
// 使其执行结果为:你好,我叫鸣人
setTimeout(mingren.sayHello, 3000)
$$answer
方法 1:放到函数中
$$jsdemo$$
$$edit$$
const mingren = {
name: "鸣人",
sayHello() {
console.log(`你好,我叫${this.name}`)
},
}
// 修改以下代码
// 使其执行结果为:你好,我叫鸣人
// 方法 1:放到函数中
setTimeout(() => mingren.sayHello(), 3000)
方法 2:使用 bind
$$jsdemo$$
$$edit$$
const mingren = {
name: "鸣人",
sayHello() {
console.log(`你好,我叫${this.name}`)
},
}
// 修改以下代码
// 使其执行结果为:你好,我叫鸣人
// 方法 2:使用 bind
setTimeout(mingren.sayHello.bind(mingren), 3000)
$$