当前位置: > > > JS - ES2015/ES6新特性详解5(代理、反射、Symbols、Unicode编码)

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)

十五、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 对象的拦截操作( getdeletehas), 内部都调用对应的 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 允许对象的属性不仅可以通过 stringES5)命名,还可以通过 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