函数内部的this指向
JavaScript在函数体内定义了this关键字,this是一个指针型变量,它动态引用当前的运行环境,这些 this 的指向,是当我们调用函数的时候确定的。调用方式的不同决定了this 的指向不同,一般指向我们的调用者。
`` 【示例1】下面的示例在全局上下文中声明一个变量n,初始化值为1,然后在obi对象内定义一属性n,初始化值为2。使用函数 f检测不同运行环境下n值的变化,以此检测this指针的引用对象
<script>
var n = 1; //声明全局变量并初始化
var obj = {
f: function () { //定义方法f
console.log(this.n); //访问当前运行环境中n属性值
},
n: 2, //定义属性n,赋值为2
};
// obj环境执行
obj.f() //2
var f1 = obj.f;
//window环境执行
f1();
</script>
在上面的代码中,obj.f()表示在obj对象上调用 f 函数,则调用对象为obj,此时this就指向obj,this.n就等于obj.n,即返回结果为2。当把obj.f 赋值给变量 f1,然后在全局上下文中调用 f1 函数,则 f 函数体的运行环境在全局上下文中执行,此时this就指向 window,this.n就等于window.n,即返回结果为1。
【示例2】*this总是指代函数的当前运行环境。*针对示例1的代码,如果使用下面3种方式调用函数,会发现返回值都是1。
<script>
var n = 1; //声明全局变量并初始化
var obj = {
f: function () { //定义方法f
console.log(this.n); //访问当前运行环境中n属性值
},
n: 2, //定义属性x,赋值为2
};
// 立即执行函数运行环境在全局
(obj.f = obj.f)(); //1
(false || obj.f)(); //1
(obj.f,obj.f)(); //1
</script>
在上面的代码中,小括号左侧都是一个表达式,表达式的值都是obj.f,而在【示例1】中可以看到使用obj.f()调用函数f, 返回值是2, 为什么现在换一种表示方法返回值就都是1呢?
问题的关键是如何正确理解“运行环境”。上面3个表达式中,obj.f=obj.f是赋值表达式,把obj.f赋值给obj.f,obj.f是一个地址,把地址赋值给obj.f属性,表达式的运行环境发生在全局上下文中, 此时的函数f内的this就指向了全局上下文的调用对象 window.
false ll obj.f是一个逻辑表达式,左侧值为 false,则运算右侧,返回obj.f的值,即引用地址。由于这个逻辑表达式运算发生在全局作用域内,此时的f函数内的this就指向了全局对象。
obj.f,obj.f是一个逗号运算表达式,逗号左侧和右侧的obj.f都是一个地址,都被运算一次,最后返回第2个操作数的值,即返回引用地址。由于这个操作发生在全局作用域内,所以f函数内this也指向了全局对象。
但是,对于下面形式的调用,不会返回1,而是返回2,即this指向obj对象。因为,小括号不是一个运算符,它仅是一个逻辑分隔符,不执行运算,不会产生运行环境,当使用小括号调用函数时,此时生成的运行环境就是obj了。
<script>
var n = 1; //声明全局变量并初始化
var obj = {
f: function () { //定义方法f
console.log(this.n); //访问当前运行环境中n属性值
},
n: 2, //定义属性x,赋值为2
};
// obj环境执行
(obj.f = obj.f)(); //1
(false || obj.f)(); //1
(obj.f,obj.f)(); //1
(obj.f)(); //2
</script>