this的应用场景

上下文环境

在了解this应用场景之前需要了解什么是上下文环境.可以阅读该文章this和执行上下文环境的理解
关于this的应用场景可以看这里,因为这个知识点的篇幅非常的长,参考至this的应用场景总结

如图1所示:this探讨,关于this,首先需要知道函数中的this只有在调用后才能知道它的值是怎么样的,而不是常识般认为this指向对象本身,或者指向对象的作用域.因为函数调用时会生成一个新的执行上下文环境. 里面会涉及到LSH可以参考此文章LSH查询

 <script>
     var n = 'hello world !';
     function example() {
         this.n = 0;
     }
     let vm = example()
     console.log(n); 
     // -> 结果为 0
 </script>
图1:this探讨

这是必考对面试知识点,在看到这类题,需要做对事情就是预解析放在第一步,然后再去执行操作.

this的决定因素

实际中,this是 上下文执行环境中的一个属性,this的指向也不是如常识一般指向谁,而是依据调用栈和执行位置决定的(或者说执行环境),并且 this 是在运行时绑定的,并不是在编写时绑定.所以this指向什么完全取决于函数在哪里被调用. 为了更好理解看图2所示:

    <script>
        // 书中的一段话.
        function foo() {
            var a = 2;
            this.bar();
        }
        function bar() {console.log(this.a);}
        foo(); // undefined

        /*
        预解析
        function foo(){
            this.bar;
            var a;
            a = 2;
            this.bar();
        }
        ... 
        foo()

        1. 对foo函数进行声明提升,执行foo
        2. 对a和bar进行变量提升,bar在前a在后,因为bar是函数,调入栈中,在队列中第一执行
        3. 搜索引擎通过LSH查询,找到a,a=2进行赋值操作.
        4. this指向谁,根据调用栈: 全局 -> foo();调用位置是: 全局, 判断,此时this指向全局,调用bar()
        5. 执行bar(),依据调用栈: 全局 -> bar(), 调用位置:全局,判断,此时this指向全局.
           执行this.a 引擎通过LSH查询
           在宽松模式下,全局环境没有找到a变量,所以会创建一个a,而a没有值. 此时undefined
           (严格模式下,全局执行环境不会创建a变量,所以会抛出错误)
        6. 执行console.log(),因为this执行环境中a没有赋值,所以undefined.
        7. 那么思考,a在哪里呢,a在foo()的作用域中,而此时bar调用a明显跨域,依据闭包原理,bar是访问不到foo内部的a,
           如果要访问a,则需要显示传入参数,调用a的作用域.
        */
    </script>
图2:this的决定因素

因为在该this和执行上下文环境的理解文章中有说到判断this. 所以这边就添加过来.

注意:书写函数时,应尽量书写具名函数,以方便需要用到自身的时候进行回调,如果是匿名函数,则会因为没有指向函数对象的词法标识符,而无法 找到自身,从而无法调用

this指向是可以通过固定this来修复的,这里称为显示绑定/硬绑定, 例如call,apply,bind,new, 然后说在他们的优先级以及显示绑定后的this指向.

判断this

根据优先级来判断函数在某个调用位置应用的是哪条规则,按照下面顺序进行,如图3所示:判断this

1. 函数是否在new中调用(new绑定)? 如果是的话,this绑定的是新创建的对象
   var bar = new foo()
2. 函数是否通过call,apply(显式绑定)或硬绑定调用? 如果是,this绑定是指定的对象.
   var bar = foo.call(obj2)
3. 函数是否在某个上下文对象中调用(隐式绑定)? 如果是,this绑定的是那个上下文对象.
   var bar = obj1.foo()
4. 如果不是的话,使用默认绑定,如果在严格模式下,就绑定到undefined,否则全局对象.
   var bar = foo()
就是这样. 对于正常的函数调用来说,理解了这些就明白this的绑定原理.
图3:判断this

但也有例外, 这个例外以后再补充,也是在该文章.

this的应用场景

普通函数或全局函数调用

如图4所示: 普通函数或全局函数调用后的this

 <script>
      var n = 'hello world'
      function example(){
          this.n = 0;
      }
      example() // 因为调用后this指向全局,所以n重新将n赋值为0
      console.log(n);
      // -> 0
  </script>
图4:普通函数或全局函数调用后的this

严格模式下,未指定环境对象而调用函数,this的值是undefined。

构造函数调用

如果直接调用构造函数,那么效果和图4一样,但是使用new关键字,此时this会指向该新对象. 如图5所示:构造函数new调用this变化

  <script>
      function Foo(){
          this.x = 10;
          console.log(this); 
          // -> Foo {x: 10}
      }
      var foo = new Foo()
      console.log(foo.x); 
      // -> 10
  </script>
图4:构造函数new调用this变化

作为对象的方法调用

如图5所示, this作为对象方法调用可以看到,this指向该对象.

 <script>
     var obj = {
         x : 10,
         foo:function(){
             console.log(this);
             // -> {x: 10, foo: ƒ}
             console.log(this.x);
             // -> 10
         }
     }
     obj.foo()
 </script>
图5: this作为对象方法调用

如果this不作为对象的方法调用,结果会是window,如图6所示.

<script>
    var obj = {
        x : 10,
        foo:function(){
            console.log(this);
            // -> {x: 10, foo: ƒ}
            console.log(this.x);
            // -> 10
        }
    }
    let fn = obj.foo
    fn()
    // -> Window
</script>
图6: this不作为对象的方法调用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值