• js深入(四)万脸懵圈的this指向


    作为一个js菜鸡的我而言,在之前讲到过那么多的js链式查找机制,比如说原型链,作用域链等等,想当然的把这个机制带入到了this指向上边,结果就是这个this指向指的我万脸懵逼(标题换字了,担心被河蟹),在经过漫长的通(gou)俗(pi)易(bu)懂(tong)的 ECMAScript规范阅读之后,分享一下我所认知的this指向

    简而言之,js中this的指向不是在函数定义的时候确定的,而是在调用的时候创建阶段确定的,也就是说this指向谁,完全取决于函数的调用方式

    常见的几种调用方式

    • 直接调用, 比如说

        function a() {
        console.log(this);  
        }
        
        a();  
      

    这个例子里边this指向的是全局对象,在客户端的全局对象是window对象,在node 中的全局对象是global对象

        (function a() {
            function b() {
                console.log(this);  
            }
            b()
        })()
    

    直接调用指的是直接用函数名称后边加()执行调用的函数,无论是否在全局作用域

    • 间接调用

        const obj ={
            name:'obj对象',
            a(){
                console.log(this)
            }
        }
        obj.a()
      

    如图

    在图中我们可以看到我们在对象里边调用对象里边的方法的时候,this指向的是obj对象,

    或者说外边有一个函数 然后给一个obj对象的属性赋值

        const obj ={
            name:'obj对象',
            a(){
                console.log(this)
            }
        }
        obj.a()
        obj.b=function(){
            console.log(this,'b')
        }
        obj.b()
    

    打印的结果都是obj对象

    • new调用

    当我们他用过new 创建一个新的对象的时候,new会调用这个构造函数来创建一个对象,那么这个对象里边的this是这个被new的函数调用的,那么自然 new调用的时候,this就是指向这个新对象的

        function A(data) {
            this.data = data;
        }
        class B{
            constructor(data){
                  this.data = data
            }
        }
        let a = new A("A");
        let b = new B("B");
        console.log(a.data);   
        console.log(b.data);   
    

    如图

    这个new,在创建对象的时候做了什么,我们会在下一篇博客里边仔细说明

    • 箭头函数中的this

    箭头函数可以理解成是是一个语法糖,他没有自己的this绑定,箭头函数中使用的this是包含他的那个函数的this

    比如说

        const obj = {
            a() {
                return () => {
                    console.log(this);
                };
            }
        }    
    

    上边这段代码被转译成es5 的时候如下

    const obj = {
        a: function a() {
            var _this = this;
            return function () {
                console.log(_this);
            };
        }
    };
    

    综合以上所有的代码,得出一个结论就是,在js中this的绑定正常来讲是指向调用这个方法的对象来确定的,当然还有一些不正常的方法,可以改变this的指向

    注意 ,下边介绍的几种方法,不能改变箭头函数的this指向,箭头函数本身是没有this绑定的,在介绍完不正常的情况后,再来说一说那些能够改变this指向的方法

    ECMAScript 5.1 规范的this指向

          js中this的绑定正常来讲是指向调用这个方法的对象来确定的  
    

    这句话在理论上是这么讲,在工作中正常的调用的话,这个理论是没有毛病的,在 ECMAScript 5.1 的规范里边规定,在js里边分为语言类型和规范类型

    • 语言类型

    ECMAScript 里边的语言类型规定的是我们可以直接操作的一些类型,比如string number,object等等这些

    • 规范类型

    规范类型ECMAScript 里边指的是一种抽象的规范,他们并不是让我们用来进行操作的,二是用来描述一些行为或者逻辑的,比如说typeof delete等等

    ECMAScript 5.1 里边的this规定大概讲就是这样的,每个对象里边有一个Reference 规范类型,this会根据Reference这个规范类型进行赋值

    ECMAScript 5.1

    规范奉上 Reference 这个东西大家简单的理解成是()前边的那一块就好了,上边我们讲的那些正常的就是说左边是

    • 函数定义表达式
    • 属性访问表达式
    • 对象创建表达式
    • 属性创建表达式

    这几种情况,在这几种情况的时候上边那句话是成立的

    但是如果不是这上边的那几句话的时候,比如说括号里边是一个和函数相关计算或者一个运算符等等

    这个时候this会指向undefined ,这个时候在非严格模式的情况下会被隐式转换成window对象

        var value = 1;
    
        var obj = {
          value: 2,
          a() {
            return this.value;
          }
        }
        
        console.log(obj.a());
        console.log((obj.a)());
        console.log((obj.a = obj.a)());
        console.log((false || obj.a)());
        console.log((obj.a, obj.a)());
    

    记得之前看到过这个一个例子,运行结果如图

    时间关系就说这些,下一篇博客会说new在运行时候过程和改变this指向的一些方法,
    以上是我对this指向的一些认识,有不足的地方希望之处

  • 相关阅读:
    给文章生成二维码
    用HTML5 Canvas做一个画图板
    失败多少次不要紧,人们只会记住你成功的那一次
    关于读大学的意义
    卸载Anaconda
    Anaconda基本命令
    plt.imshow()
    matplotlib不显示图片
    在Anaconda环境下使用Jupyter Notebook
    join()
  • 原文地址:https://www.cnblogs.com/netUserAdd/p/11149986.html
Copyright © 2020-2023  润新知