this指向问题以及如何改变this指向方法

一、this指向问题

先了解this分别在不同情况都指向谁,一般情况下this的最终指向的是哪个调用它的对象(通俗讲就是 谁调用指向谁),二般情况分具体看待,以下分情况谈谈。
1. 全局作用域或者普通函数中this指向全局对象window ,如果一个函数中有this,但是它没有被上一级的对象所调用,那么this指向的就是window(注意定时器里面的this指向window)
案例一、

function Hello(){
    var user = "你好";
    console.log(this.user); //undefined 因为window对象中没有user属性
    console.log(this); //Window
}
Hello(); //相当于window.Hello();
//this最终指向的是调用它的对象,这里的函数Hello实际是被Window对象所点出来的

案例二、

function fn(){
    console.log(this); //Window
}
window.fn();
//定时器函数
setTimeout(function(){
    console.log(this); //Window
},1000);

案例三、自调用函数this也指向window

(function(){
    console.log(this); //Window
})()

2. 如果一个函数中有this,这个函数有被上一级的对象所调用,那么this指向的就是上一级的对象。绑定事件函数this指向的是函数的调用者
案例一、

var person = {
    user:"你好",
    fn:function(){
        console.log(this.user); //你好  因为fn函数被person所调用,所以this指向person
        console.log(this); //输出person对象 {user: "你好", fn: ƒ}
    }
}
person.fn(); //this执行时被它的上一级对象person{user: "你好", fn: ƒ}调用

案例二、

var btn = document.querySelector('button');
btn.onclick=funcion(){
    console.log(this);//this指向的是btn这个按钮对象
};
btn.addEventListener('click',function(){
    console.log(this);//this指向的是btn这个按钮对象
});

3. 如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象

var numberObj = {
    a:10,
    b:{
        //a:12,
        fn:function(){
            console.log(this.a); //undefind  有两个对象b和numberObj ,所以此this.a指向它的上一级,因为b对象中没有a属性 所以输出undefind
        }
    },
    fn1:function(){
        console.log(this.a);  //10 
    }
}
numberObj.fn1(); // fn1函数被numberObj 所调用,所以this指向numberObj对象
numberObj.b.fn(); // 尽管fn函数是被外层numberObj对象所调用,但是fn里面的this还是指向他的此处的上一级b对象

4. 当this遇到return---- 如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例。还有一点就是虽然null也是对象,但是在这里this还是指向那个函数的实例,因为null比较特殊。
案例一、

function fn()  
{  
    this.user = '张三';  
    return {};  
}
var a = new fn;  
console.log(a.user); //undefined

案例二、

function fn()  
{  
    this.user = '张三';  
    return function(){};
}
var a = new fn;  
console.log(a.user); //undefined

案例三、

function fn()  
{  
    this.user = '张三';  
    return 1;
}
var a = new fn;  
console.log(a.user); //张三  因为 new关键字改变this指向 下文会细说

案例四、

function fn()  
{  
    this.user = '张三';  
    return null;
}
var a = new fn;  
console.log(a.user); //张三

二、改变this指向方法

方法一、new关键字改变this指向

//构造函数 this
function Fn(){
    this.user = "您好";
}
var a = new Fn();
console.log(a.user); //您好

用变量a创建了一个Fn的实例(相当于复制了一份Fn到对象a里面),此时仅仅只是创建,并没有执行,而调用这个函数Fn的是对象a,那么this指向的自然是对象a,那么为什么对象a中会有user,因为你已经复制了一份Fn函数到对象a中,用了new关键字就等同于复制了一份
方法二、call()改变this指向
fun.call(thisArg,arg1,arg2,…)
案例一、

var a = {
    user:"您好",
    fn:function(){
        console.log(this.user); //您好
    }
}
var b = a.fn;
b.call(a);  //若不用call,想当与b() 也就是window.b()执行后this指的是Window对象

案例二、

var o={
    name:'andy'
}
function fn(a,b){
    console.log(this); // 输出o对象
    console.log(a+b); // 3
}
//调用函数 改变this指向
fn.call(o,1,2);

//实现继承
function Father(uname,age,sex){
    this.uname=uname;
    this.age=age;
    this.sex=sex;
}
function Son(uname,age,sex){
    Father.call(this,uname,age,sex);
}
var son=new Son('小明',18,'男');
console.log(son); // {uname:'小明',age:18,sex:'男'}

方法三、apply() 改变this指向
fun.apply(thisArg,[argsArray]) , apply方法和call方法有些相似,它也可以改变this的指向,也可以有多个参数,但是不同的是,第二个参数必须是一个数组
案例一、

var a = {
    user:"您好",
    fn:function(){
        console.log(this.user); //您好
    }
}
var b = a.fn;
b.apply(a);  // 如果没有apply 就相当与b()  b()等于a.fn 也就是函数fn,加上apply() 并且括号参数指定为a 也就说明this指向a对象

案例二、

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

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

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

方法四、bind() 改变this指向
fun.bind(thisArg,arg1,arg2,…)
不会调用函数,可以改变函数内部this指向,返回的是原函数改变this之后产生的新函数 (如果有的函数我们不需要立即调用,但是又想改变this指向此时用bind)

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

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

var a = {
    user:"王五",
    fn:function(){
        console.log(this.user); //王五
    }
}
var b = a.fn;
var c = b.bind(a);
c();  // 因为bind返回的是一个函数,要输出必须要调用

call和apply都是改变上下文中的this并立即执行这个函数,bind方法可以让对应的函数想什么时候调就什么时候调用,并且可以将参数在执行的时候添加,这是它们的区别

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值