Have you ever been asked weird and detailed questions in a job interview?

[]==[] //false []==! [] //true {}==! {} //false {}==! [] //VM1896:1 Uncaught SyntaxError: Unexpected token == ! []=={} //false []==! {} //true undefined==null //trueCopy the code

Do you want to slap the interviewer in the face? Ha ha, is not after seeing a face meng force, two faces at a loss? I thought, what is this

In fact, these are all paper tigers, know the principle and conversion rules, understand these easy, easy to fry chicken, really not difficult, we want to hit all paper tigers, do not believe?

[] == [] and [] ==! [] Why is the output true and not something else?

[]==[] Why false

Based should know object is a reference type, a little js will glance out [] = = [] output will be false, because the [] on the left and the right of the [] looks long, but their address and reference is different, this is the comparison of the same type, so relatively less trouble, temporarily don’t understand [] = = [] : [] : [] : [] : [] : [] : [] : [] : [] : [] : [] : [] : [] : [] : [] : [] : []

Front end basic advance (1) : memory space detailed diagram

Variable objects and heap memory

Simple types are in the stack and object types are in the heap var a = 20; var b = 'abc'; var c = true; Var e= {m: 20}// The address is assumed to be 0x0012ff7c var e= {m: 20}// A new memory space is assumed to be 0x0012ff8f console.log(e==d); //falseCopy the code
So why are the reference values in the heap, and the original values in the stack, aren’t they all in memory, why aren’t they all together? Well, let’s find out! (Digress)

First, let's look at the code:

function Person(id,name,age){ this.id = id; this.name = name; this.age = age; } var num = 10; var bol = true; var str = "abc"; var obj = new Object(); var arr = ['a','b','c']; Var person = new person (100," Fool's motto ",25);Copy the code

Then let’s look at the memory analysis diagram:

The variables num, BOL, and STR are basic data types, and their values are stored directly on the stack. Obj, Person, and ARr are compound data types, and their reference variables are stored on the stack, pointing to the actual objects stored in the heap. As you can see from the figure above, we can't manipulate the data in the heap directly, that is, we can't manipulate objects directly, but we can manipulate objects through references to objects in the stack, just like we can manipulate a TV with a remote, except that the TV itself has no control buttons.

Now let’s answer the question why reference values are in the heap and original values are in the stack:

Remember a word: energy is balanced, nothing more than time for space, space for time problem heap is bigger than stack, stack is faster than stack, object is a complex structure, and can be expanded freely, such as: array can be infinite expansion, the object can add attributes freely. They are placed in the heap so as not to affect stack efficiency. Instead, it references the actual object in the heap and operates on it. Compared to simple data types, simple data types are more stable and take up less memory. Simple data types are not put in the heap because it takes time to find the actual object by referring to it in the heap, and the combined cost is much greater than the cost of getting the actual value directly from the stack. So the values of simple data types are stored directly on the stack.

Understand JS memory allocation

The god that knows certainly can drift, here basically give computer foundation weak child shoe fills a class.

[] = =! [] Why true?

First step: you need to understand what the ECMAScript specification of == really means GetValue takes the value of a subexpression (eliminating lvalue references) in the expression [] ==! In [], the result of [] is a reference to an empty array (arrays are reference types, as described above), and! [], which returns false as required in sections 11.4.9 and 9.2.

First let’s look at the precedence of the operator:

Just see here is not gnashing teeth, the fun is still coming, ha ha

! Taking the inverse operator takes precedence over ==, so let’s see first! How is it defined in ECAMScript?

So! [] will end with a Boolean value (this is crucial in relation to the match selection below).

The behavior of comparing the two is in section 11.9.3, so turn to 11.9.3:

In this algorithm, [] is Object,! [] ==! [] ==! [] matches condition 8, so [] == ToNumber(Boolean) is recursively called for comparison.

[] Returns true or false. This is not up to you or me. The ECMAScript specification defines the result as true or false:

[] is an object, so the value of the corresponding Boolean object is true; So! The corresponding Boolean value for [] is false and then compares [] == ToNumber(false)

Look again at the conversion of Number in the ECMAScipt specification

It can be concluded that the comparison at this time is []==0;

ToPrimitive(x) == y if Type(x) is Object and Type(y) is String or Number. Can be compared with the picture above.

ToPrimitive calls toString by default (as in 8.2.8), so ToPrimitice([]) equals the empty string.

The ECMAScript standard defines the ToPrimitice method:

Is not to see this definition, or a face meng force,ToPrimitive this hell what thing? Doesn’t that mean nothing?

JS::ToPrimitive

I have checked the information, and what I want to say can be summarized as follows:

ToPrimitive(obj,preferredType) takes two arguments, the first obj is the converted object, The second preferredType is the type you want to convert to (default null, accept Number or String). When executing ToPrimitive(obj,preferredType) if the second parameter is null and obj is a Date instance, In other cases, the preferredType is set to Number. If the preferredType is Number, ToPrimitive executes as follows: 1. If obj is the original value, return it; 2. Otherwise, call obj.valueof () and return the original value if the result is executed. 3. Otherwise, call obj.toString() and return it if the result is original; 4. Otherwise, an exception is thrown. If the preferredType is String, swap steps 2 and 3 above, i.e. If obj is the original value, return it; 2. Otherwise, call obj.toString() and return it if the result is original; 3. Otherwise, call obj.valueof () and return the original value if the result is executed. 4. Otherwise, an exception is thrown.Copy the code

Obj.valueof () = obj.tostring () = obj.tostring () = obj.tostring ();

ToString is used to return a string representation of an object.

var obj = {}; console.log(obj.toString()); //[object Object] var date = new Date(); console.log(date.toString()); //Sun Feb 28 2016 13:40:36 GMT+0800Copy the code

The valueOf method returns the original valueOf an object, which may be a string, value, bool, etc., depending on the object.

var obj = { name: "obj" }; console.log(obj.valueOf()); //Object {name: "obj"} var arr1 = [1]; console.log(arr1.valueOf()); //[1] var arr2 = []; console.log(arr2.valueOf()); Var date = new date (); console.log(date.valueOf()); //1456638436303 As shown in the code, three different object instances called valueOf return different dataCopy the code

Primitive values refer to one of the five basic data types [‘Null’,’Undefined’,’String’,’Boolean’,’Number’].

With that in mind, here’s a simple example:

var a={}; ToPrimitive(a) indicates a preferredType, but does not indicate a Date instance, so the preferredType is Number Returns the string string with a.tostring (), the original value. So the final ToPrimitive(a) is "[object object]".Copy the code

If the description is hard to understand, a lot of descriptions are obscure and difficult to understand, we use code to speak:

const toPrimitive = (obj, preferredType='Number') => { let Utils = { typeOf: function(obj) { return Object.prototype.toString.call(obj).slice(8, -1); }, isPrimitive: function(obj) { let types = ['Null', 'String', 'Boolean', 'Undefined', 'Number']; return types.indexOf(this.typeOf(obj)) ! = = 1; }}; if (Utils.isPrimitive(obj)) { return obj; } preferredType = (preferredType === 'String' || Utils.typeOf(obj) === 'Date') ? 'String' : 'Number'; if (preferredType === 'Number') { if (Utils.isPrimitive(obj.valueOf())) { return obj.valueOf() }; if (Utils.isPrimitive(obj.toString())) { return obj.toString() }; } else { if (Utils.isPrimitive(obj.toString())) { return obj.toString() }; if (Utils.isPrimitive(obj.valueOf())) { return obj.valueOf() }; } } var a={}; ToPrimitive(a); //"[object object]Copy the code

ToPrimitive([])= 0; ToPrimitive([])= 0;

So it’s going to be zero“” = = 0In this state, I’m going to keep looking and comparing this picture

Typeof (“”)= string; toNumber(“”)==0; toNumber(“”)==0;

So toNumber(“”)=0, and then the problem of 0 == 0, so []==! [] The answer to the 0 == 0 question is clearly true, with many twists and turns

So just to conclude

Graphical representation of the == operation rule

== null; undefined == null; true = null; And both of them are false when compared to all other values. String == Boolean, both operands need to be converted to Number. 3. String/Boolean == Number, String/Boolean is converted to Number. 4. Object == Primitive. You need to convert Object to Primitive(valueOf and toString). See, there are only four rules! Is it clear and simple?Copy the code

Main references are articles and literature

Chinese version of the ECMAScript5.1 specification

Through a simple graph, let you thoroughly, forever understand JS == operation

What is the conversion priority of the plus operator in JavaScript?

Like my summary of the article point a star my github blog address, summary of the first article, bad and reference do not get support also hope forgive me!