当前位置:   article > 正文

两年前端却不知this为何许?_两年前端应该知道

两年前端应该知道

       说来惭愧,再讲一个故事吧。带着2年前端经验的我去面试,被闭包问住了,尴尬了整个面试气氛。第二次,OK,失败了总要知道为什么吧,于是闭包被我简单的攻略了。面试官问我闭包时,拿起笔就写了一个简易版的闭包。好啊,既然你知道闭包,那你说说在你写的这个闭包的这一段代码里,这里,这里,这里this分别是什么?啊啊啊啊,老天,Are you kidding me?
    Q:

  1. // (1)这里this指代什么?
  2. function a(){
  3.     // (2)这里this指代什么?
  4.     var c = 2;
  5.     function b(){
  6.         // (3)这里呢?this又指代什么?
  7.         return c;
  8.     }
  9.     return b;
  10. }
  11. a()();
A:(1)处指window,(2)处指的是a,(3)处指的是b。
面试官:嗯?是吗?你不好好想想吗?

我的内心:啊啊啊,哪里有洞。。。我是有多菜。

是,你没有看错,我确实是这么回答的,很可笑啊,我一直都觉得这真的是耻辱啊,我想我一辈子都不会忘记。不过,这个面试官很nice,给我道出了正确答案,还告诉我为什么。这场面试下来,我所有的自信心都被摧毁得破碎不堪,但它却是我最有收获的一次面试,也成为我前端路上的一次转折点。
        正确的应该是:这三处均指的是window对象。

       This,何意?这,这里,这个。在JavaScript中,它是关键字,既不是变量,也不是属性名,所以它是不允许被赋值的。那它是什么关键字呢?在JavaScript中,它指的是函数调用的上下文(context)。
        根据ECMAScript3和非严格的ECMAScript5对函数调用的规定,this的值是全局对象。在严格模式下,则是undefined。和变量不同,关键字没有作用域的限制,嵌套函数(闭包)不会从调用它的函数中继承this。若想访问外部函数的this值,需要将它的值保存在一个变量里,这个变量和内部函数都同在一个作用域内。可看下面代码:

  1. var o = {
  2.     m: function(){
  3. var self = this;
  4. console.log(this === o); // true, this就是这个对象o
  5. f();
  6. // 定义一个嵌套函数f()
  7. function f(){
  8.     console.log(this === o); // false,this的值是全局对象或者undefined
  9.     console.log(self === o); // true, self值外部函数的this值
  10. }
  11.     }
  12. };
  13. o.m();

       this是在运行时基于函数的执行环境绑定的。在全局函数中,this等于window,而当函数被作为某个对象的方法调用时,this等于那个对象。不过,随着函数使用场合不同,this的值可能发生变化。我们知道,在JavaScript中,调用函数有4种方式:

  • 普通的函数调用
  • 作为对象的方法调用
  • 作为构造函数调用
  • 通过它们的call()和apply()间接调用

那么就从它的调用方式简单分析一下,如有错误,烦请批评指正:

(1)作为函数

这是最通常的函数用法,属于全局性调用,因此this等于全局对象。

  1. function f(){
  2.     window.x = 1;
  3.     console.log(this.x);
  4. }
  5. f(); // 1

对代码做些改变再看,

  1. var x = 1;
  2. function f(){
  3.     console.log(this.x);
  4. }
  5. f(); // 1
  6. console.log(window.x); // 1

window.x与this.x值相等。再变一下,

  1. var x = 1;
  2. function f(){
  3.     this.x = -1;
  4. console.log(this.x);
  5. }
  6. f(); // -1
  7. console.log(x); // -1

在f()中给this.x赋值为-1,结果x的值跟着改变为-1,所以this等于全局对象。

(2)作为方法

当函数作为某个对象的方法调用时,这时this的值就是这个对象。

  1. function f(){
  2.     console.log(this.x);
  3. }
  4. var o = {
  5.     x: -1,
  6.     m: f
  7. };
  8. o.m(); // -1
  9. o.x = 1;
  10. o.m(); // 1

对象的属性值改变,f()里面this.x跟着改变。可以在f()里面打印一下this,看看结果呢!

(3)作为构造函数

作为构造函数调用时,使用new关键字初始化一个实例对象,这时this等于这个实例对象。

  1. function f(){
  2.     this.name = "zrn";
  3. }
  4. var o = new f();
  5. console.log(o.name); // "zrn"

运行结果为”zrn”,表示这并非全局对象。变一下代码,

  1. var name = "window";
  2. function f(){
  3.     this.name = "zrn";
  4. }
  5. var o = new f();
  6. console.log(o.name); // "zrn"
  7. console.log(name); // "window"

name的值互不干涉。

(4)通过call()或者apply()调用

call()和apply()的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this的值。第一个参数(context)是函数运行的作用域,第二个参数是参数数组(argArr),不过使用call()时,要将这些参数逐个列举出来。如果未传递context,则context是全局对象(啊,说的有点多了)。

  1. var name = "window";
  2. function f(){
  3.     console.log(this.name);
  4. }
  5. var o = {name: "zrn"};
  6. f.call(); // "window", this指的是window
  7. f.apply(o); // "zrn", this指的是对象o
结束语:以上就是我对this的基础理解了,不过理解与正确地使用又差一大截,所以只有不断地实践,不断地积累,才能够对this的使用信手拈来,达到炉火纯青的地步,所以,come on!
ps: call()和apply()方法是很强大的方法,期待更深入的学习它们。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/591036
推荐阅读
相关标签
  

闽ICP备14008679号