JavaScript中如何确定this的指向?

版权声明:本文为博主原创文章,可以转载不可复制。 https://blog.csdn.net/qq_32331073/article/details/82899884


首先

  • JS中存在变量提升,实际上提升的是声明,而不是初始化
  • 不同于Java反射中method.invoke(obj),Java在运行时使用指令invokedynamic动态解析,与静态解析一样会判断obj对应的类是否持有method,否则会报出异常。而JavaScript中一个函数可以被独立执行,也可以绑定到任何对象上执行,这是因为:JS中函数被单独保存在内存中,然后再返回函数的地址,地址可以绑定到任何对象的属性上

严格模式

为了消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为,提高编译效率和运行速度,官方提出了严格模式,通过在代码前声明’use strict’来显式开启,而且它同时支持全局局部

  • 全局

     "use strict"
     myFunction();
    
  • 局部

     function myFunction() {
           "use strict";
            y = 3.14;   // 报错 (y 未定义)
    }
    

严格模式下有诸多限制,对于this指向我们只需要关心这几个特性:

  • 非严格模式下,全局对象为node:global、browser:window,严格模式下,全局对象为undefined
  • 严格模式下,不能使用未声明的变量(并不影响变量提升);
  • delete 操作不能删除全局变量(包括对象和函数)(是因为全局对象为undefined)

this关键字

JS中的this关键字行为,与其他语言有所不同,且自身在严格模式(use strict)非严格模式下也有差别。

全局上下文(函数外)
  • 无论是否为严格模式,均指向全局对象。注意:严格模式下全局对象为undifined
函数上下文(函数内)
  • 默认的,指向函数的调用对象,且是最直接的调用对象:

    • 简单调用,指向全局对象注意:严格模式下全局对象为undifined,某些浏览器未实现此标准也可能会是window
      • 简单调用一
        var o = {
         	prop: 37,
         	f: function() {
              return this.prop;
         	}
        };
        var f = o.f;
        console.log(f()); // 37
        
      • 简单调用二
         function func(){
           return this;
         }
         console.log(func()); // 37
        
      • 简单调用三
        var o = {
         prop: 37,
         f: function() {
            return func();
         }
        };
        function func(){
          return this;
        }
        console.log(o.f()); // 37
        
    • 作为对象本身属性调用;
    • 将函数作为属性传递给新对象,调用;
    • 原型链继承函数调用;
    • Getter、Setter调用;
  • Function.prototype.call(this,...args)Function.prototype.apply(this,[arg0,arg1...])指定调用对象;

  • Function.prototype.bind(this,...args)绑定,bind()方法创建一个新函数,生成的新函数忽略之后所有的bind(),并且this被bind方法的第一个参数永久绑定,之后不管它如何被调用都不会发生改变

  • 箭头函数,没有自己的this绑定,它将会保留封闭词汇上下文中的this值,在箭头函数创建时被设置,且之后无论是:

    • 将函数作为属性传递给新对象,调用、
    • callapply直接指定调用对象、
    • 还是bind

    都不会改变this,(注意:call, bind, or apply,仍然能够传递调用参数,可以把第一个参数设置为null);

  • 将函数作为构造方法(使用new关键字),this指向正在构造的新对象。注意:默认情况下构造方法返回this,但是可以通过return返回值来修改,不过,如果返回值不是对象(e.g 1,“test”),那么仍将返回this;

  • 作为Dom事件处理函数,this指向触发事件的Dom元素对象:

    document.querySelector("#id").addEventListener("click",function(){ alert(this); }); //HTTPElement
    document.querySelector("#id").onclick = function(){  alert(this); }; //HTTPElement
    
  • 作为行内on-event处理函数,this指向所在Dom元素对象,事实上这个this事件对象event一样,是直接将确定的值,传递到JavaScript脚本中:

    <button onclick="alert(this.tagName.toLowerCase());">
       Show this
    </button>
    <button onclick="document.getElementById('demo').innerHTML=this;">
       Show this
    </button>
    
  • 特殊的,当函数在另一个函数中调用的时候,同样遵守上述所有规则。
    如下所有情况,最终都是简单调用,指向全局对象,严格模式下全局对象为undefined

    document.querySelector("#id").addEventListener("click",function(){ alert(test()); }); //[object Window]
    function test(){ 
       return this
    }
    
    <button onclick="alert(test());">
     Show this
    </button>
    <button onclick="alert((function() { return this; })());">
     Show this
    </button>
    

猜你喜欢

转载自blog.csdn.net/qq_32331073/article/details/82899884