目录
this指向问题
全局函数调用:
对象方法调用:
构造函数调用:
事件处理:
箭头函数:
setTimeout和setInterval
7.使用call、apply或bind
call 方法
apply 方法
bind 方法
总结
this指向问题
-
全局函数调用:在全局作用域中调用函数时,this指向全局对象(浏览器中是window对象)。
function sayHello() {
console.log(this);
}
sayHello(); // 输出:Window {...}
-
对象方法调用:当函数作为对象的方法被调用时,this指向调用该方法的对象。
const person = {
name: 'Alice',
greet: function() {
console.log('Hello, ' + this.name);
}
};
person.greet(); // 输出:Hello, Alice
-
构造函数调用:使用new关键字创建对象时,this指向新创建的对象。
function Person(name) {
this.name = name;
}
const bob = new Person('Bob');
console.log(bob.name); // 输出:Bob
-
事件处理:在事件处理函数中,this指向触发事件的元素。
<button id="myButton">Click me!</button>
<script>
document.getElementById('myButton').addEventListener('click', function() {
console.log(this); // 输出:button#myButton
});
</script>
-
箭头函数:箭头函数没有自己的this上下文,它会捕获其所在上下文的this值,作为自己的this值,除非它是在全局作用域中定义的。
const obj = {
arr: [1, 2, 3],
sum: () => {
return this.arr.reduce((a, b) => a + b, 0);
}
};
console.log(obj.sum()); // 输出:6
-
setTimeout和setInterval
在JavaScript中,setTimeout和setInterval函数用于设置定时器,分别用于延迟执行和重复执行指定的函数。与普通函数调用不 同,setTimeout和setInterval中的回调函数不会自动绑定到任何特定的对象上,它们的this值通常指向全局对象(在浏览器中是window对象),除非显式地使用call、apply或bind方法来改变this的值。
function delayedGreeting() {
console.log('Hello, ' + this.name);
}
const person = { name: 'Dave' };
// 直接使用setTimeout,this将指向全局对象
setTimeout(delayedGreeting, 1000); // 输出:Hello, undefined(因为this.name是undefined)
// 使用bind来绑定this
setTimeout(delayedGreeting.bind(person), 1000); // 输出:Hello, Dave
-
7.使用call、apply或bind:这些方法允许你显式地设置this的值。
function sayName(name) {
console.log('My name is ' + this.name + ' and you are ' + name);
}
const person = { name: 'Alice' };
sayName.call(person, 'Bob'); // 输出:My name is Alice and you are Bob
在JavaScript中,call、apply和bind这三个方法都可以用来显式地设置this的值,它们主要区别在于参数传递的方式不同。
call 方法
call方法调用一个函数,将this关键字设置为指定的对象,并在调用时将其余参数逐个传递给该函数。
语法:
functionName.call(thisArg, arg1, arg2, ...);
示例:
function greet(greeting, punctuation) {
console.log(greeting + ' ' + this.name + punctuation);
}
const person = { name: 'Alice' };
// 使用call方法调用greet函数,将this设置为person对象
greet.call(person, 'Hello', '!'); // 输出:Hello Alice!
// 2. call的应用场景 - 检测数据类型
// 2.1 typeof 检测数据类型不够精确的
console.log(typeof '123') // string
console.log(typeof []) // object
console.log(typeof null) // object
// 2.2 Object.prototype.toString() 返回的结果是[object xxx类型]
// console.log(Object.prototype.toString('123')) // [object Object]
console.log(Object.prototype.toString.call('123')) // [object String]
console.log(Object.prototype.toString.call(123)) // [object Number]
console.log(Object.prototype.toString.call([])) // [object Array]
console.log(Object.prototype.toString.call(null)) // [object Null]
apply 方法
apply方法与call方法类似,但它接受一个参数数组,而不是多个参数。
语法:
functionName.apply(thisArg, [argsArray]);
示例:
function sum(a, b) {
console.log(this.name + ' calculates the sum as ' + (a + b));
}
const person = { name: 'Bob' };
// 使用apply方法调用sum函数,将this设置为person对象,并传递参数数组
sum.apply(person, [5, 7]); // 输出:Bob calculates the sum as 12
// 2. 使用场景- 求数组的最大值/最小值
console.log(Math.max(...[1, 2, 3])) // 3
// apply 或者 call 如果不需要改变this指向 写 null
console.log(Math.max.apply(null, [8, 2, 3])) // 8
console.log(Math.min.apply(null, [8, 2, 3])) // 2
bind 方法
bind方法创建一个新的函数,在调用时将this关键字设置为提供的值,第一个参数之后的所有参数都将作为新函数的参数,供调用时使用。
语法:
let boundFunc = functionName.bind(thisArg, arg1, arg2, ...);
示例:
function sayHello() {
console.log('Hello ' + this.name);
}
const person = { name: 'Carol' };
// 使用bind方法创建一个新的函数,将this设置为person对象
const sayHelloToCarol = sayHello.bind(person);
// 调用新创建的函数
sayHelloToCarol(); // 输出:Hello Carol
// 2. 使用场景 - 不需要调用函数,但是又想改变函数内部的this指向
// 1. 发送短信5秒倒计时业务
const codeBtn = document.querySelector('.code')
let flag = true // 开关变量,用来防止多次点击
codeBtn.addEventListener('click', function () {
if (flag) {
// 1.2 利用定时器做倒计时效果 setInterval
let i = 5
// 点击之后立马变化文字
this.innerHTML = `05秒后重新获取`
// 定时器
let timerId = setInterval(function () {
i--
this.innerHTML = `0${i}秒后重新获取`
// 1.3 时间到了 就显示文字为 重新获取
if (i === 0) {
this.innerHTML = `重新获取`
// 停止定时器
clearInterval(timerId)
flag = true
}
}.bind(this), 1000)
// 关闭开关
flag = false
}
})
bind方法返回的是一个新的函数,这意味着你可以将这个新函数赋值给一个变量,或者将它作为回调函数传递给其他函数。
总结
- call和apply方法都是立即执行函数。
- call接受参数列表,apply接受一个参数数组。
- bind返回一个新的函数,可以稍后执行。
这些方法在JavaScript中非常有用,特别是在需要控制函数内部this上下文的场景中。