结论:
一 :在一个函数上下文中,this由调用者提供,由调用函数的方式来决定。若是调用者函数,被某一个对象所拥有,那么该函数在调用时,内部的this指向该对象。若是函数独立调用,那么该函数内部的this,则指向undefined。可是在非严格模式中,当this指向undefined时,它会被自动指向全局对象。面试
从结论中咱们能够看出,想要准确肯定this指向,找到函数的调用者以及区分他是不是独立调用就变得十分关键。segmentfault
// demo01 var a = 20; function fn() { console.log(this.a); } fn(); //fn()是调用者,为独立调用,非严格模式下指向所有对象window,所以结果为20
// demo02 var a = 20; function fn() { function foo() { console.log(this.a); } foo(); } fn(); //fn()是调用者,为独立调用,非严格模式下指向所有对象window,所以结果为20
// demo03 var a = 20; var obj = { a: 10, c: this.a + 20, fn: function () { return this.a; } } console.log(obj.c); // 对象obj中的c属性使用`this.a + 20`来计算。这里咱们须要明确的一点是,单独的`{}`是不会造成新的做用域的,所以这里的`this.a`,因为并无做用域的限制,因此它仍然处于全局做用域之中。因此这里的this实际上是指向的window对象,所以结果为40。 console.log(obj.fn()); //fn()是调用者,他不是独立调用,被对象obj所调用,所以它的this指向指向obj所以结果为10
再来看一些容易理解错误的例子,加深一下对调用者与是否独立运行的理解。app
var a = 20; var foo = { a: 10, getA: function () { return this.a; } } console.log(foo.getA()); // 10 var test = foo.getA; console.log(test()); // 20
foo.getA()
中,getA是调用者,他不是独立调用,被对象foo所拥有,所以它的this指向了foo。而test()
做为调用者,尽管他与foo.getA的引用相同,可是它是独立调用的,所以this指向undefined,在非严格模式,自动转向全局window。函数
稍微修改一下代码,你们自行理解。this
var a = 20; function getA() { return this.a; } var foo = { a: 10, getA: getA } console.log(foo.getA()); // 10
灵机一动,再来一个。以下例子。code
function foo() { console.log(this.a) } function active(fn) { fn(); // 真实调用者,为独立调用 } var a = 20; var obj = { a: 10,~~~~ getA: foo } active(obj.getA); // 20
JavaScript内部提供了一种机制,让咱们能够自行手动设置this的指向。它们就是call与apply。全部的函数都具备着两个方法。它们除了参数略有不一样,其功能彻底同样。它们的第一个参数都为this将要指向的对象。对象
以下例子所示。fn并不是属于对象obj的方法,可是经过call,咱们将fn内部的this绑定为obj,所以就可使用this.a访问obj的a属性了。这就是call/apply的用法。继承
function fn() { console.log(this.a); } var obj = { a: 20 } fn.call(obj); //结果为20
箭头函数中,没有this。若是你在箭头函数中使用了this,那么该this必定就是外层的this。也正是由于箭头函数中没有this,所以咱们也就无从谈起用call/apply/bind来改变this指向。
在ES6中,会默认采用严格模式,所以this也不会自动指向window对象了,而箭头函数自己并无this,所以this就只能是undefined,这一点,在使用的时候,必定要慎重慎重再慎重,否则踩了坑你都不知道本身错在哪!这种状况,若是你还想用this,就不要用使用箭头函数的写法。ip
箭头函数 this指向是在定义的时候处在的对象就是它的this。箭头函数的this看外层的是否有函数,若是有,外层函数的this就是内部箭头函数的this,若是没有,则this是window。作用域
var a = 10; var obj = { a:99, fn1: () => { console.log(this.a)}, fn2:function () { console.log(this.a)} } obj.fn1(); //10 obj.fn2(); //99
let btn1 = document.getElementById('btn1'); let obj = { name: 'kobe', age: 39, getName: function () { btn1.onclick = () => { console.log(this);//obj }; } }; obj.getName();
上例中,因为箭头函数不会建立本身的this,它只会从本身的做用域链的上一层继承this。
那假如上一层并不存在函数,this指向又是谁?
let btn2 = document.getElementById('btn2'); let obj = { name: 'kobe', age: 39, getName: () => { btn2.onclick = () => { console.log(this);//window }; } }; obj.getName();
上例中,虽然存在两个箭头函数,其实this取决于最外层的箭头函数,因为obj是个对象而非函数,因此this指向为Window对象
参考文章:
全方位解读this
你还没搞懂this
// 修改$对象里面的代码,使得如下代码运行正常 var $ = { fn:function () { console.log(1); }, fn2:function () { console.log(2); } } $.fn().fn2(); // 答案: var $ = { fn:function () { console.log(1); return this; // 返回this,能够继续调用函数 }, fn2:function () { console.log(2); } } $.fn().fn2();