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)