深入理解JavaScript之this

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。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容

  • 1. this之谜 在JavaScript中,this是当前执行函数的上下文。因为JavaScript有4种不同的...
    百里少龙阅读 977评论 0 3
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,494评论 18 139
  • 为什么要封装 public不安全,private在类外无法使用,应该如何解决?用到 封装: ①隐...
    今天庹阅读 176评论 0 1
  • 吴芸茜 2007年一到上海交通大学出版社,我就向业内“老法师”们请教:应该向哪个“版块”发力?老编辑给出的答案都惊...
    吴芸茜阅读 1,677评论 3 4
  • 我爱海!这是不容质疑的!一直认为那里是人间的天堂。蔚蓝的海面,湛蓝的天空,偶尔几只掠过的海鸟,海天一色,分不出地平...
    34c15754c30b阅读 245评论 0 1