首先,我们先了解下函数内部的 this 指向:
- 普通函数的 this 指向:
window
function func() {
console.log("普通函数的this指向:" + this);
}
func(); // 控制台打印输出:普通函数的this指向:[object Window]
- 对象方法调用的 this 指向:
该方法所属的对象
var obj = {
name: 'Oct13_JJP',
sayHello: function() {
console.log("对象方法调用的this指向:" + this);
}
}
obj.sayHello(); // 控制台打印输出:对象方法调用的this指向:[object Object]
- 构造函数调用的 this 指向:
实例对象。原型对象里面的this也是指向实例对象
function SayHello() {
console.log("构造函数调用的this指向:" + this);
}
new SayHello(); // 控制台打印输出:构造函数调用的this指向:[object Object]
- 事件绑定方法的 this 指向:
事件的调用对象
<button id="btn">点我</button>
var btn = document.getElementById("btn");
btn.onclick = function() {
console.log("事件绑定方法的this指向:" + this); // 控制台打印输出:事件绑定方法的this指向:[object HTMLButtonElement]
}
- 定时器函数的 this 指向:
window
setTimeout(function() {
console.log("定时器的this指向:" + this); // 控制台打印输出:定时器的this指向:[object Window]
}, 1000)
- 立即执行函数的 this 指向:
window
(function() {
console.log("立即执行函数的this指向:" + this); // 控制台打印输出:立即执行函数的this指向:[object Window]
})();
清楚了函数内部的this指向之后,要改变函数内部的this指向,也非常简单!
在Javascript中,要改变函数内部的 this 指向问题,通常有call()、apply()、bind()这三种方法。
call()方法
语法:func.call(thisObj, arg1, arg2, ...)
var person = {
fullName: function() {
return this.firstName + '-' + this.lastName
}
}
function func() {
console.log(this); // 控制台打印输出:window
}
func(); // 调用方法 func(),此时的this指向是 window
// 如果我们要将 this 指向 person 这个对象,可以调用 call() 方法
func.call(person); // 此时的 this 指向的就是 person 这个对象
// -----------------------------------------------------------------------------
// call()方法除了传递对象,还可以传递实参
var person = {
fullName: function() {
return this.firstName + '-' + this.lastName
}
}
function func(name, age) {
console.log("姓名:" + name + ",性别:" + age);
}
func.call(person, "Oct13_JJP", "男");
call()方法的作用:
- 可以调用函数
- 可以改变函数内部的 this 指向
- 可以实现继承
// 有两个构造函数 Father 和 Son,现在想让 Son 继承 Father 的name,age,sex属性
function Father(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
function Son(name, age, sex) {
Father.call(this, name, age, sex)
}
var son = new Son("Oct13_JJP", "男", 20)
console.log(son); // 控制台打印输出:Son {name: "Oct13_JJP", age: "男", sex: 20}
apply()方法
语法:func.apply(thisObj, [arg1, arg2, ...])
var person = {
fullName: function() {
return this.firstName + '-' + this.lastName
}
}
function func() {
console.log(this); // 控制台打印输出:window
}
func(); // 调用方法 func(),此时的this指向是 window
// 如果我们要将 this 指向 person 这个对象,可以调用 apply() 方法
func.apply(person); // 此时的 this 指向的就是 person 这个对象
// -----------------------------------------------------------------------------
var person = {
fullName: function() {
return this.firstName + '-' + this.lastName
}
}
function func(name, age) {
console.log("姓名:" + name + ",性别:" + age);
}
// 与 call() 方法不同的是,apply() 的参数必须是数组形式
func.apply(person, ["Oct13_JJP", "男"]); // 控制台打印输出:姓名:Oct13_JJP,性别:男
apply()方法的作用:
- 可以调用函数
- 可以改变函数内部的 this 指向
bind()方法
语法:func.bind(thisObj, arg1, arg2, ...)
var person = {
fullName: function() {
return this.firstName + '-' + this.lastName
}
}
function func(name, age) {
console.log(this);
}
func.bind(person); // 控制台不输出任何内容,因为 bind 方法不会调用函数,只会改变函数内部的 this 指向
// 其返回值由 this 指向的值和初始化参数改造的原函数拷贝
var f = func.bind(person);
f(); // 控制台打印输出:{fullName: ƒ}
// -----------------------------------------------------------------------------
var person = {
fullName: function() {
return this.firstName + '-' + this.lastName
}
}
function func(name, age) {
console.log("姓名:" + name + ",性别:" + age);
}
var fn = func.bind(person, "Oct13_JJP", "男");
fn(); // 控制台打印输出:姓名:Oct13_JJP,性别:男
bind()方法的作用:
- 不会调用函数
- 可以改变函数内部的 this 指向
- 返回值由 原函数改变this之后产生的新函数(原函数拷贝)
总结
相同点:
- 都可以改变函数内部的 this 指向
区别: - call()、apply()会调用函数
- bind()不会调用函数,而是会创建一个新函数
- call()、apply()传递的参数格式不一样,call()传递参数的格式:arg1, arg2, ... ,apply()传递的参数必须是数组的格式:[arg1, arg2, ...]
- bind()是返回原函数拷贝后的新函数,便于稍后调用;call()、apply()则是立即调用 。 常见的应用场景:
- call() 常用于继承
- apply() 常用于获取数组中的最大值与最小值
- bind() 常和 setTimeout 一起使用