preface
What about data types in JavaScript?
You’ve probably all been asked this question in front end interviews.
A: Data types in Javascript include primitive types and reference types. Primitive types include NULL, undefined, Boolean, string, symbol, bigInt, and number. The reference type refers to Object.
Yeah, that’s what I said, but it’s usually the first question, and it leads to a lot of questions, like
Null
和Undefined
What’s the difference? What do you need to pay attention to in the front end?typeof null
Why is itobject
?- why
ES6
To put forwardSymbol
? BigInt
What problem was solved?- why
0.1 + 0.2! = = 0.3?
How do you solve this problem? - How do I know if a value is an array?
- .
Weakly typed language
Because JavaScript is a weakly typed or dynamic language. This means that you don’t need to declare the type of the variable in advance. The type is automatically determined as the program runs, which means that you can use the same variable to hold different types of values
var foo = 42; // foo is a Number now
foo = "bar"; // foo is a String now
foo = true; // foo is a Boolean now
Copy the code
While this feature brings us convenience, it also brings us a lot of type errors. Just think about it, if JS is a strong type of language, then there is no conversion between various types, there is a layer of estrangement or a layer of protection, will it be better to maintain it? This is probably why TypeScript was born.
To master JavaScript data types is the most basic knowledge of a front-end
Null or undefinded
define
Undefined denotes an undefined variable. A null value represents an empty object pointer.
Back to basics: In the beginning, JavaScript designer Brendan Eich just defined NULL, which is treated as an object, just like in Java. But because there are two types of data in JavaScript: raw data types and reference data types. Brendan Eich decided that the value for “nothing” had better not be an object.
So the design of Javascript is that NULL is an object that means “nothing” and is zero when converted to a value; Undefined is a primitive value for “none”, which is NaN when converted to a value.
Number(null)
/ / 0
5 + null
/ / 5
Number(undefined)
// NaN
5 + undefined
// NaN
Copy the code
The difference and application of Null and Undefined
Null means “no object”, meaning there should be no value. Typical usage is as follows
- As arguments to a function, indicating that the function’s arguments are not objects.
- As the end of the object prototype chain.
Object.getPrototypeOf(Object.prototype)
// null
Copy the code
Undefined means “missing value”, that is, there should be a value here, but it is not defined yet. Typical usage:
- When a variable is declared, but not assigned, it equals
undefined
. - When the function was called, the argument that should have been provided was not provided
undefined
. - The object has no assigned attribute, which has a value of
undefined
. - The function returns no value by default
undefined
.
var i;
i // undefined
function f(x){console.log(x)}
f() // undefined
var o = new Object(a); o.p// undefined
var x = f();
x // undefined
Copy the code
What should we pay attention to in short?
JavaScript: undefined, null, false, “”, 0, NAN
This can sometimes lead to problems such as
let a = 0;
console.log(a || '/'); // If a is null or Undefined, it will print '/'. If a is null or Undefined, it will print '/'.
Copy the code
And of course we could write that
let a = 0;
if (a === null || a === undefined) {
console.log('/');
} else {
console.log(a);
}
Copy the code
Still not very elegant, so the ES specification proposes the null value merge operator (??).
Null-value merge operator (??) Is a logical operator that returns the right-hand operand if the left-hand operand is null or undefined, otherwise returns the left-hand operand.
The above example can be written as:
let a = 0;
console.log(a??'/'); / / 0
Copy the code
Typeof NULL — error made by JS
typeof null // "object"
Copy the code
Values in JavaScript are represented by a label representing the type and the actual data value. The first version of JavaScript stored values in 32-bit bits and identified the type by the lower one or three bits of the value, with the object’s type tag 000. The following
- 1: Integer (int)
- 000: Reference type (Object)
- 010: Floating point double
- 100: String (string)
- 110: Boolean (Boolean)
But there are two special values:
- Undefined: integer −2^30 (minus 2^30, outside the range of integers)
- Null, machine code null pointer (defined by C/C++ macros), the lower three digits are also 000
Since null represents a null pointer (the lower three digits are also 000), the type label for NULL is 000, and typeof NULL therefore returns “object”.
This is a JavaScript design error, but it can’t be fixed because it would affect the existing code
Number – 0.1 + 0.2! = = 0.3
The phenomenon of
Something like the following occurs in JavaScript
0.1 + 0.2
0.30000000000000004
Copy the code
why
We need to convert decimal to binary as we work with floating point numbers. Decimal The rules for converting a decimal to binary are as follows:
Multiply the number after the decimal point by 2 and take the integer part of the result (either 1 or 0), then multiply the decimal part by 2 again and take the integer part of the result… And so on, until the decimal part is zero or the number of digits is enough. Then put the integer parts in order
According to the above rules, the final 0.1 is expressed as follows:
0.000110011001100110011(0011Infinite loop)...Copy the code
So the loss of precision isn’t a problem with the language, it’s an inherent flaw in floating-point storage.
JavaScript stores all values of the Number type in 64-bit double precision floating-point numbers. According to IEEE754, the binary Number of 0.1 retains only 52 significant digits, i.e
1.100110011001100110011001100110011001100110011001101 * 2^ (-4)
Copy the code
Similarly, the binary number of 0.2 is
1.100110011001100110011001100110011001100110011001101 * 2^ (-3)
Copy the code
Thus accuracy is lost in conversion between bases. Here’s how it works
0.00011001100110011001100110011001100110011001100110011010
+0.00110011001100110011001100110011001100110011001100110100-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- =0.01001100110011001100110011001100110011001100110011001110
Copy the code
Therefore, the final calculation result is 0.1 + 0.2! = = 0.3
How to solve
- Convert numbers into whole numbers
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;
}
Copy the code
- The class library
There are many math libraries on NPM that support JavaScript and Node.js, such as math.js, Decimal. js, d.js, and so on
- ES6
ES6 adds a tiny constant to the Number object, number.epsilon
Number.EPSILON
/ / 2.220446049250313 e-16
Number.EPSILON.toFixed(20)
/ / "0.00000000000000022204"
Copy the code
The purpose of introducing such a small quantity is to set a margin of error for floating-point calculations, and if the error can be less than Number.EPSILON, the result can be considered reliable.
function withinErrorMargin (left, right) {
return Math.abs(left - right) < Number.EPSILON
}
withinErrorMargin(0.1+0.2.0.3)
Copy the code
Future solutions –TC39 Decimal proposal
The proposal is currently in Stage 1. BigInt extends JS’s positive bounds beyond 2^53 safe integer problems. Decimal solves the JS Decimal problem -2^53. This proposal introduces a new native type in JS: decimal(suffix M), which states that the number is a decimal operation.
let zero_point_three = 0.1m + 0.2m;
assert(zero_point_three === 0.3m);
// Examples of proposals
function 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));
Copy the code
Extension – Storage of floating-point numbers in memory
So what does the final floating-point number look like in memory? EEE754 provides a definition for the representation of floating point numbers
(-1)^S * M * 2^E
The meaning of each symbol is as follows: S, the sign bit, determines the positive and negative, 0 is positive, 1 is negative. M is the significant number, greater than 1 and less than 2. E is the exponent.
Javascript is a 64-bit double-precision floating-point number, with the highest 1 bit being the sign bit S, the next 11 bits being the exponent E, and the remaining 52 bits being the significant digit M.
Use this visualization tool to view the binary representation of floating point numbers in memory.
BigInt — Breaking the biggest limits
JavaScript’s Number type is a double precision IEEE 754 64-bit floating-point type. The maximum value in JavaScript is 2^53.
BigInt, an arbitrary precision numeric type, has entered the stage3 specification. BigInt can represent an arbitrarily large integer. To create a BigInt, we simply append the n suffix to any integer literal. For example, let’s write 123 as 123n. The global BigInt(number) can be used to convert a number to a BigInt, meaning that BigInt(123) === 123n. Now let me use these two points to solve the problem we mentioned earlier:
I’m the only one and the most beautiful
define
ES6 introduces a new primitive data type, Symbol, that represents unique values
let s = Symbol(a);typeof s
// "symbol"
Copy the code
Application scenarios
-
Define a set of constants that are not equal. Erase magic string
-
Object is guaranteed to have different property names
let mySymbol = Symbol(a);// The first way
let a = {};
a[mySymbol] = 'Hello! ';
// The second way
let a = {
[mySymbol]: 'Hello! '
};
// The third way
let a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello! ' });
// All the above methods give the same result
a[mySymbol] // "Hello!"
Copy the code
Vue
In theprovide
和inject
.provide
和inject
You can allow an ancestor component to inject a dependency into all of its descendants, regardless of how deep the component hierarchy is, for as long as the upstream and downstream relationship is established. But this is also very invasive to useSymbols
As akey
Can avoid to reduce the interference to the component code, do not have the same naming problems
Array – a special existence of an object
Can you tell us how to determine Array?
Why do you ask this question?
Because the array is a special existence, is one of the data structures we usually contact the most, it is a special object, its index is the “ordinary object” key value. But it has some methods that “normal objects” don’t have, such as maps
Typeof is a javascript natively provided operator to determine the data type, which returns a string representing the data typeof the parameter. But we can’t use typeof to determine if it’s an array. Because both typeof arrays and ordinary objects and null return “object”
const a = null;
const b = {};
const c= [];
console.log(typeof(a)); //Object
console.log(typeof(b)); //Object
console.log(typeof(c)); //Object
Copy the code
A method to determine an array
Object.prototype.toString.call()
.
Every Object that inherits Object has a toString method, which, if not overridden, returns [Object type], where type 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]"
Copy the code
- Array.isArray()
const a = [];
const b = {};
Array.isArray(a);//true
Array.isArray(b);//false
Copy the code
Array. IsArray () is the ES5 new method, when there is no Array. The isArray (), you can use the Object. The prototype. ToString. Call () implementation
if (!Array.isArray) {
Array.isArray = function(arg) {
return Object.prototype.toString.call(arg) === '[object Array]';
};
}
Copy the code
instanceof
.instanceof
The operator can be used to determine the value of a constructorprototype
Whether the object to which the attribute refers exists on another prototype chain for the object to be detected. Because the constructor of an array isArray
, so it can be judged as follows.Note that arrays are also objects, soa instanceof Object
Also for thetrue
const a = [];
const b = {};
console.log(a instanceof Array);//true
console.log(a instanceof Object);//true, the Object constructor can also be found on the array's prototype chain
console.log(b instanceof Array);//false
Copy the code
constructor
. The instance instantiated by the constructor has oneconstructor
Properties.
function B() {};
let b = new B();
console.log(b.constructor === B) // true
Copy the code
Arrays are instantiated by a function called Array. So you can
let c = [];
console.log(c.constructor === Array) // true
Copy the code
Note: Constructor is subject to change. So it’s not recommended
let c = [];
c.constructor = Object;
console.log(c.constructor === Array); // false
Copy the code
conclusion
According to the above description, personally recommended judgment methods have the following priorities
isArray
> Object.prototype.toString.call()
> instanceof
> constructor
conclusion
This paper discusses and analyzes some common data type problems in JavaScript. I hope I can help you in your interview or in your daily work. Some of the other things that I might not have mentioned like type conversions and so on, we’ll have a chance to talk about that
Finally, welcome to pay attention to my public account – front-end grocery store, technical issues more discussion ~
reference
- Undefined and null
- The history of “typeof null”
- 0.1 + 0.2 does not equal 0.3? Why does JavaScript have this “slutty” operation?
- An in-depth understanding of precision loss in JavaScript
- 0.1 + 0.2! == 0.3, will soon be a thing of the past
- BigInt: an arbitrary precision integer in JavaScript
- ECMAScript introduction to 6
- How do you know an array is an array in JavaScript?