We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
本质上JavaScript数组的特殊之处在于JavaScript的数组不一定是连续内存。 而维基百科关于数组的定义:
在计算机科学中,数组数据结构(英语:array data structure),简称数组(英语:Array),是由相同类型的元素(element)的集合所组成的数据结构,分配一块连续的内存来存储。
JavaScript的数组是否分配连续内存取决于数组成员的类型,如果统一是单一类型的数组那么会分配连续内存,如果数组内包括了各种各样的不同类型,那么则是非连续内存。
非连续内存的数组用的是类似哈希映射的方式存在,比如声明了一个数组,他被分配给了1001、2011、1088、1077四个非连续的内存地址,通过指针连接起来形成一个线性结构,那么当我们查询某元素的时候其实是需要遍历这个线性链表结构的,这十分消耗性能。
而线性储存的数组只需要遵循这个寻址公式,进行数学上的计算就可以找到对应元素的内存地址。
a[k]_address = base_address + k * type_size
非线性储存的数组其速度比线性储存的数组要慢得多。
ES6之前:
var a = []; // 1.基于instanceof a instanceof Array; // 2.基于constructor a.constructor === Array; // 3.基于Object.prototype.isPrototypeOf Array.prototype.isPrototypeOf(a); // 4.基于getPrototypeOf Object.getPrototypeOf(a) === Array.prototype; // 5.基于Object.prototype.toString Object.prototype.toString.apply(a) === '[object Array]';
以上,除了 Object.prototype.toString 外,其它方法都不能正确判断变量的类型。原因是只要手动指定了某个对象的 __proto__ 属性为 Array.prototype,便会导致了该对象继承了 Array 对象,这种毫不负责任的继承方式,使得基于继承的判断方案瞬间土崩瓦解。
Object.prototype.toString
__proto__
Array.prototype
因此 ES6 中有了更好判断数组类型的方法Array.isArray():
Array.isArray()
Array.isArray([]); // true Array.isArray({0: 'a', length: 1}); // false
数组原型提供的方法非常之多,主要分为三种,一种是会改变自身值的,一种是不会改变自身值的,另外一种是遍历方法。
基于ES6,改变自身值的方法一共有9个,分别为pop、push、reverse、shift、sort、splice、unshift,以及两个ES6新增的方法copyWithin 和 fill。 对于能改变自身值的数组方法,日常开发中需要特别注意,尽量避免在循环遍历中去改变原数组的项。
基于ES7,不会改变自身的方法一共有9个,分别为concat、join、slice、toString、toLocateString、indexOf、lastIndexOf、未标准的toSource以及ES7新增的方法includes。
基于ES6,不会改变自身的方法一共有12个,分别为forEach、every、some、filter、map、reduce、reduceRight 以及ES6新增的方法entries、find、findIndex、keys、values。
以上方法具体不再赘述,详情可参考:【深度长文】JavaScript数组所有API全解密以及Array - JavaScript | MDN
这些方法之间存在很多共性。比如:
function(value,index,array){}
thisArg
Array.prototype 的所有方法均具有鸭式辨型这种神奇的特性。它们不止可以用来处理数组对象,还可以处理类数组对象。
例如 javascript 中一个纯天然的类数组对象字符串(String),像join方法(不改变当前对象自身)就完全适用,可惜的是 Array.prototype 中很多方法均会去试图修改当前对象的 length 属性,比如说 pop、push、shift, unshift 方法,操作 String 对象时,由于String对象的长度本身不可更改,这将导致抛出TypeError错误。
推荐一个查询方法是不是会造成mutate的网站:Does it mutate?
The text was updated successfully, but these errors were encountered:
No branches or pull requests
非连续内存
本质上JavaScript数组的特殊之处在于JavaScript的数组不一定是连续内存。
而维基百科关于数组的定义:
JavaScript的数组是否分配连续内存取决于数组成员的类型,如果统一是单一类型的数组那么会分配连续内存,如果数组内包括了各种各样的不同类型,那么则是非连续内存。
非连续内存的数组用的是类似哈希映射的方式存在,比如声明了一个数组,他被分配给了1001、2011、1088、1077四个非连续的内存地址,通过指针连接起来形成一个线性结构,那么当我们查询某元素的时候其实是需要遍历这个线性链表结构的,这十分消耗性能。
而线性储存的数组只需要遵循这个寻址公式,进行数学上的计算就可以找到对应元素的内存地址。
非线性储存的数组其速度比线性储存的数组要慢得多。
数组类型的判断
ES6之前:
以上,除了
Object.prototype.toString
外,其它方法都不能正确判断变量的类型。原因是只要手动指定了某个对象的__proto__
属性为Array.prototype
,便会导致了该对象继承了 Array 对象,这种毫不负责任的继承方式,使得基于继承的判断方案瞬间土崩瓦解。因此 ES6 中有了更好判断数组类型的方法
Array.isArray()
:方法
数组原型提供的方法非常之多,主要分为三种,一种是会改变自身值的,一种是不会改变自身值的,另外一种是遍历方法。
改变自身值的方法(9个)
基于ES6,改变自身值的方法一共有9个,分别为pop、push、reverse、shift、sort、splice、unshift,以及两个ES6新增的方法copyWithin 和 fill。
对于能改变自身值的数组方法,日常开发中需要特别注意,尽量避免在循环遍历中去改变原数组的项。
不会改变自身的方法(9个)
基于ES7,不会改变自身的方法一共有9个,分别为concat、join、slice、toString、toLocateString、indexOf、lastIndexOf、未标准的toSource以及ES7新增的方法includes。
遍历方法(12个)
基于ES6,不会改变自身的方法一共有12个,分别为forEach、every、some、filter、map、reduce、reduceRight 以及ES6新增的方法entries、find、findIndex、keys、values。
以上方法具体不再赘述,详情可参考:【深度长文】JavaScript数组所有API全解密以及Array - JavaScript | MDN
这些方法之间存在很多共性。比如:
function(value,index,array){}
和thisArg
这样两个形参。Array.prototype 的所有方法均具有鸭式辨型这种神奇的特性。它们不止可以用来处理数组对象,还可以处理类数组对象。
例如 javascript 中一个纯天然的类数组对象字符串(String),像join方法(不改变当前对象自身)就完全适用,可惜的是 Array.prototype 中很多方法均会去试图修改当前对象的 length 属性,比如说 pop、push、shift, unshift 方法,操作 String 对象时,由于String对象的长度本身不可更改,这将导致抛出TypeError错误。
最佳实践
要获取 index 就用 Array.indexOf,不然就用 Array.includes 获取布尔值
Array.filter 会遍历整个数组,并且返回多个值。Array.find 只返回满足这个回调第一个元素的值
Array.some 返回一个需要的布尔值
后者会遍历两遍数组,推荐使用 Array.reduce 作为数组累加器
参考资料
The text was updated successfully, but these errors were encountered: