Blog A Paranoid Guy

JavaScript this关键字


说道 JavaScript 高大上的技巧,this 关键字莫过之一了,而且 this 的使用频率相当高。不同与 Javathis 的三种用法,JavaScriptthis 明确说只有一种用法,那就是 指向调用函数的对象 。下面分三种情况讨论:


作为对象方法调用

    var obj = {
        x: 0,
        foo: function(x) {
            this.x = x;
        }
    };
    obj.foo(10);
    console.log(obj.x); //10

这一种情况, this 绑定了调用函数的 obj 对象


作为函数调用

这种情况其实和第一种情况类似,请看:

    var x = 0;

    function foo(x) {
        this.x = x;
    } 
    foo(10);
    console.log(this.x); //10

这里的 this 指向了全局 window , 类比第一种情况,可以写成这样(假设可以):

    var window = {
        x: 0,
        foo: function(x) {
            this.x = x;
        }
    };
    window.foo(x);
    console.log(this.x); //10

呵呵~~看出个所以然了吧,这不就是把全局 window 当做 this 绑定的对象嘛!

还有一种特例就是,对象函数的内部函数会丢失当前对象 this 的引用,请看:

    var obj = {
        x: 0,
        foo: function(x) {
          var boo = function(x) {
            this.x = x;
          };
          boo(x);
        }
    };
    obj.foo(10);
    console.log(obj.x); //0
    console.log(this.x); //10

明显,boo 函数的 this 指向了全局 window , x 的值并没有因此改变。遇到这种情况,可以这样解决:

    var obj = {
        x: 0,
        foo: function(x) {
          var that = this; //保存当前this引用
          var boo = function(x) {
            that.x = x;
          };
          boo(x);
        }
  };
  obj.foo(10);
  console.log(obj.x); //10

这里用一个 that 变量保存了 this 引用,以致于 that 指向当前对象。


作为构造函数调用

    function Foo(x) {
        this.x = x;
    }
    var foo1 = new Foo(10);
    console.log(foo.x); //10

当构造函数被实例化时,this 自动指向实例化对象。

总结以上三种情况,都归结于一句话:this 指向调用函数的对象


apply() 和 call()

最后,说一下 JavaScritp 提供的改变 this 绑定的方法 apply()call() 。这两个方法都接收两个参数:要应用的对象和传入的参数,它们唯一的区别是 apply() 的参数传入一个数组,call() 只能一个一个的传入参数。知其一必知其二,下面我们拿 apply() 说事:

   var obj = {
     x: 10,
     y: 10
   };

   var foo = function() {
     return this.x - this.y;
   };
   
   console.log(foo.apply(obj)); //0

函数 Foo 绑定了对象 obj ,于是 this 指向 obj ,这是 apply() 最简单的用法。

apply() 还有一个很有用的用法,说明一下:

    var array = [1, 2, 3, 4, 5];
    
    console.log(Math.max.apply(null, array)); //5
    console.log(Math.min.apply(null, array)); //1

数组被传入 Math.max()Math.min() 方法中,第一个参数置空,表示没有对象调用。它们返回了数组的最大值和最小值


下一篇 Java IO流接口

Comments