We often see some "strange" statements on the Internet or in interview questions, such as
{}+{} // "[object Object][object Object]" {}+[] // 0 []+{} // "[object Object]" []+[] // ""
In Javascript, the +
operator is an overloaded operator that can be used to splice characters. string, and adding two "numbers". Which case is the case depends on the types of parameters on both sides of the operator.
We won’t encounter such troublesome things in daily development, but it’s always good to figure it out. In the specification, Balabala said a lot, which is simply:
1. For native types, as long as one of the parameters is a string, it will be processed by string concatenation, otherwise it will be processed by digital addition. Those that are not numbers will be converted into numbers first and then added.
The native types are: undefined, null, boolean, number, string.
Here are some examples:
0 + '1' // '01' null + 1 // 1 true + 1 // 2 false + 1 // 0 undefined + 2 // NaN, 因为undefined转成Number是NaN
2. For reference types, you need to convert them to native types first, and then add them according to the above rules. How to convert is detailed in the specification, but the specification seems a bit laborious. To put it simply: it is converted into a string by default. If you want to do something special, please override the valueOf()
method.
Let’s take an example:
function Complex(a, b) { this.a = a; this.b = b; } Complex.prototype.valueOf() { return this.a; } new Complex(2, 3) + new Complex(4, 5); // 6
But because Js does not support real operator overloading, that is, it cannot be added to obtain a custom type object, so the above example is rarely used in practical code.
But the current knowledge is enough to answer the original question. But wait, why is {}+[]
different from []+{}
? This is actually a grammatical issue. The former is equivalent to:
{} +[]
is actually two sentences, []
converted into a number is 0. It is easy to verify({}+[]) === '[object Object]'
+[] // 0
Someone may ask, what is new Date()
##valueOf() Isn’t it converted into a number? Why is the addition result still of string type?
Date is connected in string mode, but it will be converted into a number during comparison.
<,
>, so it is necessary to study it , the following js code roughly describes its behavior.
<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">/**
* @param input 即要转换的对象
* @preferredType 期望转换成的类型,可以是string或number
*/
function ToPrimitive(input, preferredType) {
if (typeof input !== 'object') {
return input; // 本来就是原生类型
}
var hint = preferredType || 'default';
if (typeof input['@@toPrimitive'] === 'function') { // @@toPrimitive是个内部方法,这里只是示例说明其工作原理
return input['@@toPrimitive'](input, hint); // 这就是为什么Date能特殊处理的原因
}
if (hint === 'string') {
return input.toString();
}
return input.valueOf();
}</pre><div class="contentsignin">Copy after login</div></div><div class="contentsignin">Copy after login</div></div>Please refer to the specifications for details
{}+{} // "[object Object][object Object]" {}+[] // 0 []+{} // "[object Object]" []+[] // ""
+ operator is an overloaded operator that can be used to splice strings and add two "numbers". Which case is the case depends on the types of parameters on both sides of the operator.
We won’t encounter such troublesome things in daily development, but it’s always good to figure it out. Balabala said a lot in the specification, which is simply:
0 + '1' // '01' null + 1 // 1 true + 1 // 2 false + 1 // 0 undefined + 2 // NaN, 因为undefined转成Number是NaN
valueOf() method.
function Complex(a, b) { this.a = a; this.b = b; } Complex.prototype.valueOf() { return this.a; } new Complex(2, 3) + new Complex(4, 5); // 6
{}+[] different from
[]+{}? This is actually a grammatical issue. The former is equivalent to:
{} +[]
[] converted into a number is 0. It is easy to verify
({}+[]) === '[object Object]'
+[] // 0
new Date() ##valueOf()
Isn’t it converted into a number? Why is the addition result still of string type? <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">new Date().valueOf();
// 1491904757087
1 + new Date();
// "1Tue Apr 11 2017 18:02:16 GMT+0800 (CST)"</pre><div class="contentsignin">Copy after login</div></div><div class="contentsignin">Copy after login</div></div>
This is a special treatment for the Date class, @@toPrimitive. By default, the addition of
is connected in string mode, but it will be converted into a number during comparison. <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">new Date() < new Date(&#39;2018-01-01&#39;)
// true, 现在是2017</pre><div class="contentsignin">Copy after login</div></div><div class="contentsignin">Copy after login</div></div>
Converting reference types to native types is used in many operators, such as
, ></pre>
, so it is necessary to study it , the following js code roughly describes its behavior. <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">/**
* @param input 即要转换的对象
* @preferredType 期望转换成的类型,可以是string或number
*/
function ToPrimitive(input, preferredType) {
if (typeof input !== 'object') {
return input; // 本来就是原生类型
}
var hint = preferredType || 'default';
if (typeof input['@@toPrimitive'] === 'function') { // @@toPrimitive是个内部方法,这里只是示例说明其工作原理
return input['@@toPrimitive'](input, hint); // 这就是为什么Date能特殊处理的原因
}
if (hint === 'string') {
return input.toString();
}
return input.valueOf();
}</pre><div class="contentsignin">Copy after login</div></div><div class="contentsignin">Copy after login</div></div>