preface
As JavaScript becomes more and more popular, more and more developers begin to contact and use JavaScript.
At the same time, I also found that many developers do not have a clear understanding of the most basic original values and wrapper objects of JavaScript.
In this article, I'll introduce them in detail.
🧐 Let's go!
text
Primitive types
Primitive types are also called "basic types".
Currently, there are several primitive types in JavaScript:
- String (string)
- number
- boolean (boolean)
- null (empty)
- undefined
- bigint (large integer, ES6)
- symbol (sign? ES6)
📝 As follows:
typeof 'chenpipi'; // "string" typeof 12345; // "number" typeof true; // "boolean" typeof null; // "object" typeof undefined; // "undefined" typeof 12345n; // "bigint" typeof Symbol(); // "symbol"
💡 Particular attention
Although typeof null returns "object", it does not mean that null is an object. In fact, it is a Bug of JavaScript, and it has been so since the birth of JavaScript.
In the initial implementation of JavaScript, the value in JavaScript is represented by a label representing the type and the actual data value. The label type of the object is 0. Since null represents a null pointer (0x00 in most platforms), the type label of null is 0, and typeof null returns "object".
The history of "typeof null": https://2ality.com/2013/10/typeof-null.html
Primitive values
The original value is the value (data) of the original type.
A primitive value is data that is not an object and has no methods.
The original value is a kind of non object data without any method.
In other words, the values of primitive types such as string, number and boolean do not have any properties and methods.
😨 At this time, does the little friend with keen sense of smell have noticed something wrong?
It's cumin! I added cumin! (manual dog head and cross off)
🤓 There is a very interesting point here, but before discussing this issue, let's know the packaging object.
Wrapper objects
All primitive types except null and undefined have their corresponding wrapper objects:
- String (string)
- Number
- Boolean (Boolean)
- BigInt (large integer, ES6)
- Symbol (logo? ES6)
Object
Object is a reference type.
First, the wrapper object itself is an object and a function.
String instanceof Object; // true String instanceof Function; // true
Constructor
Instance
String, Number and Boolean all support the use of the new operator to create corresponding wrapper object instances.
📝 For example, the declaration of String (excerpt):
interface StringConstructor { new(value?: any): String; (value?: any): string; readonly prototype: String; } declare var String: StringConstructor;
📝 The data obtained by using the new operator is an Object:
// character string typeof 'pp'; // "string" typeof new String('pp'); // "object" new String() instanceof Object; // true // number typeof 123; // "number" typeof new Number(123); // "object" new Number() instanceof Object; // true // Boolean typeof true; // "boolean" typeof new Boolean(true); // "object" new Boolean() instanceof Object; // true
📝 We can call the valueOf() function of the wrapper object instance to get its original value:
// character string let s = new String('pp'); s.valueOf(); // "pp" typeof s.valueOf(); // "string" // number let n = new Number(123); n.valueOf(); // 123 typeof n.valueOf(); // "number" // Boolean let b = new Boolean(true); b.valueOf(); // true typeof b.valueOf(); // "boolean"
"Attention"
BigInt and Symbol belong to "incomplete classes" and do not support the new operator.
📝 For example, BigInt's statement (excerpt):
interface BigIntConstructor { (value?: any): bigint; readonly prototype: BigInt; } declare var BigInt: BigIntConstructor;
You can see that there are no new operator related functions in the declaration of BigInt.
Ordinary function
Wrapper objects can also be used as normal functions.
The String(), Number() and Boolean() functions can be used to explicitly type convert any type of data.
In addition, the Object() function can also be used for explicit type conversion, but it will not be expanded in this article.
String
📝 Example code:
typeof String(); // "string" String(); // "" String('pp'); // "pp" String(123); // "123" String(true); // "true" String(false); // "false" String(null); // "null" String(undefined); // "undefined" String([]); // "" String({}); // "[object Object]"
💡 Tip 1
When we use the String() function to convert an object, JavaScript will first access the toString() function on the object. If it is not implemented, it will look up along the prototype chain.
🌰 For example: execute string ({tostring() {return 'pp';}}) The returned result is "pp", not "[object]".
Therefore, the String() function cannot be used to judge whether a value is an object (rollover).
💡 Tips 2
The common way to judge an object is object prototype. toString({}) === '[object Object]'.
🌰 Take a chestnut: execute object prototype. toString({ toString() { return 'pp'; } }) Returned is "[object]".
Number
📝 Example code:
typeof Number(); // "number" Number(); // 0 Number(''); // 0 Number('pp'); // NaN Number(123); // 123 Number(true); // 1 Number(false); // 0 Number(null); // 0 Number(undefined); // NaN Number([]); // 0 Number({}); // NaN
💡 Tips
For the Number() function, perhaps the most practical conversion is to convert true and false to 1 and 0.
Boolean
📝 Example code:
typeof Boolean(); // "boolean" Boolean(); // false Boolean(''); // false Boolean('pp'); // true Boolean(0); // false Boolean(1); // true Boolean(null); // false Boolean(undefined); // false Boolean([]); // true Boolean({}); // true
💡 Tips
In some cases, we will use 0 and 1 in the data to represent the true and false state. At this time, we can use Boolean() to judge the state.
BigInt
The BigInt() function converts an integer to a large integer.
This function accepts an integer as a parameter. If the incoming parameter is a floating point number or any non numeric data, an error will be reported.
📝 Example code:
BigInt(123); // 123n BigInt(123n); // 123n typeof 123n; // "bigint" typeof BigInt(123); // "bigint"
BigInt & Number
It should be noted that BigInt and Number are not strictly equal (loosely equal).
📝 Example code:
123n === 123; // false 123n == 123; // true
Symbol
The Symbol() function is used to create a value of type symbol.
This function accepts a string as a descriptor (parameter) and will be converted to a string (except undefined) if other types of values are passed in.
Note that each symbol value is unique, even if their descriptors are the same.
And the data of symbol type can only be created through the Symbol() function.
📝 Example code:
// The following return value is simulated by Devtools, not the actual value Symbol('pp'); // Symbol(pp) Symbol(123); // Symbol(123) Symbol(null); // Symbol(null) Symbol({}); // Symbol([object Object]) // type typeof Symbol('pp'); // "symbol" Symbol('pp') === Symbol('pp'); // false // descriptor Symbol('pp').description; // "pp" Symbol(123).description; // "123" Symbol({}).description; // "[object Object]" Symbol().description; // undefined Symbol(undefined).description; // undefined
The original value is not an object
🎃 Here comes the interesting one~
No properties, no functions
As mentioned earlier in this article, "raw value is a kind of non object data without any method."
We all know that objects can have properties and methods.
But the string is not an object, so you can't add properties to the string.
📝 Do a small experiment:
let a = 'chenpipi'; console.log(a.length); // 8 // Try adding a new attribute a.name = 'Wu Yanzu'; console.log(a.name); // undefined // Attempt to modify an existing property typeof a.slice; // "function" a.slice = null; typeof a.slice; // "function"
🎬 Slag skin small theater
At this time, a small partner of toutie uses the refutation skill.
Don't fool around here, scum. I usually write bugs. When I don't write code, I can call methods on strings, numbers and Boolean values!
📝 For example, the following code can execute normally and get the expected results:
// character string let s = 'chenpipi'; s.toUpperCase(); // "CHENPIPI" 'ChenPiPi'.slice(4); // "PiPi" // number let n = 123; n.toString(); // "123" (123.45).toFixed(2); // "123.5" // Boolean value let b = true; b.toString(); // "true" false.toString(); // "false"
💡 Useless little knowledge
Have you found that the function cannot be called directly after the literal value of the number? For example, execute 123 Tostring() will report syntax error.
This is because the number (floating point number) itself uses the decimal point, The calling function also needs to use the decimal point, so there is ambiguity (string and Boolean value do not have this trouble).
In this case, we can wrap the numbers in parentheses (e.g. 123) toString(); Or use two consecutive decimal points To call functions, such as 123 toString().
🤔 It's strange
Since strings are not objects, why do strings have properties and methods?
On second thought, numbers are numbers. How can there be methods in numbers?
This is indeed illogical, but it contradicts reality.
What's going on???
I can't translate this
The answer is revealed~
😎 Operate secretly
Take the string as an example. When we read the properties or methods of the string in the code, JavaScript will silently perform the following operations:
- Create a temporary wrapper object instance by new String();
- Execute our code logic through the created object (read properties or execute functions);
- Temporary objects are no longer used and can be destroyed.
📝 Such as the following chestnuts:
let a = 'chenpipi'; console.log(a); // "chenpipi" // ------------------------------ let b1 = a.length; console.log(b1); // 8 // The above code is equivalent to: let b2 = (new String(a)).length; console.log(b2); // 8 // ------------------------------ let c1 = a.toUpperCase(); console.log(c1); // "CHENPIPI" // The above code is equivalent to: let c2 = (new String(a)).toUpperCase(); console.log(c2); // "CHENPIPI"
Numbers are the same as Booleans, but numbers are created by new Number() to create temporary objects, while Booleans are created by new Boolean().
📝 In addition to the above example, the most powerful proof is their constructor:
'chenpipi'.constructor === String; // true (12345).constructor === Number; // true true.constructor === Boolean; // true
All this is done secretly by JavaScript, and the temporary objects generated in the process are one-time (throw them away when they are used up).
😮 i see
Wuhu, that makes sense!
This also explains why we can access properties and methods on strings, but can't add or modify properties.
That's because the goal of our actual operation is actually the temporary object created by JavaScript, not the string itself!
Therefore, our add or modify operation actually takes effect, but it takes effect on the temporary object!
📝 Like this:
// In the code: let a = 'chenpipi'; a.name = 'Wu Yanzu'; console.log(a.name); // undefined // amount to: let a = 'chenpipi'; (new String(a)).name = 'Wu Yanzu'; console.log(a.name); // undefined // amount to: let a = 'chenpipi'; let temp = new String(a); temp.name = 'Wu Yanzu'; console.log(a.name); // undefined
Summary
🎉 The above is the whole content of this article.
Finally, let's summarize:
- Most primitive types have corresponding packaging objects;
- Some packaging objects can be new, others can't;
- Wrapper objects are generally used for explicit type conversion;
- There are properties and methods on the object;
- There are no attributes and methods on the original value;
- The original value cannot have attributes and methods;
- But we can manipulate the original value as we manipulate the object;
- This is because JavaScript secretly makes small actions when executing code;
- JavaScript uses temporary wrapper objects to perform operations on behalf of the original values.
We usually don't pay much attention to this when we write code. In fact, these won't affect us when we write code.
So, isn't this article for nothing?
🙉 Yes, not all~
Know yourself and the enemy and win every battle.
Learning these useless little knowledge can be regarded as a deeper understanding of JavaScript. At least it can be used to boast (manual dog head ~).
Relevant information
JavaScript advanced programming (4th Edition)
Authoritative guide to JavaScript (6th Edition)
Primitive - MDN: https://developer.mozilla.org/en-US/docs/Glossary/Primitive
The history of "typeof null": https://2ality.com/2013/10/typeof-null.html
Portal
Open source homepage: tangerine peel
Eazax Cocos game development kit
More sharing
Cocos Creator Performance Optimization: DrawCall
"Draw a cool radar picture in Cocos Creator"
"Write a perfect wave with Shader"
Managing pop ups gracefully and efficiently in Cocos Creator
Interpretation of Cocos Creator source code: engine startup and main cycle
JavaScript memory explanation & Analysis Guide
Cocos Creator Editor Extension: Quick Finder
official account
Rookie Inn
😺 I am Chen pipi, a game developer who is still learning and a Cocos Star Writer who loves sharing.
🎨 This is my personal official account, but it is not limited to game development and front-end technology sharing.
💖 Every original is very attentive. Your attention is the driving force of my original!
Input and output.