JavaScript 集合对象
1. 集合对象
1.1 Object
关于Object类型的创建和底层存储原理我在另一篇文章有说明: JavaScript 对象属性底层原理
我们知道了大多数情况下Object底层都是Hash结构,我们再看看V8中从Object派生的继承图

1.2 Array
数组是一种类列表对象,可以存储重复的对象,只能用整数作为数组元素的索引。
在V8中数组继承于Object,数据结构依然是Hash表。
//An instance of the built-in array constructor (ECMA-262, 15.4.2).
//Definition at line 3562 of file v8.h
class V8_EXPORT Array : public Object {
public:
uint32_t Length() const;
/**
* Creates a JavaScript array with the given length. If the length
* is negative the returned array will have length 0.
*/
static Local<Array> New(Isolate* isolate, int length = 0);
V8_INLINE static Array* Cast(Value* obj);
private:
Array();
static void CheckCast(Value* obj);
};
1.3 Map
Map对象保存键值对,Key可以是任何值(对象或原始值),Value也可以是任何值。
- Key的比较是基于 "SameValueZero" 算法:NaN 是与 NaN 相等的(虽然 NaN !== NaN),剩下所有其它的值是根据 === 运算符的结果判断是否相等。
根据ECMA6-262的定义
Map object must be implemented using either hash tables or other mechanisms that, on average, provide access times
that are sublinear on the number of elements in the collection.
Map可以是hash表结构或相等访问时间的结构.
根据以下定义,在V8中Map继承于Object,数据结构依然是Hash表。
//An instance of the built-in Map constructor (ECMA-262, 6th Edition, 23.1.1).
class V8_EXPORT Map : public Object {
public:
size_t Size() const;
void Clear();
V8_WARN_UNUSED_RESULT MaybeLocal<Value> Get(Local<Context> context,Local<Value> key);
V8_WARN_UNUSED_RESULT MaybeLocal<Map> Set(Local<Context> context,Local<Value> key,Local<Value> value);
V8_WARN_UNUSED_RESULT Maybe<bool> Has(Local<Context> context,Local<Value> key);
V8_WARN_UNUSED_RESULT Maybe<bool> Delete(Local<Context> context,Local<Value> key);
/**
* Returns an array of length Size() * 2, where index N is the Nth key and
* index N + 1 is the Nth value.
*/
Local<Array> AsArray() const;
/**
* Creates a new empty Map.
*/
static Local<Map> New(Isolate* isolate);
V8_INLINE static Map* Cast(Value* obj);
private:
Map();
static void CheckCast(Value* obj);
};
Object VS Map
1. 相同
都允许你按键存取一个值、删除键、检测一个键是否绑定了值
2. 不同
- Object的键只能是字符串或者Symbols. Map的键可以是任意值,包括函数、对象、基本类型。
- Map中的键值是有序的, 而Object中的键则不是。当遍历时,Map对象是按插入的顺序返回键值。
- Map可以通过size属性获取键值对个数, Object则不行。
注: ES5中的Object.keys()可以返回普通对象的所有属性,但是如果是方法对象,定义在原型链上的属性无法通过该方法获取 - Map内置有Iterator可以直接迭代,而Object的迭代需要先获取它的键的数组,然后再进行迭代。
- Map在涉及频繁增删键值对的场景下会相对Object性能较好。
1.4 Set
Set对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。
根据ECMA6-262的定义
Set objects must be implemented using either hash tables or other mechanisms that, on average, provide access times
that are sublinear on the number of elements in the collection.
Distinct values are discriminated using the SameValueZero comparison algorithm.
- Set可以是hash表结构或相等访问时间的结构
- Key的比较是基于 "SameValueZero" 算法
根据以下定义,在V8中Set继承于Object,数据结构依然是Hash表。
//An instance of the built-in Set constructor (ECMA-262, 6th Edition, 23.2.1).
class V8_EXPORT Set : public Object {
public:
size_t Size() const;
void Clear();
V8_WARN_UNUSED_RESULT MaybeLocal<Set> Add(Local<Context> context,Local<Value> key);
V8_WARN_UNUSED_RESULT Maybe<bool> Has(Local<Context> context,Local<Value> key);
V8_WARN_UNUSED_RESULT Maybe<bool> Delete(Local<Context> context,Local<Value> key);
/**
* Returns an array of the keys in this Set.
*/
Local<Array> AsArray() const;
/**
* Creates a new empty Set.
*/
static Local<Set> New(Isolate* isolate);
V8_INLINE static Set* Cast(Value* obj);
private:
Set();
static void CheckCast(Value* obj);
};
1.5 WeakMap
WeakMap 对象是一组键/值对的集合,其中的键是弱引用的。其键必须是对象,而值可以是任意的。
与Map相比区别:
- Map内部有两个数组(一个存放键,一个存放值), 给map 设置值时会同时将键和值添加到这两个数组的末尾。从而使得键和值的索引在两个数组中相对应,因此赋值和搜索操作都是 O(n) 的时间复杂度。
- 因为数组会一直引用着每个键和值,这种引用使得垃圾回收算法不能回收处理他们,即使没有其他任何引用存在了。
- WeakMap 持有的是每个键或值对象的“弱引用”,这意味着在没有其他引用存在时垃圾回收能正确进行。正由于这样的弱引用,WeakMap 的 key 是不可枚举的 (没有方法能给出所有的 key)。
1.6 WeakSet
它和 Set 对象的区别有两点:
- WeakSet对象中只能存放对象引用, 不能存放值, 而 Set 对象都可以.
- WeakSet对象中存储的对象值都是被弱引用的, 如果没有其他的变量或属性引用这个对象值, 则这个对象值会被当成垃圾回收掉. 正因为这样, WeakSet 对象是无法被枚举的, 没有办法拿到它包含的所有元素.
2. 集合对象的遍历
2.1 For In
遍历对象的可枚举(enumerable为true,非Symbol)属性,以及对象从其构造函数原型中继承的属性。
原理:首先枚举当前对象的enumerable为true的所有属性,然后枚举从原型链中构造函数原型中继承的属性(更接近原型链中对象的属性覆盖原型属性)。
ES 5标准,设计目的用于遍历key
注:使用for in循环数组会有如下缺陷
- 索引是字符串型的数字,因而不能直接进行几何运算
- 遍历顺序可能不是实际的内部顺序
- 会遍历数组所有的可枚举属性,包括原型。例如的原型方法method和name属性
//函数和实例的遍历
function F0(){
this.a = "1";
}
F0.b = "2";
for(var k in F0){
console.log(k);//b
}
var fi0=new F0();
for(var k in fi0){
console.log(k);//a
}
//函数继承的遍历
function F1(){
this.a = "a";
this.c = "F1";
}
function F2(){
this.b = "b";
this.c = "F2"
}
F2.prototype=new F1();
var fi2 = new F2();
for(var k in fi2){
console.log(k+":"+fi2[k]);//b:b,c:F2,a:a
}
//数组遍历
var ar1 = [1,2,3];
ar1.a = "a";
for(var k in ar1){
console.log(k);//0,1,2,a
}
2.2 For of
检查对象是否具有Symbol.iterator属性,如果存在,就调用该属性返回的遍历器方法。以上的集合都已经内置了该属性,所有可以使用For of遍历。
ES 6标准,遍历value
与for in相比,有如下区别
- 处集合对象外,还支持类对象和字符串
- 不支持遍历普通对象,但可通过与Object.keys()搭配使用实现遍历
- 遍历后的输出结果为数组元素的值
var ar2 = [1,2,3]
ar2.length = 5;
ar2.push(4);
for (var k in ar2) {
console.log(ar2[k]); //1,2,3,4
}
for (var v of ar2) {
console.log(v); //1,2,3,undefined,undefined,4
}
Refers:
http://www.ecma-international.org/publications/standards/Ecma-262.htm
https://v8docs.nodesource.com/node-10.6/annotated.html
JavaScript 集合对象的更多相关文章
- javascript数组对象排序
javascript数组对象排序 JavaScript数组内置排序函数 javascript内置的sort函数是多种排序算法的集合 JavaScript实现多维数组.对象数组排序,其实用的就是原生的s ...
- javascript中对象的深度克隆
记录一个常见的面试题,javascript中对象的深度克隆,转载自:http://www.2cto.com/kf/201409/332955.html 今天就聊一下一个常见的笔试.面试题,js中对象的 ...
- JS中集合对象(Array、Map、Set)及类数组对象的使用与对比
原文地址 在使用js编程的时候,常常会用到集合对象,集合对象其实是一种泛型,在js中没有明确的规定其内元素的类型,但在强类型语言譬如Java中泛型强制要求指定类型. ES6引入了iterable类型, ...
- JavaScript原生对象及扩展
来源于 https://segmentfault.com/a/1190000002634958 内置对象与原生对象 内置(Build-in)对象与原生(Naitve)对象的区别在于:前者总是在引擎初始 ...
- javascript 函数对象
http://hi.baidu.com/gdancer/blog/item/a59e2c12479b4e54f919b814.html jQuery的一些写法就是基于这篇文章的原理的.. 函数 ...
- JavaScript DOM 对象
JavaScript DOM 对象 什么叫DOM,DOM是文档对象模型(Document Object Model,是基于浏览器编程(在本教程中,可以说就是DHTML编程)的一套API接口,W3C ...
- [转]JavaScript RegExp 对象参考手册
JavaScript RegExp 对象参考手册 RegExp 对象 RegExp 对象表示正则表达式,它是对字符串执行模式匹配的强大工具. 直接量语法 /pattern/attributes 创建 ...
- 【timeisprecious】【JavaScript 】JavaScript RegExp 对象
JavaScript>RegExp正则表达式 1 .From Runnob JavaScript RegExp 对象(概览) JavaScript RegExp 对象(教程) RegExp 对象 ...
- 前端基础:JavaScript DOM对象
JavaScript DOM对象 通过HTML DOM,可以访问JavaScript HTML文档的所有元素. 一.HTML DOM(文档对象模型) 当网页被加载时,浏览器会创建页面的文档对象模型(D ...
随机推荐
- holer实现外网访问内网数据库
外网访问本地数据库 本地安装了数据库,只能在局域网内访问,怎样从公网也能访问内网数据库? 本文将介绍使用holer实现的具体步骤. 1. 准备工作 1.1 安装并启动数据库 默认安装的数据库端口是33 ...
- openstack常用命令-neutron篇
列出当前租户所有的网络 neutron net-list 列出所有租户的所有网络(需要管理员权限) neutron net-list --all-tenants 创建一个网络(vlan/flat) n ...
- 如何开发NPM包
创建包目录 D:\>mkdir mypackage && cd mypackage D:\mypackage>npm init --yes 进入mypackage目录,你会 ...
- java 对同一个文件进行读写操作
同一个文件是不可以进行同时的读写的,因为我们写入文件会覆盖原文件的,如果这样,对于同一文件来来说,文件发生覆盖,无法进行下次读取 当然,对于两个不同的文件,可以一边读一边写的操作 题目:一个文本中存储 ...
- 基于selenium+phantomJS的动态网站全站爬取
由于需要在公司的内网进行神经网络建模试验(https://www.cnblogs.com/NosenLiu/articles/9463886.html),为了更方便的在内网环境下快速的查阅资料,构建深 ...
- C语言的AT指令
今天跟人聊嵌入式,对面是某国际硬盘生产商的嵌入式软件工程师,问了我很简单的问题,如何快速将一个变量赋给某个特定的地址. 按我们思路就是unsigned *a = address1: *a = add ...
- Mac pip install mysql-python
首次在mac os 下,用pip install MySQL-Python时经常出现如下错误: sh: mysql_config: command not foundTraceback (most r ...
- Adjacency matrix based Graph
Interface AddVertex(T data) AddEdge(int from, int to) DFS BFS MST TopSort PrintGraph using System; u ...
- ngix匹配规则
语法规则: location [=|~|~*|^~] /uri/ { … } =:开头表示精确匹配 ^~:开头表示uri以某个常规字符串开头,理解为匹配 url路径即可.nginx不对url做编码,因 ...
- 右键菜单添加包含ICON图片的快捷打开方式
右键菜单添加包含ICON图片的快捷打开方式: ①保存如下代码为“submit.reg”, ②修改对应的程序地址 ③双击创建的文件,导入到注册表中,即可 Windows Registry Editor ...