在Javascript中 This 指向 和 闭包是绕不开的问题, 今天我们来谈一下关于This
主要是根据看《JavaScript 语言精粹》 和《you don't konw Js》 以及 一些博客文章 而总结的···
在《JavaScript 语言精粹》中说到,this 取决于调用的模式,它指向什么完全取决于函数在哪里被调用, 在JavaScript 中共有四种模式
1、方法调用模式 (隐式绑定)
当时函数被作为一个对象的属性时,我们称它为一个方法,当时这个方法被调用时,this 被绑定到该对象。
1 var myObject = { 2 value :0, 3 increment:function(inc) { 4 this.value += typeof inc === 'number' ? inc :1; 5 } 6 } 7 8 myObject.increment(); 9 console.log(myObjec.value); // 1 10 11 myObject .increment(3); 12 console.log(myObjec.value); //4
对象属性引用链只有上一层或者说最后一层在调用位置上起作用
1 function foo() { 2 console.log(this.a); 3 } 4 5 var obj2 = { 6 a: 42, 7 foo:foo 8 }; 9 10 var obj1 = { 11 a: 2, 12 obj2: obj2 13 }; 14 15 obj1.obj2.foo(); //42
2、函数调用模式(默认绑定)
当函数不是对象属性时,它就是被当做一个函数来调用的···
在此模式下,this 绑定到全局对象即window上,如果在方法内部调用一个函数,此内部函数仍然符合此种模式···《语言精粹》里面认为这是一个bug,因为不能直接共享该方法对对象的访问权。不过也能容易解决这个问题,可以定义一个变量that 赋值为this. 在严格模式下,不能将全局对象用于默认绑定,this会绑定到undefined···
1 //增加一个double方法 2 myObject.double = function() { 3 var that = this; 4 var helper = function() { 5 that.value = add(that.value,that.value); 6 } 7 helper(); 8 } 9 10 myObject.double(); 11 console.log(myObject.value); //6
此时对象中value=3,所以最终结果为6.
3、 构造器调用模式
如果在一个函数前面带上new 来调用,背地里会创建一个连接到该函数的prototype 成员的新对象,同时this 会绑定到那个新对象上。
1 //增加一个double方法 2 myObject.double = function() { 3 var that = this; 4 var helper = function() { 5 that.value = add(that.value,that.value); 6 } 7 helper(); 8 } 9 10 myObject.double(); 11 console.log(myObject.value); 12 13 var Quo = function(str) { 14 this.str = str; 15 } 16 17 Quo.prototype.get_status = function() { 18 return this.status; 19 } 20 21 var quo = new Quo("park"); 22 conlose.log(que.get_status()); //park
如果构造函数中有返回值且为一个对象,则this 会绑定到该对象上···如果返回为普通类型的值,则无影响··
四、Apply 调用模式 (显示绑定)
函数也可以拥有方法,apply方法让我们构造一个函数数组传给调用函数,第1个是要绑定给this 的值,第2个是参数数组。
1 var statusObject = { 2 status:'A-OK'; 3 }; 4 5 var status = Quo.prototype.get_status.apply(statusObject); //'A-OK'
statusObject 和 Quo 没有什么直接关系,但是可以利用apply调用它没有的 get_status方法,因为此时 this 已经绑定到 statusObject 上了。