前言
做为一个初学者,原型与闭包可以说是 JavaScirpt 中理解起来最难的部分了,当然,目前了解的也只是了解到了一些皮毛。遂对以前项目中的一些了解,和个人理解总结一下 。
分类
由于this处于不同的特定位置,所以this的指向也是不同的,大致可以分为:
1,全局下的this,
2,局部函数中的this
this包含在一段函数或者代码中,我们称之为‘代码段’,"代码段"可以分为三种:
全局代码
函数体
eval代码(eval就不讨论了)
每一个"代码段"都会在某一个特定位置当中执行,而在每一个代码段执行之前,都会在特定位置生成相应的环境,由于特定位置不同生成的环境不同,所以this的指向也就不同,也就是上面提到的两种。
全局中的this
在全局执行上下文中(在任何函数体外部),this都指向全局对象:
在函数内部,this的值取决与函数被调用的方式。
this的值在函数定义的时候是确定不了的,只有函数调用的时候才能确定this的指向。
实际上this的最终指向的是那个调用它的对象。(也不一定正确)
函数中的this
对于全局的方法调用,this指向window对象(node下为global):
但值得注意的是,以上代码是在非严格模式下。然而,在严格模式下,this的值将保持它进入执行上下文的值:
即在严格模式下,如果this没有被执行上下文定义,那它为undefined。
特定位置生成环境时:
若方法被window(或global)对象调用(称为全局调用),即执行window.foo(),那this将会被定义为window(或global);
若被普通对象调用,即执行obj.foo(),那this将会被定义为obj对象;(称为对象调用)
但若未被对象调用,即直接执行foo(),在非严格模式下,this的值默认指向全局对象window(或global),在严格模式下,this将保持为undefined。
通过this调用全局变量:
对于全局调用,this指向的是全局对象window(或global)。(注意严格模式的不同)
1,作为对象的方法
当函数作为对象的方法调用时,它的this值是调用该函数的对象。也就是说,函数的this值是在函数被调用时确定的,在定义函数时确定不了(箭头函数除外)。
1,this 的值同时也只受最靠近的成员引用的影响,
2,在原型链中,this 的值为当前对象
虽然这里调用的是一个继承方法,但this所指向的依然是tang对象。
2,函数调用apply、call、bind时
当一个函数在其主体中使用this关键字时,可以通过使用函数继承自Function.prototype的call或apply方法将this值绑定到调用中的特定对象。即this的值就取传入对象的值:
与apply、call不同,使用bind会创建一个与foo具有相同函数体和作用域的函数。但是,特别要注意的是,在这个新函数中,this将永久地被绑定到了bind的第一个参数,无论之后如何调用。
5. 箭头函数
箭头函数是 ES6 语法的新特性,在箭头函数中,this的值与创建箭头函数的上下文的this一致。
在全局代码中,this的值为全局对象:
var foo =(() =>this)
//在浏览器中foo() ===window// true
// 在node中foo() === global// true
其实箭头函数并没有自己的this。所以,调用this时便和调用普通变量一样在作用域链中查找,获取到的即是创建此箭头函数的上下文中的this。
当箭头函数在创建其的上下文外部被调用时,箭头函数便是一个闭包,this的值同样与原上下文环境中的this的值一致。由于箭头函数本身是不存在this,通过call、apply或bind修改this的指向是无法实现的。
作为对象的方法:
箭头函数foo的this被设置为创建时的上下文(在上面代码中,也就是全局对象)的this值,而且无法通过其他调用方式设定foo的this值。
与普通函数对比,箭头函数的this值是在函数创建创建确定的,而且无法通过调用方式重新设置this值。普通函数中的this值是在调用的时候确定的,可通过不同的调用方式设定this值。
总结
this关键字的值取决于其所处的位置(上下文环境):
简单来说就是this的代替的是外层的参数(外层包括全局,函数)
在全局环境中,this的值指向全局对象( window 或 global )。
在函数内部,this的取值取决于其所在函数的调用方式,也就是说this的值是在函数被调用的时候确定的,在创建函数时无法确定。
1,箭头函数是个例外,箭头函数本身不存在this,而在箭头函数中使用this获取到的便是创建其的上下文中的this。
2,使用函数的继承方法call、apply和bind会修改this的指向。
3,使用bind方法会使this的值永久的绑定到给定的对象,无法再通过调用call和apply方法修改this的值,箭头函数调用call、apply或bind方法无法修改this。