关于非箭头函数中this指向哪个对象的问题

回家的路上,我试图忘掉玛利亚·塞克斯,当我爸跟我说晚安的时候--他每次喝完一瓶啤酒就会醉过去,可今天他喝了两瓶(惊叹!)--我试着忘记玛利亚·塞克斯。半小时以后,伊奇来到我的房里,刚洗完淋浴,散发着清新的味道,穿着破烂的“探险家朵拉”睡衣,给我脸颊上来了一个邋遢的湿吻,我试着忘记她;一个小时之后,我妈来到房间门外,说:“我真为你骄傲,萨姆。”这时,我还在想着她。 --《忽然七日》

每个函数内部都有两个特殊的对象,分别是arguments对象和this对象。对于arguments对象,我们知道他是一个类数组,里面的项是传递进来的参数;还需要注意的地方是它还具有一个callee属性,arguments.callee属性的值就是函数本身。同时每个函数都包含有下面三个属性:length,prototype,caller。length属性表明函数所期望接收的参数个数;prototype属性就不解释了;caller属性的值是调用该函数的那个函数的一个引用。

而我们今天要谈的就是函数内部的一个特殊的对象——this。this引用的是函数据以执行的环境对象,对于非箭头函数来说:具体指向哪个对象取决于函数调用时所处的环境,而不是函数被声明时的那个环境;但是对于的箭头函数的情况便是和此相反:具体指向哪个对象取决于函数被声明时所处的那个环境,而不是被调用时所处的环境。

分析普通函数的调用情况,大致可以分为下面几种:

  • 1.作为对象的方法调用;
  • 2.作为普通函数被调用;
  • 3.作为构造器函数被调用;
  • 4.被某些能够延长作用域链的函数间接调用,比如Function.prototype.call和Function.prototype.bind函数。

这里既然提到了Function.prototype.apply(),Function.prototype.call()的话,那就打个岔吧,在加入Function.prototype.bind(),下面捋一捋他们的区别。

首先,三个函数都能够改变函数所处的环境对象。其中apply()和call()是改变后立马执行的,这两者之间的区别是apply()能够接收数组以及类数组对象作为第二个参数以便传入多个参数;而call()就不行,他必须显式的把每一个参数分别作为call的第二参数,第三参数依次传递过去。而对于bind函数来说,这个方法会创建一个函数的实例,他的this值会被绑定到那个传入的参数上。和前两者的关键区别在于,他不执行。需要注意的地方是:如果我们对上面三个函数传入的环境对象是null或者undefined的话,那么函数的实际执行环境将会是全局执行环境,在浏览器中就是window,在node环境里就是global。下面可以举个例子看一下:

var a = 999;
function fun(){console.log(this.a);}
fun.apply(null);//9

言归正传,下面来讨论一下在不同的调用函数的方式下this指向哪个对象的分析方法:

  • 1.当作为对象方法被调用时,this指向该对象;
  • 2.当作为普通函数调用时,this总是指向全局对象。这一点是很让人迷惑的,看看下面的这个例子:
var a = 999;
var obj = {"a" : 111, "fun": function(){
  console.log(this.a);
  var test = function(){console.log(this.a);
  test();
}};
obj.fun();//111/n999

可以很明显的看到,我们的fun()被调用是返回的是999,说明他的执行环境是全局环境。对于这种情况,有的时候的确是会给我们带来挺多不必要的麻烦,比如说下面这个例子:

window.id = "window";
var callback = function(){
  console.log(this.id);
};
document.getElementById("div1").onclick = function(){
  console.log(this.id);//"div1"
  callback();//"window"
}

对于这个callback而言,我们最初是希望它的环境对象是div1的DOM对象的,然而实际上却被绑定到了全局对象window上,而这并不是我们所希望的。当然,这样做也是具有解决办法的,像下面这样。

window.id = "window";
document.getElementById("div1").onclick = function(){
  var that = this;
  console.log(this.id);//"div1"
  var callback = function(){console.log(that.id);};
  callback();//"div1"
}

或者通过call和apply后者bind来改变环境对象。

window.id = "window";
var callback = function(){
  console.log(this.id);
};
document.getElementById("div1").onclick = function(){
  console.log(this.id);//"div1"
  callback.apply(this);//"div1"
}
  • 3.作为构造器函数调用:凡是正常的构造器函数,他们之中的this都是引用着构造器所返回的对象的。
  • 4.当函数利用apply()或者call()以及bind()改变环境对象时,函数的环境对象为这三个方法所传入的那第一个参数对象。

拓展:思考下面这样这样会不会出错

var getId = document.getElementById;
getId("someID");

答案是会出错的。首先,需要明确的是:函数的名字仅仅是一个包含指针的变量而已。因此,即使在不同的环境中执行,他们所指向的都是同一个函数。因此,我们的document.getElementById和getId都是指向同一个函数的,不同的时他们所指向的环境对象的不同,对于前者来说他的环境对象时document而后者的环境对象确实window。而对于该函数的内部实现机理来说,我们时必须要求为document的,所以调用getID的话会出错。

我们活着的每一刻背后都隐藏着成千上万个不一样的瞬间。

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

推荐阅读更多精彩内容