首发我的博客浏览器
JavaScript 中的this
,你们都用过。可是它到底指向哪里呢?今天在阅读 《你不知道的JavaScript (上卷)》再结合本身平时看的博客,对它又有了新的认识,在此来作个小结,再碰到this
,就不再用担忧不知道它指向哪里了。
如下示例(在浏览器端运行)app
function sayHi(){ var hi = 1; console.log(this.hi); } var hi = 2; var obj = { hi : 3, sayHi : sayHi } // output sayHi(); // 2 obj.sayHi(); // 3
从上述代码的执行结果咱们能够看出,直接调用 sayHi()
函数,它输出的 this.hi
不指向函数体内本身定义的 hi
变量,也就是说,this
的指向与词法做用域无关,这也是刚接触 JavaScript的同窗常犯的一个错误(包括我本身),认为 this.xx
就指向函数体里面定义的变量 xx
。sayHi
函数的只定义了一次,但obj.sayHi()
与 sayHi()
的输出结果不同,也偏偏证实了 函数体内this的指向与函数定义的位置无关,而与函数被调用的位置有关,至于为何输出结果不同,在下文会讲到。函数
默认绑定比较常见,表现形式就是在全局做用域中独立调用,如上文中的 sayHi()
,这种直接调用方式函数体内的 this
就应用了默认绑定规则,默认绑定有如下两种状况。oop
this
绑定到 undefined
this
指向全局对象 window
/***** 如下例子为处在严格模式下 *****/ function fn1(){ 'use strict' console.log(this); } fn1(); // undefined /***** 如下例子处于非严格模式下被调用 *****/ function fn2(){ console.log(this); } fn2(); // window function fn3(){ console.log(this); } /* * 这也是在非严格模式下被调用 * 由于在函数定义时没有用严格模式 */ 'use strict' fn3(); // window
隐式绑定的常见形式为 obj.fn()
,若obj
对象中有 fn
这个方法(fn能够在别处定义,但必须被添加到obj中做为obj的一个属性方法),那么 fn
中的 this
就指向 obj
对象,如最开始代码中 obj.sayHi()
输出3,就是由于sayHi
中的this
隐式绑定到obj
对象。(我的以为默认绑定中绑定到window对象时也能够归类为隐式绑定,由于在全局对象中,非严格模式且不考虑ES6的话,全部的全局变量都自动成为window的属性)。来看个具备迷惑性的例子(出自于原书)post
function foo() { console.log( this.a ); } var obj = { a: 2, foo: foo }; var bar = obj.foo; // 函数别名! var a = "oops, global"; // a 是全局对象的属性 bar(); // "oops, global"
这是个具备迷惑性的例子,obj
对象有函数 foo
这个方法,后面又在全局做用域中,bar
引用了这个方法,最后再调用 bar
。咱们只须要关注函数最后被调用的位置,它是在全局做用域中被单独调用的,因此仍是为默认绑定,指向 window
this
显示绑定就比较简单了,用 call,apply,bind方法,都会绑定函数中的this到传入的参数对象中code
所谓new绑定就是在用构造函数new一个对象的时候,其中的this指向生成的对象。这就完了嘛?尚未哦。对象
简单的说,箭头函数中的this,会绑定到函数外(也就是上一层做用域中的this),函数外的this指向哪,箭头函数中的this就指向哪。(代码出自于原书)blog
function foo() { // 返回一个箭头函数 return (a) => { //this 继承自 foo() console.log( this.a ); }; } var obj1 = { a:2 }; var obj2 = { a:3 }; var bar = foo.call( obj1 ); /* * foo先绑定this到obj1对象上,因此foo内的this指向obj1, * 返回的箭头函数根据词法做用域规则,继承了外部foo的this, * 因此箭头函数中的this指向obj1 */ bar.call( obj2 ); // 2, 不是 3 ! /* * 箭头函数中this一但绑定,不可更改 * 此时仍是指向obj1 * 因此输出的是 obj1.a => 2 */
new > 显示 > 隐式 > 默认继承
上述知识来自《你不知道的JavaScript(上卷)》