搞懂this指向

237 阅读3分钟

搞懂this指向

ps 为什么要搞懂this?因为JavaScript是面向对象编程,而this指向的就是对象

谁调用就指向谁

例子:


function test() {
    var name = "测试";
    console.log(this.name); // ''
    console.log(this); // window
}
test();

this最终指向的是调用它的对象,这里的函数test实际是被Window对象所点出来的。


function test() {
    var name = "测试";
    console.log(this.name); // ''
    console.log(this); // window
}
window.test();

效果是一样的,因为定义的函数也是window的一个属性。

在看另外个例子

var test = {
    name: '测试',
    fn: function() {
        console.log(this.name); // 测试
    }
}
​
test.fn()

这里this是指向对象test,按说法谁调用它就指向谁,那自然就是对象test。当然要在函数创建后这个说法才成立。

this永远指向的是最后调用它

var test = {
    age:10,
    test2:{
        age:12,
        fn:function(){
            console.log(this.age); //undefined
            console.log(this); //window
        }
    }
}
var call = test.test2.fn;
call();

这里指向的是window,因为this永远指向的是最后调用它的,也就是看它执行的时候是谁调用的。这个例子虽然函数fu是被test2所引用,但是在将fn赋值给变量call的时候并没有执行所以最终指向的是window

构造函数版this


function fn(){
    this.user = "测试";
}
var test = new fn();
console.log(test.user); // 测试

这里之所以对象test可以点出函数Fn里面的user是因为new关键字可以改变this的指向,用了new关键字就是创建一个对象实例,我们这里用变量test创建了一个fn的实例(相当于复制了一份Fn到对象test里面),此时仅仅只是创建,并没有执行,而调用这个函数fn的是对象test,那么this指向的自然是对象test。

首先new关键字会创建一个空的对象,然后会自动调用一个函数apply方法,将this指向这个空对象,这样的话函数内部的this就会被这个空的对象替代。

当this碰到return时


function fn()  
{  
    this.user = '测试';  
    return {};  
}
var test = new fn;  
console.log(test.user); //undefined

function fn()  
{  
    this.user = '测试';  
    return 1;  
}
var test = new fn;  
console.log(test.user); //测试

如果函数返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例。

自行改变this的指向

开发环境的数据,测试环境没有开发环境的数据,只有改变环境才能更换数据。call,apply,bind 就是一般用来指定this的环境

call()

var test = {
    age:10,
    test2:{
        age:12,
        fn:function(){
            console.log(this.age); //undefined
            console.log(this); //window
        }
    }
}
var fn2 = test.test2.fn;
fn2();

这里fn2指向的是window,通过call方法,第一个参数可以将fn2 window环境指向为你需要的环境中

var test = {
    age:10,
    test2:{
        age:12,
        fn:function(){
            console.log(this.age); // 12
        }
    }
}
var fn2 = test.test2.fn;
fn2.call(test);

也可以添加多个参数

var test = {
    age:10,
    test2:{
        age:12,
        fn:function(e, ee){
            console.log(this.age); // 12
            console.log(e+ee); //3
        }
    }
}
var fn2 = test.test2.fn;
fn2.call(test, 1, 2);

apply()

apply方法和call方法有些相似,它也可以改变this的指向,唯一不同的就是apply第二个参数只能是数组

var test = {
    age:10,
    test2:{
        age:12,
        fn:function(e, ee){
            console.log(this.age); // 12
            console.log(e+ee); //6
        }
    }
}
var fn2 = test.test2.fn;
fn2.call(test,[1,2,3]);

ps 注意如果call和apply的第一个参数写的是null,那么this指向的是window对象

bind()

bind方法和call、apply方法有些不同,bind方法是返回的是一个修改过后的函数。

var test = {
    age:10,
    test2:{
        age:12,
        fn:function(){
            console.log(this.age); 
        }
    }
}
var fn2 = test.test2.fn;
fn2.bind(test);

这样会发现是没有执行的,因为bind返回的是一个修改后的函数,没有调用他

var test = {
    age:10,
    test2:{
        age:12,
        fn:function(){
            console.log(this.age); // 12
        }
    }
}
var fn2 = test.test2.fn;
var fn3 = fn2.bind(test);
fn3()

这样就可以调用,当然bind也是支持多个参数的,用法跟call一样