This is the 9th day of my participation in the August Gwen Challenge. For details, see: August Gwen Challenge juejin.cn/post/698796…
The data type
It is divided into basic type data and reference type data
Basic type data
- String, Number, Boolean, Null, Undefined, Symbol, BigInt
- Values are stored in stack memory
Reference type data
-
Object
- Math, Date, RegExp, Function, Array
-
Values are stored in heap memory, and reference addresses are stored in stack memory.
Data type detection
Data type detection methods can be divided into three types:
- typeof
- insatnceof
- toString
typeof
-
Basic type data, except null, can return the data type correctly;
- Typeof null “object”. Is a bug designed by JS itself. If you need to determine whether data is null, you can directly determine XXX === null
-
All types of reference data except function return object;
- typeof function “function”
insatnceof
This approach is derived from the knowledge of prototype chains.
When the constructor is new, the newly generated object inherits the properties and methods of the constructor. The result on the prototype chain is that the proto of the new object points to the constructor’s prototype, so you can use instanceof to determine if the newly generated object is an instanceof a constructor.
var ObjectFactory = function () {
// Create an object
var obj = new Object(a)// Return the first argument as a constructor
var Constructor = [].shift.call(arguments)
// Copy the constructor's prototype to the object's prototype
obj.__proto__ = Constructor.prototype
// Call the constructor with obj as this, arguments
var ret = Constructor.apply(obj, arguments)
If the constructor returns an object, it returns it directly, otherwise we return the object created by this (new)
return typeof ret === 'object'? ret: obj
}
// The effect is equivalent
var a = ObjectFactory(Person, 'sven');Copy the code
- Basic type data all return false, the result is not accurate
- Reference type data returns true, which is more accurate
Instanceof code implementation
function myInstanceof(left,right){
// Use typeof to determine if it is a basic data type. If so, return false
if(typeofleft ! = ="object" || left=== null) {return false; }// getProtypeOf is an Object API that can get the parameters of the prototype Object
let proto = Object.getPrototypeOf(left);
while(true) {// Loop down until you find objects with the same prototype
if(proto===null) {return false; }if(proto === right.prototype){return true; } proto =Object.getPrototypeOf(proto); }}Copy the code
toString
Object. The prototype. The toString () method is the archetype of the Object and returns the format for [Object] Xxx (capitalize the first letter)
- The data type returned is accurate enough to distinguish window from Document
- The call method is required for values of all data types except ordinary object objects
Object.prototype.toString.call(xxx)
Copy the code
A universal method for determining data types
function getType(obj){
let type = typeof obj;
if(type ! = ="object") {// Check typeof first, if it is a basic data type, return directly
return type;
}
// If typeof returns object, regex returns result
return Object.prototype.toString().call(obj).replace(/^[Object (\S+)]$/.'$1');
}
Copy the code
Depth copy
It’s all about the first layer of data, not the whole outermost layer.
Shallow copy
Create a new object of your own to accept the object values you want to copy or reference again
- Primitive data: Assign a copy of the value directly to the new data
- Reference type data: Copied over is the reference address of the value. So if the value of the reference type is changed in the new data, the original data will also be changed
Deep copy
A complete copy of an object from memory to the target object, and a new space in the heap memory to store the new object, and the modification of the new object does not change the original object, the two achieve true separation.
- Primitive data: Assign a copy of the value directly to the new data
- Reference type data: copies the heap data directly into the new memory, so that if the value of the reference type is changed in the new data, the original data will not change
Shallow copy method
object.assign()
- Two arguments: target source(which can be multiple) No return value
- If the value of the source object is modified after the copy, the changed value is printed before the modification
Note:
- Do not copy non-enumerable properties
- Inheritance properties are not copied
- Property values of type Symbol can be copied
It can be understood as internally looping through the properties of the original object, assigning the properties of the original object to the corresponding properties of the new object.
Extended operator
Just expand the data in the new object.
- Extended operators are convenient when the first layer of data is all primitive data types
Concat (), slice ()
Shallow copy method for arrays
arr.concat();
arr.slice();
Copy the code
Implement the shallow copy method manually
function shallowClone(target){
if(typeof target === "object"&& target ! = =null) {let cloneTarget = Array.isArray(target) ? [] : {};
for(let prop in target){
if(target.hasOwnProperty(prop)){ cloneTarget[prop] = target(prop); }}return cloneTarget;
} else {
returntarget; }}Copy the code
Deep copy method
JSON.stringify()
Parse () serializes an object into a JSON string, converts the contents of the object into a string, and finally generates a new object from the JSON string using json.parse ()
Note:
- If the object contains data of type function, undefined, symbol, etc., the key-value pair will disappear after copying
- Copying data of type Date becomes a string
- Copying RegExp objects becomes empty
- Non-copy-non-enumerable properties
- Object prototype chains cannot be copied
- If the object contains NaN, infinity, etc., it will become NULL after being copied
- Unable to copy a circular reference to an object
Handwritten base edition deep copy
function deepClone(target){
let cloneObj = {};
for(let prop in target){
if(typeof target[prop] === "object"&& target[prop] ! = =null){
cloneObj[prop] = deepClone(target[prop]);
} else {
cloneObj[prop] = target[prop];
}
return cloneObj;
}
Copy the code
- You still cannot copy non-enumerable properties and values of type symbol
- Function, Date, and Math cannot be deeply copied only for common objects
- A circular reference to an object cannot be resolved
Handwritten final deep copy
// Strictly determine whether the data is reference type data
const isComplexDataType = obj= > (typeof obj === 'object' || typeof obj === 'function') && (obj ! = =null)
const deepClone = function (obj,hash = new WeakMap(a)){
if(obj.constructor === Date) return new Date(obj); // The date object returns a new date object
if(obj.constructor === RegExp) return new RegExp(obj); The regular object returns a new regular object directly
// If the loop is referenced, use weakMap
if(hash.has(obj)) return hash.get(obj)
let allDesc = Object.getOwnPropertyDescriptors(obj);
// Walks through the properties of all keys of the passed argument
let cloneObj = Object.create(Object.getPrototypeOf(obj),allDesc);
// Inherit the prototype chain
hash.set(obj,cloneObj);
for(let key of Reflect.ownKeys(obj)){
cloneObj[key] = (isComplexDataType(obj[key]) && typeofobj[key] ! = ='function')? deepClone(obj[key],hash) : obj[key]; }return cloneObj;
}
Copy the code