This article brings you relevant knowledge about objects in JavaScript. Objects in JavaScript are also variables, but objects contain many values. I hope it will be helpful to you after reading this article.
JavaScript has six main language types:
string, number, boolean, undefined, null, object
Basic types: string, number, boolean, undefined, null; the basic types themselves are not objects.
Butnullis sometimes regarded as an object, and typeof null will return object. In fact, null is a basic type. The reason is that different objects are represented as binary at the bottom level. In JavaScript, if the first three digits of the binary number are0, it will be judged as the object type, and null means all 0s, so typeof will return object.
Array is also a type of object with some additional behaviors. The organization of arrays is more complex than ordinary objects.
Functions are essentially the same as ordinary functions, except that they can be called, so you can operate functions in the same way as objects.
String
Number
Date
Boolean
Object
Function
Array
.a is called attribute access, and ['a'] is called operator access.
//对象中的属性名始终是字符串 myobj={} myobj[myobj]='bar'//赋值 myobj['[object object]'] //'bar'
es6 Add computable attribute names, you can use [] in text form to wrap an expression as the attribute name
var perfix = 'foo' var myobj={ [perfix + 'bar'] :'hello' } myobj['foobar']//hello
Starting from es5, all attributes have attribute descriptors. For example, you can directly determine whether the attribute is readable and writable.
/* * 重要函数: * Object.getOwnPropertyDescriptor(..) //获取属性描述符 * Object.defineProperty(..) //设置属性描述符 */ writeble(可读性) configurable(可配置性) enumerable (可枚举性)
for in can be used to traverse the enumerable attribute list of the object (including the [[Prototype]] chain), and you need to manually obtain the attribute value . Can traverse arrays and ordinary objects
es6 is new and can be used to traverse the attribute values of arrays. The for of loop will first request an iterator object from the accessed object, and then Iterate through all return values by calling the next() method of the iterator object.
Arrays have built-in @@iterators,
var arr = [1, 2, 3] var it = arr[Symbol.iterator]()//迭代器对象 console.log(it.next());//{value: 1, done: false} console.log(it.next());//{value: 2, done: false} console.log(it.next());//{value: 3, done: false} console.log(it.next());//{value: undefined, done: true} /* * 用es6 的Symbol.iterator 来获取对象的迭代器内部属性。 * @@iterator本身并不是一个迭代器对象,而是一个返回迭代器对象的函数。 */
Because the object does not have a built-in @@iterator, the for...of traversal cannot be automatically completed. However, you can define @@iterator for any object you want to traverse, for example:
var obj={ a:1,b:2 } Object.defineProperty(obj, Symbol.iterator, { enumerable: false, writable: false, configurable: true, value: function () { var self = this var idx = 0 var ks = Object.keys(self) return { next: function () { return { value: self[ks[idx++]], done: (idx > ks.length) } } } } }) //手动遍历 var it = obj[Symbol.iterator]()//迭代器对象 console.log(it.next());//{value: 1, done: false} console.log(it.next());//{value: 2, done: false} console.log(it.next());//{value: undefined, done: true} //for of 遍历 for (const v of obj) { console.log(v); } //2 //3
/* forEach:会遍历所有并忽略返回值 some:会一直运行到回调函数返回 true(或者"真"值) every:会一直运行到回调函数返回 false(或者"假"值) map: filter:返回满足条件的值 reduce: some和every 和for的break语句类似,会提前终止遍历 */
As mentioned above, the main language types of JavaScript There are six types: string, number, boolean, null, undefined, and object; the first five are basic types, and the last object is a reference type.
Stack: automatically allocates memory space and is automatically released by the system. It stores basic type values and reference types. The address of
Heap: dynamically allocated memory, the size is variable and will not be automatically released. Reference type values are stored in it
Basic types use value passing; reference types use address (pointer) passing. Assign the address stored in stack memory to the received variable.
Shallow copy: A shallow copy of an object will copy the 'main' object, but will not copy the objects in the object. The 'inner object' is shared between the original object and its copy.
Deep copy: A deep copy of an object not only copies each attribute of the original object out one by one, but also deeply copies the objects contained in each attribute of the original object. The method is recursively copied to the new object, so modifications to one object will not affect the other object.
For example:
var anotherObject={ b:"b" } var anotherArray=[] var myObject={ a:'a', b:anotherObject, //引用,不是副本 c:anotherArray //另外一个引用 } anotherArray.push(anotherObject,myObject) /* 如何准确的复制 myObject? 浅复制 myObject,就是复制出 新对象中的 a 的值会复制出对象中a 的值,也就是 'a', 但是对象中的 b、c两个属性其实只是三个引用,新对象的b、c属性和旧对象的是一样的。 深复制 myObject,除了复制 myObject 以外还会复制 anotherObject 和 anotherArray。 但是这里深复制 myObject会出现一个问题,anotherArray 引用 anotherObject 和 myObject, 所以又需要复制 myObject,这样就会由于循环引用导致死循环。 后面会介绍如何处理这种情况。 */
object.assign(), spread operator (…)
var obj1 = {x: 1, y: 2} var obj2 = Object.assign({}, obj1); console.log(obj1) //{x: 1, y: 2} console.log(obj2) //{x: 1, y: 2} obj2.x = 2; //修改obj2.x console.log(obj1) //{x: 1, y: 2} console.log(obj2) //{x: 2, y: 2} var obj1 = { x: 1, y: { m: 1 } }; var obj2 = Object.assign({}, obj1); console.log(obj1) //{x: 1, y: {m: 1}} console.log(obj2) //{x: 1, y: {m: 1}} obj2.y.m = 2; //修改obj2.y.m console.log(obj1) //{x: 1, y: {m: 2}} console.log(obj2) //{x: 2, y: {m: 2}}
slice(), concat, Array.from(), spread operator (...), concat, for loop
var arr1 = [1, 2, [3, 4]], arr2 = arr1.slice(); console.log(arr1); //[1, 2, [3, 4]] console.log(arr2); //[1, 2, [3, 4]] arr2[0] = 2 arr2[2][1] = 5; console.log(arr1); //[1, 2, [3, 5]] console.log(arr2); //[2, 2, [3, 5]]
During the serialization process of JSON.stringify(), undefined, arbitrary functions and symbol values will be ignored during the serialization process (appearing in non- when it is in the property value of an array object) or is converted to null (when it appears in an array).
var obj1 = { x: 1, y: { m: 1 }, a:undefined, b:function(a,b){ return a+b }, c:Symbol("foo") }; var obj2 = JSON.parse(JSON.stringify(obj1)); console.log(obj1) //{x: 1, y: {m: 1}, a: undefined, b: ƒ, c: Symbol(foo)} console.log(obj2) //{x: 1, y: {m: 1}} obj2.y.m = 2; //修改obj2.y.m console.log(obj1) //{x: 1, y: {m: 1}, a: undefined, b: ƒ, c: Symbol(foo)} console.log(obj2) //{x: 2, y: {m: 2}}
function deepClone(obj){ let result = Array.isArray(obj)?[]:{}; if(obj && typeof obj === "object"){ for(let key in obj){ if(obj.hasOwnProperty(key)){ if(obj[key] && typeof obj[key] === "object"){ result[key] = deepClone(obj[key]); }else{ result[key] = obj[key]; } } } } return result; } var obj1 = { x: { m: 1 }, y: undefined, z: function add(z1, z2) { return z1 + z2 }, a: Symbol("foo"), b: [1,2,3,4,5], c: null }; var obj2 = deepClone(obj1); obj2.x.m = 2; obj2.b[0] = 2; console.log(obj1); console.log(obj2); //obj1 { a: Symbol(foo) b: (5) [1, 2, 3, 4, 5] c: null x: {m: 1} y: undefined z: ƒ add(z1, z2) } //obj2 { a: Symbol(foo) b: (5) [2, 2, 3, 4, 5] c: null x: {m: 2} y: undefined z: ƒ add(z1, z2) }
The above deep copy method encounters a circular reference and will fall into a cyclic recursive process, causing the stack to explode. Therefore improvements are needed.
To solve the problem of stack explosion due to loop recursion, you only need to determine whether the fields of an object refer to this object or any parent of this object Level is enough.
function deepClone(obj, parent = null){ // 改进(1) let result = Array.isArray(obj)?[]:{}; let _parent = parent; // 改进(2) while(_parent){ // 改进(3) if(_parent.originalParent === obj){ return _parent.currentParent; } _parent = _parent.parent; } if(obj && typeof obj === "object"){ for(let key in obj){ if(obj.hasOwnProperty(key)){ if(obj[key] && typeof obj[key] === "object"){ result[key] = deepClone(obj[key],{ // 改进(4) originalParent: obj, currentParent: result, parent: parent }); }else{ result[key] = obj[key]; } } } } return result; } // 调试用 var obj1 = { x: 1, y: 2 }; obj1.z = obj1; var obj2 = deepClone(obj1); console.log(obj1); console.log(obj2);
function deepClone(obj, parent = null){ let result; // 最后的返回结果 let _parent = parent; // 防止循环引用 while(_parent){ if(_parent.originalParent === obj){ return _parent.currentParent; } _parent = _parent.parent; } if(obj && typeof obj === "object"){ // 返回引用数据类型(null已被判断条件排除)) if(obj instanceof RegExp){ // RegExp类型 result = new RegExp(obj.source, obj.flags) }else if(obj instanceof Date){ // Date类型 result = new Date(obj.getTime()); }else{ if(obj instanceof Array){ // Array类型 result = [] }else{ // Object类型,继承原型链 let proto = Object.getPrototypeOf(obj); result = Object.create(proto); } for(let key in obj){ // Array类型 与 Object类型 的深拷贝 if(obj.hasOwnProperty(key)){ if(obj[key] && typeof obj[key] === "object"){ result[key] = deepClone(obj[key],{ originalParent: obj, currentParent: result, parent: parent }); }else{ result[key] = obj[key]; } } } } }else{ // 返回基本数据类型与Function类型,因为Function不需要深拷贝 return obj } return result; } // 调试用 function construct(){ this.a = 1, this.b = { x:2, y:3, z:[4,5,[6]] }, this.c = [7,8,[9,10]], this.d = new Date(), this.e = /abc/ig, this.f = function(a,b){ return a+b }, this.g = null, this.h = undefined, this.i = "hello", this.j = Symbol("foo") } construct.prototype.str = "I'm prototype" var obj1 = new construct() obj1.k = obj1 obj2 = deepClone(obj1) obj2.b.x = 999 obj2.c[0] = 666 console.log(obj1) console.log(obj2) console.log(obj1.str) console.log(obj2.str)
Note: Deep copy of Function type:
bind(): Use fn.bind() to make a deep copy of the function, but it cannot be used because of the problem with the this pointer;
eval(fn.toString()): Only arrow functions are supported. Ordinary function function fn(){} is not applicable;
new Function(arg1,arg2,...,function_body): The parameters and function body need to be extracted;
PS: Generally not A deep copy of Function is required.
[Related recommendations:javascript learning tutorial]
The above is the detailed content of Detailed explanation of JavaScript basic objects (organized and shared). For more information, please follow other related articles on the PHP Chinese website!