概念
解析器在调用函数时,每次都会像函数内传递进一个隐含的参数this,this指向一个对象,这个对象称为函数的上下文对象。
根据函数调用方式的不同,this会指向不同的对象。
何时确定
何时
执行上下文生命周期中的创建阶段(生成变量对象,建立作用域链,确定this指向)
this的指向是在函数被调用的时候确定的
为什么
在JS中,数组,函数,对象都是引用类型,在参数传递时也就是引用传递。
因为函数在JS中,既可以当作值传递和返回,也可以当作对象和构造函数。
所有函数在运行时需要确定其当前的执行环境,this就确定了。
this会根据运行环境的改变而改变,同时函数中的this也只能在运行时才能最终确定运行环境。
怎么理解?
函数中的this是什么时候确定的?=> 执行上下文的生命周期确定的,所以跟函数的运行环境有关系。
因此函数中的this会在函数调用时确定this的指向。
this使用的分类:
全局作用域下的this
函数作用域下的this
要想确定函数this的指向,找到函数的调用者,和区分它是否是独立调用
- 在一个函数上下文中,this由调用者提供,由调用的方式决定
- 如果函数独立调用,那么在严格模式下,该函数内部的this指向undefined,非严格模式下,当this指向undefined时,会自动指向window对象。
事件绑定
行内绑定
行内绑定有两种方式:指向window对象或者当前节点
<!-- 运行环境在节点对象中,因此this指向本节点对象 -->
<input type="button" value="按钮" onclick="console.log(this)">
<input type="button" value="按钮" onclick="clickFun()">
<script>
function clickFun(){
this // 此函数的运行环境在全局window对象下,因此this指向window;
}
</script>
复制代码
区别在于绑定的事件是否是函数,是函数就指向window,不是函数,只是函数语句的,就指向当前元素。
动态绑定
<input type="button" value="按钮" id="btn">
<script>
var btn = document.getElementById('btn');
btn.onclick = function(){
this ; // this指向本节点对象
}
</script>
复制代码
事件监听
事件监听中的this和动态绑定基本一致。
构造函数中的this
构造函数中的this 指向新建的对象。具体参考于构造函数章节。
window定时器中的this
以setInterval为例。
setInterval是window对象下内置的一个方法,接收两个参数,第一个参数允许是一个函数或者一段可执行的JS代码。第二个参数是指向前面函数或者代码的时间间隔。
var obj = {
fun:function(){
this ;
}
}
setInterval(obj.fun,1000); // this指向window对象
setInterval('obj.fun()',1000); // this指向obj对象
复制代码
setInterval的第一个参数为fun时,由于JS中函数是可以被当作值来做引用传递,实际上就是将这个函数的地址当作参数传递给setInterval方法,换句话说,就是setInterval接收一个函数作为参数后,过了1000毫秒,函数的运行已经是在window对象下了,也就是说函数的调用者已经变成了window对象。所以其中的this则指向window对象。
而当setInterval接收一段可执行的代码时,1000毫秒后,JS引擎去执行这段代码,则是通过obj.fun指向函数,因此this指向obj对象。
总结: 当定时器接收一个函数作为第一个参数时,则函数中this指向window对象。如果接收一段可执行的代码时,则this的指向取决于这段可执行的代码。
call,apply方法
call,apply方法都是用来强制指定函数调用时this的指向。
this指向call,apply方法的第一个参数。