美文网首页
深入理解JavaScript之this

深入理解JavaScript之this

作者: 萧玄辞 | 来源:发表于2017-10-24 09:05 被阅读0次

this是JavaScript中的一个很特别的关键字,同时,它也是JavaScript中最复杂的机制之一,重要性同闭包、原型不相伯仲。如果你缺乏对this的清晰认识,this的指向足以让你眼花缭乱,这完全就是一种魔法。

this是什么

当一个函数被调用时,除了传入了函数的显式参数以外,名为this的隐式参数也被传入了函数。this引用了与该函数调用进行隐式关联的一个对象,被称之为函数上下文。函数上下文包含了函数在哪里被调用(调用栈)、函数的调用方式、传入的参数等信息。this在函数运行时进行绑定,并不是在编写时绑定,它的上下文取决于函数调用时得各种条件。this的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式,而this则指的是调用函数的那个对象。

现在,我们来看看在具体的调用方式中this是怎样的。

一. 作为函数进行调用

当一个函数作为函数进行调用时,是区别于其他调用机制:方法、构造器以及apply、call。

使用这种方式进行调用通常在函数上使用了()操作符,使用了()操作符的表达式并没有将函数作为对象的一个属性。

下面是一个示例:

``` js

function foo(){

console.log(this.a);

}

var a=2;

foo();//2

```

如你所见,a是声明在全局作用域中的变量,a也是全局对象的一个同名属性。当foo()被调用时,this.a被解析称为了全局变量a,因此this指向全局对象,函数的上下文是全局上下文——window对象。

如果使用严格模式(strict mode),则this并不能指向全局对象,this此时将会指向undefined:

``` js

function foo(){

"use strict";

console.log(this.a);

}

var a=2;

foo();

//TypeError: Cannot read property 'a' of undefined(…)

```

二. 作为方法进行调用

当一个函数被赋值为对象的一个属性,并使用引用该函数的这个属性进行调用时,那么函数就是作为对象的一个方法进行调用的。

示例如下:

``` js

var obj={

a:2

};

obj.foo=function(){

console.log(this.a);

};

obj.foo();//2

```

如果你对面向对象了解的话,你肯定知道,一个方法所属的对象在该方法体内可以以this的形式进行引用。在这里,将函数作为对象的一个方法进行调用时,该对象就变成了函数的上下文,并且在函数内部可以以this参数的形式进行访问。

请看下面示例:

``` js

function foo(){

console.log(this.a);

}

var obj={

a:2,

foo:foo

};

var bar=obj.foo;

var a="two";

bar();//"two"

```

在这里,虽然bar是obj.foo的一个引用,但是实际上,它引用的是foo函数本身,因此此时的bar()其实是一个不带任何修饰的函数调用,因此this指向全局对象。当使用严格模式时,this指向undefined。

三. 作为构造器进行调用

将函数进行构造器(constructor)进行调用,我们要在函数进行调用前使用new关键字。

``` js

function foo(){

return this

}

new foo();

```

将函数作为构造器进行调用,或者说使用new来调用函数,会自动执行下面的操作。

- 创建一个新的空对象。

- 传递给构造器的对象是this参数,从而成为构造器的函数上下文。

- 如果没有显式的返回值,新创建的对象则作为构造器的返回值进行返回。

请看下面代码:

``` js

function foo(a){

this.a=a;

}

var bar=new foo(2);

console.log(bar.a);

```

作为构造函数调用时foo()时,我们会构造一个新对象并把它绑定到foo(...)调用中的this上。

四. 使用apply()/call()方法进行调用

在函数调用的时候,JavaScript为我们提供了一种方式,可以显式指定任何一个对象作为其函数上下文。JavaScript的每个函数都有apply()和call()方法,它们的功能相同,仅仅是传入参数不同。

通过函数的apply()方法来调用函数,我们要给apply()传入两个参数:一个是作为函数上下文的对象,另外一个是作为函数参数所组成的数组。call()方法的使用方式类似,唯一不同的是,给函数传入的参数是一个参数列表,而不是单个数组。

请看示例:

``` js

function foo(){

console.log(this.a);

}

var obj={

a:2,

};

foo.call(obj);

```

在这段代码中,通过foo.call(...),我们在调用foo时强制把它的this绑定到obj上。

总结

如果要判断一个运行中函数的this绑定,就需要找到这个函数的直接调用位置,然后根据其调用方式来判断this的绑定对象。

1. 作为构造器进行调用,this指向新创建的对象。

2. 使用call/apply方法调用时,this指向指定的对象。

3. 作为方法进行调用时,this指向拥有该方法的对象

4. 作为普通函数进行调用时,this指向全局对象window,严格模式下指向undefined。

相关文章

网友评论

      本文标题:深入理解JavaScript之this

      本文链接:https://www.haomeiwen.com/subject/xaftpxtx.html