For JavaScript types, it can be simply summarized as: compared to strongly typed languages, it is a weak (loose) type language; there are basic types and reference types, and they are the difference is that a fixed space exists in the stack memory, and a pointer to the implementation location is stored in the stack memory without fixed space and a pointer to the implementation location is stored in the stack memory.
Many books on the market have a lot of space to talk about. This article will talk about several aspects, which may require you to have some simple understanding of JavaScript, especially the types of JavaScript. If you don't understand it yet, you can pick up a book about JavaScript and read it again.
1. Basic types and reference types
1. Basic Type: Undefined/Null/Boolean/Number/String
2. Reference type: Object/Array/Function/Date/RegExp/Error/Map/Set…
Why are the reference types not enumerated? Because you only know so much about it, at least in the article I talked about these are enough. Others may be rarely used, and even those like Map and Set are not supported by all browsers.
2. Judgement of JavaScript Type
There are two operators in JavaScript that can be used to determine types. They are typeof and instanceof, but the circle is very small, and they are not so well-matched, and they are notoriously unreliable. A few situations are also correct, but in many cases they are unreliable. Just look at it and you will know:
// When it's reliable:
typeof 'sofish' // string
new String('sofish') instanceof String // true
// When it is unreliable:
typeof [] // object
typeof null // object
'sofish' instanceof String // false
Uh~ Many beginner JavaScript programmers may swear. Most people already have libraries such as jQuery when they need to use JS. They have all encapsulated them so that you can easily detect types. Of course, in fact, it is not troublesome to detect, because the sentence "In JavaScript, everything is an object", of course, as mentioned in many documents, undefined is actually just a global attribute with NaN and Infinity. You probably know. But "object" can help us:
/* Detect object type
* @param: obj {JavaScript Object}
* @param: type {String} JS type name starting with uppercase
* @return: {Boolean}
*/
function is(obj, type) {
return (obj).slice(8, -1) === type;
}
In this way, we can use the is function to help us solve type judgment, and this simple function has good compatibility and can be used in your project. Situation is like:
is('sofish', 'String') // true
is(null, 'Null') // true
is(new Set(), 'Set') // true
3. JavaScript type conversion
In JavaScript, the type of variables (properties) can be changed. The most common thing you see is the conversion between String and Number. How to turn 1 + '2' into 12? It is necessary to understand the + sign operator here, which is a mathematical operator and also a string hyphen in JavaScript. Therefore, novices will often see an interesting phenomenon. When using the + sign, sometimes the calculation is not what they want, but using the - sign, you can always get the "correct" answer.
1 + '2' // '12'
1 + (+'2') // 3
1 - '2' // -1
This is actually caused by the dual role of +. In the above code, you can notice that the second expression uses a + sign in front of String, forcing its class to be converted to Number. For JavaScript type conversion understanding, in most cases, just understand + has a dual role. Other understandable classes, similar ones can be modified with assignment/overload, and even include Error:
var err = new Error();
(err instanceof Error); // true
err = 'sofish';
(err); // 'sofish'
4. JavaScript reference types
This is a difficult point in this article. Compared to basic types, references can add properties and methods to them; references are references that assign a reference type value to a variable, and they point to the same value stored in heap memory. Variables (properties) can be overloaded, but copying will be a very interesting thing, we will talk about it in detail later.
1. Add properties and methods
We will see in the following code that assuming we will not report an error to a basic similar assignment, but it will be invalid when fetching:
var arr = [1,2,3];
= 'world';
(); // 'world'
var str = 'sofish';
= 'world';
(); // undefined
2. Operation of referring to type values
Since the reference type is stored in the stack memory is a reference, when we point to the same original value, the operation on the value will affect all references; an example here is that reassignment (not a direct operation on the value) will recreate an object and will not change the original value. for example:
var arr = [1,2,3], sofish = arr;
('hello world');
(arr); // [1, 2, 3, 'hello world']
// Non-same type
sofish = ['not a fish']; // When sofish changes similarly, the original value will not be changed
(arr);// [1, 2, 3, 'hello world']
3. Copying of reference type values
Operations on the original value will affect all references, which is not necessarily what we want. Sometimes we need to copy a brand new object without affecting other references when operating. In general, there are few specific operations like Date / Function / RegExp..., mainly for Array and Object to add items, attributes, etc. So what we need to understand is how to copy Array and Object objects.
3.1 Copying of arrays
In the Array object, the slice method exists to return an intercepted array, and in ES5 filter, etc. also return a new array, so we may use this method to copy.
var arr = [1, 2, 3];
var sofish = ();
// Operation on new arrays will not affect the original array
('hello world');
(arr); // [1, 2, 3]
3.2 Copying of objects
In Array copying, we use the slice method. In fact, for Array and Object, we can use the for ... in loop to traverse and assign values to copy.
var obj = { name: 'sofish' }, sofish = {}, p;
for (p in obj) sofish[p] = obj[p];
// Operation on new objects will not affect the original value
= function() {};
(obj); // { name: 'sofish' }
3.3 Shadow / Deep Copy
Like the above operation, it is what we often call Shadow Copy. However, both Array and Object can have multiple layers (dimensionality). Copy like this only takes into account the value of the top layer. Both Array and Object in possible values still point to the original object. for example:
var arr = [1, { bio: 'not a fish' } ], sofish = [], p;
for(p in arr) {
sofish[p] = arr[p];
}
// Operations on objects `cat` contained in `sofish` affect the original value
sofish[1].bio = 'hackable';
(arr);// [1, cat: { bio: 'hackable' } ]
So how to do it? Let's use a copy() function to solve this problem:
/* Copy the object
* @param: obj {JavaScript Object} Original object
* @param: isDeep {Boolean} is a deep copy
* @return: {JavaScript Object} Return a new object
*/
function copy(obj, isDeep) {
var ret = ? [] : {}, p, prop;
// Use with the is function
if(!isDeep && is(obj, 'Array')) return ();
for(p in obj) {
if(!(p)) continue;
prop = obj[p];
ret[p] = (is(prop, 'Object') || is(prop, 'Array')) ?
copy(prop, isDeep) : prop;
}
return ret;
}
In this way, we can copy an Array or Object through the copy(obj, isDeep) function. You can test it:
var arr = [1, {bio: 'not a fish'}];
var sofish = copy(arr);
// Shallow copy does not affect the original value for the operation of the first layer, but affects the second layer
('cat');
(arr); // [1, {bio: 'not a fish'}]
sofish[1].bio = 'hello world';
(arr) // [1, {bio: 'hello world'}]
// Deep copy will not affect the original value
sofish = copy(arr, 1);
sofish[1].bio = 'foo or bar';
(arr); // [1, {bio: 'hello world'}]
That's it. You should basically understand the more difficult points about types. Of course, replication is the most troublesome point. In addition to Array and Object that often require operation, there is also replication of Date / Function / RegExp.