Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.
preface
JavaScript is a weakly typed programming language, meaning that when declaring variables, you do not need to specify their data types. So how many data types does JavaScript contain? The answer is eight, divided into basic and reference data types.
- null
- undefined
- Boolean
- String
- Number
- Symbol
- BigInt
- Object (reference data type)
Base data types and reference data types
Basic data types are stored in stack memory. They occupy a small space and are fixed in size. They are accessed by value and are frequently used data.
Reference data types are held in heap memory, which is usually large and of variable size. What is stored in stack memory is a pointer to an address in the heap, that is, the address is stored in the stack and the contents are stored in the heap.
Introduction to eight data types
null
The NULL type has only one value, the special value NULL. Logically, a null value represents an empty object pointer, so typeof NULL === “object”.
undefined
Undefined also has only one value, the special value undefined. When a variable is declared with var or let but not initialized, it is equivalent to assigning undefined value to the variable. However, it should be noted that variables containing undefined value are different from undefined variables.
let name;
// let age;
console.log(name); / / output is undefined
console.log(age); / / an error
Copy the code
Boolean
Boolean Is one of the most common data types. It has two literals: true and false. These two Booleans are different from numeric values, so true is not equal to 1 and false is not equal to 0.
Although there are only two Booleans, all other ECMAScript type values have corresponding Boolean equivalents.
Truthy says true | Falsy says false |
---|---|
true | false |
Number of non-zero | Plus or minus 0 |
[](empty array) |
""(empty string) |
{}(empty object) |
undefined |
Infinity | null |
. | NaN |
String
String The String type represents zero or more sequences of 16-bit Unicode characters. Strings can be represented by double quotation marks (“”), single quotation marks (“), or backquotation marks (‘). However, if a string begins with a quotation mark, it must still end with that quotation mark. For example, writing the following will cause syntax errors
let name = 'Mr. Chen?'; // Syntax error, quotation marks do not match, even my comment turned redCopy the code
Strings in ECMAScript are immutable, meaning that their values cannot change once they are created. To change a string value in a variable, you must first destroy the original string and then save another string containing the new value to the variable.
Number
The Number type is interesting. It can be used to represent integers and floating-point numbers. Different numeric types have their own numeric literal formats.
let year = 1998; // A decimal integer
let birthday = 0x1AB // hexadecimal 427,0x is a hexadecimal prefix
let age = 027; // octal 23,0 is a prefix for an 8-base number
Copy the code
To define a floating point number, the value must contain a decimal point, and there must be at least one number after the decimal point. Because storing floating-point numbers uses twice as much memory as storing integer values, ECMAScript always tries to convert values to integers. Similarly, if the value itself is an integer followed by a 0 (such as 1.0), it will be converted to an integer.
let floatNum1 = 1.; // There is no number behind the decimal point, so it is treated as an integer 1
let floatNum2 = 5.0; // The decimal point is followed by zero and is treated as an integer 10
Copy the code
Floating-point numbers can also be represented in scientific notation for very large or very small values.
let floatNum3 = 3.14125 e7; / / equal to 31412500
let floatNum4 = 3e-17; / / is equal to 0.00000000000000003
Copy the code
In addition, there is a special value called NaN, which stands for “Not a Number,” which is used to indicate that an operation intended to return a Number failed, rather than throwing an error.
console.log(0/0); // NaN
console.log(-0/+0); // NaN
Copy the code
If the numerator is non-zero and the denominator is signed or unsigned 0, Infinity or -infinity is returned.
console.log(5/0); // Infinity
console.log(5/-0); // -Infinity
Copy the code
NaN has several unique attributes. First, any operation that involves NaN always returns NaN (such as NaN/10). Second, NaN does not equal any value including NaN, that is, NaN! = NaN. So how do we determine if a variable is NaN? ECMAScript provides the isNaN() function, which takes a parameter, which can be of any data type, and determines whether the parameter is “not a number.” This function attempts to convert the argument to a value, and any value that cannot be converted to a value causes the function to return true.
console.log(isNaN(NaN)); // true
console.log(isNaN(10)); // false, 10 is a number
console.log(isNaN("10")); // false, "10" can be converted to the value 10
console.log(isNaN("Mr. Chen?")); // true, cannot be converted to a numeric value
console.log(isNaN(true)); // false, which can be converted to the value 1
Copy the code
In my opinion, the isNaN() function simply checks whether a variable can be converted to a value, returning false if it can, and vice versa. It cannot be used to determine NaN strictly because Chen can also return true.
ES6 provides the number.isnan () method to determine whether a value is strictly equal to NaN. It first checks if the value passed is numeric and returns false if it is not. Returns true if and only if the argument is NaN!
Symbol
Symbol is a new data type in ES6 that is used to represent unique values, ensuring that object properties use unique identifiers without risk of property collisions.
It needs to be initialized using the Symbol() function, or a string argument can be passed as a description of the Symbol.
let sym1 = Symbol(a);let sym2 = Symbom();
let sym3 = Symbol('Xiao Chen');
let sym4 = Symbol('Xiao Chen');
console.log(sym1 == sym2); // false
console.log(sym3 == sym4); // false
Copy the code
Here is an example of using Symbol as an attribute.
let mySymbol = Symbol(a);// The first way
let obj = {};
obj[mySymbol] = 'Mr. Chen?';
// The second way
let obj = {
[mySymbol]: 'Mr. Chen?'
};
// The third way
let obj = {};
Object.defineProperty(obj, mySymbol, { value: 'Mr. Chen?' });
// All the above methods give the same result
obj[mySymbol] // "Xiao Chen"
Copy the code
BigInt
The purpose of the BigInt data type is to have a wider range of integer values than the Number data type supports (previously the maximum Number could represent was 2^ 53-1). The ability to represent integers with arbitrary precision is especially important when performing mathematical operations on large integers. With BigInt, integer overflow is no longer a problem.
BigInt was introduced in ES2020, I didn’t see BigInt in the JS elevation book’s table of contents, understand the basic usage below.
// Add n
console.log(1n); // 1n
// Use the constructor BigInt
console.log(BigInt(1)); // 1n
1n= = =BigInt(1) // true
typeof 1n; // bigint
Copy the code
Object
Object is a reference data type. It is a collection of data and functions, and objects are created by the new operator followed by the name of the object type.
// write method 1:
let obj = {name:'Mr. Chen?'.gender:'male'}
// write method 2:
let obj1 = new Object({name:'Mr. Chen?'.gender:'male'})
//
let obj2 = {}
obj2.name = 'Mr. Chen?'
obj2.gender = 'male'
Copy the code
A method for determining data types
typeof
typeof undefined // "undefined"
typeof true // "boolean"
typeof "Mr. Chen?" // "string"
typeof 123 // "number"
typeof NaN // "number" (note that NaN is also number)
typeof 123n // "bigint"
typeof Symbol(a)// "symbol"
typeof console.log // "function"
typeof null // "object" (this is special)
typeof {} // "object"
typeof [1.2.3] // "object"
Copy the code
Typeof does not have a null type in it, because null itself represents an empty object pointer and therefore returns object.
Why is there a function type?
According to the Little Red Book, functions are considered objects in ECMAScript and do not represent a data type. However, functions have their own special properties. To do this, it is necessary to distinguish functions from other objects through the Typeof operator.
The problem with using Typeof to detect data types is that there is no way to distinguish between arrays and objects. Because arrays print “object”, typeof is not an optimal solution.
instanceof
The instanceof operator detects if a variable is an instanceof a type of data by looking up a chain of stereotypes.
a instanceof A // If the right variable's 'prototype' is in the left variable's prototype chain.
Copy the code
Note that instanceof applies only to object types, not values of primitive types.
How to check the Array type?
[] instanceof Array // true
{} instanceof Array // false
(console.log) instanceof Function // true
Copy the code
As you can see, it can detect arrays of type Array, but there is a problem here. The Array constructor instance also has Object on its prototype chain, meaning that [] instanceof Object also returns true. We can write a function that first checks for Array and then checks for Object. Our function looks like this.
function checkArray(obj) {
if(obj instanceof Array) return 'Array';
if(obj instanceof Object) return 'Object';
else return 'Others'
}
Copy the code
But it’s tricky, so is there a more universal test? There is.
Object.prototype.toString()
Object. The prototype. The toString () can be said to be the data types of the ultimate solution.
Object.prototype.toString.call({}) // '[object Object]'
Object.prototype.toString.call([]) // '[object Array]'
Object.prototype.toString.call(console.log) // '[object Function]'
Object.prototype.toString.call('Mr. Chen?') // '[object String]'
Object.prototype.toString.call(123) // '[object Number]'
Object.prototype.toString.call(true) // '[object Boolean]'
Object.prototype.toString.call(Symbol()) // '[object Symbol]'
Object.prototype.toString.call(null) // '[object Null]' !!!
Object.prototype.toString.call(undefined) // '[object Undefined]'
Object.prototype.toString.call(new Date()) // '[object Date]'
Object.prototype.toString.call(Math) // '[object Math]'
Object.prototype.toString.call(new Set()) // '[object Set]'
Object.prototype.toString.call(new WeakSet()) // '[object WeakSet]'
Object.prototype.toString.call(new Map()) // '[object Map]'
Object.prototype.toString.call(new WeakMap()) // '[object WeakMap]'
Copy the code
This method not only detects Array types, but also null, as well as Date, Math, Set, and so on.
But after consulting relevant information, it needs to be explained
- Passing in a primitive data type can also determine the result because the value is wrapped.
null
和undefined
The ability to output results is handled by the internal implementation.- Custom type results are printed
"[object Object]"
So we need to useinstanceof
To judge.
Let’s write another method that gets rid of all the extra stuff, just the data type.
function test(obj){
let res = Object.prototype.toString.call(obj)
let str = res.split("") [1]
return str.substring(0,str.length-1)}/ / test
// test([]) prints Array
Copy the code
conclusion
JavaScript’s data types, when used in general, feel pretty simple (or even ignored), but dig a little deeper and you’ll find a lot of detail about how data is stored (stacks), how floating-point numbers are stored and represented, prototype chains, and more. I just write articles to consolidate what I have learned and deepen my memory.
🎉 well, Chen in this wish to see this article or have not seen friends, happy National Day!
The resources
- JavaScript Advanced Programming (Version 4)
- The Definitive JavaScript Guide (7th edition)
- Other great authors on the web