难懂的this

来源:互联网 发布:人工智能屠宰场小女孩 编辑:程序博客网 时间:2024/05/01 22:46

JavaScript中很多时候会用到this,下面详细介绍每一种情况。在这里我想首先介绍一下宿主环境这个概念。一门语言在运行的时候,需要一个环境,叫做宿主环境。对于JavaScript,宿主环境最常见的是web浏览器,浏览器提供了一个JavaScript运行的环境,这个环境里面,需要提供一些接口,好让JavaScript引擎能够和宿主环境对接。JavaScript引擎才是真正执行JavaScript代码的地方,常见的引擎有V8(目前最快JavaScript引擎、Google生产)、JavaScript core。JavaScript引擎主要做了下面几件事情:

一套与宿主环境相联系的规则;JavaScript引擎内核(基本语法规范、逻辑、命令和算法);一组内置对象和API;其他约定。

但是环境不是唯一的,也就是JavaScript不仅仅能够在浏览器里面跑,也能在其他提供了宿主环境的程序里面跑,最常见的就是nodejs。同样作为一个宿主环境,nodejs也有自己的JavaScript引擎–V8。


this 的工作原理

JavaScript 有一套完全不同于其它语言的对 this 的处理机制。 在五种不同的情况下 ,this 指向的各不相同。

1 全局范围内

this;

当在全部范围内使用 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添加或者改变属性值。

 1 <script type="text/javascript"> 2     foo = "bar"; 3  4     function testThis() { 5       foo = "foo"; 6     } 7  8     console.log(this.foo); //logs "bar" 9     testThis();10     console.log(this.foo); //logs "foo"11 </script>

2 函数调用

foo();

这里 this 也会指向全局对象。

注意: 在严格模式下(strict mode),不存在全局变量。 这种情况下 this 将会是 undefined。
3 方法调用

test.foo(); 

这个例子中,this 指向 test 对象。

4 调用构造函数

new foo(); 

如果函数倾向于和 new 关键词一块使用,则我们称这个函数是 构造函数。 在函数内部,this 指向新创建的对象。

5 显式的设置 this

function foo(a, b, c) {}var bar = {};foo.apply(bar, [1, 2, 3]); // 数组将会被扩展,如下所示foo.call(bar, 1, 2, 3); // 传递到foo的参数是:a = 1, b = 2, c = 3

当使用 Function.prototype 上的 call 或者 apply 方法时,函数内的 this 将会被 显式设置为函数调用的第一个参数。

因此函数调用的规则在上例中已经不适用了,在foo 函数内 this 被设置成了 bar。

注意,当直接调用函数时,this 指向全局对象 【上述 的第二点】。被认为是JavaScript语言另一个错误设计的地方,因为它从来就没有实际的用途。

Foo.method = function() {    function test() {        // this 将会被设置为全局对象(译者注:浏览器环境中也就是 window 对象)    }    test();}

一个常见的误解是 test 中的 this 将会指向 Foo 对象,实际上不是这样子的。


function Foo() {}Foo.prototype.method = function() {};function Bar() {}Bar.prototype = Foo.prototype;new Bar().method();

当 method 被调用时,this 将会指向 Bar 的实例对象。

0 0
原创粉丝点击