面向对象语言中 this 表示当前对象的一个引用。
但在 JavaScript 中 this 不是固定不变的,它会随着执行环境的改变而改变。
- 在方法中,this 表示该方法所属的对象。
- 如果单独使用,this 表示全局对象。
- 在函数中,this 表示全局对象。
- 在事件中,this 表示接收事件的元素。
- 在显式函数绑定时,我们可以自己决定this的指向
实例
var person = {
firstName: "LeBron",
lastName : "James",
id : 8888,
fullName : function() {
return this.firstName + " " + this.lastName;
}
};
方法中的 this
在对象方法中, this 指向调用它所在方法的对象。
在上面一个实例中,this 表示 person 对象。
fullName 方法所属的对象就是 person。
fullName : function() { return this.firstName + " " + this.lastName; }
单独使用 this
单独使用 this,则它指向全局对象。
在浏览器中,window 就是该全局对象为 [object Window]:
在node中,指向的是一个{}
var x = this;
函数中使用 this(默认)
在函数中,函数的所属者默认绑定到 this 上。
在浏览器中,window 就是该全局对象为 [object Window]:
在node中,指向的就是global对象
function myFunction() { return this; }
事件中的 this
在 HTML 事件句柄中,this 指向了接收事件的 HTML 元素:
<button onclick="this.style.display='none'"> 点我后我就消失了 </button>
显式函数绑定
在 JavaScript 中函数也是对象,对象则有方法,apply 和 call 就是函数对象的方法。这两个方法异常强大,他们允许切换函数执行的上下文环境(context),即 this 绑定的对象。
在下面实例中,当我们使用 person2 作为参数来调用 person1.fullName 方法时, this 将指向 person2, 即便它是 person1 的方法:
var person1 = {
fullName: function () {
return this.firstName + " " + this.lastName;
}
}
var person2 = {
firstName: "Zach",
lastName: "Muyi",
}
var name = person1.fullName.call(person2); // 返回 "Zach Muyi"
console.log(name);
修改this指向
构造函数的原型prototype中,有call(), apply(), bind()方法来修改this指向。
call(执行环境对象,实参列表);
调用call方法,第一个参数就是要把b添加到哪个环境中,简单来说,this就会指向那个对象。
var Person = {
name: "zhangsan",
age: 19
}
function aa(x, y) {
console.log(x + "," + y);
console.log(this);
console.log(this.name);
}
aa(4, 5); //this指向window--4,5 window 空
aa.call(Person, 4, 5); //this指向Person--4,5 Person{}对象 zhangsan
apply(执行环境对象,实参列表数组);
apply方法和call方法有些相似,它也可以改变this的指向,同样apply也可以有多个参数,但是不同的是,第二个参数必须是一个数组
var Person = {
name: "zhangsan",
age: 19
}
function aa(x, y) {
console.log(x + "," + y);
console.log(this);
console.log(this.name);
}
aa.apply(Person, [4, 5]); //this指向Person--4,5 Person{}对象 zhangsan
bind(执行环境对象)(实参列表);
同样bind也可以有多个参数,并且参数可以执行的时候再次添加,但是要注意的是,参数是按照形参的顺序进行的,且bind返回一个修改this后的函数,需声明变量接收手动调用。
var obj = {
name: 'Diana',
sayName: function (a,b,c) {
console.log(this.name);
console.log(a,b,c); // 1,2,3
}
}
var b = obj.sayName;
b.bind(obj); // 代码没有被打印,这就是bind和call、apply方法的不同,实际上bind方法返回的是一个修改过后的函数。
// 新建一个变量c来接收bind修改后的函数
var c = b.bind(obj, 1, 2);
console.log(c); // 发现c是一个[Function: bound sayName]函数
// 执行c
c(3); // Diana
总结:call和apply都是改变上下文中的this并立即执行这个函数,bind方法可以让对应的函数想什么时候调就什么时候调用,并且可以将参数在执行的时候添加,这是它们的区别,根据自己的实际情况来选择使用。