What is the result of adding an Object and an Array in javascript?
I tried this code in the address bar:
javascript: alert({} + [])
The result is: [object Object].
javascript: alert(typeof ({} + [])开发者_如何学Python)
The result is: string.
Can somebody explain to me what's going on?
The concatenation operator (+) concatenates two string values together. If you give it things that are not string values, then it calls the .toString()
method on them first.
In response to the comment below, "Yes it does!"
Object.prototype.toString = function () { return "a"; };
Array.prototype.toString = function () { return "b"; };
var foo = {} + [];
alert(foo); // alerts 'ab'
Without the above modifications to the prototypes, if you have alert({} + [])
then you are taking {}.toString()
(which is "[Object object]"
) and [].toString()
(which is ""
as the array is empty), then concatenating them (which is still "[Object object]"
). This is a string and typeof
will tell you that it is a string.
It looks like because the +
operator is not defined to accept arguments as one []
and one {}
, it basically converts both to strings (makes more sense than trying to cast them into numbers) and then applies +
as the concatenation operator.
Edit: In response to the changed question, I think they are still being converted into a string first. Here's a session in spidermonkey where I tried it out:
js> x=[]+{}
[object Object]
js> z=x[0]
[
js> x.length
15
js> x=[]+{}
[object Object]
js> x.length
15
js> x[0]
[
js> x[1]
o
js> for (var i=0;i<x.length;i++) {print(x[i]);}
[
o
b
j
e
c
t
O
b
j
e
c
t
]
js> typeof(x)
string
js> print(x)
[object Object]
What is happening is that the result of {}+[]
is a string, but not en empty string. Rather it is the string "[object Object]".
It's a bit more complex.
You'll find a very good explanation how it works here: http://www.adequatelygood.com/2010/3/Object-to-Primitive-Conversions-in-JavaScript
But it seems the way ben cherry described did changed (also what I regonized). If you will run his example:
function population(country, pop) {
return {
country: country,
pop: pop,
toString: function () {
return "[Population " +
"\"" + country + "\" " +
pop +
"]";
},
valueOf: function () {
return pop;
}
};
}
var america_pop = population("USA", 350e6);
var mexico_pop = population("Mexico", 200e6);
var canada_pop = population("Canada", 200e6);
alert(america_pop); // [Population "USA" 350000000
var north_america_pop = america_pop + mexico_pop + canada_pop;
alert(north_america_pop); // 750000000
This isn't true anymore, the alerts will be:
350000000
750000000
alert(obj) call valueOf() not toString() anymore, execpt if you use Array.join
alert([america_pop]); // [Population "USA" 350000000
There was already a thread about: valueOf() vs. toString() in Javascript
They clearify that, valueOf is always called when [hint] is a number and that's always the case, except if you join an Array. that's confusing, because if you call 'string' + 'string' this is definitely a string context, but JS will first take look at the number context, and call always the valueOf() method not toString() if it's a primitive value
I'm afraid it's a little but more complicated than how it is explained here.
The question's title is:
What is the result of adding an Object and an Array in JavaScript?
And it then the question asks about the {}+[]
expression, which everyone here assumes that evaluates to '[object Object]'
- but does it always?
Press Shift+Control+J right now and type {}+[]
at the >
prompt:
Maybe it's a browser bug? Let's try the same in Node:
Something interesting is going on here.
The plus ( +
) - which is actually called the "addition operator" and not the "concatenation operator" as someone wrote here - see ECMA-262, 6th Edition, Section 12.7.3 - The Addition operator ( + ) - either performs string concatenation or numeric addition, which is very important to understand examples like this.
Someone once asked me a question like this:
If alert({}+[])
shows '[object Object]'
and x = {}+[]
puts '[object Object]' into x
then why writing {}+[]
in the Console or Node REPL gives 0
?
The answer is that while using the plus operator on object and array coverts them to strings - the string '[object Object]'
and an empty string, respectively - here we are in fact not adding and object to an array! The {}
is interpreted as an empty block and evaluated to nothing, so the +
is now evaluated as a unary operator coercing the []
array to a number, which happens to be zero for an empty array - but it is not the number of elements, but rather 0 for an empty array, the first element converted to a number if it can be or NaN if it can't for one-element arrays, and NaN for any arrays with more than one element.
Some more interesting results, try all combinations of {}
and []
with +
, -
, *
and /
operators:
$ node
> []+[]
''
> {}+{}
'[object Object][object Object]'
> []+{}
'[object Object]'
> {}+[]
0
> []-[]
0
> {}-{}
NaN
> []-{}
NaN
> {}-[]
-0
> []*[]
0
> {}*{}
NaN
> []*{}
NaN
> {}*[]
... ^C
> []/[]
NaN
> {}/{}
NaN
> []/{}
NaN
> {}/[]
SyntaxError: Invalid regular expression: missing /
at Object.exports.createScript (vm.js:24:10)
at REPLServer.defaultEval (repl.js:137:25)
at bound (domain.js:250:14)
at REPLServer.runBound [as eval] (domain.js:263:12)
at REPLServer.<anonymous> (repl.js:392:12)
at emitOne (events.js:82:20)
at REPLServer.emit (events.js:169:7)
at REPLServer.Interface._onLine (readline.js:210:10)
at REPLServer.Interface._line (readline.js:546:8)
at REPLServer.Interface._ttyWrite (readline.js:823:14)
This is one of the best ways to learn all of the quirks of the languages inside out.
Basically the toString
method will be invoked. You can actually override the default behavior by writing a toString
method that returns a number.
var obj1 = {
toString: function () {
return 1;
}
},
obj2 = {
toString: function () {
return 2;
}
};
alert(typeof (obj1 + obj2));
精彩评论