this是什么
—大多语言中,’this’代表由类实例化的当前对象。在JavaScript中,’this’通常表示’拥有’方法的对象,但具体取决于一个函数被调用的方式。方法调用模式
当一个函数被保存为对象的一个属性并调用该方法时,this被绑定至该对象。即使用”obj.method”形式
1 2 3 4 5 6 7 8 | var val = "outer"; var methodCall = { val: "inner", printVal: function(){ console.log(this.val); } } methodCall.printVal(); //"inner" |
构造器调用模式
类似面向对象语言中对象的概念,使用new后,this被绑定至该实例。
1 2 3 4 5 6 7 8 9 10 11 | var val = "outer"; function methodCall(){ this.val = "inner"; } methodCall.prototype = { printVal: function(){ console.log(this.val); } } var a = new methodCall(); a.printVal(); //"inner" |
函数调用模式
函数未作为对象的属性时,其当作一个正常函数来调用,此时this被绑定至全局对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | var val = "outer"; function methodCall(){ this.val = "inner"; } methodCall.prototype = { printVal: function(){ var that = this; var innerPrintVal = function(){ console.log(that.val); console.log(this.val) } innerPrintVal(); } } var a = new methodCall(); a.printVal(); |
打印结果为
1 2 | inner outer |
- a.printVal调用printVal的方式为构造器调用模式,这时的this被绑定到a的作用域。将其赋给that,此时that就代表了a的作用域。
- a.printVal调用innerPrintVal的方式为函数调用模式,这时的this被绑定到全局作用域。
注意,在a.printVal中,this是被绑定在a的作用域上的。但是在调用innerPrintVal时,this在该函数中被再一次绑定到全局作用域了。因此在innerPrintVal中调用console.log(this.val)打印的结果为”outer”
apply/call模式
手动指定this的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | var val = "outer"; function printVal(){ console.log(this.val); } function methodCall(){ this.val = "inner"; } methodCall.prototype = { printVal: function(){ console.log(this.val); } } var a = new methodCall(); a.printVal(); //"inner" a.printVal.call(a); //"inner" printVal.call(a); //"inner" printVal(); //"outer" printVal.apply(window); //"outer" a.printVal.apply(window); //"outer" |
输出结果为:
1 2 3 4 5 6 | inner inner inner outer outer outer |
可以看出,无论是采用构造器调用模式的a.printVal或是采用函数调用模式的printVal,this均会被apply/call绑定为手动指定的值