本文深入解析JavaScript中this的动态指向机制,指出其取决于函数调用位置。详细对比了普通函数与箭头函数在this绑定上的差异,并介绍了通过call、apply和bind改变this指向的具体用法及代码示例。
JavaScript this指向原理与改变方法详解
在JavaScript学习过程中,this的指向问题常令初学者困惑。本文将系统梳理this的指向规则,并介绍改变this指向的几种常用方法。
this的指向机制
一、this的指向机制
理解this指向前,需明确两个核心概念:
1. this始终指向一个对象;
2. this的具体指向完全由函数被调用的位置决定;
第一点易于理解,因为JavaScript中万物皆对象。第二点表明,函数调用位置不同,this指向的对象也不同,这意味着this具有动态变换的特性。接下来通过一个简单示例观察this的动态变化。
<script>
function fun(){
console.log(this.name);
}
var change={
name:'hello',
f:fun
}
var name ='world'
var result=change.f()//hello
fun();//world
</script>
上述示例清晰展示了this指向的变化。由于函数存在于对象change内部,此时this指向函数外部的对象,因此输出结果为hello。
通过上述示例,相信大家对this的动态指向切换已有一定了解。
常见this指向场景
接下来,我们对this使用最频繁的几种场景进行总结,最常见的基本包括以下3种:
对象中的方法、事件绑定、构造函数、定时器
前两种场景较为常见,此处重点分析定时器中的this指向问题。
var obj = {
fun:function(){
this ;
}
}
setInterval(obj.fun,1000); // this指向window对象
setInterval('obj.fun()',1000); // this指向obj对象
setInterval()是window对象下的内置方法,接收两个参数:第一个参数可以是函数或可执行的JS代码片段,第二个参数则是执行前者的时间间隔(毫秒)。
在上面的代码中,setInterval(obj.fun,1000)的第一个参数是obj对象的fun方法。由于JS中函数可作为值进行引用传递,实际是将该函数的地址作为参数传递给setInterval方法。换言之,setInterval接收了一个函数引用,1000毫秒后,该函数的运行环境已处于window对象下,即函数的调用者变为window对象,因此其中的this指向全局window对象。
而在setInterval('obj.fun()',1000)中,第一个参数实际传入的是一段可执行的JS代码字符串。1000毫秒后,当JS引擎执行这段代码时,是通过obj对象来查找并调用fun函数。此时函数的运行环境仍在对象obj内部,因此函数内部的this指向obj对象。
改变this指向的方法
除了上述情况,我们还需要掌握三个可以改变this指向的方法,包括箭头函数、call()和apply()。
箭头函数:官方解释指出,引入箭头函数的原因之一是其不绑定this。在箭头函数中,this被设置为封闭的词法环境的值,换言之,箭头函数中的this取决于该函数被创建时的环境。
var globalObject = this; var foo = (() => this); console.log(foo() === globalObject); // true // 接着上面的代码 // 作为对象的一个方法调用 var obj = {foo: foo}; console.log(obj.foo() === globalObject); // true // 尝试使用call来设定this console.log(foo.call(obj) === globalObject); // true // 尝试使用bind来设定this foo = foo.bind(obj); console.log(foo() === globalObject); // true
无论如何,foo的this被设置为其被创建时的环境(在上面的例子中,就是全局对象)。这同样适用于在其他函数内创建的箭头函数:这些箭头函数的this被设置为封闭的词法环境的。
// 创建一个含有bar方法的obj对象,
// bar返回一个函数,
// 这个函数返回this,
// 这个返回的函数是以箭头函数创建的,
// 所以它的this被永久绑定到了它外层函数的this。
// bar的值可以在调用中设置,这反过来又设置了返回函数的值。
var obj = {
bar: function() {
var x = (() => this);
return x;
}
};
// 作为obj对象的一个方法来调用bar,把它的this绑定到obj。
// 将返回的函数的引用赋值给fn。
var fn = obj.bar();
// 直接调用fn而不设置this,
// 通常(即不使用箭头函数的情况)默认为全局对象
// 若在严格模式则为undefined
console.log(fn() === obj); // true
// 但是注意,如果你只是引用obj的方法,
// 而没有调用它
var fn2 = obj.bar;
// 那么调用箭头函数后,this指向window,因为它从 bar 继承了this。
console.log(fn2()() == window); // true
call和apply方法:将一个对象作为call或者apply的第一个参数,this将会被绑定到这个参数对象上。
var obj = {parent:'男'};
var parent = '28';
function child(obj){
console.log(this.parent);
}
child(); // 28
child.call(obj); //男
child.apply(obj); //男
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。