this关键字详解

关于this的绑定

默认绑定 this 默认 绑定到 windows

  1. 在全局环境中,this默认绑定到 windows
  2. 函数独立调用时,this默认绑定到 windows
  3. 被嵌套函数独立调用时, this 默认绑定到 windows
  4. IIFE 立即执行函数, 实际上是函数申明之后立即调用
  5. 闭包函数, 是独立调用,而不是方法调用。

        var a = true;
        function fun(){
            function test(){
                console.log(a)
            }
            return test;
        }
    
        var o = {
            a : false;
            fun : fun;
        }
    
        o.fun()(); // true

    由于闭包的this默认绑定到window对象,但又常常需要访问嵌套函数的this,所以常常在嵌套函数中使用var that = this,然后在闭包中使用that替代this,使用作用域查找的方法来找到嵌套函数的this值

        var a = true;
        function fun(){
            var that = this; //  用来记录 fun 的 this 
            function test(){
                console.log(that.a)
            }
            return test;
        }
    
        var o = {
            a : false;
            fun : fun;
        }
        o.fun()(); // false

隐式绑定

在方法调用时(被对象包含的函数,被对象直接调用时),this隐式的 绑定到该对象上。

```
    var a = 0;
    function fun(){
        console.log(this.a)
    }

    var o = {
        a : 1;
        fun : fun;
    }
    o.fun() // 1

```

当对象嵌套时,依然是直接对象

```
    var a = 0;
    function fun(){
        console.log(this.a)
    }
    var o1 = {
        a : 1;
        fun : fun;
        o2:{
            a : 2;
            fun : fun;
        }
    }
    // fun函数的直接对象o1
    o1.fun() // 1
    // fun函数的直接对象是O2 
    o1.o2.fun()  // 2
```

显示绑定

通过 call() ,bind() ,apply() 方法, 把对象绑定到this上。叫做显示绑定。

``` 
    var a = 1;
    functiont fun(){
        console.log(this.a)
    }
    var o = {
        a : 0;
    }
    fun()  // 1   独立调用
    fun.call(obj); // 0   
```

在javascript中新增了一些内置函数,具有显式绑定的功能,例如数组的迭代方法:map()、forEach()、filter()、some()、every()

```
     var a = 'windows';
    function fun(e){
        console.log(e,this.id)
    }
    var o = {
        a : 'o-object';
    }
    [1,2,3].forEach(fun) // 1 'windows'  2 'windows'  3 'windows'
    // 当我们指定了绑定对象,this 就会改变
    [1,2,3].forEach(fun,obj ) // 1 'o-object'  2 'o-object'  3 'o-object'
```

隐式丢失

指的是,隐式绑定的对象有时候会出现绑定对象的丢失,从而默认绑定到windows,主要是赋值操作。
  1. 函数别名
    var a = 0;
    function fun(){
        console.log(this.a)
    }
    var o = {
        a : 2;
        fun : fun;
    }
    // 在这里出现赋值操作,使得o.fun 有了新的别名bar 造成了隐私丢失。
    // 因为只是把fun函数赋给了foo,而foo与o对象则毫无关系。 
    var foo = o.fun;
  1. 参数传递
    常见的一个例子:
    var a = 0;
    function fun(){
        console.log(this.a);
    }
    var o = {
        a : 1;
        fun : fun;
    }
    // 其实 o.fun 在作为参数传递时候, 也是一个赋值操作。
    // 同样的道理 只是把fun函数赋给了setTimeout 的一个形参  ,而与o对象则毫无关系。
    setTimeout(o.fun,100) // 0
  1. 间接引用
    function fun(){
        console.log( this.a );
    }

    var a = 0;
    var o1 = {a : 1, fun : fun};
    var p2 = {a : 2};

    o1.fun() // 1 方法调用
    //将o1.fun函数赋值给o2.fun函数,然后立即执行。相当于仅仅是fun函数的立即执行
    (o2.fun = o1.fun)();//0
    // 注意上下两种的区别
    o2.fun = o1.fun;
    o2.fun() // 2

其实 在 javascript 内存角度上 O 和 o.fun 是存储在不同的地址上的。 只有o.fun() 才算是 从o 对象上去调用fun。否则,默认的是直接调用方法。因此绑定到了windows上。

    (o2.fun = o1.fun)();//0
    (false || 01.fun)();//0
    (1, o1.fun)();//0
  1. 实现一个改变不了的this的绑定
    利用显示绑定手段,可以是this不能被修改。就是将函数的调用封装起来 ,显示的绑定this对象。

        var a = 0;
        function fun(){
            console.log(this.a)
        }
        var o = {
            a : 2;
        }
    
        var foo = function(){
            fun.call(o) // 封装调用,显示绑定this对象
        }
    
        foo() // 0
        setTimeout(foo,100);//2
        foo.call(window);//2
上一篇:JavaScript对象 Object类型基础


下一篇:leetcode 646. 最长数对链 java