ES6提供的 Set 【WeakSet】 和 Map 【WeakMap】 数据结构
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>ES6提供的 Set 【WeakSet】 和 Map 【WeakMap】 数据结构</title> </head> <body> <script type="text/javascript"> /* 基本类型: String、Number、Boolean、Null、Undefined、Symbol 【typeof 检测基本类型】 引用类型:对象(Object)、数组(Array)、函数(Function) */ // js基本数据类型 let a = undefined console.log(typeof a) // undefined let b = null console.log(typeof b) // object let c = 1 console.log(typeof c) // number let d = true console.log(typeof d) // boolean let e = 'abc' console.log(typeof e) // string // 可以用在一个整数字面量后面加 n 的方式定义一个 BigInt ,如:10n,或者调用函数BigInt() // BigInt 是一种内置对象,它提供了一种方法来表示大于 2^53 - 1 的整数。这原本是 Javascript中可以用 Number 表示的最大数字 // BigInt 可以表示任意大的整数 // BigInt 和 Number 不是严格相等的,但是宽松相等的 const f = 10n; console.log(f, typeof f) // 10n "bigint" const g = BigInt(10) console.log(g, typeof g) // 10n "bigint" console.log(0n === 0) // false console.log(0n == 0) // true // 每个从Symbol()返回的symbol值都是唯一的。一个symbol值能作为对象属性的标识符;这是该数据类型仅有的目的 const sy = Symbol(); const sy1 = Symbol(42); console.log(typeof sy, sy1) // symbol Symbol(42) console.log(Symbol(1) === Symbol(1)) // false // 引用数据类型 let obj = new Object // 等价 new Object() 无参数()可省略 console.log(obj, obj instanceof Object) // {} true // Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__ console.log(Object.create({})) let arr = new Array console.log(arr, arr instanceof Object, typeof arr) // [] true object // 用 Object.create实现类式继承 // ParentClass - 父类(superclass) function ParentClass() { this.x = 0; this.y = 0; } // 父类的方法 ParentClass.prototype.move = function(x, y) { this.x += x; this.y += y; console.info('ParentClass is change.'); }; // ChildClass - 子类(subclass) function ChildClass() { ParentClass.call(this); // call super constructor. } // 子类续承父类 ChildClass.prototype = Object.create(ParentClass.prototype); ChildClass.prototype.constructor = ChildClass; let newObj = new ChildClass() console.log(newObj, newObj instanceof Object) // ChildClass {x: 0, y: 0} true console.log(newObj, newObj instanceof ParentClass) // ChildClass {x: 0, y: 0} true newObj.move(2,2) // ParentClass is change. let fn = function(){ console.log(this) } console.log(fn, fn instanceof Object, typeof fn) // f(){console.log(this)} true function // constructor判断 console.log([] instanceof Array);//->true console.log(/^$/ instanceof RegExp);//->true console.log([] instanceof Object);//->true console.log([].constructor === Array);//->true console.log([].constructor === Object);//->false 我们的constructor可以避免instanceof检测的时候,用Object也是true的问题 console.log({}.constructor === Object); // true /* Array.isArray() ECMAScript5将Array.isArray()正式引入JavaScript,目的就是准确地检测一个值是否为数组 IE8不支持 两个或者多个typeof一起使用时,返回值一定是"string"; 检测的不管是数组还是正则都返回的是"object",所以typeof不能判断一个值是否为数组 Object.prototype.toString.call(value) 判断某个对象值属于哪种内置类型 */ // 接下来谈下这个 ES6中的Set 和 Map 数据结构 // Set 数据结构 let mySet = new Set() console.log(mySet,typeof mySet) // Set(0){} "object" mySet.add(1) mySet.add(2) mySet.add(2) mySet.add(3) console.log(mySet) // Set(3){1,2,3} let setTest = new Set([1,2,3,4,5,5,6,6]) let setArr = [...setTest] console.log(setTest) // Set(3){1,2,3,4,5,6} console.log(setArr) // [1, 2, 3, 4, 5, 6] // 结论 /* Set 数据结构 类似于数组但是Set不会添加重复的值 Set 加入值的时候,不会发生类型转换 [...new Set(array)] 可以去除数组重复成员的方法 [...new Set('string')].join('') 可以去除字符串里面的重复字符 Set函数可以接受一个数组(或者具有 iterable 接口的其他数据结构)作为参数,用来初始化 Array.from方法可以将 Set 结构转为数组 【Array.from是将类数组转为数组的一种方法】 将类数组转为数组的方法: 1、Array的slice方法 例如:let arr = Array.prototype.slice.call(arguments); 2、Array.from() 例如:let arr = Array.from(arguments); 只要有length属性的对象,都可以应用此方法转换成数组 3、扩展运算符... 例如:let arr = [...arguments]; 这种数据结构必须有遍历器接口 4、jquery的$.makeArray() 例如:let arr = $.makeArray(arguments); 使用Array的slice方法,此方法如果不传参数的话会返回原数组的一个拷贝,因此可以用此方法转换类数组到数组 let arr = Array.prototype.slice.call(arguments); // 等同于 let arr = [].slice.call(arguments) */ // WeakSet 数据结构 const myWeakSet = new WeakSet(); // myWeakSet.add(1) // 报错 Invalid value used in weak set console.log(myWeakSet,typeof myWeakSet) // WeakSet {} "object" const arrs = [[1, 2], [3, 4]]; const ws = new WeakSet(arrs); console.log(ws) // WeakSet {[1, 2], [3, 4]} // 结论 /* WeakSet 结构与 Set 类似,也是不重复的值的集合 WeakSet 的成员只能是对象,而不能是其他类型的值 WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用, 如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存 WeakSet 没有size属性 ES6 规定 WeakSet 不可遍历 */ // Map 数据结构 const mp = new Map(); console.log(mp,typeof mp) // Map(0) {} "object" const items = [ ['name', '小明'], ['age', 28] ] items.forEach( ([key, value]) => mp.set(key, value) ) console.log(mp) // Map(2) {"name" => "小明", "age" => 28} const map = new Map(); map.set(1, 'aaa').set(1, 'bbb') console.log(map,map.get(1)) // Map(1) {1 => "bbb"} 'bbb' const mapTest = new Map([ [1, 'one'], [2, 'two'], [3, 'three'], ]) console.log([...mapTest.keys()]) // [1, 2, 3] console.log([...mapTest.values()]) // ['one', 'two', 'three'] console.log([...mapTest.entries()]) // [[1,'one'], [2, 'two'], [3, 'three']] console.log([...mapTest]) // [[1,'one'], [2, 'two'], [3, 'three']] // 结论 /* 对同一个键多次赋值,后面的值将覆盖前面的值 读取【get方法】一个未知的键,则返回undefined 只有对同一个对象的引用,Map 结构才将其视为同一个键 同样的值的两个实例,在 Map 结构中被视为两个键 Map 的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键 Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。 如果你需要“键值对”的数据结构,Map 比 Object 更合适 任何具有 Iterator 接口、且每个成员都是一个双元素的数组的数据结构都可以当作Map构造函数的参数, Set和Map都可以用来生成新的 Map Map 结构转为数组结构,比较快速的方法是使用扩展运算符(...) */ // WeakMap 数据结构 const wmp = new WeakMap(); console.log(wmp, typeof wmp) // WeakMap {} "object" let key = {age: 1} console.log(wmp.set(key,20)) // WeakMap {{…} => 20} console.log(wmp.get(key)) // 20 // 结论 【WeakMap与Map的区别有两点】 /* WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为键名 WeakMap的键名所指向的对象,不计入垃圾回收机制 如果你要往对象上添加数据,又不想干扰垃圾回收机制,就可以使用 WeakMap WeakMap的专用场合就是,它的键所对应的对象,可能会在将来消失。WeakMap结构有助于防止内存泄漏 WeakMap 弱引用的只是键名,而不是键值。键值依然是正常引用 WeakMap 的另一个用处是部署私有属性 class _xx开头的 */ </script> </body> </html>