Type of data

  • Primitive values: Also called primitive types (NULL, Undefined, String, Boolean, Number, BigInt, Symbol)

  • Reference values: Object, Date, Array, Function, RegExp

The difference between

  • Reference types are stored in heap memory
var a = {name:"Southern blue"};
var b;
b = a;
a.name = "nanlan";
console.log(b.name);    // nanlan
b.age = 18;
console.log(a.age);     / / 18
var c = {
  name: "xiaoju".age: 20
};
Copy the code

The unnamed file is. PNG

A and B both point to the same address, and C is newly created separately. Each of them, as a reference type, holds a reference address in stack memory that points to a value stored in heap memory. So there is a shallow copy, where the reference type changes the original object because the reference address is the same

  • Base types are stored in stack memory

Issues involved: Deep copy and shallow copy

Type test

typeof

Disadvantages: Returns object for null or reference types (Date, RegExp)

typeof null         // object
typeof []           // object
typeof /^\w/g       // object
typeof new Date()   // object 
Copy the code

instanceof

Disadvantages: All reference types are instances of Object

result = variable instanceof Constructor
Copy the code
let arr = [];
let reg = /^\w\g/
arr instanceof Array       // true
arr instanceof  Object     // true
reg instanceof Regxp       // true
reg instanceof  Object     // true
Copy the code

The principle of instanceof

The right prototype is on the left prototype chain

function myInstanceOf(leftValue, rightValue) {
 leftValue = left.__proto__;
 let rightProto = right.prototype;
 while (true) {
   if (leftValue === null) return false;
   if (leftValue === rightProto) return true; leftValue = leftValue.__proto__; }}Copy the code

Knowledge: prototype chain inheritance

And then let’s look at some other interesting examples

function Foo() {}Object instanceof Object // true
Object instanceOf Function  // true
Function instanceof Function // true
Function instanceof Object // true
Foo instanceof Foo // false
Foo instanceof Object // true
Foo instanceof Function // true
Copy the code

Let’s say the first one, the first entry

Prototype rightProto = Object. Prototype // not equal leftValue = Function.proto__ = object. prototype // leftValue === rightProtoCopy the code

Now look at Foo instanceof Foo is false

// The first check is not equal
leftValue = Foo.__proto__ = Function.prototype
rightProto = Foo.prototype

// The second judgment is not equal
leftValue  = Funtion.protype._proto_ = Object.prototype
rightProto = Foo.prototype

// The third judgment is not equal
leftValue = Object.prototype._proto_ = nullreturnfalse
Copy the code

Best judge the type of value

 Object.prototype.tostring.call()
Copy the code
let arr = []
let n = null
// Object.prototype.tostring.call(arr) // [object Array]
// Object.prototype.tostring.call(n) // [object Null]
Copy the code

Type conversion

This blog post goes into a lot of detail about the type conversion headache JavaScript is having

Above is my summary of explicit conversion and implicit conversion, mubu.com/app/edit/ho…

Explicit conversion

Commonly used is mainly the following several, given the connection address is ES5 specification, write very detailed.

  • Boolean () : es5. Making. IO / # x9.2

Boolean is relatively simple to convert according to the ToBoolean specification

  • The Number () : es5. Making. IO / # x9.3

Follow the ToNumber specification to transform. If a String is not a number, it returns NaN. If it is a number, it depends. Here are a few examples

Number("123") - >123
Number("0xA") -> Hexadecimal to decimal10Of course, the same is true of all other bases, which are converted to decimalNumber("0xA") -> Hexadecimal to decimal10
Number('0') - > -0
Number('00123') - >123
Number('Infinity') - >Infinity
Number('3.3 e-7) - >3.3 e-7
Copy the code

If the input parameter is of type Object, ToPrimitive is called and ToNumber is used to convert it

  • String () : es5. Making. IO / # x9.8

If the input parameter is of type Number, it will be converted according to 9.8.1. Just a couple of examples

String(-0) /String(+0) - >0
String(NaN) - >NaN
String(Infinity) - >"Infinity"
String(3.3 e-7) - >"3.3 e-7"
String(9007199254740991) - >"9007199254740991"
Copy the code

If the input parameter is Object, the ToPrimitive method is called, with a different default parameter, hint String

String () and toString ()

The difference is that String() can convert null and undefined, while toString() cannot. Please let me know if there are any other differences. ToString () is one layer ahead of String(). For example, when an input parameter is of type Object, ToPrimitive calls toString()

Valueof () and toString(), ToPrimitive

  • ToString: A string representing this object. Null and undefined have no toString methods

  • ValueOf: returns the original valueOf the object
console.log(({}).valueOf()) / / {}
console.log([].valueOf()) //  []
console.log([0].valueOf()) / / [0]
console.log([1.2.3].valueOf()) / / [1, 2, 3]
console.log((function(){var a = 1; }).valueOf())// function (){var a = 1; }
console.log((/\d+/g).valueOf()) // /\d+/g
console.log((new Date(2021.1.1)).valueOf())  / / 1612108800000
Copy the code
  • ToPrimitive es5. Making. IO / # x9.1

See if it makes sense

Implicit conversion

Conditions that trigger implicit conversions: unary, binary (+), ==, if,? :, &&

Unary operator

Let me give you some examples

Binary operator

[]+[], {}+{},[]+{}

[] lprim = ToPrimitive([]) = ToPrimitive([], Number) Rprim = ToPrimitive([]) rprim = ToPrimitive([]) rprim = ToPrimitive([])

{}+{},[]+{},[]+undefined,[]+null

A piece of code

function isNative (Ctor) {
  return typeof Ctor === 'function' && /native code/.test(Ctor.toString())
}
isNative(Promise)
isNative(MutationObserver)
isNative(setImmediate)
Copy the code

The above code is found in the vUE source code, I think more interesting

Classic Interview questions

The interview questions 1

How to make a = =1 && a==2 && a==3
Copy the code
function A(value){ this.value = value } A.prototype.toString = function(){ return this.value ++ } const a = new A(1); if (a == 1 && a == 2 && a == 3) { console.log("hi nanlan!" ); }Copy the code

Then a===1 && a===2 a===3(independent of implicit conversion)

var value = 0; //window.value Object.defineProperty(window, 'a', { get: function() { return this.value += 1; }}); console.log(a===1 && a===2 && a===3) //trueCopy the code

The interview questions 2

How to make f(1)(2)(3) = 6;Copy the code
function f(){
  let args = [...arguments];
  let add = function(){ args.push(... arguments)return add
  }
  add.toString = function(){
    return args.reduce((a,b) = >{
      return a+b
    })
  }
  return add
}

console.log(f(1) (2) (3))
Copy the code

The toString() method was overridden for both questions

conclusion

Seemingly simple data type, actually can be derived from a lot of knowledge. A primitive type (also called primitive values) is different from a reference type. You can see why the value of a const object can change but the reference address is immutable

This is followed by each method for detecting base and reference types, and the differences between them. Explicit conversions (Number(), Boolean(), String()…) And implicit conversions, which are mostly about toString(), valueOf(), and ToPrivitive

With reference to

JavaScript deep headache on type conversion)

JavaScript deep headache type conversion (part 2)