JS - ES2015/ES6新特性详解5(代理、反射、Symbols、Unicode编码)
相关文章系列:
JS - ES2015/ES6新特性详解1(let、const、For..of循环、迭代器、生成器)
JS - ES2015/ES6新特性详解2(Set, WeakSet, Map, WeakMap、箭头函数)
JS - ES2015/ES6新特性详解3(默认参数、不定参数、扩展运算符、解构)
JS - ES2015/ES6新特性详解4(类、模块、Promises、模板字符串)
[当前文章] JS - ES2015/ES6新特性详解5(代理、反射、Symbols、Unicode编码)
JS - ES2015/ES6新特性详解6(二进制和八进制、尾调用、其他新增的API)
JS - ES2015/ES6新特性详解1(let、const、For..of循环、迭代器、生成器)
JS - ES2015/ES6新特性详解2(Set, WeakSet, Map, WeakMap、箭头函数)
JS - ES2015/ES6新特性详解3(默认参数、不定参数、扩展运算符、解构)
JS - ES2015/ES6新特性详解4(类、模块、Promises、模板字符串)
[当前文章] JS - ES2015/ES6新特性详解5(代理、反射、Symbols、Unicode编码)
JS - ES2015/ES6新特性详解6(二进制和八进制、尾调用、其他新增的API)
十五、Proxies(代理对象)
代理对象可以创建一个具有目标对象全部行为的对象。可用于拦截,对象的虚拟化,记录/分析等。
1,使用样例
(1)代理普通对象
var obj = {words: "hello hangge"} var handler = { get: function (target, key) { return target[key].replace("hangge", "航歌"); } }; var proxy = new Proxy(obj, handler); console.log(proxy.words);

(2)代理函数对象
var fun = function () { return "I am hangge"; }; var handler = { apply: function (target, ...args) { return "I am 航歌"; } }; var proxy = new Proxy(fun, handler); console.log(proxy());

2,下面是所有运行级别元操作(meta-operations)中可能出现的traps
var handler = { // target.prop get: ..., // target.prop = value set: ..., // 'prop' in target has: ..., // delete target.prop deleteProperty: ..., // target(...args) apply: ..., // new target(...args) construct: ..., // Object.getOwnPropertyDescriptor(target, 'prop') getOwnPropertyDescriptor: ..., // Object.defineProperty(target, 'prop', descriptor) defineProperty: ..., // Object.getPrototypeOf(target), Reflect.getPrototypeOf(target), // target.__proto__, object.isPrototypeOf(target), object instanceof target getPrototypeOf: ..., // Object.setPrototypeOf(target), Reflect.setPrototypeOf(target) setPrototypeOf: ..., // for (let i in target) {} enumerate: ..., // Object.keys(target) ownKeys: ..., // Object.preventExtensions(target) preventExtensions: ..., // Object.isExtensible(target) isExtensible :... }
十六、Reflect(反射)
Reflect 与 ES5 的 Object 有点类似,包含了对象语言内部的方法,Reflect 也有 13 种方法,与 proxy 中的方法一一对应。Proxy 相当于去修改设置对象的属性行为,而 Reflect 则是获取对象的这些行为。
1,Reflect对象有下面这些静态的方法
Reflect.apply Reflect.construct Reflect.defineProperty Reflect.deleteProperty Reflect.enumerate // 废弃的 Reflect.get Reflect.getOwnPropertyDescriptor Reflect.getPrototypeOf Reflect.has Reflect.isExtensible Reflect.ownKeys Reflect.preventExtensions Reflect.set Reflect.setPrototypeOf
2,使用样例
(1) Reflect 对象的方法与 Proxy 对象的方法一一对应, 只要是 Proxy 对象的方法, 就能在 Reflect 对象上找到相对应的方法。下面代码我们使用 Proxy 方法拦截 target 对象的属性赋值行为。 它采用 Reflect.set 方法将值赋值给对象的属性, 然后再部署额外的功能。Proxy(target, { set: function(target, name, value, receiver) { var success = Reflect.set(target, name, value, receiver); if(success) { log('property ' + name + ' on ' + target + ' set to ' + value); } return success; } });
(2)下面代码中,我们让每一个 Proxy 对象的拦截操作( get、 delete、 has), 内部都调用对应的 Reflect 方法, 保证原生行为能够正常执行。 添加的工作, 就是将每一个操作输出一行日志。
var loggedObj = new Proxy(obj, { get(target, name) { console.log('get', target, name); return Reflect.get(target, name); }, deleteProperty(target, name) { console.log('delete' + name); return Reflect.deleteProperty(target, name); }, has(target, name) { console.log('has' + name); return Reflect.has(target, name); } });
(3)有了 Reflect 对象以后, 很多操作会更易读。看下面两端代码的比较:
//ES5 老写法 Function.prototype.apply.call(Math.floor, undefined, [1.75]) // 1 //ES6 新写法 Reflect.apply(Math.floor, undefined, [1.75]) // 1
十七、Symbols
Symbols 是一个新类型。 可用于创建匿名属性,用于对对象的状态进行访问控制。Symbol 允许对象的属性不仅可以通过 string(ES5)命名,还可以通过 symbol 命名。可选的 name 参数用于调试——但并不是他本身的一部分。Symbol 是唯一的,但不是私有的,因为他们使用诸如 Object.getOwnPropertySymbols 这样的方法来使用。(1)下面是一个简单的使用样例
var typeSymbol = Symbol("type"); class Pet { constructor(type) { this[typeSymbol] = type; } getType() { return this[typeSymbol]; } } var a = new Pet("dog"); console.log(a.getType()); console.log(Object.getOwnPropertyNames(a)) console.log(Symbol("a") === Symbol("a"))
(2)运行结果如下:

十八、Unicode 编码
ES6 为 Unicode 提供了更好的支持。新增了一系列的扩展来支持完整的 unicode 编码,其中包括字符串中新的 unicode 语法格式,正则表达式的 u 模式来处理代码点,新的 API 也让字符串可以处理 21 位的代码点(code points)。这些新特性允许我们使用 JavaScript 构建国际化的应用。
// 和ES5.1相同 "航".length == 2 // 正则表达式新的u模式 "航".match(/./u)[0].length == 2 // 新的unicode格式 "\u{822a}" == "航" == "\u822a" // 新的字符串方法 "航".codePointAt(0) == 0x822a // for of迭代代码点 for(var c of "航") { console.log(c); }
