如何在 Javascript 中获取此关键字的类型?

How to get type of this keyword in Javascript?

我正在操纵 Object 的原型,以便我可以添加一些扩展方法。
我发现 typeof 运算符总是 returns object 如果操作数是 this:

Object.prototype.logType = function () { console.log(typeof this); }
"Hello".logType() 

上面代码的输出是 object 而不是 string。我知道 JavaScript 中的所有内容确实都是 object,但是我需要知道 this 值的确切类型。我怎样才能做到这一点?

当你在一个原语上调用一个方法时,JS 会自动将该原语包装在它的关联对象包装器中,所以:

"Hello".logType()  

变成:

new String("Hello").logType() 

因此,this 在您的 logType 函数内部引用包装的原始值,为您提供一个对象。你可以调用.valueOf()来获取包裹在对象中的原始值:

Object.prototype.logType = function () { console.log(typeof this.valueOf()); }

"Hello".logType(); // string
(1).logType(); // number
true.logType(); // boolean
1n.logType(); // bigint
Symbol().logType(); // symbol
(() => {}).logType(); // function
({}).logType(); // object

或者,您可以按照评论中的建议使用严格模式,因为这会将 this 保留为原始原始值:

Object.prototype.logType = function () { "use strict"; console.log(typeof this); }

"Hello".logType(); // string
(1).logType(); // number
true.logType(); // boolean
1n.logType(); // bigint
Symbol().logType(); // symbol
(() => {}).logType(); // function
({}).logType(); // object

当在严格模式 之外作为 this 传递时,您会遇到一种非常罕见的情况,即您会遇到包装对象形式的原语(“盒装”),作为 String 的实例:

因此,您可以使用 this instanceof String 而不是 typeof this === 'string' 检查是否在字符串上调用了您的方法。如果你想区分继承自 String 的字符串和对象,你可以使用 this.constructor === String

要返回“常规”字符串(或 Number 的数字,或 Boolean 的布尔值等),您可以调用 this.valueOf()

(这意味着您也可以编写 typeof this.valueOf() - 但请注意,这可能会产生误导,因为任何对象都可以 return,比方说,来自其 valueOf 方法的字符串实际上没有最初是一个字符串。)

注意:您无法通过这种方式区分 'abc'.yourMethod()new String('abc').yourMethod(),因为无论哪种方式您都会得到 String 的实例。

(同样有趣:似乎对于像 BigIntSymbol 这样的新类型,您不能手动创建这样的包装器实例,new BigInt(1n) 会失败。但是 (function () { return this }).call(1n) 会达到同样的效果,虽然我不知道为什么有人会想要那个...)


综上所述:最简单 获得您想要的确切行为(this 是实际字符串)的方法是在上下文中定义您的函数严格模式:

(function {
  'use strict'
  Object.prototype.logType = function () { console.log(typeof this); }
})()

现在它将按预期工作。