JavaScript挑战练习(一)-改变this指向

一.this指向的详解

概括:this的指向到底是指向哪里?通常来说,只有当函数执行的时候才可以确定this指向的到底是谁,简单的也可以这么说:this最终指向的是那个调用它的对象。

常见的一般有以下几种情况:

第一种:在一个函数中有this,但是函数没有被上一级对象所调用,所以此时的this指向的是window(注意在严格模式下则不是),如以下代码:

function blue() {
    var blue = "蓝源";
    console.log(this.blue);//undefind
    console.log(this);//window
}
blue();//this指向调用它的那个对象,在这里相当于window

第二种:在函数中有一个this,而且该函数被上一级对象所调用,所以此时的this指向的是调用该函数的上一级对象,如以下代码:

var o = {
        name: "blue",
        fn: function(){
            console.log(this.name);//blue
            console.log(this);//指向o对象
        }
    }
o.fn();//此时this指向的是调用函数的对象o。

第三种:有一个函数中有this,函数中有多个对象,尽管这个函数是被最外层的对象调用,但是其中的this指向的只是它的上一级对象,如以下代码:

var o = {
    name: "blue",
    a: {
        fn: function(){
            console.log(this.name);//undefind,这里有两个对象o和a,调用的时候都指向上一层对象a,这里找不到声明的name
        }
    },
    fn1: function(){
        console.log(this.name);//blue
    }
}
o.fn1();
o.a.fn();

第四种(特殊情况):如果函数中有return,而且return返回的是一个对象,那么调用时候的this指向不再是指向调用这个函数的实例了,而是指向这个函数返回的对象,如以下代码:

function fn()  
{  
    this.name = 'blue';  
    return {};  
}
var a = new fn;  
console.log(a.name); //undefined,这里指向的是return返回的对象,是一个空对象

改变this指向的方法

第一种:使用call()

var a = {
    user:"blue",
    fn:function(){
        console.log(this.user); //blue
    }
}
var b = a.fn;
b.call(a);  //若不用call,则b()执行后this指的是Window对象

call方法除了第一个参数以外还可以添加多个参数,如下:

var a = {
    user:"blue",
    fn:function(c,d){
        console.log(this.user); //blue
        console.log(e+ee); //3
    }
}
var b = a.fn;
b.call(a,1,2);

第二种:使用apply()

var a = {
    user:"blue",
    fn:function(){
        console.log(this.user); //blue
    }
}
var b = a.fn;
b.apply(a);

apply方法和call方法很类似,也可以接收多个参数,但是第二个参数必须是数组,如下:

var a = {
    user:"blue",
    fn:function(e,ee){
        console.log(this.user); //blue
        console.log(c+d); //11
    }
}
var b = a.fn;
b.apply(a,[10,1]);

第三种:使用bind()
bind和call,apply的使用方法有些不同,如果我们还是按照上面的方法写代码,会发现一些问题,如下:

var a = {
    user:"blue",
    fn:function(){
        console.log(this.user);
    }
}
var b = a.fn;
b.bind(a);  //代码没有被打印

为什么代码没有被打印呢?这就是不同的地方所在,实际上执行bind之后返回的是一个函数,想下面这样写才是正确的:

var a = {
    user:"blue",
    fn:function(){
        console.log(this.user); //blue
    }
}
var b = a.fn;
var c = b.bind(a);
c();

bind()方法也可以接收多个参数,并且参数可以执行的时候再次添加,但是要注意的是,参数是按照形参的顺序进行的,如下:

var a = {
    user:"blue",
    fn:function(e,d,f){
        console.log(this.user); //blue
        console.log(e,d,f); //10 1 2
    }
}
var b = a.fn;
var c = b.bind(a,10);
c(1,2);

总结:

call(),apply()以及bind()方法都可以改变this指向,只是所使用的场景有点不一样,bind()改变后的函数想什么时候调用就什么时候调用,call和apply都是改变指向后立即调用此方法。

猜你喜欢

转载自blog.csdn.net/qq_35812380/article/details/84031276
今日推荐