在 js 中,this 这个上下文总是变化莫测,很多时候出现bug 总是一头雾水,其实,只要分清楚不同的情况下如何执行就可以了,以下就是我们给大家整理的相关内容:
在JavaScript中有一个很特别、很常用又常常让初学者很困扰的东西 ─ “this”,在这堂课中会来谈谈这个”this”。
this通常会指向一个对象,同时this会在不同的情境下指向不同的对象。让我们来看几个不同的情境,帮助我们更了解”this”。
window object (global object)
这里我们在三种不同情境去打印”this”,分别是在函数的最外层(outer environment)直接去执行;使用fuction statement去执行;使用function expression去执行(如果还不清楚function statement和function expression的差别,可以参考注1)。
结果会发现,这三个”this”都会指向同样的对象,也就是global environment的window object (global object):
这也就是说,我们可以直接利用这个function和this在window object建立新的属性:
在这里我们利用this.NewVariable = "..."
来在window object建立新的属性,函数的最后,我们则可以直接console.log(NewVariable),这里之所以可以不用打this.NewVariable或window.NewVariable是因为任何在global object (window)的属性,我们都可以直接去使用它,而不用使用”.”。
跑出来的结果会像这样子:
它会打印出我们的”Create a new property”,同时,在window这个大的object中,我们也会找到NewVariable这个属性:
method in object
我们知道,在对象里的值如果是原生值(primitive type;例如,字串、数值、逻辑值),我们会把这个新建立的东西称为「属性(property)」;如果对象里面的值是函数(function)的话,我们则会把这个新建立的东西称为「方法(method)」。
在这里,我们就要来建立method:
首先,我们利用object literal的方式创建一个对象c,里面包含属性name和方法log。log是一个匿名函数(anonymous function),函数内容很简单,就是打印this而已(关于匿名函数可参考注1)。最后则是使用c.log的方式来执行该方法。
让我们来看看,这时候的”this”会是什么呢?
答案是对象c!
当这个函数是对象里面的method时,这时候的this就会指向到包含这个method的对象
JavaScript中关于this的一个bug
让我们更进一步延伸来看这个范例:
假设我们在method log裡面多这一行this.name = "Updated Object C name"
因为我们知道”this”现在指的是对象c,所以可以想像的,当我执行这个method的时候,它会去变更c.name的值。
这个部分是没有什么大问题的,不过让我们继续看下去……。
假设我在method log裡面在做一些变更,我在这个method裡面,另外建立一个函数叫做setname,一样是用this.name = newname
的方式来修改这个object c中name属性的值。
接着执行setname这个函数,希望把object c中name的属性值改成”New name for object c”,最后再去打印”this”来看一下。
结果我们会发现,对象c中name属性的值并没有变成”New name for object c”,竟然还是一样!?怎么会这样呢?
仔细一看,我们回来看一下我们的window object,我们会发现,在window object中发现了一个新的属性”name”,而且值是”New name for object c”。
这是什么意思呢?意思是原来我们刚刚在函数setname里面的this,指向到的是global object (window object),而不再是刚刚的object C!
我们在setname这个function中,用console.log(this)来看一下:
在log这个method中,我们一共执行了三次的console.log(this)结果如下:
第一个和第三个”this”指向到的是对象c,而第二个在setname中的this,指向的则是window object (global object),而这也就是为什么setname这个function没办法帮我们修改对象c中name属性的名称,因为”this”根本没指向到对象c。
而许多人都认为,这是JavaScript的一个bug。
那么我们可以怎么做
那么碰到上述的这个例子时,我们可以怎么做来避免指向到不同的对象呢?
许多人的解法是这样的,因为我们知道对象都是用的引用的方式,所以我们可以这样做
STEP 1
我们在整个函数的最上面加上一行var self = this
(有些人会用var that = this
)。由于引用的特性,self和this会指向到同一个对象,而this指向对象c,所以self一样会指向对象c。
STEP 2
接着,把方法log内原本使用的”this”都改成”self”,这样做可以确保self指向到的是c对象而不用担心会像上面的例子一样指向到错误的对象。
结果也如同我们预期的,在第二次console.log(self)的时候,就再次替换了对象c中name属性的值。
总结
让我们来总结一下:
如果我们是在全局环境建立函数并打印this,这时候this会指向到全局对象,也就是window对象。
如果我们是在对象里面创建函数,也就是方法(method)的情况时,这时候的this一般就会指向到包含这个方法的对象(之所以说”一般”是因为除了上述bug的情况之外)。
碰到method中可能会有不知道this指向到什么的情况时,为了避免不必要的错误,我们可以在method中的最上面建立一个变量,去把它指定成this(var self = this)。
4.如果真的还是不知道那个情况下的this会指向到什么,就console.log出来看看吧!
示例代码
// function statement function a(){ console.log(this); this.NewVariable = "Create a new property"; } a(); console.log(NewVariable); var c = { name:"The C object", log: function(){ var self = this; self.name = "Updated object C name"; console.log(self); var setname = function(newname){ self.name = newname; console.log(self); } setname("New name for object c"); console.log(self) } } c.log();
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
P70系列延期,华为新旗舰将在下月发布
3月20日消息,近期博主@数码闲聊站 透露,原定三月份发布的华为新旗舰P70系列延期发布,预计4月份上市。
而博主@定焦数码 爆料,华为的P70系列在定位上已经超过了Mate60,成为了重要的旗舰系列之一。它肩负着重返影像领域顶尖的使命。那么这次P70会带来哪些令人惊艳的创新呢?
根据目前爆料的消息来看,华为P70系列将推出三个版本,其中P70和P70 Pro采用了三角形的摄像头模组设计,而P70 Art则采用了与上一代P60 Art相似的不规则形状设计。这样的外观是否好看见仁见智,但辨识度绝对拉满。
更新日志
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]