当前执行上下文(global、function 或 eval)的一个属性,在非严格模式下,总是指向一个对象,在严格模式下可以是任意值。
分类讨论
全局上下文
无论是否在严格模式下,在全局执行环境中(在任何函数体外部)this 都指向全局对象。
// 在浏览器中, window 对象同时也是全局对象:console.log(this === window); // true// 仅仅只有赋值操作,标识符会隐式绑定到全局对象a = 37;console.log(window.a); // 37console.log(a); // 37this.b = "MDN";console.log(window.b) // "MDN"console.log(b) // "MDN"//通过声明绑定到变量对象,但在全局环境中,变量对象就是它自身var c = 123;console.log(c); // 只能通过这种方式
函数上下文
在函数内部,this的值取决于函数被调用的方式。
var a = 10;var obj = {a: 20,log:function(){console.log(this.a)}}var f = obj.log;f(); // undefinedobj.log() // 20
对象的方法中的this
当函数作为对象里的方法被调用时,this 被设置为调用该函数的对象。
请注意,这样的行为完全不会受函数定义方式或位置的影响。
var o = {prop: 37,f: function() {return this.prop;}};console.log(o.f()); // 37var o = {prop: 36};function independent() {return this.prop;}o.f = independent;console.log(o.f()); // 36
原型链中的this
对于在对象原型链上某处定义的方法,同样的概念也适用。如果该方法存在于一个对象的原型链上,那么 this 指向的是调用这个方法的对象,就像该方法就在这个对象上一样。
var o = {f: function() {return this.a + this.b;}};var p = Object.create(o);p.a = 1;p.b = 4;console.log(p.f()); // 5
在这个例子中,对象
p没有属于它自己的f属性,它的f属性继承自它的原型。虽然最终是在o中找到f属性的,这并没有关系;查找过程首先从p.f的引用开始,所以函数中的this指向p。也就是说,因为f是作为p的方法调用的,所以它的this指向了p。
构造函数的this
当一个函数用作构造函数时(使用new关键字),它的this被绑定到正在构造的新对象。(如果返回值不是一个对象,则返回 this 对象)。
每个构造函数在new之后都会返回一个对象,这个对象就是this。
function C(){this.a = 37;}var o = new C();console.log(o.a); // logs 37function C2(){this.a = 37;return {a:38};}o = new C2();console.log(o.a); // logs 38
箭头函数
this指向的是函数定义时的作用域
- 箭头函数不会创建自己的
this,它只会从自己的作用域链的上一层继承this。 - 不能用call方法修改里面的this
 
箭头函数没有自己的 this 值,箭头函数中所使用的 this 都是来自函数作用域链,它的取值遵循普通普通变量一样的规则,在函数作用域链中一层一层往上找。
const obj = {a: function() { console.log(this) }}obj.a() //打出的是obj对象const obj = {a: () => {console.log(this)}}obj.a() //打出来的是window
// 使用箭头函数var circle = {radius: 10,outerDiameter() {var innerDiameter = () => {console.log(2 * this.radius);};innerDiameter();}};circle.outerDiameter(); // 打印20
对于内层函数 innerDiameter,它本身并没有 this 值,其使用的 this 来自作用域链,来自更高层函数的作用域。innerDiameter 的外层函数 outerDiameter 是普通函数,它是有 this 值的,它的 this 值就是 circle 对象。因此,innerDiameter 函数中所使用的 this 来自 outerDiameter 函数,其值为 circle 对象。
参考
总结
- 对于直接调用函数来说,不管函数被放在了什么地方,
this一定是window - 对于 
obj.fun()来说,我们只需要记住,谁调用了函数,谁就是this,所以在这个场景下 fun函数中的this就是obj对象 - 对于 
new的方式来说,this被永远绑定在了对象上面,不会被任何方式改变this 

改变 this 的指向
- call 、bind 、 apply 这三个函数的第一个参数都是 this 的指向对象,
 - call 的参数是直接放进去的,第n个参数全都用逗号分隔,直接放到后面
 - apply 的所有参数都必须放在一个数组里面传进去
 - bind 除了返回是函数,需要手动调用,它的参数和call一样
 
var a ={name : "Cherry",fn : function (a,b) {console.log( a + b)}}var b = a.fn;b.call(a,1,2) // 3b.apply(a,[1,2]) // 3b.bind(a,1,2)()
