JS - ES2015/ES6新特性详解5(代理、反射、Symbols、Unicode编码)
作者:hangge | 2017-06-22 08:10
相关文章系列:
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);
}
全部评论(0)