赞
踩
说来惭愧,再讲一个故事吧。带着2年前端经验的我去面试,被闭包问住了,尴尬了整个面试气氛。第二次,OK,失败了总要知道为什么吧,于是闭包被我简单的攻略了。面试官问我闭包时,拿起笔就写了一个简易版的闭包。好啊,既然你知道闭包,那你说说在你写的这个闭包的这一段代码里,这里,这里,这里this分别是什么?啊啊啊啊,老天,Are you kidding me?
Q:
- // (1)这里this指代什么?
- function a(){
- // (2)这里this指代什么?
- var c = 2;
- function b(){
- // (3)这里呢?this又指代什么?
- return c;
- }
- return b;
- }
- a()();
A:(1)处指window,(2)处指的是a,(3)处指的是b。
我的内心:啊啊啊,哪里有洞。。。我是有多菜。
是,你没有看错,我确实是这么回答的,很可笑啊,我一直都觉得这真的是耻辱啊,我想我一辈子都不会忘记。不过,这个面试官很nice,给我道出了正确答案,还告诉我为什么。这场面试下来,我所有的自信心都被摧毁得破碎不堪,但它却是我最有收获的一次面试,也成为我前端路上的一次转折点。
正确的应该是:这三处均指的是window对象。
This,何意?这,这里,这个。在JavaScript中,它是关键字,既不是变量,也不是属性名,所以它是不允许被赋值的。那它是什么关键字呢?在JavaScript中,它指的是函数调用的上下文(context)。
根据ECMAScript3和非严格的ECMAScript5对函数调用的规定,this的值是全局对象。在严格模式下,则是undefined。和变量不同,关键字没有作用域的限制,嵌套函数(闭包)不会从调用它的函数中继承this。若想访问外部函数的this值,需要将它的值保存在一个变量里,这个变量和内部函数都同在一个作用域内。可看下面代码:
- var o = {
- m: function(){
- var self = this;
- console.log(this === o); // true, this就是这个对象o
- f();
-
- // 定义一个嵌套函数f()
- function f(){
- console.log(this === o); // false,this的值是全局对象或者undefined
- console.log(self === o); // true, self值外部函数的this值
- }
- }
- };
- o.m();
this是在运行时基于函数的执行环境绑定的。在全局函数中,this等于window,而当函数被作为某个对象的方法调用时,this等于那个对象。不过,随着函数使用场合不同,this的值可能发生变化。我们知道,在JavaScript中,调用函数有4种方式:
那么就从它的调用方式简单分析一下,如有错误,烦请批评指正:
(1)作为函数
这是最通常的函数用法,属于全局性调用,因此this等于全局对象。
- function f(){
- window.x = 1;
- console.log(this.x);
- }
- f(); // 1
对代码做些改变再看,
- var x = 1;
- function f(){
- console.log(this.x);
- }
- f(); // 1
- console.log(window.x); // 1
window.x与this.x值相等。再变一下,
- var x = 1;
- function f(){
- this.x = -1;
- console.log(this.x);
- }
- f(); // -1
- console.log(x); // -1
在f()中给this.x赋值为-1,结果x的值跟着改变为-1,所以this等于全局对象。
(2)作为方法
当函数作为某个对象的方法调用时,这时this的值就是这个对象。
- function f(){
- console.log(this.x);
- }
- var o = {
- x: -1,
- m: f
- };
- o.m(); // -1
- o.x = 1;
- o.m(); // 1
对象的属性值改变,f()里面this.x跟着改变。可以在f()里面打印一下this,看看结果呢!
(3)作为构造函数
作为构造函数调用时,使用new关键字初始化一个实例对象,这时this等于这个实例对象。
- function f(){
- this.name = "zrn";
- }
- var o = new f();
- console.log(o.name); // "zrn"
运行结果为”zrn”,表示这并非全局对象。变一下代码,
- var name = "window";
- function f(){
- this.name = "zrn";
- }
- var o = new f();
- console.log(o.name); // "zrn"
- console.log(name); // "window"
name的值互不干涉。
(4)通过call()或者apply()调用
call()和apply()的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this的值。第一个参数(context)是函数运行的作用域,第二个参数是参数数组(argArr),不过使用call()时,要将这些参数逐个列举出来。如果未传递context,则context是全局对象(啊,说的有点多了)。
- var name = "window";
- function f(){
- console.log(this.name);
- }
- var o = {name: "zrn"};
- f.call(); // "window", this指的是window
- f.apply(o); // "zrn", this指的是对象o
结束语:以上就是我对this的基础理解了,不过理解与正确地使用又差一大截,所以只有不断地实践,不断地积累,才能够对this的使用信手拈来,达到炉火纯青的地步,所以,come on!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。