es6面试题

140 阅读4分钟

proxy及各方面应用

概述:proxy在目标对象的外层搭建了一层拦截,外界对目标对象的某些操作,必须通过这层拦截 Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。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);
  }
})

obj.count = 1
//  setting count!
++obj.count
//  getting count!
//  setting count!
//  2

Proxy的作用

1.拦截和监视外部对对象的访问

2.降低函数或类的复杂度

3.在复杂操作前对操作进行校验或对所需资源进行管理

Proxy的应用场景

1.实现私有变量

var target = {
   name: 'poetries',
   _age: 22
}
var logHandler = {
  get: function(target,key){
    if(key.startsWith('_')){
      console.log('私有变量age不能被访问')
      return false
    }
    return target[key];
  },
  set: function(target, key, value) {
     if(key.startsWith('_')){
      console.log('私有变量age不能被修改')
      return false
    }
     target[key] = value;
   }
} 
var targetWithLog = new Proxy(target, logHandler);
// 私有变量age不能被访问
targetWithLog.name; 
// 私有变量age不能被修改
targetWithLog.name = 'others'; 

//在下面的代码中,我们声明了一个私有的 apiKey,便于 api 这个对象内部的方法调用,但不希望从外部也能够访问 api._apiKey
var api = {  
    _apiKey: '123abc456def',
    /* mock methods that use this._apiKey */
    getUsers: function(){}, 
    getUser: function(userId){}, 
    setUser: function(userId, config){}
};
// logs '123abc456def';
console.log("An apiKey we want to keep private", api._apiKey);
// get and mutate _apiKeys as desired
var apiKey = api._apiKey;  
api._apiKey = '987654321';

//很显然,约定俗成是没有束缚力的。使用 ES6 Proxy 我们就可以实现真实的私有变量了,下面针对不同的读取方式演示两个不同的私有化方法。第一种方法是使用 set / get 拦截读写请求并返回 undefined:
let api = {  
    _apiKey: '123abc456def',
    getUsers: function(){ }, 
    getUser: function(userId){ }, 
    setUser: function(userId, config){ }
};
const RESTRICTED = ['_apiKey'];
api = new Proxy(api, {  
    get(target, key, proxy) {
        if(RESTRICTED.indexOf(key) > -1) {
            throw Error(`${key} is restricted. Please see api documentation for further info.`);
        }
        return Reflect.get(target, key, proxy);
    },
    set(target, key, value, proxy) {
        if(RESTRICTED.indexOf(key) > -1) {
            throw Error(`${key} is restricted. Please see api documentation for further info.`);
        }
        return Reflect.get(target, key, value, proxy);
    }
});
// 以下操作都会抛出错误
console.log(api._apiKey);
api._apiKey = '987654321';  

//第二种方法是使用 has 拦截 in 操作
var api = {  
    _apiKey: '123abc456def',
    getUsers: function(){ }, 
    getUser: function(userId){ }, 
    setUser: function(userId, config){ }
};
const RESTRICTED = ['_apiKey'];
api = new Proxy(api, {  
    has(target, key) {
        return (RESTRICTED.indexOf(key) > -1) ?
            false :
            Reflect.has(target, key);
    }
});
// these log false, and `for in` iterators will ignore _apiKey
console.log("_apiKey" in api);
for (var key in api) {  
    if (api.hasOwnProperty(key) && key === "_apiKey") {
        console.log("This will never be logged because the proxy obscures _apiKey...")
    }
}

抽离校验模块 blog.csdn.net/qq_45471661… 访问日志

预警和拦截

过滤操作

中断代理

es6中的Set和Map

Set

ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。

属性

Set.prototype.constructor: 构造函数, 默认就是Set函数。
Set.prototype.size: 返回Set实例的成员总数。
Set 实例的方法分为两大类: 操作方法( 用于操作数据) 和遍历方法( 用于遍历成员)。 下面先介绍四个操作方法。

Set.prototype.add(value): 添加某个值, 返回 Set 结构本身。
Set.prototype.delete(value): 删除某个值, 返回一个布尔值, 表示删除是否成功。
Set.prototype.has(value): 返回一个布尔值, 表示该值是否为Set的成员。
Set.prototype.clear(): 清除所有成员, 没有返回值。

应用

(1) 去除数组的重复成员,去除字符串里面的重复字符

 [...new Set(array)] ,
 [...new Set('ababbc')].join('')

(2)判断是否包含一个键

   // 对象的写法
  const properties = {
      'width': 1,
      'height': 1
  };

  if (properties[someName]) {
      // do something
  }

  // Set的写法
  const properties = new Set();

  properties.add('width');
  properties.add('height');

  if (properties.has(someName)) {
      // do something
  }

(3)数组去重

 function dedupe(array) {
      return Array.from(new Set(array));
  }

  dedupe([1, 1, 2, 3]) // [1, 2, 3]

(4)遍历操作

  • 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);
    }
    // red
    // green
    // blue

    for (let item of set.values()) {
        console.log(item);
    }
    // red
    // green
    // blue

    for (let item of set.entries()) {
        console.log(item);
    }
    // ["red", "red"]
    // ["green", "green"]
    // ["blue", "blue"]

Map

symbol

类数组和数组

reduce 及常用函数操作

数组去重

数组扁平化

排序题

数组拷贝的方式

数组

map 和set

weakMap

介绍:

WeakMap 相对于普通的 Map,也是键值对集合,只不过 WeakMap 的 key 只能是非空对象(non-null object)。WeakMap 对它的 key 仅保持弱引用,也就是说它不阻止垃圾回收器回收它所引用的 key。WeakMap 最大的好处是可以避免内存泄漏。一个仅被 WeakMap 作为 key 而引用的对象,会被垃圾回收器回收掉。

WeakMap 拥有和 Map 类似的 set(key, value) 、get(key)、has(key)、delete(key) 和 clear() 方法,但没有 size 属性,也没有任何与迭代有关的方法。

sessionStorage、localStorage,cookie的区别