this
1、this的指向是由它所在函数调用
的上下文决定的,而不是由它所在函数定义
的上下文决定的;
2、当一个函数作为函数
而不是方法来调用的时候,this指向的是全局对象
,反之this指向方法前的对象
(也就是说当出现 [对象].[函数名] 时,this指向是[对象])。
demo1: 指向方法前的对象
var obj = {
x:20,
f:function(){
console.log(this.x);
}
};
obj.f(); //输出20,f()前有obj对象所以this指向obj
obj.innerobj = {
x:30,
f:function(){
console.log(this.x);
}
}
obj.innerobj.f(); //输出30 注:此时当出现多个 . 时,要看最后函数前的 . 本例中为obj.innerobj.
demo2:指向全局对象
/*example 2*/
var x = 10;
var obj = {
x:20,
f:function(){
console.log(this.x);
var foo = function(){
console.log(this.x);
}
foo();
}
};
obj.f(); //输出20和10 在执行f函数中的foo()函数时,由于foo()前没有对象名,故默认为全局对象,输出10
/*example 3*/
var x = 10;
var obj = {
x:20,
f:function(){
console.log(this.x);
}
};
obj.f(); //输出20
var fOut = obj.f;
fOut(); //输出10 fOut()前没有对象名,所以默认为全局变量
var obj2 = {
x:30,
f:obj.f
}
obj2.f(); //输出30 f()前对象时obj2,故this指向obj2
此外记录一下this遇上return时的问题:
function fn()
{
this.user = '追梦子';
return function(){};
}
var a = new fn;
console.log(a.user); //undefined
function fn2()
{
this.user = '追梦子';
return 1;
}
var a = new fn2;
console.log(a.user); //追梦子
如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例。
改变this指向
使用函数的bind方法
var name = "window.name";
var obj = {
name : "obj.name",
getName:function(){
console.log(this.name);
return function(){
console.log(this.name);
}.bind(this);
}
};
obj.getName()(); // "obj.name" "obj.name"
使用变量接收上面的this,下面使用变量替代
var name = "window.name";
var that = null;
var obj = {
name : "obj.name",
getName:function(){
that = this;
console.log(this.name);
return function(){
console.log(that.name);
}
}
}
obj.getName()(); // "obj.name" "obj.name"
使用ES6的箭头函数
var name = "window.name";
var obj = {
name : "obj.name",
getName:function(){
console.log(this.name);
return () => {
console.log(this.name);
}
}
}
obj.getName()(); // "obj.name" "obj.name"
全局函数apply和call可以用来改变this的指向
apply和call的唯一区别,就是在传参的时候,apply的参数需要放在一个数组里面,而call不需要。
function demo(){
console.log(this.fruit);
}
// 定义一个全局变量,等同于window.fruit = "banana";
var fruit = "banana";
var obj = {
fruit : "apple"
};
demo(); //相当于window.demo()和demo.apply(window);
demo.apply(window); // "banana";
demo.call(obj); // "apple";
参考: