Contents
Preface
Please tell me about
JavaScript
the data types in ?
In front-end interviews, I think everyone has been asked this question.
Answer: Javascript
The data types in include primitive types and reference types. The primitive types include null
, undefined
, boolean
, string
, symbol
, bigInt
, number
. Reference types refer to Object
.
Yes, I answered the same way, but this is usually the first question. This question can lead to many, many questions, such as
Null
What is the difference between andUndefined
? What should we pay attention to when making short judgments on the front end?typeof null
Whyobject
?- Why
ES6
bring it upSymbol
? BigInt
What problem was solved?- Why
0.1 + 0.2 !== 0.3?
How do you solve this problem? - How to tell if a value is an array?
- …
weakly typed language
Because JavaScript
it is a weakly typed language or a dynamic language. This means that you do not need to declare the type of the variable in advance. The type will be automatically determined during the running of the program, which means that you can use the same variable to store values of different types.
var foo = 42 ; // foo is a Number now foo = "bar" ; // foo is a String now foo = true ; // foo is a Boolean now
While this feature brings us convenience, it also brings us a lot of type errors. Just imagine, if JS
it is a strongly typed language, then there is no way to convert between types, and there will be a layer of isolation or a layer of protection. Will it be easier to maintain? ——This may be TypeScript
the reason for its birth.
Mastering JavaScript
the data type is the most basic knowledge point for a front-end
null or undefined
definition
undefined
Represents an undefined variable. null
Value represents a null object pointer.
Going back to the source: At the beginning,
JavaScript
the designer
Brendan Eich
actually just defined
null
,
null
as
Java
in, treated as an object. But because
JavaScript
there are two data types in : primitive data types and reference data types.
Brendan Eich
I feel that the value representing “none” is best not an object.
Therefore Javascript
, the design is that null is an object that represents “none” and is 0 when converted to a numerical value; undefined is a primitive value that represents “none” and is NaN when converted to a numerical value.
Number ( null ) // 0 5 + null // 5 Number ( undefined ) // NaN 5 + undefined // NaN
The difference and application of Null and Undefined
null means “no object”, that is, there should be no value there. , typical usage is as follows
- As a parameter of a function, it means that the parameter of the function is not an object.
- As the end point of the object’s prototype chain.
Object . getPrototypeOf ( Object . prototype ) // null
undefined means “missing value”, that is, there should be a value here, but it has not been defined . Typical usage is:
- When a variable is declared but not assigned a value, it is equal to
undefined
. - When calling a function, an argument that should have been provided was not provided, and the argument is equal to
undefined
. - The object has no assigned property, and the value of this property is
undefined
. - When the function does not return a value, it returns by default
undefined
.
var i; i // undefined function f ( x ){ console . log (x)} f () // undefined var o = new Object (); o. p // undefined var x = f (); x // undefined
What should you pay attention to when making a short call?
javaScript
Five types of empty values and false values, namely undefined, null, false, “”, 0, NAN
This can sometimes easily lead to some problems, such as
let a = 0 ; console . log (a || '/' ); // The original intention is to output '/' as long as a is null or Undefined, but in fact, it will output ' as long as it is one of the five above. /'
Of course we can write
let a = 0 ; if (a === null || a === undefined ) { console . log ( '/' ); } else { console . log (a); }
It’s not always very elegant, so the ES specification proposes the null value coalescing operator (??)
The null value coalescing operator (??) is a logical operator that returns the right operand when the left operand is null or undefined, otherwise it returns the left operand.
The above example can be written as:
let a = 0 ; console . log (a?? '/' ); // 0
typeof null——JS mistakes
typeof null // "object"
JavaScript
The value in is represented by a label representing the type and the actual data value. The first version JavaScript
uses 32 bits to store values, and the type is identified by the low 1 or 3 bits of the value. The type label of the object is 000. as follows
- 1: Integer type (int)
- 000: Reference type (object)
- 010: Double precision floating point type (double)
- 100: string
- 110: boolean
But there are two special values:
- undefined, use the integer −2^30 (negative 2 to the 30th power, not within the range of integers)
- null, machine code null pointer (C/C++ macro definition), the lower three bits are also 000
Since null
represents a null pointer (the lower three bits 000
),因此,null
are also the type label of ) 000
, typeof null
therefore “object” is returned.
This is considered JavaScript
a design error, but it cannot be modified. After all, if modified, it will affect the existing code.
Number——0.1+0.2 !== 0.3
Phenomenon
There JavaScript
will be a phenomenon similar to the following
0.1 + 0.2 0.30000000000000004
reason
When we operate on floating point numbers, we need to convert decimal to binary. The rules for converting decimal to binary are as follows:
Multiply the number after the decimal point by 2, take the integer part of the result (either 1 or 0), then multiply the decimal part by 2, then take the integer part of the result…and so on, until the decimal part is 0 or 0 It’s OK if the number is enough. Then arrange the integer parts in order
According to the above rules, the final representation of 0.1 is as follows:
0.000110011001100110011 ( 0011 infinite loop)…
Therefore, the loss of precision is not a language problem, but an inherent flaw in floating-point number storage itself.
JavaScript
All type values are stored in 1-bit double-precision floating point numbers. According to the 64
specification , the binary number of 0.1 only retains 52 significant digits, that isNumber
IEEE754
1.100110011001100110011001100110011001100110011001101 * 2 ^(- 4 )
In the same way, the binary number of 0.2 is
1.100110011001100110011001100110011001100110011001101 * 2 ^(- 3 )
In this way, accuracy is lost in the conversion between bases. The operation is as follows
0.00011001100110011001100110011001100110011001100110011010 + 0.00110011001100110011001100110011001100110011001100110100 -------------------------------------------------- ---------- = 0.01001100110011001100110011001100110011001100110011001110
Therefore, the final calculation result is 0.1 + 0.2 !== 0.3
How to solve
- Convert number to integer
function add ( num1, num2 ) { const num1Digits = (num1. toString (). split ( '.' )[ 1 ] || '' ). length ; const num2Digits = (num2. toString (). split ( '.' )[ 1 ] || '' ). length ; const baseNum = Math . pow ( 10 , Math . max (num1Digits, num2Digits)); return (num1 * baseNum + num2 * baseNum) / baseNum; }
NPM
There are many math libraries that supportJavaScript
and on the class library , such as , , etc.Node.js
math.js
decimal.js
D.js
- ES6 adds a very small constant on the
ES6
object——Number
Number.EPSILON
Number . EPSILON // 2.220446049250313e-16 Number . EPSILON . toFixed ( 20 ) // "0.00000000000000022204"
The purpose of introducing such a small quantity is to set an error range for floating point calculations. If the error can be less than that Number.EPSILON
, we can consider the result to be reliable.
function withinErrorMargin (left, right) { return Math . abs (left - right) < Number . EPSILON } withinErrorMargin ( 0.1 + 0.2 , 0.3 )
Future solution – TC39 Decimal proposal
Proposal currently in Stage 1
. The expansion mentioned later BigInt
is JS
the positive boundary of , exceeding 2^53 safe integer problems. Decimal
It is to solve the decimal problem of JS -2^53. This proposal introduces a new native type in JS: decimal
(suffix m), which declares that the number is a decimal arithmetic.
let zero_point_three = 0. 1m + 0. 2m; assert (zero_point_three === 0. 3m); // Example function in the proposal calculateBill ( items, tax ) { let total = 0m; for ( let {price, count} of items) { total += price * BigDecimal (count); } return BigDecimal . round (total * (1m + tax), { maximumFractionDigits : 2 , round : "up" }); } let items = [{ price : 1. 25m, count : 5 }, { price : 5m, count : 1 }]; let tax = .0735m; console . log ( calculateBill (items, tax));
Extension—Storage of floating point numbers in memory
So what is the final storage of floating point numbers in memory? EEE754
A definition is given for the representation of floating point numbers
(-1)^S M 2^E
The meaning of each symbol is as follows: S is the sign bit, which determines the positive and negative values. When 0, it is a positive number, and when it is 1, it is a negative number. M refers to the number of significant digits, which is greater than 1 and less than 2. E, is the index bit.
Javascript is a 64-bit double-precision floating point number. The highest 1 bit is the sign bit S, the next 11 bits are the exponent E, and the remaining 52 bits are the significant digit M.
You can use this visualization tool to see the binary representation of floating point numbers in memory)
BigInt – Breaking the Biggest Limits
JavaScript
The Number
type is a double precision IEEE 754 64-bit floating point type.
The maximum value in JavaScript is 2^53
.
BigInt
Arbitrary precision numeric type has entered the stage3 specification. BigInt
Can represent any large integer. To create one BigInt
, we just need to add an n suffix to any integer literal. For example, write 123 as 123n. This global BigInt(number) can be used to convert a Number into a BigInt. The implication is that BigInt(123) === 123n. Now let me use these two points to solve the problems we mentioned earlier:
Symbol——I am the unique and most beautiful boy
definition
ES6 introduces a new primitive data type Symbol
to represent unique values
let s = Symbol (); typeof s // "symbol"
Application scenarios
- Define a set of constants to ensure that the set of constants are not equal. Remove magic string
- Ensure different property names in objectslet mySymbol = Symbol (); //The first way of writing let a = {}; a[mySymbol] = ‘Hello!’ ; // The second way of writing let a = { [mySymbol]: ‘Hello!’ }; // The third way of writing let a = {}; Object . defineProperty (a, mySymbol, { value : ‘Hello!’ }); // The above writing methods all get the same result a[mySymbol] // “Hello!”
Vue
inprovide
andinject
.provide
andinject
allows an ancestor component to inject a dependency into all its descendants, no matter how deep the component hierarchy is, and it will always take effect from the time the upstream and downstream relationships are established. But this is also very intrusive. UsingSymbols
askey
can avoid interference with component code and avoid problems such as the same naming.
Array – a special existence in an object
Please tell me how to judge Array?
Why is this question asked?
Because the array is a special existence, it is one of the data structures we usually come into contact with the most. It is a special object, and its index is key
the value of the “ordinary object”. But it also has some methods that “ordinary objects” do not have, such as map
etc.
typeof
It is javascript
a natively provided operator to determine the data type. It will return a string representing the data type of the parameter. But we can’t typeof
judge whether it is an array by . Because typeof
arrays and ordinary objects null
both return “object”
const a = null ; const b = {}; const c= []; console . log ( typeof (a)); //Object console . log ( typeof (b)); //Object console . log ( typeof (c )); //Object
How to judge an array
Object.prototype.toString.call()
.
EveryObject
object that inherits hastoString
a method. IftoString
the method is not overridden, it will be returned[Object type]
, wheretype
is the type of the object.
const a = [ 'Hello' , 'Howard' ]; const b = { 0 : 'Hello' , 1 : 'Howard' }; const c = 'Hello Howard' ; Object . prototype . toString . call (a); / /"[object Array]" Object . prototype . toString . call (b); //"[object Object]" Object . prototype . toString . call (c); //"[object String]"
- Array.isArray()const a = []; const b = {}; Array . isArray (a); //true Array . isArray (b); //false
Array.isArray()
It isES5
a newly added method. If it does not existArray.isArray()
, it can beObject.prototype.toString.call()
implemented using
if (! Array . isArray ) { Array . isArray = function ( arg ) { return Object . prototype . toString . call (arg) === '[object Array]' ; }; }
instanceof
.instanceof
The operator can be used to determine whether the object pointed to by a constructor’sprototype
property exists on the prototype chain of another object to be detected. Because the constructor of the array isArray
, it can be judged by the following. Note: Because arrays are also objects, soa instanceof Object
is alsotrue
const a = []; const b = {}; console . log (a instanceof Array ); //true console . log (a instanceof Object ); //true, the Object constructor console can also be found on the prototype chain of the array .log ( b instanceof Array ); //false
constructor
. An instance instantiated through a constructor has aconstructor
property.
function B () {}; let b = new B (); console . log (b. constructor === B) // true
And arrays are Array
instantiated by a function called . so ok
let c = []; console . log (c. constructor === Array ) // true
Note: the constructor will be changed. Therefore, it is not recommended to judge this way
let c = []; c. constructor = Object ; console . log (c. constructor === Array ); // false
in conclusion
According to the above description, the personally recommended judgment methods have the following priorities:
isArray
>>>Object.prototype.toString.call()
instanceof
constructor
Summarize
JavaScript
This article discusses and analyzes some common data type issues in . I hope it can be helpful to everyone in interviews or daily work. Other things that may not have been mentioned, such as type conversion, etc., will be discussed again when we have the opportunity.
Finally, everyone is welcome to pay attention to my official account – Front-end Grocery Store, and discuss more technical issues~
refer to
- The difference between undefined and null
- The history of “typeof null”
- 0.1 + 0.2 is not equal to 0.3? Why does JavaScript have this “saucy” operation?
- A deeper understanding of precision loss in JavaScript
- Famous JavaScript interview question: 0.1 + 0.2 !== 0.3, will soon become a thing of the past
- [[Translation]BigInt: Arbitrary precision integer type in JavaScript]( https://juejin.cn/post/684490… )
- Getting Started with ECMAScript 6
- In JavaScript, how to determine whether an array is an array?