When the for...in loop object in js, the output key value order is confusing

Solve the problem of circular complex objects, key value order confusion

Problem Description

Looping over key values ​​is correct when looping over purely numeric indexed objects

insert image description here

When the object becomes a complex object, the output key becomes complex

insert image description here

solution

//循环中使用
for(let item in this.objectOrder(data)){
    
    
	this.objArr.push(item)
}
 
//方法
objectOrder(obj) {
    
    //排序的函数
	var newkey = Object.keys(obj).sort(); //先用Object内置类的keys方法获取要排序对象的属性名,再利用Array原型上的sort方法对获取的属性名进行排序,newkey是一个数组
	var newObj = {
    
    };//创建一个新的对象,用于存放排好序的键值对
	for (var i = 0; i < newkey.length; i++) {
    
    //遍历newkey数组
	    newObj[newkey[i]] = obj[newkey[i]];//向新创建的对象中按照排好的顺序依次增加键值对
	}
	return newObj;//返回排好序的新对象
}

insert image description here

When looping objects, the output key value order is confused

Before ES6, the common way to loop objects is to use: for...in. But the problem with the for...in loop is that it traverses the properties in the prototype chain, so you need to use hasOwnProperty to check whether the property belongs to the object.

After ES6, we have a better way to loop objects:

  • Object.keys (creates an array containing all properties of the object),
const fruits ={
    
    
    appple:22,
    pear:34,
    orange:88
}
var keys = Object.keys(fruits);
console.log(keys);  //["appple", "pear", "orange"]
  • Object.values ​​(creates an array containing the value of each property in the object),
const fruits ={
    
    
    appple:22,
    pear:34,
    orange:88
}

var values =Object.values(fruits);
console.log(values); //[22, 34, 88]
  • Object.entries (creates a two-dimensional array, each internal array has 2 elements, the first element is the attribute name, the second attribute value)
const fruits ={
    
    
    appple:22,
    pear:34,
    orange:88
}
var entries = Object.entries(fruits);
console.log(entries);
// [['appple',22],['pear',34],['orange',88]]
const fruits ={
    
    
    appple:22,
    pear:34,
    orange:88
}
for (const [fruit,num] of entries) {
    
    
    console.log(`we have ${
      
      num} ${
      
      fruit}`);  //we have 22 appple ...
}

Object对应的方法也存在相同的问题,可以使用类似的方法进行修改

下面主要说的是 for…in

Why is the order messed up when looping objects?

1.这本身就是一个ECMA的一个规范,数字按升序输出,字符串按创建顺序输出,并且数字优先级高于字符串
2.JS本身是不能被计算机识别,需要通过V8转化为字节码
3.那么针对ECMA的一个规范,v8对这个规范做的优化策略
4.排序属性 elements,用来存储数字。 常规属性 properties 用来存储字符串。为了优化,引入对象内属性
5.对象属性多后,会采用慢属性来存储数据,快属性就是采用线性数据结构,慢属性就是采用非线性结构,比如字典来存储数据。

1. Traverse the integer properties first (integer properties, in ascending order), and then traverse other properties in the order they were created.

  • integer attribute
String(Math.trunc(Number(prop)) === prop

当上面的判断结果为 true,prop 就是整数属性,否则不是。

example:

"49" 是整数属性,因为 String(Math.trunc(Number('49')) 的结果还是 "49"。
"+49" 不是整数属性,因为 String(Math.trunc(Number('+49')) 的结果是 "49",不是 "+49"。
"1.2" 不是整数属性,因为 String(Math.trunc(Number('1.2')) 的结果是 "1",不是 "1.2"。

「数字属性应该按照索引值⼤⼩升序排列,字符串属性根据创建时的顺序升序排列。并且数字属性优先于字符串」

2. First of all, the JS code itself will not be directly executed by the computer. The computer can only receive binary assembly code, so a layer of conversion is required in the middle, and this conversion is the v8 engine in chrome

在v8 里是怎么样存储和读取对象属性的呢,

1. 在v8里,将对象里的属性,分为两大类。数字类型,叫排序属性,在v8里叫elements。字符串类型,叫常规属性,在v8里叫properties。
在v8里,为了有效的存储和访问这对象属性,分别使用两个线性结构来保存这两个属性。

2. 在elements对象中,会按照顺序存放排序属性,properties属性则指向了properties对 象,在properties对象中,会按照创建时的顺序保存了常规属性。

3. 但是这样也存在一个问题,在查找排序属性时,直接通过索引即可。但是对象,需要找到properties,然后找到propteries里的属性,这样无疑多了一层操作,所以引入了一个新名词 对象内属性( in- object properties)

4. 但是常规属性也有个数限制,超过是个,默认是10个,就要开辟新的空间来保存常规属性

针对数量少的对象属性,采用以上策略完全没有问题,但是对象数量多了以后,会采用排序非线性字典结构来存储

  • Linear structure: is a collection of ordered data elements. Common linear structures, linear tables, stacks, queues, double queues, strings (one-dimensional arrays)
  • Non-linear structure: Its logical feature is that a node element may have multiple direct predecessors and multiple direct successors.

At this time, the data is stored in a linear structure, and the search is definitely fast, but if a large amount of modified data is involved, it will consume a lot of performance, so there is a lot of data, and v8 adopts slow sorting

  • Quick sort: using a linear structure
  • Slow sorting: using non-linear structures, such as dictionaries

3. At the same time, it is related to the browser. Chrome is different from IE, so the following conclusions are given:

Chrome Opera 的 JavaScript 解析引擎遵循的是新版 ECMA-262 第五版规范。因此,使用 for-in 语句遍历对象属性时遍历书序并非属性构建顺序。
而 IE6 IE7 IE8 Firefox Safari 的 JavaScript 解析引擎遵循的是较老的 ECMA-262 第三版规范,属性遍历顺序由属性构建的顺序决定。

Chrome Opera 中使用 for-in 语句遍历对象属性时会遵循一个规律:
它们会先提取所有 key 的 parseFloat 值为非负整数的属性,然后根据数字顺序对属性排序首先遍历出来,然后按照对象定义的顺序遍历余下的所有属性。

https://blog.csdn.net/wk15038187622/article/details/104062244

Guess you like

Origin blog.csdn.net/weixin_52755319/article/details/129873982