介绍
Function
实例的 bind()
方法创建一个新函数,当调用该新函数时:
- 它会调用原始函数并将其
this
关键字设置为给定的值(示例①) - 同时,还可以传入其他参数,这些参数会插入到调用新函数时传入的参数的前面(示例②)。
- 连续使用bind,如果已经绑定过一次
this
(传null也算), 后面调用的时候不会修改this绑定(示例③)。 - 如果使用
new
运算符构造绑定函数,则忽略该值。
js
bind(thisArg)
bind(thisArg, arg1)
bind(thisArg, arg1, arg2)
bind(thisArg, arg1, arg2, /* …, */ argN)
bind(thisArg)
bind(thisArg, arg1)
bind(thisArg, arg1, arg2)
bind(thisArg, arg1, arg2, /* …, */ argN)
示例①:
js
const md = {
value: 42, getValue: function () {
return this.value;
},
};
const x1 = md.getValue;
console.log(x1()) // undefined
const x = md.getValue.bind(md)
console.log(x()) // 42
const md = {
value: 42, getValue: function () {
return this.value;
},
};
const x1 = md.getValue;
console.log(x1()) // undefined
const x = md.getValue.bind(md)
console.log(x()) // 42
示例②:
js
const originFunc = function (...restParams) {
console.log(...restParams) // 1, 2, 3, 4, 5, 6
}
const x = originFunc.bind(null, 1, 2, 3)
x(4, 5, 6)
const originFunc = function (...restParams) {
console.log(...restParams) // 1, 2, 3, 4, 5, 6
}
const x = originFunc.bind(null, 1, 2, 3)
x(4, 5, 6)
示例③:
js
"use strict"; // 防止 `this` 被封装到到包装对象中
function log(...args) {
console.log(this, ...args);
}
let boundLog = log.bind("this value a", 1, 2);
boundLog() // this value a 1 2
boundLog = boundLog.bind("this value b", 3, 4);
boundLog() // this value a 1 2 3 4
boundLog = boundLog.bind("this value c", 5, 6);
boundLog() // this value a 1 2 3 4 5 6
"use strict"; // 防止 `this` 被封装到到包装对象中
function log(...args) {
console.log(this, ...args);
}
let boundLog = log.bind("this value a", 1, 2);
boundLog() // this value a 1 2
boundLog = boundLog.bind("this value b", 3, 4);
boundLog() // this value a 1 2 3 4
boundLog = boundLog.bind("this value c", 5, 6);
boundLog() // this value a 1 2 3 4 5 6
示例④:
js
class Base {
constructor(...args) {
console.log(new.target === Base);
console.log(...args);
}
}
// 如果目标函数是可构造的,绑定函数也可以使用 new 运算符进行构造
const BoundBase = Base.bind("aa", 1, 2);
// 这样做的效果就好像目标函数本身被构造一样。前置的参数会像通常一样传递给目标函数,而提供的 this 值会被忽略(因为构造函数会准备自己的 this)
new BoundBase(3, 4);
// true
// 1, 2, 3, 4
class Base {
constructor(...args) {
console.log(new.target === Base);
console.log(...args);
}
}
// 如果目标函数是可构造的,绑定函数也可以使用 new 运算符进行构造
const BoundBase = Base.bind("aa", 1, 2);
// 这样做的效果就好像目标函数本身被构造一样。前置的参数会像通常一样传递给目标函数,而提供的 this 值会被忽略(因为构造函数会准备自己的 this)
new BoundBase(3, 4);
// true
// 1, 2, 3, 4
应用举例
设置函数的缺省参数
js
const print = console.log.bind(console, `【login】:`)
print('hello')
// 【login】: hello
const print = console.log.bind(console, `【login】:`)
print('hello')
// 【login】: hello
处理setTimeout中的this指向
Note
在默认情况下,在 setTimeout()
内部,this
关键字将被设置为 globalThis
js
class LateBloomer {
constructor() {
this.petalCount = Math.floor(Math.random() * 12) + 1;
}
bloom() {
// 延迟 1 秒后宣布开花
setTimeout(this.declare.bind(this), 1000);
setTimeout(this.declare, 500)
}
declare() {
console.log(`I am a beautiful flower with ${this.petalCount} petals!`);
}
}
const flower = new LateBloomer();
flower.bloom();
// I am a beautiful flower with undefined petals!
// 22.js:13I am a beautiful flower with 9 petals!
class LateBloomer {
constructor() {
this.petalCount = Math.floor(Math.random() * 12) + 1;
}
bloom() {
// 延迟 1 秒后宣布开花
setTimeout(this.declare.bind(this), 1000);
setTimeout(this.declare, 500)
}
declare() {
console.log(`I am a beautiful flower with ${this.petalCount} petals!`);
}
}
const flower = new LateBloomer();
flower.bloom();
// I am a beautiful flower with undefined petals!
// 22.js:13I am a beautiful flower with 9 petals!
绑定类
在类上使用 bind()
会保留大部分类的语义,只是当前类的所有静态自有属性会丢失。然而,由于原型链被保留,你仍然可以访问从父类继承的静态属性。
js
class Base {
static baseProp = "基类属性";
}
class Derived extends Base {
static derivedProp = "派生类属性";
}
const BoundDerived = Derived.bind(null);
console.log(BoundDerived.baseProp); // "基类属性"
console.log(BoundDerived.derivedProp); // undefined
console.log(new BoundDerived() instanceof Derived); // true
class Base {
static baseProp = "基类属性";
}
class Derived extends Base {
static derivedProp = "派生类属性";
}
const BoundDerived = Derived.bind(null);
console.log(BoundDerived.baseProp); // "基类属性"
console.log(BoundDerived.derivedProp); // undefined
console.log(new BoundDerived() instanceof Derived); // true