js中this指向问题
js中this指向问题老生常谈的问题了,在这里说一下我所理解的层面的this。
this 指的是当前对象,如果在全局范围内使用this,则指代当前页面window;如果在函数中使用this,则this指代什么是根据当前函数是在什么对象上调用。我们可以使用call和apply改变函数中this的具体指向。
console.log(this === window) // true
console.log(window.alert === this.alert) // true
console.log(this.parseInt("021",10)) // 21
//parseInt(string,radix);
// 当只使用一个参数时,我们都知道是将其转为整数;
// radix 取值为 2~36,表示当前数是几进制,并将这个数转成十进制,当不在这个范围时,会输出NaN;
函数中的this是在运行时候决定的,而不是函数定义时。
function foo(){
console.log(this.fruit);
}
// 定义一个全局变量,等同于window.fruit = "banana";
var fruit = "banana";
// 此时函数中的this指向window;
foo(); // "banana"
var o = {
fruit : "apple",
foo : foo
};
// 此时函数中的this指向o
o.foo(); // "apple"
全局函数apply和call可以用来改变this的指向,如下:
function foo(){
console.log(this.fruit);
}
// 定义一个全局变量,等同于window.fruit = "banana";
var fruit = "banana";
var o = {
fruit : "apple"
};
foo.apply(window); // "banana";
foo.call(o); // "apple";
apply和call的唯一区别,就是在传参的时候,apply的参数需要放在一个数组里面,而call不需要;
因为在JavaScript中,函数也是对象,我们看下面这个例子:
function foo(){
if(this === window){
console.log("this is window");
}
};
// 函数foo也是对象,可以为对象定义属性,然后属性为函数
foo.boo = function(){
if(this === foo){
console.log("this is foo");
}else if(this === window){
console.log("this is window");
}
};
// 等价于 window.foo();
foo(); // "this is window";
// 可以看到函数中this的指向调用函数的对象
foo.boo(); // "this is foo";
// 可以使用call改变函数中this指向
foo.boo.call(window); // "this is window";
对象中的嵌套函数的this指向不是当前对象,而是window,看如下例子:
var name = "window.name";
var obj = {
name : "obj.name",
getName:function(){
console.log(this.name);
return function(){
console.log(this.name);
}
}
}
obj.getName()(); // "obj.name" "window.name"
同样是obj调用的getName和getName里面的方法,结果却是不同的值,这就说明嵌套函数中的this已经不指向当前对象了,而指向window。
那么,我们要怎样解决上述问题呢?主要有三种解决办法,如下:
1.使用函数的bind方法,绑定当前this;
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"
2.使用变量将上面的this接收一下,然后下面不使用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"
3.使用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"