zoukankan      html  css  js  c++  java
  • 深入js——this

    this

    this是与执行上下文绑定的,每个执行上下文都有一个this;执行上下文有3种:全局执行上下文、函数执行上下文和eval执行上下文,因此this也有3种,全局执行上下文中的this、函数执行上下文中的this和eval执行上下文中的this。eval我们很少使用,因此这里我们只讨论全局执行上下文中的this、函数执行上下文中的this。

    全局执行上下文的this

    在全局执行上下文中,this指向全局对象,因此在浏览器环境中,this执行window。

    函数执行上下文的this

    函数执行上下文的this有些复杂,主要是因为它与作用域不同,不是静态绑定到一个函数的,而是与函数如何被调用有关,也就是说一个函数每次的this可能不一样。

    这里尤其要记住,不要混淆作用域和this,这两者可以说没有任何关系,作用域是在函数定义时就确定的,而this是在函数调用时确定的。

    JavaScript中共有以下4种函数调用方式:

    • 对象调用方法方式;
    • 函数调用方式;
    • apply/call方式;
    • 构造函数方式;

    对象调用方法方式

    当一个函数被保存为对象的一个属性时,我们称此函数为方法。使用对象来调用其内部的一个方法,该方法的 this 是指向对象本身的

    var obj ={
      value:3,
      dosth:function(){
        return this.value;//通过obj.do()调用时,this指向obj
      }
    }
    console.log(obj.dosth());//3
    

    函数调用方式

    当一个函数并非一个对象的属性时,那么它就是被当做一个函数来调用的。此时,相当于再全局环境中调用此函数,this指向全局对象

    var dosth = function(){
      return this.value;
    }
    console.log(dosth());//undefined
    var value= 2;
    console.log(dosth());//2
    

    通过call/apply方式

    apply/call是最直观的可以看出this指向的调用模式,在apply/call中指定的第一个参数就是要绑定给this的值

    var value = 2;
    var obj ={value:3}
    obj.double = function(){
      var helper = function(){
        this.value = this.value*2;
      }
     helper.call(obj);//改变调用方式
    }
    obj.double();
    console.log("obj的value值为:"+obj.value+",window的value值为:"+value);//obj的value值为:6,window的value值为:2
    

    不过要注意,在非严格模式下,当第一个参数为null或undefined时,this将指向window。

    构造函数方式

    当一个函数采用new操作符调用时,它就成为构造函数。也就是说,构造函数只是普通函数,只是在new的那一刻,其被成为构造函数。通过new操作符调用一个函数时,new操作符背后干了4件事:

    • 创建一个空对象obj
    • 将obj的原型指向构造函数(这样obj就可以访问到构造函数原型中的属性)
    • 使用call,改变构造函数this的指向到obj,并执行构造函数代码(这样obj就可以访问到构造函数中的属性)
    • 返回新对象

    因此,构造函数中的this就是新对象本身

    嵌套函数中的this不会从外层函数中继承

    这可以算是一个JavaScript的设计问题,也就是当采用上文提到的第2种调用方式——函数调用方式时,this始终指向window,这会导致内部函数调用时this无法指向外部函数的this(很多情况下我们是希望指向外部函数的this)。

    var obj ={value:3}
    obj.double = function(){
      var helper = function(){
        this.value = this.value*2;
      }
      helper();
    }
    obj.double();
    console.log("obj的value值为:"+obj.value+",window的value值为:"+value);//obj的value值为:3,window的value值为:4
    

    可以发现,执行了obj.double()后,obj.value值并没有变化,而全局变量value的值*2了。因为helper虽然在obj.double内部,但其采用函数模式调用时,this指向的是window而不是obj。解决这个问题也很简单:

    • 方案一:将this赋值给其他变量保存
    var value = 2;
    var obj ={value:3}
    obj.double = function(){
      var that = this;//将this赋值给that
      var helper = function(){
        that.value = that.value*2;
      }
      helper();
    }
    obj.double();
    console.log("obj的value值为:"+obj.value+",window的value值为:"+value);//obj的value值为:6,window的value值为:2
    

    此方法采用一个变量that来保存this,这样helper函数里使用that时其实就与this无关了,就是在使用一个普通的变量。其实,这个方法的的本质是把 this 体系转换为了作用域的体系

    • 方案二:es6的箭头函数
    var value = 2;
    var obj ={value:3}
    obj.double = function(){
      var helper = () => {
        this.value = this.value*2;
      }
      helper();
    }
    obj.double();
    console.log("obj的value值为:"+obj.value+",window的value值为:"+value);//obj的value值为:6,window的value值为:2
    

    ES6中的箭头函数并不会创建其自身的执行上下文,所以箭头函数中的this取决于它的外部函数

  • 相关阅读:
    c# 图片保存为流Stream,再次加载时提示System.ArgumentOutOfRangeException: 要求非负数的解决办法
    VS 2019 Git failed with a fatal error的解决办法
    IIS安全狗卸载后,IIS8.5,网站无法访问的解决方法
    sqlserver 全文检索提高精确度的一个方法
    Win10应用商店打不开的解决办法
    Dapper解析嵌套的多层实体类
    Aspose.Words转换为PDF的时候字体丢失的问题解决
    IIS ASP.NET MVC 上传文件到NAS目录
    windows xp .net framework 4.0 HttpWebRequest 报The underlying connection was closed,基础连接已关闭
    c# 计算中文字节数与JAVA不符的解决方法
  • 原文地址:https://www.cnblogs.com/youhong/p/12213865.html
Copyright © 2011-2022 走看看