详解JavaScript的三种this指向方法
作者:凌云木丶丶
讲一下call()方法
在 JavaScript 中,call() 方法用于调用一个函数,可以指定函数体内 this 对象的值。这里的 this 指的是函数执行时所在的上下文对象,也就是函数执行时所处的环境,同时可以传递参数列表来执行函数。
call() 方法接受的第一个参数是要绑定给 this 的值,后面的参数是传递给函数的参数列表。通过 call() 方法,可以改变函数内部 this 的指向,并且立即执行函数。
以下是 call() 方法的语法:
functionName.call(thisArg, arg1, arg2, ...)
functionName:要调用的函数名称。thisArg:函数执行时绑定的this值,即函数内部的上下文对象。arg1, arg2, ...:要传递给函数的参数列表。
当调用 call() 方法时,它会立即执行函数,并将指定的 thisArg 绑定到函数内部的 this 上下文。这意味着函数内部的 this 将引用 thisArg 所指定的对象。
另外,call() 方法还可以接受多个参数作为函数的参数列表,并依次传递给函数。
下面是一个使用 call() 方法的简单例子:
const person = {
fullName: function() {
return this.firstName + " " + this.lastName;
}
}
const person1 = {
firstName: "John",
lastName: "Doe"
}
const person2 = {
firstName: "Mary",
lastName: "Doe"
}
// 使用 call() 方法指定 person1 作为函数内部的 this 对象
const fullName1 = person.fullName.call(person1); // 返回 "John Doe"
// 使用 call() 方法指定 person2 作为函数内部的 this 对象
const fullName2 = person.fullName.call(person2); // 返回 "Mary Doe"
在上面的例子中,call() 方法被用于在不同的上下文中调用 person.fullName() 函数。通过使用 call() 方法,我们可以指定函数内部 this 的值,并且让函数在不同的上下文中执行,从而达到我们的目的。
使用 call() 方法的主要场景包括:
- 显式设置函数内部的
this上下文。 - 在借用其他对象的方法时,将当前对象作为
this上下文。 - 调用函数并传递参数列表。
总结:
call()方法用于调用一个函数并设置函数内部的this值。它接受一个对象作为thisArg,将该对象绑定到函数内部的this上下文,并可以传递参数列表给函数。这个方法常用于显式设置函数的执行上下文和借用其他对象的方法。
讲一下bind()方法
bind() 方法是 JavaScript 中的一个内置函数,用于创建一个新的函数,这个新函数与原函数绑定了指定的 this 对象和部分参数,并且在调用时这些参数会被预先传入。bind() 方法的语法如下:
functionName.bind(thisArg, arg1, arg2, ...)
functionName:要绑定上下文的函数名称。thisArg(必选参数):函数执行时绑定的this值,即函数内部的上下文对象。arg1, arg2, ...(可选参数):要预设的参数列表。
bind() 方法会返回一个新的函数,该新函数的 this 值被永久地绑定到 thisArg 所指定的对象。当调用这个新函数时,它会以指定的上下文执行,并将预设的 arg1、arg2 等参数预先传入新函数。
使用 bind() 方法,可以实现改变函数内部的 this 指向,以及部分参数的预先传入。这个方法在一些特定的场景下非常有用,比如在回调函数中使用,可以解决 this 指向问题。例如:
示例一:
var person = {
name: "John",
greet: function (message) {
console.log(message + ", " + this.name);
},
};
var anotherPerson = {
name: "Ben",
};
var boundGreet = person.greet.bind(person, "Hello");
boundGreet(); // 输出:Hello, John
var boundGreet = person.greet.bind(anotherPerson, "Hello");
boundGreet(); // 输出:Hello, Ben
示例二:
const obj = {
name: 'Tom',
sayHi() {
console.log(`Hi, my name is ${this.name}`);
},
};
// 在回调函数中使用 bind() 方法改变 sayHi() 函数内部的 this 指向
setTimeout(obj.sayHi(), 1000); // 立即执行 输出:Hi, my name is Tom
setTimeout(obj.sayHi.bind(obj), 1000); // 1s后执行 输出:Hi, my name is Tom
上面代码直接用 setTimeout(obj.sayHi(), 1000); 不也可以,为什么还要加上bind()
上面代码直接使用
setTimeout(obj.sayHi(), 1000)会立即调用obj.sayHi()函数,并把它的返回值作为第一个参数传递给setTimeout()函数,相当于setTimeout(undefined, 1000)。所以实际上是没有等待1秒后再执行sayHi()的效果的。而
setTimeout(obj.sayHi.bind(obj), 1000)中,bind()方法会返回一个绑定了obj作为上下文的新函数,并不会立即调用。所以setTimeout()函数会等待1秒后再调用这个新函数,保证了1秒后再执行sayHi()函数。
又例如,预先传入部分参数的情况:
function add(x, y) {
return x + y;
}
// 使用 bind() 方法预先传入参数 1,得到一个新的函数
const addOne = add.bind(null, 1);
console.log(addOne(2)); // 输出:3
在上面的例子中,使用 bind() 方法预先传入了参数 1,得到一个新的函数 addOne,在调用这个新函数时,只需要再传入一个参数 2,即可完成 1 + 2 的操作。
讲一下apply方法
apply() 方法是 JavaScript 中的一个函数方法,用于在特定的作用域中调用函数,并将参数以数组形式传递。
语法:
function.apply(thisArg, [argsArray])
参数说明:
thisArg:可选参数,指定函数执行时的作用域对象。在函数内部使用this关键字时,将引用该参数指定的对象。如果省略或传入null或undefined,则在调用时使用全局对象(通常是window对象)作为作用域。argsArray:可选参数,一个数组或类数组对象,包含传递给函数的参数。如果省略或传入null或undefined,则表示不传递任何参数。
使用 apply() 方法可以实现以下功能:
- 在特定作用域中调用函数:通过指定
thisArg参数,可以在特定对象的作用域中执行函数,修改函数内部的this引用。 - 传递参数数组:将参数以数组形式传递给函数,可以方便地在调用函数时动态传递参数。
示例:
function greet(name, age) {
console.log(`Hello, ${name}! You are ${age} years old.`);
}
const person = {
name: 'Alice',
age: 25
};
greet.apply(person, ['Bob', 30]);
// 输出:Hello, Bob! You are 30 years old.
// 相当于在person对象作用域里面打印了 "Hello, Bob! You are 30 years old." 打招呼的话
在上面的示例中,我们定义了一个 greet 函数用于打招呼,接受一个 name 参数和一个 age 参数。然后,我们创建了一个 person 对象,包含 name 和 age 属性。通过使用 apply() 方法,我们将 person 对象作为函数调用的作用域,并传递一个包含 'Bob' 和 30 的参数数组。最终,函数在 person 对象的作用域中执行,并输出相应的结果。
apply和call的区别
需要注意的是,apply() 方法和 call() 方法的作用类似,唯一的区别是参数的传递方式不同。apply() 方法使用数组形式传递参数,而 call() 方法使用逐个参数传递。
apply()其他应用场景
当使用 apply() 方法时,还可以在某些情况下提供更灵活和动态的函数调用。以下是一些使用 apply() 方法的其他例子:
动态改变函数的上下文:
function greet() {
console.log(`Hello, ${this.name}!`);
}
const person1 = { name: 'Alice' };
const person2 = { name: 'Bob' };
greet.apply(person1); // 输出:Hello, Alice!
greet.apply(person2); // 输出:Hello, Bob!
通过使用 apply() 方法,可以动态地将不同的对象作为函数调用的上下文(this)。
数组操作:
const numbers = [1, 2, 3, 4, 5]; const max = Math.max.apply(null, numbers); const min = Math.min.apply(null, numbers); // const max = Math.max(...numbers); // const min = Math.min(...numbers); console.log(max); // 输出:5 console.log(min); // 输出:1
在这个例子中,通过使用 apply() 方法,将数组作为参数传给 Math.max() 和 Math.min() 函数,从而得到数组中的最大值和最小值。
配合
arguments对象使用:
function sum() {
// 将 arguments 对象转换为真正的数组
const argsArray = Array.prototype.slice.call(arguments);
// 使用 reduce 方法对数组中的元素进行累加求和,初始值为 0
return argsArray.reduce((total, num) => total + num, 0);
// 这里传入的实参0是可选参数initialValue,用于指定累积的初始值
// 如果没有提供初始值,则将使用数组的第一个元素作为初始值,并从第二个元素开始进行迭代。
// 所以不写也是OK的,结果相同
}
const numbers = [1, 2, 3, 4, 5];
// 使用 apply 方法将 numbers 数组作为参数传递给 sum 函数,并执行求和操作
const result = sum.apply(null, numbers);
console.log(result); // 输出:15
在这个例子中,sum() 函数接收任意数量的参数,并使用 apply() 方法将参数数组传递给函数。通过将 arguments 对象转换为真正的数组,我们可以对参数进行操作,例如在此例中计算它们的总和。
总之,apply() 方法提供了一种动态调用函数的方式,并且在某些情况下非常有用,特别是在需要改变函数上下文、操作数组或处理不定数量的参数时。
以上就是详解JavaScript的三种this指向方法的详细内容,更多关于JavaScript this指向的资料请关注脚本之家其它相关文章!
