美文网首页
[转载]JavaScript的this

[转载]JavaScript的this

作者: 你喜欢吃青椒吗_c744 | 来源:发表于2019-07-29 11:15 被阅读0次

注意:谁调用它,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

相关文章

网友评论

      本文标题:[转载]JavaScript的this

      本文链接:https://www.haomeiwen.com/subject/ibhvrctx.html