zoukankan      html  css  js  c++  java
  • Javasript中this指向问题和改变this指向的方法

    在学习javascript中我们往往会被this的指向问题弄的头昏转向,今天我们就来学习一下this的指向问题,和改变this指向的方法。

    一.this的指向问题

    在学习this的指向问题之前我们需要明白两点:

    1:this永远指向一个对象;
    
    2:this的指向完全取决于函数调用的位置;

    针对上面第一点我们能很好理解,因为在javascript中一切都是对象。第二点其实也是好理解,当函数调用的位置不同是,this的指向的对象就不同,所以可以说this的指向可以动态变换的,下面我们先通过一个简单的例子来看一下this的指向是变换的

    <script>
    function fun(){
         console.log(this.name);
    
     }
     var change={
         name:'hello',
         f:fun
     }
     var name ='world'
     var result=change.f()//hello
     fun();//world
    </script>

    通过上述例子我们可以很清楚的看到this的指向的变化,因为有一个函数在对象change里面,所以this就是指向的函数外部的对象,所以输出了hello。

    想必看完上述例子后大家对this的动态指向切换有了一定的了解。

    那么接下来,我们对this使用最频繁的几种情况做一个总结,最常见的基本就是以下3种:

    对象中的方法,事件绑定 ,构造函数 ,定时器

    前两个就不必多说了,我们看一下定时器中的this指向问题,

    var obj = {
        fun:function(){
            this ;
        }
    }
    ​
    setInterval(obj.fun,1000);      // this指向window对象
    setInterval('obj.fun()',1000);  // this指向obj对象

    setInterval() 是window对象下内置的一个方法,接受两个参数,第一个参数允许是一个函数或者是一段可执行的 JS 代码,第二个参数则是执行前面函数或者代码的时间间隔;

    在上面的代码中,setInterval(obj.fun,1000) 的第一个参数是obj对象的fun ,因为 JS 中函数可以被当做值来做引用传递,实际就是将这个函数的地址当做参数传递给了 setInterval 方法,换句话说就是 setInterval 的第一参数接受了一个函数,那么此时1000毫秒后,函数的运行就已经是在window对象下了,也就是函数的调用者已经变成了window对象,所以其中的this则指向的全局window对象;

    而在 setInterval('obj.fun()',1000) 中的第一个参数,实际则是传入的一段可执行的 JS 代码;1000毫秒后当 JS 引擎来执行这段代码时,则是通过 obj 对象来找到 fun 函数并调用执行,那么函数的运行环境依然在 对象 obj 内,所以函数内部的this也就指向了 obj 对象;

    除了这些我们还需要理解三个可以改变this指向的函数,包括箭头函数,call(),apply()

    箭头函数:官方有解释,箭头函数引入的其中一个原因,就是其不绑定this;在箭头函数中,箭头函数的this被设置为封闭的词法环境的,换句话说,箭头函数中的this取决于该函数被创建时的环境。

    var globalObject = this;
    var foo = (() => this);
    console.log(foo() === globalObject); // true

    // 接着上面的代码
    // 作为对象的一个方法调用
    var obj = {foo: foo};
    console.log(obj.foo() === globalObject); // true
    
    // 尝试使用call来设定this
    console.log(foo.call(obj) === globalObject); // true
    
    // 尝试使用bind来设定this
    foo = foo.bind(obj);
    console.log(foo() === globalObject); // true

    无论如何,foo 的 this 被设置为他被创建时的环境(在上面的例子中,就是全局对象)。这同样适用于在其他函数内创建的箭头函数:这些箭头函数的this被设置为封闭的词法环境的。

    // 创建一个含有bar方法的obj对象,
    // bar返回一个函数,
    // 这个函数返回this,
    // 这个返回的函数是以箭头函数创建的,
    // 所以它的this被永久绑定到了它外层函数的this。
    // bar的值可以在调用中设置,这反过来又设置了返回函数的值。
    var obj = {
      bar: function() {
        var x = (() => this);
        return x;
      }
    };
    
    // 作为obj对象的一个方法来调用bar,把它的this绑定到obj。
    // 将返回的函数的引用赋值给fn。
    var fn = obj.bar();
    
    // 直接调用fn而不设置this,
    // 通常(即不使用箭头函数的情况)默认为全局对象
    // 若在严格模式则为undefined
    console.log(fn() === obj); // true
    
    // 但是注意,如果你只是引用obj的方法,
    // 而没有调用它
    var fn2 = obj.bar;
    // 那么调用箭头函数后,this指向window,因为它从 bar 继承了this。
    console.log(fn2()() == window); // true
    call和apply方法:将一个对象作为call或者apply的第一个参数,this将会被绑定到这个参数对象上
    var obj = {parent:'男'};
    var parent = '28';
    function child(obj){
        console.log(this.parent);
    }
    child(); // 28  
    child.call(obj); //
    child.apply(obj); //
  • 相关阅读:
    android实现点击短链接进入应用 并获得整个连接的内容
    机房收费系统=三层+设计模式
    【数据库】SQL优化方法汇总
    HBase 数据库检索性能优化策略--转
    How to fix “HTTP Status Code 505 – HTTP Version Not Supported” error?--转
    使用VBS控制声音
    MSG命令使用详解
    bat删除系统默认共享
    C#:消息队列应用程序
    读写XML文档时,去掉新增加节点的“空命名空间”(xmlns=””)
  • 原文地址:https://www.cnblogs.com/meteorll/p/13950876.html
Copyright © 2011-2022 走看看