目录
按照《Javascript The Good Parts》第四章的描述,假如函数是对象的方法,则函数的this指向所属对象。如果函数不是任何对象的属性,那么函数体中的this将指向“global object”,也就是窗体“window”。所以下面这段代码里,helper的this指向的就是window。
示例1
代码:
<html>
<head>
</head>
<body>
<script>
let myObject = {
value: 1,
};
myObject.double = function ( ) {
var that = this; // Workaround.
var helper = function ( ) {
that.value = that.value + that.value;
this.test = "test";
};
helper(); // Invoke helper as a function.
document.write(helper.test + "\n");
document.write(window.test + "\n");
};
// Invoke double as a method.
myObject.double( );
document.writeln(myObject.value);
</script>
</body>
</html>
运行效果:
分析:
this的指向
第一个this
var that = this; // Workaround.
第一个this处于myObject的成员函数double内,所以this指向myObject
第二个this
第二个this处于helper内,而helper是一个function,根据前面的陈述,this指向window
this.test = "test";
实际的效果也验证了这一点:helper没有test属性,故helper.test打印undefined,而window.test打印test
that的作用
前面说了,myObject.double的this指向myObject。但是,尽管helper定义在double函数的定义内,helper的this却指向window。为了能在helper中操作myObject,利用下面的性质:
函数可以访问其上一级作用域里声明的变量
声明that,将this赋值给that,于是helper就可以获取myObject的value属性并操作。
示例2--setTimeout中的this
根据《Professional Javascript for web developers》的说法:
All code executed by a timeout using a conventional anonymous function
runs in the global scope, so the value of this inside the function will always
point to window when running in nonstrict mode and undefined when running
in strict mode. When setTimeout is instead provided an arrow function, this
preserves the lexical scope in which it was defined。假如在setTimeout中使用普通的匿名函数,匿名函数将运行在全局作用域,匿名函数中的this指向全局的window(非严格模式)或者undefiend(严格模式)。假如在setTimeout中使用=>函数,函数则运行于其所在的作用域。
代码1 (非严格模式)
<!DOCTYPE html>
<html>
<body>
<h2>My Heading</h2>
<p>Play around with the code and click on the "Run" button to view the result.</p>
<p id="demo"></p>
<p id="demo2"></p>
<p id="demo3"></p>
<script>
// Online Javascript Editor for free
// Write, Edit and Run your Javascript code using JS Online Compiler
var v = 1;
class test
{
constructor() {
this.v = 2;
}
p()
{
let f = function(){document.getElementById("demo").innerHTML ="Welcome!" + this.v;};
setTimeout(f, 1000);
}
p2()
{
setTimeout(() => document.getElementById("demo2").innerHTML ="Welcome again!" + this.v, 1000);
}
p3()
{
setTimeout(function(){document.getElementById("demo3").innerHTML ="Welcome!" + this.v;}, 1000);
}
}
let t = new test;
t.p();
t.p2();
t.p3();
</script>
</body>
</html>
效果1
由于在函数p2中使用了=>定义函数,所以this指向了test。故this.v = 2。另外的两个函数p和p3使用了匿名函数,所以this指向window(非严格模式)。
代码2(严格模式)
// Online Javascript Editor for free
// Write, Edit and Run your Javascript code using JS Online Compiler
var v = 1;
class test
{
constructor() {
this.msg = 1;
}
p()
{
let f = function(){console.log("Welcome to Programiz!" + this.v);};
setTimeout(f, 1000);
}
p2()
{
setTimeout(() => console.log("Welcome to Programiz again!" + this.msg), 1000);
}
p3()
{
setTimeout(function(){console.log("Welcome to Programiz!" + this.v);}, 1000);
}
}
let t = new test;
t.p();
t.p2();
t.p3();
效果2
由于在programiz环境下使用的是严格模式,所以this.v显示为undefined