无标题文章this的用法

原文链接:https://segmentfault.com/a/1190000008590012

一、全局上下文

在全局运行上下文中(在任何函数体外部),this指代全局对象,无论是否在严格模式下。在浏览器中,全局对象为window对象。

console.log(this.document === document); // true
console.log(this === window); // true
this.a = 37;
console.log(window.a); // 37

二、函数上下文

在函数内部,this的值取决于函数是如何调用的。

1、直接调用
在非严格模式下,this的值不会在函数执行时被设置,此时的this的值会默认设置为全局对象。
function foo(){
 return this;
}

foo() === window; // true
在严格模式下,this将保持他进入执行环境时的值,所以下面的this将会默认为undefined
function foo(){
  "use strict"; // 严格模式
  return this;
}

foo() === undefined; // true
在严格模式下,如果this未被执行的上下文环境定义,那么它将会默认为undefined。
2、对象方法中的this

当以对象里的方法的方式调用函数时,它们的this是调用该函数的对象。

下面的例子中,当obj.f()被调用时,函数内的this将绑定到obj对象。
var obj = {
    prop: 37,
    foo: function() {
       return this.prop;
    }
};

console.log(obj.foo()); // 37

注意,在何处或者如何定义调用函数完全不会影响到this的行为。

在上一个例子中,我们在定义obj的时候为其成员foo定义了一个匿名函数。但是,我们也可以首先定义函数然后再将其附属到obj.foo。这样做this的取值也和上面一致:

 var obj = { prop: 37 };

function independent() {
   return this.prop;
}

obj.foo = independent;

console.log(obj.foo()); // 37
这说明this的值只与函数foo作为obj的成员被调用有关系。

类似的,this的绑定只受最靠近的成员引用的影响。

在下面的这个例子中,我们把一个方法g当作对象obj.b的函数调用。

在这次执行期间,函数中的this将指向obj.b。事实上,这与对象本身的成员没有多大关系,最靠近的引用才是最重要的。
var obj = { prop: 37 };

function independent() {
  return this.prop;
}

obj.b = {
  g: independent,
  prop: 42
};

console.log(obj.b.g()); // 42
3、原型链中的this

相同的概念在定义在原型链中的方法也是一致的。

如果该方法存在于一个对象的原型链上,那么this指向的是调用这个方法的对象,表现得好像是这个方法就存在于这个对象上一样。
var obj = {
   f : function(){ 
    return this.a + this.b; 
  }
};
var p = Object.create(obj);
p.a = 1;
p.b = 4;

console.log(p.f()); // 5

在这个例子中,对象p没有属于它自己的f属性,它的f属性继承自它的原型。但是这对于最终在obj中找到f属性的查找过程来说没有关系;查找过程首先从p.f的引用开始,所以函数中的this指向p。也就是说,因为f是作为p的方法调用的,

所以它的this指向了p。这是JavaScript的原型继承中的一个有趣的特性。
4、getter与setter中的this

相同的概念也适用时的函数作为一个getter或者setter调用。作为getter或setter函数都会绑定this到从设置属性或得到属性的那个对象。

function modulus(){
   return Math.sqrt(this.re * this.re + this.im * this.im);
}

var obj = {
  re: 1,
  im: -1,
  get phase(){
    return Math.atan2(this.im, this.re);
  }
};

Object.defineProperty(obj, 'modulus', {
  get: modulus,
  enumerable: true,
  configurable: true
});

console.log(obj.phase, obj.modulus); // -0.785 1.414
5、构造函数中的this
当一个函数被作为一个构造函数来使用(使用new关键字),它的this与即将被创建的新对象绑定。

注意:当构造器返回的默认值是一个this引用的对象时,可以手动设置返回其他的对象,如果返回值不是一个对象,返回this。

function Fn(){
   this.a = 37;
}

var obj = new Fn();
console.log(obj.a); // 37

function Foo(){
  this.a = 37;
  return { a: 38 };
}

obj = new Foo();
console.log(obj.a); // 38
6、call和apply

当一个函数的函数体中使用了this关键字时,通过所有函数都从Function对象的原型中继承的call()方法和apply()方法调用时,

它的值可以绑定到一个指定的对象上。
 function add(c, d){
   return console.log(this.a + this.b + c + d);
 }

 var obj = {
    a: 1,
    b: 3
 };

 add.call(obj, 5, 7); // 1 + 3 + 5 + 7 = 16
 add.apply(obj, [10, 20]); // 1 + 3 + 10 + 20 = 34

使用call和apply函数的时候要注意,如果传递的this值不是一个对象,JavaScript将会尝试使用内部 ToObject操作将其转换为对象。因此,如果传递的值是一个原始值比如7或foo,那么就会使用相关构造函数将它转换为对象,所以原始值7通过new Number(7)被转换为对象,而字符串foo使用new String('foo')转化为对象,例如:

function bar() {
  console.log(Object.prototype.toString.call(this));
}

bar.call(7); // [object Number]
7、bind()方法

ECMAScript 5引入了Function.prototype.bind。调用fn.bind(someObject)会创建一个与fn具有相同函数体和作用域的函数,但是在这个新函数中,this将永久地被绑定到了bind的第一个参数,无论这个函数是如何被调用的。

function fn(){
  return this.a;
}

var g = fn.bind({ a: "azerty" });
console.log(g()); // "azerty"

var obj = {
  a: 37,
  foo: fn,
  go: g
};
console.log(obj.foo(), obj.go()); // 37, "azerty"
8、DOM事件处理函数中的this

当函数被用作事件处理函数时,它的this指向触发事件的元素(一些浏览器在动态添加监听器时不遵守这个约定,除非使用addEventListener)。

// 获取文档中的所有元素的列表
var elements = document.getElementsByTagName('*');

for(var i = 0; i < elements.length; i++){
  // 当元素被点击时,就会变成蓝色
  elements[i].addEventListener('click', function (e) {
    e.stopPropagation();
    console.log(this);
    console.log(e.currentTarget);
    console.log(e.target);
 // 上面3个值是一样的
    this.style.backgroundColor = '#A5D9F3';
  });
}
9、内联事件处理函数中的this
当代码被内联处理函数调用时,它的this指向监听器所在的DOM元素:
<button onclick="alert(this.tagName.toLowerCase());">
  Show this
</button>

上面的alert会显示button。注意只有外层代码中的this是这样设置的:

<button onclick="alert((function(){return this})());">
  Show inner this
</button>

在这种情况下,没有设置内部函数的this,所以它指向global/window对象(即非严格模式下调用的函数未设置this时指向的默认对象)。

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

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,599评论 18 139
  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,679评论 0 9
  • 与其他语言相比,函数的this关键字在JavaScript中的表现略有不同,此外,在严格模式和非严格模式之间也会有...
    codingC阅读 565评论 0 0
  • 官方中文版原文链接 感谢社区中各位的大力支持,译者再次奉上一点点福利:阿里云产品券,享受所有官网优惠,并抽取幸运大...
    HetfieldJoe阅读 6,922评论 15 54
  • 每个人心中有个小小的世界 安静的角落里有纷飞的白雪 那是祥和的感觉 每个人心中有个美好 圣诞节温暖的教堂里唱出了喜...
    陌上紫烟阅读 259评论 0 1