this指向浅析

作者: Miaoz0070 | 来源:发表于2020-06-01 14:48 被阅读0次

    在开发过程中,使用this总会出现问题,时不时的会出现获取不到自己想要的对象和值,只要写js就必然要弄懂this指向问题。最近总结了下this指向问题,记录下来,方便之后巩固学习,也分享给大家希望能有所帮助。

    • 常见的window方法:alter,document,setTimeout,setInterval,一般使用都不会window.xx,而直接使用xx。如果this指向性是window的话,也可以使用this.xx。

    • use strict:严格模式,在脚本或函数的头部添加 "use strict"; 表达式来声明。指令只允许出现在脚本或函数的开头。
      在“use strict”严格模式下,没有直接的挂载者(或称调用者)的函数中this是指向window。在“use strict”严格模式下,没有直接的挂载者的话,this默认为undefined。以下都是在非严格模式下讨论。

    • 普通函数this指向:
      this对象是在运行时基于函数的执行环境绑定的:在全局函数中,this指向的是window;当函数被作为某个对象的方法调用时,this就等于那个对象。
      1.总是代表着它的直接调用者,如obj.fn,fn里的最外层this就是指向obj
      2.默认情况下,没有直接调用者,this指向window,严格模式下(设置了'use strict'),this为undefined
      3.call,apply,bind改变this指向
      call: 第一个参数是this的指向,后面传入的是一个参数列表。当第一个参数为null、undefined的时候,默认指向window。如:xx.call(obj, 'xx', 'xx2', 'xx3')
      apply: 方法接收两个参数,第一个参数是this的指向,第二个参数是一个参数数组。当第一个参数为null、undefined的时候,默认指向window。如:xx.apply(obj, ['xx', 'xx2', 'xx3'])
      bind :call 方法很相似,第一个参数是this的指向,从第二个参数开始是接收的参数列表。区别在于bind方法返回值是函数以及bind接收的参数列表的使用。低版本浏览器没有该方法,需要自己手动实现.
      三者相似之处:
      1、都是用来改变函数的this对象的指向的。
      2、第一个参数都是this要指向的对象。
      3、都可以利用后续参数传参。
      区别:
      call和apply都是对函数的直接调用,而bind方法返回的仍然是一个函数,因此后面还需要()来进行调用才可以
      1.call和apply功能几乎一致,唯一的区别就是传参的方式
      2.call和apply的第一个参数如果为null或者undefined,那么this指向window
      3.call和apply的第一个参数如果为值类型的数据,那么会将这个值类型的数据,转换成其对应的引用类型的数据,然后再将this指向这个引用类型的数据
      4.call和apply立即执行这个函数,bind方法可以让对应的函数想什么时候调就什么时候调用,并且可以将参数在执行的时候添加,这是它们的区别,根据自己的实际情况来选择使用。
      5.当参数的个数确定的情况下可以使用call;当参数的个数不确定的情况下可以使用apply

    • 箭头函数改变this指向
      箭头函数的this定义:箭头函数的this是在定义函数时绑定的,不是在执行过程中绑定的。简单的说,函数在定义时,this就继承了定义函数的对象。这会很好的解决匿名函数和setTimeout和setInterval的this指向问题。我们不用再去给其用that变量存储this。
      1.默认指向定义它时,所处上下文的对象的this指向。即ES6箭头函数里this的指向就是上下文里对象this指向,没有上下文对象,this就指向window。
      2.即使是call,apply,bind等方法也不能改变箭头函数this的指向。
      3.看箭头函数定义的环境是什么 (找上一个 {})。
      4.定义环境执行时 this指向谁,箭头函数的 this就指向谁。
      5.箭头函数的this在定义的时候就确定,逐级向上查找找到最近的函数作用域的this。
      6.匿名函数没有直接调用者,this指向window。

    • 场景
      场景1:

    function a(){
        var user = "xx";
        console.log(this.user); //undefined,window全局中没有定义user,所以是undefined
        console.log(this); //Window
    }
    a();
    

    this最终指向的是调用它的对象,这里的函数a是,window调用。

    场景2:

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

    这里的fn是a在调用,所以fn中的this指向就是指向对象a。强调:this的指向在函数创建的时候是决定不了的,在调用的时候才能决定,谁调用的就指向谁。

    场景3:

    var obj = {
        a:1,
        b:{
            a:12,
            fn:function(){
                console.log(this.a); //12
            }
        }
    }
    o.b.fn();
    

    场景1:如果一个函数中有this,但是它没有被上一级的对象所调用,那么this指向的就是window,这里需要说明的是在js的严格版中this指向的不是window。
    场景2:如果一个函数中有this,这个函数有被上一级的对象所调用,那么this指向的就是上一级的对象。
    场景3:如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象。

    var obj = {
        a:1,
        b:{
            // a:12, 注释掉
            fn:function(){
                console.log(this.a); //undefined
            }
        }
    }
    o.b.fn();
    

    我们对象b中没有属性a,但是this指向还是对象b,因为this只会指向它的上一级对象,不管这个对象中有没有this要的东西。

    场景4(特殊情况):

    var obj = {
        a:1,
        b:{
            a:12,
            fn:function(){
                console.log(this.a); //undefined
                console.log(this); //window
            }
        }
    }
    var s = obj.b.fn;
    s();
    

    这种情况this指向的是window,因为具体执行调用方法是在s()执行即window.s(),之前的var s = obj.b.fn;只是被引用,却没有执行调用。
    this永远指向的是最后调用它的对象,也就是看它执行的时候是谁调用的,场景4中虽然函数fn是被对象obj所引用,但是在将fn赋值给变量j的时候并没有执行所以最终指向是window,场景3是不一样的,场景3是直接执行了fn。

    场景5(特殊情况):
    如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例。

    //1.1
    function fn()  
    {  
        this.user = 'xx';  
        return {};  
    }
    var a = new fn;  
    console.log(a.user); //undefined,this指向返回的对象。
    //1.2
    function fn()  
    {  
        this.user = 'xx';  
        return function(){};
    }
    var a = new fn;  
    console.log(a.user); //undefined,,this指向返回的对象。
    //2.1
    function fn()  
    {  
        this.user = 'xx';  
        return 1;
    }
    var a = new fn;  
    console.log(a.user); //xx,this指向实例a。
    //2.2
    function fn()  
    {  
        this.user = 'xx';  
        return undefined;
    }
    var a = new fn;  
    console.log(a.user); //xx,this指向实例a。
    //2.3
    function fn()  
    {  
        this.user = 'xx';  
        return undefined;
    }
    var a = new fn;  
    console.log(a); //fn {user: "xxx"}
    //2.4null比较特殊,虽然null也是对象,但是在这里this还是指向那个函数的实例。
    function fn()  
    {  
        this.user = 'xx';  
        return null;
    }
    var a = new fn;  
    console.log(a.user); //xx
    
    

    场景6构造函数this:

    function Fn(){
        this.user = "xx";
    }
    var a = new Fn();
    console.log(a.user); //xx
    

    为什么this会指向a?首先new关键字会创建一个空的对象,然内部机制会将this指向这个空对象,函数内部的this就会被这个空的对象替代。

    this指向有很多种情况,需要在实际开发中自己去理解。

    相关文章

      网友评论

        本文标题:this指向浅析

        本文链接:https://www.haomeiwen.com/subject/gvaqohtx.html