浅谈javascript-this关键字

前言

JavaScript中this变量是一个令人难以摸清的关键字,当初学习javascript的时候被这个this指向问题折腾的我是惨不忍睹,漏洞百出。一度想在后面的代码过程中放弃对this的使用,但是this在javascript当中用处太广泛了。
充分了解this的相关知识有助于我们在编写面向对象的JavaScript程序时能够游刃有余,没办法只能硬着头皮上呀。被虐多次再结合自己查阅相关文档资料,总算有一点小小心得。特分享出来,供大家参考!

this简述

关于this的清this所引用的对象到底是哪一个,也许很多资料上都有自己的解释。例如我钟爱的《高三》对this也是简单几页翻过。最后翻阅到MDN上面的wen技术文档,上面解释深得我意。

在绝大多数情况下,函数的调用方式决定了this的值。this不能在执行期间被赋值,在每次函数被调用时this的值也可能会不同。
--MDN社区web技术文档

由此可以推出this的在不同的情况下,this的指向各不相同。简单来说就分为5种情况

1、全局环境

var a = "先制定一个小目标,下一顿饭加一个鸡腿";
console.log(this);  // 这里this就指向 window
console.log(this.a);  //控制台输出  "先制定一个小目标,下一顿饭加一个鸡腿"

这一种情况相信大家都非常好理解,在全局环境当中this默认是指向window

2、函数中调用

function foo1() {
   function bar() {
     console.log(this);
  }
    bar();
}
foo1();     // 输出window

当foo1()执行的时候 ,间接相当于window.foo1()执行函数中的this是指向window,因此控制台相应输出window结果。(foo1() 间接也等于 window.foo1(),这样就是相当于window在调用这个函数,因此this也是指向于window。)

3、对象中调用

var x = "今天交房租";
var obj = {
foo:function() {
    console.log(this.x);
},
x:"房租减免";
};
obj.foo();   //控制台输出 "房租减免"

这是当对象obj调用foo()函数,this指向了这个调用对象,即this就等于obj,控制台式输出就变成了obj.最后控制台便输出 "房租减免",唉!!这要是从房东嘴巴里面输出该多好!!

4、构造函数中

var name = "hahaha";
function Obj() {
this.name = "CheDabang";
}
var person = new Obj();
console.log(person.name); //输出 CheDabang

这里通过new运算符创建一个 Obj的对象实例。
变成person{this.name},因此这里this的指向也随着指向这个新实例对象。因此控制台输出 CheDabang

5、apply、call中调用

当一个函数的函数体中使用了this关键字时,通过所有函数都从Function对象的原型中继承的call()方法和apply()方法调用的时候,它的值可以绑定到一个指定的对象上。

function add(c, d){
return this.a + this.b + c + d;
}
var o = {a:1, b:3};
console.log(add.call(o, 5, 7));              //1 + 3 + 5 + 7 = 16
console.log(add.apply(o, [10, 20]));        // 1 + 3 + 10 + 20 = 34

小练习

以上就是我们常常出现的5种情况,看到这么多情况的介绍。诸位看官,也晕了吧。不要着急,让我们再来几个小练习感受一下这位this大爷的指向。

this虐我千百遍,不敢不待如大爷!!!
题目①
Code
var a = 10;
function test(){
  a = 5;
  console.log(a);
  console.log(this.a);
  var a ;
  console.log(this.a);
  console.log(a);
}
test(); 
new test();  

当调用test()的时候,控制台分别输出 5、10、10、5
当调用 new test()的时候,控制台分别输出 5、undefined、undefined、5

解析
var a = 10 ==> var window.a = 10 ;
当test()调用的时候,间接也相当于window.test()调用。因此当这个函数执行的时候,这里面的this指向的是window对象,因此this.a 指向的是window = 10;

当new test() 实例化,因此this指向的是这个实例的对象,因此这个新对象的a,并没有直接定义过。所以控制台输出undefined

题目②

Code
var Funllname = "john Doe";
var obj = {
  Funllname:"Colin Thrig",
  prop:{
    getFullname:function(){
      return this.Funllname;
    }
  },
};
 console.log(obj.prop.getFullname());
var test = obj.prop.getFullname;
 console.log(test());

控制台输出
undefined
john Doe

解析

控制台结果1:当obj.prop.getFullname()在调用的时候,相当于执行了其中的函数。而由于调用这个函数的是obj.prop调用的,因此this就直接指向obj.prop,但是obj.prop这个对象当中并没有定义Fullname,因此输出undefined

控制台结果2:当var test = obj.prop.getFullname; 这个时候就间接相当于==>var test = function(){return this.Funllname;}
因此当test()调用的时候,就相当于 ==> window.test();,因此其中的this便指向了window对象,所以便输出了 john Doe

题目③
Code
var sex = "male";
var saySex = {
sex:"female",
saySex:function(){
    function getSex(){
        console.log("this.sex="+this.sex);
        }
    getSex();
    }
}
saySex.saySex(); 

控制台输出
this.sex = male

解析

控制台结果:当saySex.saySex()调用的时候,只是相当saySex的函数被调用。之后在函数中,函数getSex()被调用,此时this便指向getSex().而函数getSex()默认情况下是指向window的,因此这里输出this.sex = male

题目④

Code
var name = "chedabang";
function sayName(){
var a = {
    name:"加一个鸡腿",
    sayName:getName
};

function getName(){
    console.log(this.name);
}

getName(); 
a.sayName(); 
getName.call(a);
}
sayName();

控制台输出
chedabang
加一个鸡腿
加一个鸡腿

解析

当sayName()运行的时候时候,先是里面的第一个函数运行,getName().因此因此其中的this,便默认指向了window,因此this.name ==> chedabang
其次a.sayName()运行,因为sayName = getName。所以即当于getName再次被调用,由于存在调用对象a。因此此时this又重新指向对象a,对象 a 当中存在name属性,因此输出加一个鸡腿
最后 getName.call(a).运行的时候,将对象a给绑定到上面,因此函数里面的this就不指向window,而指向的是绑定的对象a,因此输出 加一个鸡腿

题目⑤

Code
var a = {
    name:"张三",
    sayName:function(){
    console.log("this.name="+this.name);
  }
};
var name = "李四";
function sayName1(){
  var sss = a.sayName;
  sss();
  a.sayName();
  (a.sayName)();
  (b = a.sayName)();
}
sayName1();

控制台输出:
this.name=李四
this.name=张三
this.name=张三
this.name=李四

解析

当sayName1()运行的时候,sayName1函数内部首先是
控制台结果1:var sss = a.sayName ==> var sss = function(){console.log("this.name="+=this.name);} 像前面我们总结的一样函数中调用,因此这里的this指向window对象,因此输出this.name=李四
控制台结果2:a.sayName();这里a直接调用其中的匿名函数,因此此时this指向a,因此a.name = "张三",所有控制台输出this.name=张三

控制台结果3:这里(a.sayName)();其实间接相当于 == a.sayName();这里指的是值立即执行。不管如何始终是对象a在调用sayName这个函数。因此控制台也就跟着一起输出this.name=张三

控制台结果4:和控制台结果3一样,代表变量b立即执行,而b和控制台结果1中sss一样,也属于函数中调用,因此this这里指向window。即控制台输出this.name=李四

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

推荐阅读更多精彩内容