首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

游戏开发之旅-JavaScript数据结构

本节是第四讲的第二十七小节,上一节我们为大家介绍了Symbol类型、Date对象、Error对象、RegExp对象,本节将为大家介绍JavaScript的数据结构Map、Set、WeakMap、WeakSet等。

JavaScript数据结构

数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。JavaScript的常用的数据结构Array, Object,结构型数据:JSON,其它数据结构:Map, Set, WeakMap , WeakSet。

Map对象

Map 对象保存键值对,并且能够记住键的原始插入顺序。任何值(对象或者原始值) 都可以作为一个键或一个值。

new Map([iterable])

//Iterable 可以是一个数组或者其他 iterable 对象,其元素为键值对(两个元素的数组,例如: [[ 1, 'one' ],[ 2, 'two' ]])。每个键值对都会添加到新的 Map。null 会被当做 undefined。

例如:let myMap = new Map([[1, 'one'],[2, 'two']]);//myMap.get(1)

let myMap = new Map();

let keyObj = {};

let keyFunc = function() {};

let keyString = 'a string';

// 添加键

myMap.set(keyString, "和键'a string'关联的值");

myMap.set(keyObj, "和键keyObj关联的值");

myMap.set(keyFunc, "和键keyFunc关联的值");

myMap.size; // 3

// 读取值

myMap.get(keyString);    // "和键'a string'关联的值"

myMap.get(keyObj);       // "和键keyObj关联的值"

myMap.get(keyFunc);    // "和键keyFunc关联的值"

let myMap = new Map();

myMap.set(NaN, "not a number");

myMap.get(NaN); // "not a number"

Objects 和 maps 的比较

Objects 和 Maps 类似的是,它们都允许你按键存取一个值、删除键、检测一个键是否绑定了值。因此(并且也没有其他内建的替代方式了)过去我们一直都把对象当成 Maps 使用。不过 Maps 和 Objects 有一些重要的区别,在下列情况里使用 Map 会是更好的选择:

意外的键:Map 默认情况不包含任何键。只包含显式插入的键。一个 Object 有一个原型, 原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。

键的类型:一个 Map的键可以是任意值,包括函数、对象或任意基本类型。一个Object 的键必须是一个 String 或是Symbol。

键的顺序:Map 中的 key 是有序的。因此,当迭代的时候,一个 Map 对象以插入的顺序返回键值。一个 Object 的键是无序的

Size:Map的键值对个数可以轻易地通过size 属性获取Object 的键值对个数只能手动计算

迭代:Map 是 iterable 的,所以可以直接被迭代。迭代一个Object需要以某种方式获取它的键然后才能迭代。

性能:在频繁增删键值对的场景下表现更好。在频繁添加和删除键值对的场景下未作出优化。

Map对象常用属性和方法

Map.size//返回Map对象的键/值对的数量。

Map.clear()//移除Map对象的所有键/值对 。

Map.delete(key)//如果 Map 对象中存在该元素,则移除它并返回 true;否则如果该元素不存在则返回 false。随后调用 Map.prototype.has(key) 将返回 false 。

Map.entries()//返回一个新的 Iterator 对象,它按插入顺序包含了Map对象中每个元素的 [key, value] 数组。

Map.get(key)//返回键对应的值,如果不存在,则返回undefined。

Map.has(key)//返回一个布尔值,表示Map实例是否包含键对应的值。

Map.keys()//返回一个新的 Iterator对象, 它按插入顺序包含了Map对象中每个元素的键 。

Map.set(key, value)//设置Map对象中键的值。返回该Map对象。

Map.values()//返回一个新的Iterator对象,它按插入顺序包含了Map对象中每个元素的值 。

let myMap = new Map();

myMap.set(0, "zero");

myMap.set(1, "one");

for (let [key, value] of myMap) {

console.log(key + " = " + value);//将会显示两个log。一个是"0 = zero"另一个是"1 = one"

}

for (let key of myMap.keys()) {

console.log(key); //// 将会显示两个log。一个是 "0" 另一个是 "1"

}

for (let value of myMap.values()) {

console.log(value);

}

// 将会显示两个log。一个是 "0 = zero" 另一个是 "1 =one"

for (let [key, value] of myMap.entries()) {

console.log(key + " = " + value);

}

//将会显示两个logs。一个是 "0 = zero" 另一个是 "1 = one"

myMap.forEach(function(value, key) {

console.log(key + " = " + value);

})

Set对象

Set 对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。Set对象是值的集合,你可以按照插入的顺序迭代它的元素。Set中的元素只会出现一次,即 Set 中的元素是唯一的。另外,NaN和undefined都可以被存储在Set 中, NaN之间被视为相同的值(NaN被认为是相同的,尽管 NaN !== NaN)。

new Set([iterable])

//Iterable 如果传递一个可迭代对象,它的所有元素将不重复地被添加到新的 Set中。如果不指定此参数或其值为null,则新的 Set为空。

let myArray = ["value1", "value2", "value3"];

// 用Set构造器将Array转换为Set

let mySet = new Set(myArray);

mySet.has("value1"); // returns true

// 用...(展开操作符)操作符将Set转换为Array

console.log([...mySet]); // 与myArray完全一致

let text = 'India';

let mySet = new Set(text);  // Set {'I', 'n', 'd', 'i', 'a'}

mySet.size;  // 5

// 大小写敏感

new Set("Firefox")  // Set(7) [ "F", "i", "r", "e", "f", "o", "x" ]

new Set("hello")  // Set(4) [ "h", "e", "l",  "o" ]

let mySet = new Set();

mySet.add(1); // Set [ 1 ]

mySet.add(5); // Set [ 1, 5 ]

mySet.add(5); // Set [ 1, 5 ]

mySet.add("some text"); // Set [ 1, 5, "some text" ]

let o = ;

mySet.add(o);

mySet.has(1); // true

mySet.has(3); // false

mySet.has(5);              // true

mySet.has(Math.sqrt(25));  // true

mySet.has("Some Text".toLowerCase()); // true

mySet.has(o); // true

mySet.size; // 5

Set对象常用属性及方法

Set.size //返回 Set 对象中的值的个数

Set.add(value) //在Set对象尾部添加一个元素。返回该Set对象。

Set.clear() //移除Set对象内的所有元素。

Set.delete(value) //移除Set的中与这个值相等的元素,返回Set.prototype.has(value)在这个操作前会返回的值。

Set.entries() //返回一个新的迭代器对象,该对象包含Set对象中的按插入顺序排列的所有元素的值的[value, value]数组。

Set.has(value) //返回一个布尔值,表示该值在Set中存在与否。

Set.keys() //与values()方法相同,返回一个新的迭代器对象,该对象包含Set对象中的按插入顺序排列的所有元素的值。

Set.values() //返回一个新的迭代器对象,该对象包含Set对象中的按插入顺序排列的所有元素的值。

Set对象迭代

for (let item of mySet) console.log(item); // 按顺序输出:1, "some text", {"a": 1, "b": 2}, {"a": 1, "b": 2}

for (let item of mySet.keys()) console.log(item); // 按顺序输出:1, "some text", {"a": 1, "b": 2}, {"a": 1, "b": 2}

for (let item of mySet.values()) console.log(item); // 按顺序输出:1, "some text", {"a": 1, "b": 2}, {"a": 1, "b": 2}

for (let [key, value] of mySet.entries()) console.log(key);// 按顺序输出:1, "some text", {"a": 1, "b": 2}, {"a": 1, "b": 2}

// 用forEach迭代

mySet.forEach(function(value) {

console.log(value);

});

WeakMap对象

WeakMap 对象是一组键/值对的集合,其中的键是弱引用的。其键必须是对象,而值可以是任意的。

在 JavaScript 里,map API 可以通过使其四个 API 方法共用两个数组(一个存放键,一个存放值)来实现。给这种 map 设置值时会同时将键和值添加到这两个数组的末尾。从而使得键和值的索引在两个数组中相对应。当从该 map 取值的时候,需要遍历所有的键,然后使用索引从存储值的数组中检索出相应的值。

但这样的实现会有两个很大的缺点,首先赋值和搜索操作都是 O(n) 的时间复杂度( n 是键值对的个数),因为这两个操作都需要遍历全部整个数组来进行匹配。另外一个缺点是可能会导致内存泄漏,因为数组会一直引用着每个键和值。这种引用使得垃圾回收算法不能回收处理他们,即使没有其他任何引用存在了。

相比之下,原生的 WeakMap 持有的是每个键对象的“弱引用”,这意味着在没有其他引用存在时垃圾回收能正确进行。原生 WeakMap 的结构是特殊且有效的,其用于映射的 key 只有在其没有被回收时才是有效的。

正由于这样的弱引用,WeakMap 的 key 是不可枚举的 (没有方法能给出所有的 key)。如果key 是可枚举的话,其列表将会受垃圾回收机制的影响,从而得到不确定的结果。因此,如果你想要这种类型对象的 key 值的列表,你应该使用 Map。

基本上,如果你要往对象上添加数据,又不想干扰垃圾回收机制,就可以使用 WeakMap。

new WeakMap([iterable])

//Iterable 是一个数组(二元数组)或者其他可迭代的且其元素是键值对的对象。每个键值对会被加到新的 WeakMap 里。null 会被当做 undefined。

WeakSet对象

WeakSet 对象允许你将弱保持对象存储在一个集合中。

WeakSet 对象是一些对象值的集合, 并且其中的每个对象值都只能出现一次,在WeakSet的集合中是唯一的。

它和 Set 对象的区别有两点:

与Set相比,WeakSet 只能是对象的集合,而不能是任何类型的任意值。

WeakSet持弱引用:集合中对象的引用为弱引用。如果没有其他的对WeakSet中对象的引用,那么这些对象会被当成垃圾回收掉。这也意味着WeakSet中没有存储当前对象的列表。正因为这样,WeakSet 是不可枚举的。

new WeakSet([iterable]);

//iterable 如果传入一个可迭代对象作为参数, 则该对象的所有迭代值都会被自动添加进生成的 WeakSet 对象中。null 被认为是 undefined。

以上内容部分摘自视频课程04网页游戏编程JavaScript-27数据结构,更多示例请参见网站示例。跟着张员外讲编程,学习更轻松,不花钱还能学习真本领。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20201107A0BUWS00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券