函数.prototype.call()
使用 call() 方法,您可以编写可用于不同对象的方法。换句话说,通过 call(),一个对象可以使用属于另一个对象的方法。更多信息
const person = {
fullName: function() {
return this.firstName + " " + this.lastName;
}
}
const person1 = {
firstName:"John",
lastName: "Doe"
}
const person2 = {
firstName:"Mary",
lastName: "Doe"
}
// This will return "John Doe":
console.log(person.fullName.call(person1));
call() 允许为一个不同的对象分配和调用属于一个对象的函数/方法。
call() 为函数/方法提供了一个新的 this 值。使用 call(),您可以编写一次方法,然后在另一个对象中继承它,而不必为新对象重写该方法。
> 使用链式构造函数调用对象
您可以使用调用来链接对象的构造函数(类似于 Java)。
在以下示例中,Product 对象的构造函数使用两个参数定义:名称和价格。
另外两个函数 Food 和 Toy 调用 Product,传递 this、name 和 price。Product 初始化属性 name 和 price,这两个专门的函数定义了类别。
function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {
Product.call(this, name, price);
this.category = 'food';
}
function Toy(name, price) {
Product.call(this, name, price);
this.category = 'toy';
}
const cheese = new Food('feta', 5);
const fun = new Toy('robot', 40);
console.log(cheese);
console.log(fun);
> 使用 call 调用匿名函数
在这个例子中,我们创建了一个匿名函数,并使用 call 在数组中的每个对象上调用它。
这里匿名函数的主要目的是为每个对象添加一个打印函数,能够打印出该对象在数组中的正确索引。
const animals = [
{ species: 'Lion', name: 'King' },
{ species: 'Whale', name: 'Fail' }
];
for (let i = 0; i < animals.length; i++) {
(function(i) {
this.print = function() {
console.log('#' + i + ' ' + this.species
+ ': ' + this.name);
}
this.print();
}).call(animals[i], i);
}
> 使用 call 调用函数并指定“this”的上下文
在下面的例子中,当我们调用 greet 时,this 的值将绑定到对象 obj。
function greet() {
const reply = [this.animal, 'typically sleep between', this.sleepDuration].join(' ');
console.log(reply);
}
const obj = {
animal: 'cats', sleepDuration: '12 and 16 hours'
};
greet.call(obj); // cats typically sleep between 12 and 16 hours
> 使用 call 来调用函数而不指定第一个参数
在下面的示例中,我们调用 display 函数而不传递第一个参数。如果没有传递第一个参数,则 this 的值绑定到全局对象。
var sData = 'Wisen';
function display() {
console.log('sData value is %s ', this.sData);
}
display.call(); // sData value is Wisen
注意:在严格模式下, this 的值将是未定义的。见下文。
'use strict';
var sData = 'Wisen';
function display() {
console.log('sData value is %s ', this.sData);
}
display.call(); // Cannot read the property of 'sData' of undefined
如需更多阅读,您可以访问参考
函数.prototype.bind()
bind() 方法创建一个新函数,当调用该函数时,将其 this 关键字设置为提供的值,并在调用新函数时在任何提供的参数之前提供给定的参数序列。
const module = {
x: 42,
getX: function() {
return this.x;
}
};
const unboundGetX = module.getX;
console.log(unboundGetX()); // The function gets invoked at the global scope
// expected output: undefined
const boundGetX = unboundGetX.bind(module);
console.log(boundGetX());
// expected output: 42
> 创建绑定函数
bind() 的最简单用途是创建一个函数,无论它如何调用,都会使用特定的 this 值调用。
JavaScript 新手的一个常见错误是从对象中提取一个方法,然后稍后调用该函数并期望它使用原始对象作为它的 this(例如,通过在基于回调的代码中使用该方法)。
然而,如果没有特别注意,原始对象通常会丢失。从函数创建绑定函数,使用原始对象,巧妙地解决了这个问题:
this.x = 9; // 'this' refers to global 'window' object here in a browser
const module = {
x: 81,
getX: function() { return this.x; }
};
module.getX();
// returns 81
const retrieveX = module.getX;
retrieveX();
// returns 9; the function gets invoked at the global scope
// Create a new function with 'this' bound to module
// New programmers might confuse the
// global variable 'x' with module's property 'x'
const boundGetX = retrieveX.bind(module);
console.log(boundGetX());
// returns 81
> 部分应用功能
bind() 的下一个最简单的用法是使用预先指定的初始参数创建一个函数。
这些参数(如果有)跟在提供的 this 值之后,然后插入到传递给目标函数的参数的开头,然后是在调用时传递给绑定函数的任何参数。
function list() {
return Array.prototype.slice.call(arguments);
}
function addArguments(arg1, arg2) {
return arg1 + arg2;
}
const list1 = list(1, 2, 3);
// [1, 2, 3]
const result1 = addArguments(1, 2);
// 3
// Create a function with a preset leading argument
const leadingThirtysevenList = list.bind(null, 37);
// Create a function with a preset first argument.
const addThirtySeven = addArguments.bind(null, 37);
const list2 = leadingThirtysevenList();
// [37]
const list3 = leadingThirtysevenList(1, 2, 3);
// [37, 1, 2, 3]
const result2 = addThirtySeven(5);
// 37 + 5 = 42
const result3 = addThirtySeven(5, 10);
// 37 + 5 = 42
// (the second argument is ignored)
> 使用 setTimeout()
默认情况下,在 setTimeout() 中,this 关键字将设置为窗口(或全局)对象。当使用需要 this 来引用类实例的类方法时,您可以将 this 显式绑定到回调函数,以维护实例。
function LateBloomer() {
this.petalCount = Math.floor(Math.random() * 12) + 1;
}
// Declare bloom after a delay of 1 second
LateBloomer.prototype.bloom = function() {
window.setTimeout(this.declare.bind(this), 1000);
};
LateBloomer.prototype.declare = function() {
console.log(`I am a beautiful flower with ${this.petalCount} petals!`);
};
const flower = new LateBloomer();
flower.bloom();
// after 1 second, calls 'flower.declare()'
如果您想了解有关绑定方法的更多信息,请阅读此资源