问题
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.
回答1:
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]"
回答2:
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 aundefined
ornull
thisArg is replaced with the global object andToObject
is applied to all other values and that result is passed as thethis
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
回答3:
The spec says that this
is always an object.
Else if Type(thisArg) is not Object, set the ThisBinding to ToObject(thisArg).
回答4:
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.
来源:https://stackoverflow.com/questions/9039121/why-cant-this-be-a-primitive