this指向


this:执行上下文,this一般存在于函数中,表示当前函数的执行上下文,如果函数没有执行,那么this没有内容,只有函数在执行后this才有绑定。

this执行的位置

  1. 默认执行:this指向window,严格模式指向undefined
    非严格模式下
 function fn(){
        console.log(this);    // window
    }
 fn();

``

在这里插入图片描述
          严格模式下

 function fn(){
        "use strict";
        console.log(this);   //undefined
    }
 fn();

在这里插入图片描述

  1. 通过对象执行(通过上下文对象执行,隐式执行):obj.fn():当前的执行对象
    下面案例中的this,如果fn直接执行时,this的执行是调用它的fn(),但是创建了一个对象obj,在obj中有一个对象b,通过对象obj.b()执行该函数,那么此时的this就是执行它的直接父级obj对象,所以此时的this的输出就是下面显示的结果。
function fn(){
    console.log(typeof this);     //object
    console.log(this);       

var a = 10;
var obj = {
    a:20,
    b:fn
}
obj.b();

在这里插入图片描述

  1. 显式执行(通过函数的方法bind执行):指定的是谁,就是谁
    找回隐式丢失的this,其实就是使用显式执行,强行绑定
    通过bind方法强行将this执行window。关于bind方法将在下面详细介绍。
 function fn(){
      console.log(this);
 }
 var f = fn.bind(window);
 f();

在这里插入图片描述

  1. 使用构造函数执行(通过new执行)
    在构造函数或者构造函数原型对象中 this 指向构造函数的实例

    这里通过构造函数的方式,利用new关键字创建了一个对象实例,将这个this指向这个对象a,我们这里用变量a创建了一个Fn的实例(相当于复制了一份Fn到对象a里面),此时仅仅只是创建,并没有执行,而调用这个函数Fn的是对象a,那么this指向的自然是对象a,那么为什么对象a中会有user,因为你已经复制了一份Fn函数到对象a中,用了new关键字就等同于复制了一份。

function Fn(){
    this.user = "小张";
}
var a = new Fn();
console.log(typeof a);   //object
console.log(a.user);   //小张

在这里插入图片描述
当this碰到return时

来看看几个例子

function fn()
{
    this.user = "小张";
    return {};
}
var a = new fn();
console.log(a.user);    //undefined
function fn()
{
    this.user =  "小张";
    return 1;
}
var a = new fn();
console.log(a.user); // 小张
function fn()  
{  
    this.user = "小张";  
    return undefined;
}
var a = new fn;  
console.log(a.user);  //小张
function fn()  
{  
    this.user =  "小张";  
    return undefined;
}
var a = new fn;  
console.log(a);      //fn {user:  "小张"}
function fn()  
{  
    this.user ="小张";  
    return null;
}
var a = new fn;  
console.log(a.user); //小张

那么这几个例子表示什么意思呢?
如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例。还有一点就是虽然null也是对象,但是在这里this还是指向那个函数的实例,因为null比较特殊

bind()、call()和apply()的关系

  • apply()
    使用 apply, 你可以继承其他对象的方法:
    在 JavaScript 严格模式下,如果 apply() 方法的第一个参数不是对象,则它将成为被调用函数的所有者(对象)。在“非严格”模式下,它成为全局对象。
    注意这里apply()的第一个参数是null,在非严格模式下,第一个参数为null或者undefined时会自动替换为指向全局对象,apply()的第二个参数为数组类数组

  • call()
    call()是apply()的一颗语法糖,作用和apply()一样,同样可实现继承,唯一的区别就在于call()接收的是参数列表,而apply()则接收参数数组。

  • bind()
    bind()的作用与call()和apply()一样,都是可以改变函数运行时上下文,区别是call()和apply()在调用函数之后会立即执行,而bind()方法调用并改变函数运行时上下文后,返回一个新的函数,供我们需要时再调用。

 var name="小王",age=17;
   var obj={
       name:"小张",
       objAge:this.age,
       myFun:function(fm,t){
           console.log(this.name+"年龄"+this.age,"来自"+fm+"去往"+t);
       }
   };
   var db={
         name:"小红",
         age:36
     };
     obj.myFun.call(db,"上海","淮南");
     obj.myFun.apply(db,["上海","淮南"]);
     obj.myFun.bind(db,"上海","淮南")();
     obj.myFun.bind(db,["上海","淮南"])();

在这里插入图片描述
从上面四个结果不难看出:
call 、bind 、 apply 这三个函数的第一个参数都是 this 的指向对象,第二个参数差别就来了:
call 的参数是直接放进去的,第二第三第 n 个参数全都用逗号分隔,直接放到后面 obj.myFun.call(db,‘成都’, … ,‘string’ )。
apply 的所有参数都必须放在一个数组里面传进去 obj.myFun.apply(db,[‘成都’, …, ‘string’ ])。
bind 除了返回是函数以外,它 的参数和 call 一样。
当然,三者的参数不限定是 string 类型,允许是各种类型,包括函数 、 object 等等!

如何选用

如果不需要关心具体有多少参数被传入函数,选用apply();
如果确定函数可接收多少个参数,并且想一目了然表达形参和实参的对应关系,用call();
如果我们想要将来再调用方法,不需立即得到函数返回结果,则使用bind();

总结

call()、apply()和bind()都是用来改变函数执行时的上下文,可借助它们实现继承;
call()和apply()唯一区别是参数不一样,call()是apply()的语法糖;
bind()是返回一个新函数,供以后调用,而apply()和call()是立即调用。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值