JavaScript 之 this

在 JavaScript 中,this 的值是动态的,即一个函数中在不同的情况下被调用,this 的值可能是不同的。

全局的 this

在浏览器中,全局的 this 就是 window。

this === window; // true

this 在函数中的值

JavaScript 中函数的被调用主要有几种方式:

  • 作为对象的方法
  • 作为函数
  • 作为构造函数
  • 使用 apply 或 call

不同的调用方式,this 的值是不同的。除此之外,bind 也会改变 this 的值。

下面就具体解释下 this 在函数中的值。

作为对象的方法

作为对象的方法时,this 为对象。

var obj = {
  name: 'obj',
  describe: function(){
    return 'I am a ' + this.name;
  }
};
obj.describe(); // 'I am a obj'

作为函数

作为函数时,this 为 window(在浏览器中)。

function foo(){
  return this === window;
}
foo(); // true

var obj = {
  name: 'obj',
  describe: function(){
    return 'I am a ' + this.name;
  }
};
window.name = 'window';
var bar = obj.describe;
bar(); // 'I am a window'

使用 apply 或 call

使用 apply 或 call,this 为 apply 或 call 传入的第一个参数。

function foo(){
  return this.name;
}
var obj = {name: 'obj'};
foo.apply(obj); // 'obj'
foo.call(obj); // 'obj'

作为构造函数

作为构造函数, this 会指向构造函数的原型对象。

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

MyClass.prototype = {
  name: 'My class'
};

var obj = new MyClass(); // 控制台输出 'My class'

使用 bind

使用 bind,this 为 bind 的第一个参数。

function foo(){
  return this.name;
}

var bar = foo.bind({name: 'bar'});
bar(); // 'bar'

练习题

下面代码中 1 ~ 7 的位置输出的值分别是什么?

(function() {
    console.log('*********0*********');
    console.log(this === window);
    var dog = {
      name: '旺财',
      describe: function() {
        console.log('汪汪,我是' + this.name);
      }
    };
    console.log('*********1*********');
    dog.describe(); // 1

    var Cat = function(name) {
      this.name = name;
    };
    Cat.prototype = {
      describe: function() {
        console.log('喵喵,我是' + this.name);
      }
    };

    var cat = new Cat('咪啊');
    console.log('*********2*********');
    cat.describe(); // 2

    dog.catLikeDescribe = cat.describe;
    console.log('*********1*********');
    dog.catLikeDescribe(); // 3

    window.name = '全局对象';
    var describe = dog.describe;
    console.log('*********4*********');
    describe(); // 4

    dog.describeWithOther = function(describeFn) {
      this.describe();
      describeFn();
    };
    console.log('*********5*********');
    dog.describeWithOther(cat.describe); // 5
    console.log('*********6*********');
    dog.describeWithOther.call(cat, cat.describe); // 6
    console.log('*********7*********');
    dog.describeWithOther(cat.describe.bind(cat)); // 7

  })();

参考


本文遵守创作共享CC BY-NC-SA 4.0协议 网络平台如需转载必须与本人联系确认。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏北京马哥教育

Python神器列传:函数神器functools模块全解析

21930
来自专栏开发与安全

从零开始学C++之模板(三):缺省模板参数(借助标准模板容器实现Stack模板)、成员模板、关键字typename

一、缺省模板参数 回顾前面的文章,都是自己管理stack的内存,无论是链栈还是数组栈,能否借助标准模板容器管理呢?答案是肯定的,只需要多传一个模板参数即可,而且...

21100
来自专栏烂笔头

Python标准库笔记(9) — functools模块

20030
来自专栏Java帮帮-微信公众号-技术文章全总结

Java基础-11总结Eclipse使用,API,Object类

1:Eclipse的概述使用(掌握) 1:Eclipse的安装 2:用Eclipse写一个HelloWorld案例,最终在控制台输出你的名字 A:创建项目 ...

36660
来自专栏数据结构与算法

洛谷P1966 火柴排队(逆序对)

首先要保证权值最小,不难想到一种贪心策略,即把两个序列中rank相同的数放到同一个位置

14710
来自专栏desperate633

深入理解SortSet类型的使用及应用Redis 有序集合(sorted set)SortSet的应用场景SortSet的常用命令

Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。

38420
来自专栏Java技术分享

反射类的main方法

有时候我们需要调用一个类的Main方法,也可说是执行这个类的代码。但是这时候这个类我们还没有写好,或者这个类是通过网络运行时传给我们的,我们就不可能在程序中知道...

20660
来自专栏PHP实战技术

PHP面试常考易错题之变量作用域解析

PHP面试中变量作用域是面试中常常出现的问题,也是必考的问题,下面就给大姐讲解一下在面试中注意的点:

14040
来自专栏yang0range

Java的面试基础题(二)

1)特点:存储对象;长度可变;存储对象的类型可不同 2)Collection (1)List:有序的;元素可重复,有索引 (add(index, elem...

19520
来自专栏Java编程

《Effective Java》——读后总结

这本书在Java开发的行业里,颇有名气。今天总算是粗略的看完了...后面线程部分和序列化部分由于心浮气躁看的不仔细。这个月还剩下一周,慢慢总结消化。

46710

扫码关注云+社区

领取腾讯云代金券