[转载]JavaScript的this

注意:谁调用它,this就指向谁

全局执行

  • 浏览器
console.log(this);
// Window {speechSynthesis: SpeechSynthesis, caches: CacheStorage, localStorage: Storage, sessionStorage: Storage, webkitStorageInfo: DeprecatedStorageInfo…}

打印出来了window对象。

  • Node
console.log(this);
// global
  • 总结:在全局作用域中它的 this 执行当前的全局对象(浏览器端是 Window,node 中是 global)。

函数执行

  • 纯粹的函数调用
    最普通的函数使用方法:
function test() {
  console.log(this);
};
test();
// Window {speechSynthesis: SpeechSynthesis, caches: CacheStorage, localStorage: Storage, sessionStorage: Storage, webkitStorageInfo: DeprecatedStorageInfo…}

我们可以看到,一个函数被直接调用的时候,属于全局调用,这时候它的 this 指向 全局对象;

  • 严格模式: 'use strict'
    如果在严格模式的情况下执行纯粹的函数调用,那么这里的的 this 并不会指向全局,而是 undefined,这样的做法是为了消除 js 中一些不严谨的行为:
use strict';
function test() {
  console.log(this);
};
test();
// undefined

当然,把它放在一个立即执行函数中会更好,避免了污染全局:

(function (){
  "use strict";
 console.log(this);
})();
// undefined

作为对象的方法调用

当一个函数被当作一个对象的方法调用的时候:

var obj = {
  name: 'qiutc',
  foo: function() {
    console.log(this.name);
  }
}
obj.foo();
// 'qiutc'

这时候,this 指向当前的这个对象;
如果把对象的方法赋值给一个变量,然后直接调用这个变量呢:

var obj = {
  name: 'qiutc',
  foo: function() {
    console.log(this);
  }
}
var test = obj.foo;
test();
// Window

可以看到,这时候 this 执行了全局,当我们把 test = obj.footext直接把等号右边当做一个函数,并不管什么objtest 直接指向了一个函数的引用,这时候,其实和 obj 这个对象没有关系了,所以,它是被当作一个普通函数来直接调用,因此,this 指向全局对象。重点。

经典例子

var obj = {
  name: 'qiutc',
  foo: function() {
    console.log(this); //直接打印出obj整个对象
  },
  foo2: function() {
    console.log(this); //打印出整个obj对象
    var _this = this;
    setTimeout(function() {
      console.log(this);  // Window
      console.log(_this);  // Object {name: "qiutc"}
    }, 1000);
  }
}
obj.foo2();
obj.foo();
  • 首先,因为谁调用this,this就指向谁,所以,foo和foo2里面的console.log(this)直接指向调用他们的obj对象,打印出Obj整个对象。
  • 然后,在看setTimeout里面的。在外面,var _this = this; 这个this是指向obj的(上面已经打印出来了)。用一个变量 _this 来储存。所以console.log(_this);可以打印出obj对象。因为我们已经用_this来指向obj对象了,所以console.log(this); // Window。this只能指向全局了。
  • 还有一点就是在foo2作用域内非setTimeout作用域内console.log(this);发现打印出obj对象。console.log(_this);也是这样。说明setTimeout块级作用域隔绝了foo2作用域的渗透。

作为一个构造函数使用

在 js 中,为了实现类,我们需要定义一些构造函数,在调用一个构造函数的时候需要加上 new 这个关键字:

function Person(name) {
  this.name = name;
  console.log(this);
}
var p = new Person('qiutc');
// Person {name: "qiutc"}

我们可以看到当作构造函数调用时,this 指向了这个构造函数调用时候实例化出来的对象;

当然,构造函数其实也是一个函数,如果我们把它当作一个普通函数执行,这个 this 仍然执行全局:

function Person(name) {
  this.name = name;
  console.log(this);
}
var p = Person('qiutc');
// Window

其区别在于,如何调用函数(new

箭头函数

在 ES6 的新规范中,加入了箭头函数,它和普通函数最不一样的一点就是 this 的指向了。用闭包来解决 this 的指向问题,用上了箭头函数就可以更完美的解决。

var obj = {
  name: 'qiutc',
  foo: function() {
    console.log(this);
  },
  foo2: function() {
    console.log(this);
    setTimeout(() => {
      console.log(this);  // Object {name: "qiutc"}
    }, 1000);
  }
}
obj.foo2();

可以看到,在 setTimeout 执行的函数中,本应该打印出在 Window,但是在这里 this 却指向了 obj,原因就在于,给 setTimeout 传入的函数(参数)是一个箭头函数:

箭头函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

根据例子我们理解一下这句话:
obj.foo2() 执行的时候,当前的 this 指向 obj;在执行 setTimeout 时候,我们先是定义了一个匿名的箭头函数,关键点就在这,箭头函数内的 this 执行定义时所在的对象,就是指向定义这个箭头函数时作用域内的 this,也就是 obj.foo2 中的 this,即 obj;所以在执行箭头函数的时候,它的 this -> obj.foo2 中的 this -> obj

简单来说, 箭头函数中的 this 只和定义它时候的作用域的 this 有关,而与在哪里以及如何调用它无关,同时它的 this 指向是不可改变的。这个箭头函数在foo2的作用域下,所以就指向foo2

所以对于箭头函数,只要看它在哪里创建的就行。

转载于

JavaScript 中的 this

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 葡萄藤PPT JS中this的指向 大家好,我是IT修真院郑州分院第6期的学员王栋,一枚正直、纯洁、善良的前端程序...
    17064阅读 3,795评论 0 2
  • 1.概念 在JavaScript中,this 是指当前函数中正在执行的上下文环境,因为这门语言拥有四种不同的函数调...
    BluesCurry阅读 4,892评论 0 2
  • 前言 本文为学习过程中的this小节,作为一名JavaScript自学未成才的编程人员,还没从“原型继承”中回过神...
    01_Jack阅读 4,093评论 0 3
  • 在面向对象的语言中(例如Java,C#等),this含义是明确且具体的,即指向当前对象。一般在编译期绑定。而在ja...
    一木_qintb阅读 3,064评论 0 0
  • 函数和对象 1、函数 1.1 函数概述 函数对于任何一门语言来说都是核心的概念。通过函数可以封装任意多条语句,而且...
    道无虚阅读 10,229评论 0 5

友情链接更多精彩内容