- 函数借用
- 事件处理
- 函数柯里化
- 实现继承和构造函数的调用
- 数组中的最大值和最小值
1.函数借用
用另外一个对象的方法来操作当前对象的数据,可以使用 call 、apply 来实现这一点
const arrayLikeObject = {
0: 'a',
1: 'b',
2: 'c',
length: 3
};
const result = Array.prototype.slice.call(arrayLikeObject);
console.log(result); // 输出: ['a', 'b', 'c']
不使用call
const arrayLikeObject = {
0: 'a',
1: 'b',
2: 'c',
length: 3
};
const result = [];
for (let i = 0; i < arrayLikeObject.length; i++) {
result.push(arrayLikeObject[i]);
}
console.log(result); // 输出: ['a', 'b', 'c']
借用了数组的 slice 方法将一个类数组对象转换为数组
2.事件处理
通过使用 bind 方法,我们可以预置 this 值和部分参数,以简化事件处理。
function handleClick(event) {
console.log('Button clicked:', this.textContent);
}
const button = document.querySelector('button');
button.addEventListener('click', handleClick.bind(button));
不使用bind
const button = document.querySelector('button');
button.addEventListener('click', (event) => {
console.log('Button clicked:', button.textContent);
});
3.函数柯里化
使用bind
function multiply(a, b) {
return a * b;
}
const double = multiply.bind(null, 2);
console.log(double(5)); // 输出: 10
const triple = multiply.bind(null, 3);
console.log(triple(5)); // 输出: 15
不使用bind
function multiply(a) {
return function(b) {
return a * b;
};
}
const double = multiply(2);
console.log(double(5)); // 输出: 10
const triple = multiply(3);
console.log(triple(5)); // 输出: 15
4.实现继承和构造函数的调用
使用call
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function () {
console.log(this.name + ' makes a noise.');
};
function Dog(name, breed) {
Animal.call(this, name); // 调用父构造函数
this.breed = breed;
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function () {
console.log(this.name + ' barks.');
};
const dog = new Dog('Rex', 'German Shepherd');
dog.speak(); // 输出: Rex makes a noise.
dog.bark(); // 输出: Rex barks.
不使用 call
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log(this.name + ' makes a noise.');
};
function Dog(name, breed) {
this.name = name; // 直接设置 name 属性
this.breed = breed;
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function() {
console.log(this.name + ' barks.');
};
const dog = new Dog('Rex', 'German Shepherd');
dog.speak(); // 输出: Rex makes a noise.
dog.bark(); // 输出: Rex barks.
5.数组中的最大值和最小值
使用apply
const numbers = [5, 6, 2, 3, 7];
const max = Math.max.apply(null, numbers);
const min = Math.min.apply(null, numbers);
console.log(max); // 输出: 7
console.log(min); // 输出: 2
不使用apply
const numbers = [5, 6, 2, 3, 7];
const max = Math.max(...numbers);
const min = Math.min(...numbers);
console.log(max); // 输出: 7
console.log(min); // 输出: 2
call的实现
Function.prototype.myCall = function (context, ...args) {
// 如果 context 为 null 或 undefined,默认设置为全局对象(在严格模式下为 undefined)
context = context || globalThis;
// 创建一个唯一的属性名,防止与 context 上的其他属性冲突
const fnSymbol = Symbol('fn');
// 将当前函数(即被调用的函数)作为 context 的一个方法
// 这里的 this 指向调用 myCall 的函数
context[fnSymbol] = this;
// 使用指定的 context 和参数调用函数,并获取结果
const result = context[fnSymbol](...args);
// 删除临时绑定的函数
delete context[fnSymbol];
// 返回结果
return result;
}
function greet(greeting, punctuation) {
return `${greeting}, ${this.name}${punctuation}`;
}
const person = {
name: 'Alice'
};
console.log(greet.myCall(person, 'Hello', '!')); // 'Hello, Alice!'
将 greet 函数临时添加为 person 对象的一个方法,使用唯一的 Symbol 值 fnSymbol 作为属性名。这就意味着 person 对象现在有一个临时的方法 fnSymbol,这个方法指向 greet 函数。
apply的实现
Function.prototype.myApply = function(context, args) {
// 如果 context 为 null 或 undefined,默认设置为全局对象(在严格模式下为 undefined)
context = context || globalThis;
// 创建一个唯一的属性名,防止与 context 上的其他属性冲突
const fnSymbol = Symbol('fn');
// 将当前函数(即被调用的函数)作为 context 的一个方法
context[fnSymbol] = this;
// 使用指定的 context 和参数数组调用函数,并获取结果
const result = context[fnSymbol](...(args || []));
// 删除临时绑定的函数
delete context[fnSymbol];
// 返回结果
return result;
};
// 示例
function greet(greeting, punctuation) {
return `${greeting}, ${this.name}${punctuation}`;
}
const person = {
name: 'Alice'
};
console.log(greet.myApply(person, ['Hello', '!'])); // 输出:'Hello, Alice!'
和call的实现没有什么区别
bind的实现
Function.prototype.myBind = function(context, ...args) {
const fn = this; // 保存原函数引用
// 返回一个新的函数
return function(...newArgs) {
// 合并原始绑定时传入的参数和调用新函数时传入的参数
const combinedArgs = [...args, ...newArgs];
// 使用指定的 context 调用原函数,并传入合并后的参数
return fn.apply(context, combinedArgs);
};
};
// 示例
function greet(greeting, punctuation) {
return `${greeting}, ${this.name}${punctuation}`;
}
const person = {
name: 'Alice'
};
const greetPerson = greet.myBind(person, 'Hello');
console.log(greetPerson('!')); // 输出:'Hello, Alice!'