JavaScript 中的 This

Photo by sydney Rae on Unsplash

this 所指向的对象与运行时上下文进行绑定,这就会导致在不同的场景下,函

数的最终运行结果不一样。但是这种灵活的构造给了函数更多的复用机会。

this 所指向的上下文或者说是对象,是在函数调用的时候决定的。但是也无外

两个场景—— this 在函数中和 this 不在函数中。

this 不在函数中

若 this 不在任何一个 function 中,那么 this 默认指向的是 module.exports

console.log(this); // {} 

module.exports.foo = 5;

console.log(this); // { foo:5 }

this 在函数中

在这种场景下,this 存在于一个对象的函数中。要看分清 this 的作用域,

只需看 Object.method 中 Object 是什么。

方法在对象中

在这个例子中,我们通过 Person.getName() 来进行调用。那么,此时 this 指

向的是 Person 这个对象。

const Person = {
  name: "Tim",
  age: 28,
  getName: function() {
    console.log(this);
    console.log("name:" + this.name + ", age:" + this.age);
  }
};

Person.getName();
// { name: 'Tim', age: 28, getName: [Function: getName] }
// name:Tim, age:28

方法在原型中

类似的,假设我们通过原型链构造一个类,然后通过对象的实例调用方法

p.getName();

那么,此时 this 指向的是 Person 这个对象。可以看到此时 this 指向的是类的

一个实例 p。

function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.getName = function() {
  console.log(this);
  console.log("name:" + this.name + ", age:" + this.age);
};

const p = new Person("Tim", 28);
p.getName();
// Person { name: 'Tim', age: 28 }
// name:Tim, age:28

其他

若 this 在函数内部,且这个函数不属于任意对象,那么 this 默认指向的是

global 对象。

function getName() {
  console.log(this); 
  console.log("name:" + this.name + ", age:" + this.age);
}

getName(); 
// global 
// name:undefined, age:undefined

陷阱

承接上面的例子,假如我们想复用现有的方法,那 this 的作用域也在变化。

假如我们直接调用原型上的方法。那么此时指向的是 Person.prototype

Person.prototype.getName();
// Person { getName: [Function] } - Person.prototype
// undefined, age:undefined

假如我们用一个变量来引用这个方法,因为此时 t 所在的环境是全局的,

所以此时 t 指向的是 global。

let t = Person.prototype.getName;
t();
// global
// name:undefined, age:undefined

总结

NodeJS 下 this 的作用域在函数调用时确定。

若 this 不在函数中,那么 this 默认指向的是 module.exports。

若 this 在函数内部且这个函数属于某个对象 , 该对象就是 this 的作用域。

若 this 在函数内部且这个函数不属于任意对象,global 就是 this 的作用域。

参考链接

Meaning of “this” in node.js modules and functions

How does the “this” keyword work?

JavaScript 的 this 原理

What is “this”?

Object methods, “this”

发表评论

电子邮件地址不会被公开。 必填项已用*标注