浅谈this指向

举报
北极光之夜。 发表于 2021/09/30 14:51:23 2021/09/30
【摘要】 总的来说,this的指向不是在函数声明时确定的,而是在调用执行时确定的,同时,this不同的指向在于遵循了一定的规则。

一.js中的特殊对象:

  首先先看以下js中有哪些特殊的对象:

1.this对象:

  本文要说的对象,比较特殊,使用环境不同,它的指向也不同。

2. window对象:

  Window 对象表示浏览器中打开的窗口。

  在客户端浏览器中,window 对象是访问 BOM 的接口,如引用 document 对象的 document 属性,引用自身的 window 和 self 属性等。同时 window 也为客户端 JavaScript 提供全局作用域。

  Window 对象表示一个浏览器窗口或一个框架。在客户端 JavaScript 中,Window对象是全局对象,所有的表达式都在当前的环境中计算。也就是说,要引用当前窗口根本不需要特殊的语法,可以把那个窗口的属性作为全局变量来使用。例如,可以只写 document,而不必写 window.document。

3.arguments对象:

  arguments 是一个对应于传递给函数的参数的类数组对象。

  arguments对象是所有(非箭头)函数中都可用的局部变量。你可以使用arguments对象在函数中引用函数的参数。

二.this指向问题:

1. 事件函数:

  event handlers(事件处理函数),响应于某个事件而调用的函数。像那种点击事件,键盘事件。此时this指向这个事件元素本身

  如,有一个按钮点击事件:

<body>
    <button id="btn"></button>
    <script>
        var btn = document.querySelector('#btn');
        //点击事件
        btn.addEventListener('click',function(){
            console.log(this);
            console.log(btn);
            console.log(this === btn);
        })
        
    </script>
</body>

   我们看输出,this与btn对应什么,与它们是否相等:

在这里插入图片描述
可以看出此时this指向这个事件元素本身。

2. 全局函数:

全局对象中,this默认指向全局

如:

 <script>
        function night(){
            console.log(this);
            console.log(this===window);
        }
        // 你看,它此时是被 window 引用的。
        night();
    </script>

运行结果可以看出它是指向全局的:

在这里插入图片描述
   当然,这只是默认情况下,如果它是被一个具名函数引用,则指向引用它的本身

如:

<button id="btn"></button>
<script>
        var btn = document.querySelector('#btn');
        function night(){
            console.log(this);
            console.log(this===window);
        }
        // 此时它被这个按钮引用
        btn.onclick = night;
    </script>

可以看出此时这个this指向的是btn这个按钮:

在这里插入图片描述

3.对象:

   哪个对象调用了函数,该函数里面的this就指向谁

 <script>
        function night(){
            return this;
        }
        // 建一个对象
        var obj = {};
        //给对象设置一个属性printThis,调用night这个函数
        obj.printThis = night;        
    </script>

   可以看出 night 函数中 this 指向 obj 这个对象 :
在这里插入图片描述

4.构造函数:

   构造函数中的 this, 指向了由构造函数实例化的对象。

 <script>
        //定义一个构造函数
     function People(name,age){
         this.name = name;
         this.age = age;
         this.say = function(){
             return "Hello world !"
         }
         this.printThis = function(){
         //返回 this
             return this;
         }
     }
      // 实例化
      var people = new People('小明',21);
    </script>

this指向了实例化的people对象。

在这里插入图片描述

5.apply和call方法:

   call() 方法与apply()方法非常相似,这两个方法都是用来改变对象的引用,能够编写用于不同对象的方法。不同之处在于传递的参数不同,参数中,第一个都是要改变的引用对象,其它多个参数一个是使用逗号分隔参数的参数列表,另一个是使用一个包含多个参数的数组。当然如果不需要传参数就不用了。

  先看一般情况,obj2.printThis()里的 this 肯定是指向它自己里的name ‘joy’

 <script>
      var obj = {
          name: 'sam'
      }
      var obj2 = {
          name:'joy',
          printThis: function(){
              return this.name;
          }
      }
      console.log(obj2.printThis());
    </script>

输出结果:

在这里插入图片描述
   通过apply方法改变obj2对象下的printThis函数的调用,this的指向改变为obj:

 <script>
      var obj = {
          name: 'sam'
      }
      var obj2 = {
          name:'joy',
          printThis: function(){
              return this.name;
          }
      }
      // 通过apply方法改变obj2对象下的printThis函数的调用,this的指向改变
      console.log(obj2.printThis.apply(obj));
    </script>

结果:

在这里插入图片描述

6.箭头函数:

   箭头函数this是静态的,this始终指向函数声明时所在作用域下的this值

  //全局 
      window.name = 'night';
      //对象里的
      var peopel = {
          name:'sky'
      }
      //普通函数
      function getName1(){
          console.log(this.name);
      }
      //箭头函数
      let getName2 = ()=>{
          console.log(this.name);
      }
      //分别调用
      getName1.call(peopel);
      getName2.call(peopel);

运行结果:
在这里插入图片描述

  因为call()方法,看出getName1的this指向已经变了,不再是全局的name,而是people对象里的name,而箭头函数getName2没变,因为它始终指向函数声明时所在作用域下的this值。

三.总结:

  总的来说,this的指向不是在函数声明时确定的,而是在调用执行时确定的,同时,this不同的指向在于遵循了一定的规则。

1.默认情况下,指向全局,浏览器的话就是指向window。

2.如果函数被调用的位置存在上下文,那么函数被隐式绑定。

3.如果存在构造函数,this指向new 的这个新对象。

4.箭头函数的是没有属于自己的this的,它会继承父作用域的this,所以它是在声明时确定的。同时,它不可以new,也没有arguments,也不能用call、bind改变。

5.call,apply能改变this的指向。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。