《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更加方便。

你可能感兴趣的:(《JS原理、方法与实践》- ES6新增对象(上篇))