《JS原理、方法与实践》- ES6新增对象(上篇)
Symbol
Symbol是ES6中新增的一种类型,其含义是符号、标志,它的作用是每调用一次都会返回一个独一无二的返回值,我们可以将此返回值作为对象的属性,这样就不会与原有的属性重名了。即使传入相同的参数,Symbol方法也会返回不同的值。Symbol只能作为方法使用,而不是使用new去创建对象。另一个作用是使用Symbol.iterator作为属性来定义遍历器。
代码示例:
var obj = {};
var abc1 = Symbol('abc');
var abc2 = Symbol('abc');
obj[abc1] = 'hello';
console.log(obj[abc1]); // hello
console.log(obj[abc2]); // undefined
console.log(obj[Symbol('abc')]); // undefined
console.log(abc1 === abc2); // false
容器对象_Set
Set是一种集合类型,类似于Array数组,但与Array存在两点不同:Set中的元素不可以重复;Set中的元素没有序号。
Set对象的属性
Set的prototype属性对象有一个size属性和8个方法:add、clear、delete、has、keys、entries、forEach和values。
代码示例:
var setTest = new Set();
// add:对象添加元素,且返回一个Set对象
setTest.add('a').add('b').add('c');
for (var v of setTest) {
console.log(v); // a, b, c
}
// has: 判断Set对象中是否包含某个元素
console.log(setTest.has('a')); // true
// values: 获取Set的值
for (var v of setTest.values()) {
console.log(v); // a, b, c
}
// keys: 与map对应,set的名-值相等
for (var v of setTest.keys()) {
console.log(v); // a, b, c
}
// entries: 获取名-值对, 与map对应。
for (var v of setTest.entries()) {
console.log(v); // ['a', 'a'],['b', 'b'], ['c', 'c']
}
// 遍历Set对象
setTest.forEach((v) => console.log(v)); // a,b,c
// delete: 删除Set对象的某一个元素
setTest.delete('a');
setTest.forEach((v) => console.log(v)); // b,c
// clear:清空Set对象
setTest.clear();
setTest.forEach((v) => console.log(v)); // 无输出
容器对象_Map
Map对象一种名值对结构。它的作用与对像不同,功能比较单一,只是保存数据的一种容器。虽然对象objct也是保存名值对,但有所不同。
如果Map的value是function类型,那么在function的方法体中Map不可以作为this使用。
如果对象的属性名全是对象,则会转换为字符串来使用(Symbol)除外,而如果Map的key是对象,则不需要转换,可以直接使用。
代码示例一:
let obj = new Object();
let map = new Map();
obj.name = 'zzh';
obj.logName = function() {
console.log(`name is ${this.name}`);
}
map.set('name', 'zzh');
map.set('logName', function() {
console.log(`name is ${this.name}`);
});
obj.logName(); // name is zzh
map.get('logName')(); // name is
map.logName(); // error: Uncaught TypeError: map.logName is not a function
代码示例二:
var key1 = new Set([1,2,3]);
var key2 = new Set([2,3,4]);
var obj = new Object();
var map = new Map();
obj[key1] = 'value';
console.log(obj[key1]); // value
console.log(obj[key2]); // value
console.log(obj[new Set()]); // value
// obj[key1]: [object Set],
// obj[key2]: [object Set],
// obj[new Set()]: [object Set]
console.log(`obj[key1]: ${key1.toString()},
obj[key2]: ${key2.toString()},
obj[new Set()]: ${(new Set()).toString()}`);
map.set(key1, 'value');
console.log(map.get(key1)); // value
console.log(map.get(key2)); // undefined
Map有一个size属性和9个方法:get, set, has, clear, delete, keys, values, entries, forEach。
Set的prototype属性对象有一个size属性和8个方法:add、clear、delete、has、keys、entries、forEach和values。
代码示例:
var mapTest = new Map();
// set:对象添加元素,且返回一个Map对象
mapTest.set('a', 97).set('b', 98).set('c', 99);
// ["a",97],["b",98],["c",98]
for (var v of mapTest) {
console.log(v);
}
// get: 根据key,查询该key对应的value
console.log(mapTest.get('a')); // 97
// has: 判断Map对象中是否包含某个元素
console.log(mapTest.has('a')); // true
// values: 获取Map的值
for (var v of mapTest.values()) {
console.log(v); // 97,98, 99
}
// keys: 遍历Map的key
for (var v of mapTest.keys()) {
console.log(v); // a, b, c
}
// entries: 获取名-值对
for (var v of mapTest.entries()) {
console.log(v); // ['a', 97],['b', 98], ['c', 99]
}
// 遍历Map对象
mapTest.forEach((v) => console.log(v)); // 97,98,99
// delete: 删除Map对象的某一个元素
mapTest.delete('a');
mapTest.forEach((v) => console.log(v)); // 98,99
// clear:清空Map对象
mapTest.clear();
mapTest.forEach((v) => console.log(v)); // 无输出
WeakSet和WeakMap
WeakSet和WeakMap是弱化了的Set和Map,具体说,就是垃圾回收器不会关注元素保存在WeakSet或WeakMap中所产生的以用。换句话说,在WeakSet或者WeakMap中保存的对象,或者在其他地方已经没有引用,垃圾回收器就可能回收它们所占用的内存,而不会考虑WeakSet和WeakMap中的引用,这样做可以有效避免内存泄漏的问题。
WeakSet和WeakMap在使用上跟Set和Map的区别主要是:WeakSet中的元素和WeakMap中的key都只能是对象类型(WeakMap的value可以是任意类型);WeakSet和WeakMap都没有size属性,都没有clear方法,都不可以遍历所包含的元素。
WeakSet的prototype一共有三个方法: add, has, delete
WeakMap的prototype一共有四个方法:get, set, has, delete
缓存对象
ES6中新增了缓存类型,相关的对象一共有三个:ArrayBuffer、TypedArray和DataView。使用缓存进行操作的速度更快,缓存主要适用于对大量二进制数据的操作。
ArrayBuffer就像一个蓄水池,TypedArray就像水盆、水桶等多种盛水的工具,每种工具的大小都是确定的,而DataView则像一种可以随便改变大小的容器,可以更加灵活的使用蓄水池中的水。
ArrayBuffer只是用来保存数据,但不可以自己操作数据;TypedArray和DataView只是操作缓存数据的工具,他们本身并不存储数据。
ArrayBuffer
var buffer = new ArrayBuffer(16);
缓存对象有一个byteLength属性和一个slice方法。byteLength表示缓存包含的字节数,slice方法可以提取出自己的一部分来创建一个新的缓存。slice方法有两个参数:start和end,start表示从那个字节开始提取,end表示提取到第几个字节,即提取的起始字节和结束字节,如果省略,则start默认为0,end默认为原始缓存所包含的字节数。
代码示例:
var buffer = new ArrayBuffer(16);
var buffer1 = buffer.slice();
var buffer2 = buffer.slice(5);
var buffer3 = buffer.slice(5, 10);
console.log(buffer.byteLength); // 16
console.log(buffer1.byteLength); // 16
console.log(buffer2.byteLength); // 11
console.log(buffer3.byteLength); // 5
slice方法所创建的缓存是新的缓存,即新的内存区域,而不是指向原来的内存地址,因此这里创建的4个缓存都是相互独立的,操作它们时不会相互影响。
TypedArray
%TypedArray%(length)
%TypedArray%(typedArray)
%TypedArray%(object)
%TypedArray%(buffer [,byteOffset[,length]])
这里的%TypedArray%代表具体的类型数组对象,TypedArray作为对象的时候自身有两个方法:from和of,这两个方法都可以返回相应的TypedArray对象。from方法的参数可以遍历的对象类型,而of方法的参数直接用每个元素自身。
代码示例:
var u8 = Uint8Array.from(new Set([1,3,5,7,9]));
var i8_1 = Int8Array.from([1,3,5,7,9]);
var i8_2 = Int8Array.of('1','3','5','7','9');
console.log(u8[3]); // 7
console.log(i8_1[3]); // 7
console.log(i8_2[3]); // 7
TypedArray创建出来的对象实例时操作缓存数据最重要的对象,它主要使用TypedArray的prototype属性对象中的属性实际操作。TypedArray的prototype属性对象一共有5个对象属性(包含直接量)和24个方法。5个对象属性分别是:constructor,buffer,byteOffset,byteLength和length。
DataView
DataView可以截取ArrayBuffer中的一块内存来使用,DataView跟TypedArray的区别在于DataView并没有固定的格式,操作比TypedArray更加方便。
如果觉得文章写得还行,请点个赞。如果想与我进一步交流,可以关注我的公众号或者加我的微信。
个人微信
公众号_前端微说.jpg
发表评论 (审核通过后显示评论):