Symbol 数据类型
- ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。它属于 JavaScript 语言的数据类型之一,其他数据类型是:undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、大整数(BigInt)、对象(Object)。
- 使用:通过
Symbol() 函数生成 Symbol.prototype.description 创建 Symbol 的时候,可以添加一个描述。const sym = Symbol('foo');
sym.description
Set数据结构
- ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。Set本身是一个构造函数,用来生成 Set 数据结构
const s = new Set();
[2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x));
for (let i of s) {
console.log(i);
}
// 2 3 5 4
Set.prototype.size :返回Set实例的成员总数。Set.prototype.add(value) :添加某个值,返回 Set 结构本身。Set.prototype.delete(value) :删除某个值,返回一个布尔值,表示删除是否成功。Set.prototype.has(value) :返回一个布尔值,表示该值是否为Set的成员。Set.prototype.clear() :清除所有成员,没有返回值。Set.prototype.keys() :返回键名的遍历器Set.prototype.values() :返回键值的遍历器Set.prototype.entries() :返回键值对的遍历器Set.prototype.forEach() :使用回调函数遍历每个成员let set = new Set(['red', 'green', 'blue']);
for (let item of set.keys()) {
console.log(item);
}
for (let item of set.values()) {
console.log(item);
}
for (let item of set.entries()) {
console.log(item);
}
let set = new Set([1, 4, 9]);
set.forEach((value, key) => console.log(key + ' : ' + value))
Map数据结构
- 它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。
size 属性返回 Map 结构的成员总数。Map.prototype.set(key, value) 设置键名key对应的键值为value,然后返回整个 Map 结构Map.prototype.get(key) 读取key对应的键值,如果找不到key,返回undefined。Map.prototype.has(key) 方法返回一个布尔值,表示某个键是否在当前 Map 对象之中。Map.prototype.delete(key) delete方法删除某个键,返回true。如果删除失败,返回false。Map.prototype.clear() clear方法清除所有成员,没有返回值。Map.prototype.keys() :返回键名的遍历器。Map.prototype.values() :返回键值的遍历器。Map.prototype.entries() :返回所有成员的遍历器。Map.prototype.forEach() :遍历 Map 的所有成员。const map = new Map([
['F', 'no'],
['T', 'yes'],
]);
for (let key of map.keys()) {
console.log(key);
}
for (let value of map.values()) {
console.log(value);
}
for (let item of map.entries()) {
console.log(item[0], item[1]);
}
for (let [key, value] of map.entries()) {
console.log(key, value);
}
for (let [key, value] of map) {
console.log(key, value);
}
Proxy用于修改某些操作的默认行为,
- 等同于在语言层面做出修改,与Object.defineProperties的行为大致一样(vue3的响应式数据就是基于Proxy写的)
var obj = new Proxy({}, {
get: function (target, propKey, receiver) {
console.log(`getting ${propKey}!`);
return Reflect.get(target, propKey, receiver);
},
set: function (target, propKey, value, receiver) {
console.log(`setting ${propKey}!`);
return Reflect.set(target, propKey, value, receiver);
}
});
- Proxy 支持的拦截操作一览。一共
13 种。
get(target, propKey, receiver) :拦截对象属性的读取。参数分别为目标对象、属性名和 proxy 实例本身var person = {
name: "张三"
};
var proxy = new Proxy(person, {
get: function(target, propKey) {
if (propKey in target) {
return target[propKey];
} else {
throw new ReferenceError("Prop name \"" + propKey + "\" does not exist.");
}
}
});
set(target, propKey, value, receiver) :拦截对象属性的设置,接受四个参数,依次为目标对象、属性名、属性值和 Proxy 实例本身,其中最后一个参数可选。has(target, propKey) :拦截propKey in proxy的操作,返回一个布尔值。可以接受两个参数,分别是目标对象、需查询的属性名。var handler = {
has (target, key) {
if (key[0] === '_') {
return false;
}
return key in target;
}
};
var target = { _prop: 'foo', prop: 'foo' };
var proxy = new Proxy(target, handler);
'_prop' in proxy
deleteProperty(target, propKey) :拦截delete操作,返回一个布尔值。(该方法解决了vue3中删除属性,不能响应式问题)var handler = {
deleteProperty (target, key) {
invariant(key, 'delete');
delete target[key];
return true;
}
};
function invariant (key, action) {
if (key[0] === '_') {
throw new Error(`Invalid attempt to ${action} private "${key}" property`);
}
}
var target = { _prop: 'foo' };
var proxy = new Proxy(target, handler);
delete proxy._prop
ownKeys(target) :拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in 循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。getOwnPropertyDescriptor(target, propKey) :拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。var handler = {
getOwnPropertyDescriptor (target, key) {
if (key[0] === '_') {
return;
}
return Object.getOwnPropertyDescriptor(target, key);
}
};
var target = { _foo: 'bar', baz: 'tar' };
var proxy = new Proxy(target, handler);
Object.getOwnPropertyDescriptor(proxy, 'wat')
Object.getOwnPropertyDescriptor(proxy, '_foo')
Object.getOwnPropertyDescriptor(proxy, 'baz')
defineProperty(target, propKey, propDesc) :拦截Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值。preventExtensions(target) :拦截Object.preventExtensions(proxy),返回一个布尔值。getPrototypeOf(target) :拦截Object.getPrototypeOf(proxy),返回一个对象。isExtensible(target) :拦截Object.isExtensible(proxy),返回一个布尔值。setPrototypeOf(target, proto) :拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。apply(target, object, args) :拦截 Proxy 实例作为函数调用的操作,比如proxy(…args)、proxy.call(object, …args)、proxy.apply(…)。construct(target, args,newTarget) :construct()方法用于拦截new命令.方法可以接受三个参数。target:目标对象。args:构造函数的参数数组。newTarget:创造实例对象时,new命令作用的构造函数const p = new Proxy(function () {}, {
construct: function(target, args) {
console.log('called: ' + args.join(', '));
return { value: args[0] * 10 };
}
});
(new p(1)).value
Reflect 。
- Reflect对象也是 ES6 新增的,意为"映射",表示把对象中常用的方法映射到Reflect对象上。所以只有静态方法。
- Reflect对象的设计目的
- 将
Object 对象的一些明显属于语言内部的方法(比如Object.defineProperty ),放到Reflect 对象上。现阶段,某些方法同时在Object 和Reflect 对象上部署,未来的新方法将只部署在Reflect 对象上。也就是说,从Reflect 对象上可以拿到语言内部的方法 - 修改某些
Object 方法的返回结果,让其变得更合理。比如,Object.defineProperty(obj, name, desc) 在无法定义属性时,会抛出一个错误,而Reflect.defineProperty(obj, name, desc) 则会返回false。 - 让
Object 操作都变成函数行为。某些Object 操作是命令式,比如name in obj 和delete obj[name] ,而Reflect.has(obj, name) 和Reflect.deleteProperty(obj, name) 让它们变成了函数行为。 Reflect 对象一共有 13 个静态方法,它与Proxy对象的方法是一一对应的
Reflect.apply(target, thisArg, args) 方法等同于Function.prototype.apply.call(func, thisArg, args) ,用于绑定this对象后执行给定函数。Reflect.construct(target, args) 方法等同于new target(...args) ,这提供了一种不使用new,来调用构造函数的方法。Reflect.get(target, name, receiver) 方法查找并返回target对象的name属性,如果没有该属性,则返回undefined。Reflect.set(target, name, value, receiver) 方法设置target对象的name属性等于valueReflect.defineProperty(target, name, desc) 方法基本等同于Object.defineProperty ,用来为对象定义属性Reflect.deleteProperty(target, name) 方法等同于delete obj[name] ,用于删除对象的属性Reflect.has(target, name) 方法对应name in obj 里面的in运算符Reflect.ownKeys(target) 方法用于返回对象的所有属性,基本等同于Object.getOwnPropertyNames 与Object.getOwnPropertySymbols 之和。var myObject = {
foo: 1,
bar: 2,
[Symbol.for('baz')]: 3,
[Symbol.for('bing')]: 4,
};
Object.getOwnPropertyNames(myObject)
Object.getOwnPropertySymbols(myObject)
Reflect.ownKeys(myObject)
Reflect.isExtensible(target) 方法对应Object.isExtensible,返回一个布尔值,表示当前对象是否可扩展。Reflect.preventExtensions(target) 对应Object.preventExtensions 方法,用于让一个对象变为不可扩展。它返回一个布尔值,表示是否操作成功。Reflect.getOwnPropertyDescriptor(target, name) 基本等同于Object.getOwnPropertyDescriptor ,用于得到指定属性的描述对象,将来会替代掉后者。Reflect.getPrototypeOf(target) 方法用于读取对象的__proto__属性Reflect.setPrototypeOf(target, prototype) 方法用于设置目标对象的原型(prototype)
|