为什么这不能是一个原语?

发布于 2024-12-29 09:53:40 字数 851 浏览 2 评论 0原文

我正在摆弄 JavaScript,并注意到 this 永远不可能是原语。我在说什么?让我解释一下。

以这个函数为例。

function test(){
    return typeof this;
}
test.call('Abc'); // 'object'
test.call(123); // 'object'

正如我所期望的那样,它们都是 'object',而不是 'string''number'

经过一番混乱(以及弄乱 instanceof)后,我明白了发生了什么。 'Abc' 正在转换为 String 对象,123 正在转换为 Number 对象。

无论如何,我的问题是为什么会发生这种情况,以及如何将对象转换回其原始对象?

我知道我可以使用 (String)this(Number)this,但是如果我不知道类型,我该怎么做?

编辑:我试图这样做:

function element(){
    var $e = $(this),
    $d = $e.closest('div');
}
element.call('#myID');

但它不起作用。 this 是一个 String 对象,jQuery 只是创建了一个对象集合,而不是使用选择器来搜索 DOM。

I was messing around with JavaScript, and noticed that this can never be a primitive. What am I talking about? Let me explain.

Take this function for example.

function test(){
    return typeof this;
}
test.call('Abc'); // 'object'
test.call(123); // 'object'

They are both 'object', not 'string' or 'number', like I'd expect.

After a bit of confusion (and messing with instanceof), I figured out what's going on. 'Abc' is being coverted to a String object, and 123 is being converted to a Number object.

Anyway, my question is why does this happen, and how do I convert an object back to its primitive?

I know I could use (String)this or (Number)this, but how can I do that if I don't know the type?

EDIT: I was trying to do this:

function element(){
    var $e = $(this),
    $d = $e.closest('div');
}
element.call('#myID');

and it wasn't working. this is a String object, and jQuery just made a collection of objects instead of using the selector to search the DOM.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

情栀口红 2025-01-05 09:53:40

正如其他人指出的那样,它根据规范被强制为一个对象。

需要注意的重要一点是,如果您处于严格模式,则不会发生强制转换。

"use strict";

function test(){
    return typeof this;
}
test.call('Abc'); // 'string'
test.call(123); // 'number'

所以真正的问题是为什么不使用 strict? ;-)


正如您在评论中指出的,如果您支持不支持严格模式的实现,您应该能够使用 .valueOf()

如果您只期望一个字符串,或者如果您也期望一个数字,但您不介意数字字符串,那么您可以这样做......

(this + '') // "Abc"
(this + '') // "123"

“但是如果我不知道类型,我该怎么做”

如果您想知道它的类型,请使用 Object.prototype 上提供的通用 toString 获取内部[[Class]] 属性。

Object.prototype.toString.call( this ); "[object String]"
Object.prototype.toString.call( this ); "[object Number]"

As others noted, it's coerced to an object as per the spec.

Important thing to note is that if you're in strict mode, the coercion doesn't happen.

"use strict";

function test(){
    return typeof this;
}
test.call('Abc'); // 'string'
test.call(123); // 'number'

So the real question is why aren't you using strict? ;-)


As you noted in your comment, you should be able to use .valueOf() if you're supporting implementations that don't support strict mode.

If you're only expecting a String, or if you're also expecting a Number, but you don't mind a numeric String instead, you could do this...

(this + '') // "Abc"
(this + '') // "123"

"but how can I do that if I don't know the type"

If you want to know its type, use the generic toString available on Object.prototype to get the internal [[Class]] property.

Object.prototype.toString.call( this ); "[object String]"
Object.prototype.toString.call( this ); "[object Number]"
你爱我像她 2025-01-05 09:53:40

我找到了,ECMAScript 5.1

Function.prototype.call

注意 thisArg 值不加修改地作为 this 值传递。这是对第 3 版的更改,其中 undefinednull thisArg 被替换为全局对象,并且 ToObject 应用于所有其他值,并且该结果作为 this 值传递。

基本上它说 undefinednull 作为第一个参数,导致 this 成为全局对象(浏览器中的 window context),所有其他值都使用 ToObject


由于 typeof 的不一致,我建议使用 Object.prototype.toString.call,它在我测试过的每个浏览器中返回一致的值:

Object.prototype.toString.call('foo') //[object String]
Object.prototype.toString.call(10000) //[object Number]
Object.prototype.toString.call(someFunc) //[object Function]
...etc

您可以比较此小提琴中的输出

I found it, ECMAScript 5.1

Function.prototype.call

NOTE The thisArg value is passed without modification as the this value. This is a change from Edition 3, where a undefined or null thisArg is replaced with the global object and ToObject is applied to all other values and that result is passed as the this value.

Basically it says undefined and null as the first parameter cause this to be the global object (window in a browser context), and all other values are converted to an object using ToObject.


Due to the inconsistencies of typeof, I recommend using Object.prototype.toString.call, which returns consistent values in every browser I've tested:

Object.prototype.toString.call('foo') //[object String]
Object.prototype.toString.call(10000) //[object Number]
Object.prototype.toString.call(someFunc) //[object Function]
...etc

you can compare the output in this fiddle

白首有我共你 2025-01-05 09:53:40

规范规定 this 始终是一个对象。

否则,如果 Type(thisArg) 不是 Object,则将 ThisBinding 设置为 ToObject(thisArg)。

The spec says that this is always an object.

Else if Type(thisArg) is not Object, set the ThisBinding to ToObject(thisArg).

许仙没带伞 2025-01-05 09:53:40

我的理解是,this 在面向对象的上下文之外没有任何意义,它始终指向某个对象的实例。所以根据定义它不能是原语。

另外,您的测试函数似乎返回了 test 函数本身的 typeof (在该上下文中是 this),而不是参数的你路过了。

My understanding is, this makes no sense outside an object-oriented context, it will always be pointing to some object's instance. So by definition it cannot be a primitive.

Also, it seems your test function is returning the typeof the test function itself (which is this in that context), and not of the parameters you're passing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文