全局this
浏览器宿主的全局环境中,this
指的是window
对象。
<script type="text/javascript">
console.log(this === window); //true
</script>
浏览器中在全局环境下,使用var
声明变量其实就是赋值给this
或window
。
<script type="text/javascript">
var foo = "bar";
console.log(this.foo); //logs "bar" console.log(window.foo); //logs "bar"
</script>
任何情况下,创建变量时没有使用var
或者let
(ECMAScript 6),也是在操作全局this
。
<script type="text/javascript">
foo = "bar";
function testThis() {
foo = "foo";
}
console.log(this.foo); //logs "bar" testThis();
console.log(this.foo); //logs "foo"
</script>
除了DOM的事件回调或者提供了执行上下文(后面会提到)的情况,函数正常被调用(不带new
)时,里面的this
指向的是全局作用域。
<script type="text/javascript">
foo = "bar";
function testThis() {
this.foo = "foo";
}
console.log(this.foo); //logs "bar"
testThis();
console.log(this.foo); //logs "foo"
</script>
当用调用函数时使用了new
关键字,此刻this
指代一个新的上下文,不再指向全局this
。
<script type="text/javascript">
foo = "bar";
function testThis() {
this.foo = "foo";
}
console.log(this.foo); //logs "bar"
new testThis();
console.log(this.foo); //logs "bar"
console.log(new testThis().foo); //logs "foo"
</script>
函数创建后其实以一个函数对象的形式存在着。
既然是对象,则自动获得了一个叫做prototype
的属性,可以自由地对这个属性进行赋值。
当配合new
关键字来调用一个函数创建实例后,此刻便能直接访问到原型身上的值。
function Thing() {
console.log(this.foo);
}
Thing.prototype.foo = "bar";
var thing = new Thing(); //logs "bar"
console.log(thing.foo); //logs "bar"
当通过new
的方式创建了多个实例后,他们会共用一个原型。比如,每个实例的this.foo
都返回相同的值,直到this.foo
被重写。
function Thing() { }
Thing.prototype.foo = "bar";
Thing.prototype.logFoo = function () {
console.log(this.foo);
}
Thing.prototype.setFoo =
function (newFoo) {
this.foo = newFoo;
}
var thing1 = new Thing();
var thing2 = new Thing();
thing1.logFoo(); //logs "bar"
thing2.logFoo(); //logs "bar"
thing1.setFoo("foo");
thing1.logFoo(); //logs "foo";
thing2.logFoo(); //logs "bar";
thing2.foo = "foobar";
thing1.logFoo(); //logs "foo";
thing2.logFoo(); //logs "foobar";
...或者不通过实例,直接操作函数的原型。
function Thing() { }
Thing.prototype.foo = "bar";
Thing.prototype.logFoo = function () { console.log(this.foo, Thing.prototype.foo); }
var thing = new Thing();
thing.foo = "foo"; thing.logFoo(); //logs "foo bar";