javascript - 使用 ES6 Proxies 隐藏私有(private)属性

标签 javascript ecmascript-6 es6-proxy

我正在尝试创建一个尽可能隐藏对象私有(private)属性的函数。我会在这里将私有(private)属性定义为以下划线开头的属性,例如。 _密码

以下是我到目前为止所得到的(感谢 Nicolas Bevacqua's great intro to proxies)。

现在我想知道:

  1. 我是否用以下代码涵盖了所有基础?还是我错过了一个重要的代理陷阱,通过它仍然可以访问对象?
  2. 这是将 Reflect 方法与代理结合使用的正确方法吗?我什至需要他们吗?
  3. 我为私有(private)属性返回的值是否真实到足以让人们认为该属性真的不存在?

到目前为止我的功能:

function privatize(obj, prefix = '_', throwError = false) {
  const proxyHandler = {
    get(target, key) {
        return private(key, 'get') ? undefined : Reflect.get(target, key);
      },
      set(target, key, value) {
        return private(key, 'set') ? undefined : Reflect.set(target, key, value);
      },
      has(target, key) {
        return private(key, 'has') ? false : Reflect.has(target, key);
      },
      deleteProperty(target, key) {
        return private(key, 'delete') ? false : Reflect.deleteProperty(target, key);
      },
      defineProperty(target, key, descriptor) {
        return private(key, 'defineProperty') ? false : Reflect.defineProperty(target, key, descriptor);
      },
      enumerate(target) {
        return Object.keys().filter((key) => {
          return !private(key, null, false);
        })[Symbol.iterator]();
      },
      ownKeys(target) {
        return Reflect.ownKeys(target).filter((key) => {
          return !private(key, null, false);
        });
      },
      getOwnPropertyDescriptor(target, key) {
        return private(key, 'getOwnPropertyDescriptor') ? false : Reflect.getOwnPropertyDescriptor(target, key);
      }
  };

  function private(key, operationName) {
    if (key.indexOf(prefix) === 0) {
      if (throwError) {
        throw new Error(`Operation '${operationName}' is not allowed on private properties.`);
      }
      return true;
    }
  }

  return new Proxy(obj, proxyHandler);
}

var o = {
  first: 'should work',
  _second: 'should fail'
};

var proxied = privatize(o);

console.log(proxied);

PS:对于 native 浏览器支持,您可能需要在 MS Edge 或 Firefox Dev Edition 中查看它。

http://jsfiddle.net/bkd7mde7/1/

最佳答案

您需要了解“不变量”的概念。例如,如果一个对象是不可扩展的,则不允许通过代理隐藏其属性,并且不可配置的属性可能不会被隐藏。您不能 defineProperty 它尚不具备的属性。 getOwnPropertyDescriptor 必须返回一个对象或 undefineddeleteProperty 无法删除不可配置的属性。 set 无法更改不可写、不可配置的属性。在各种情况下,任何或所有这些都可能导致您的代码失败(通过在运行时抛出)。

其他小问题包括 set 应该返回一个 bool 值(成功/失败),尽管我不确定 undefined 会发生什么你回来了。

关于javascript - 使用 ES6 Proxies 隐藏私有(private)属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33075882/

相关文章:

javascript - 使用 C# 从 DatePicker 获取周 ID

javascript - 检查对象值是否等于字符串值

函数 apply trap 的 javascript 代理无法访问接收者代理

javascript - 我可以使用 ES2015 类扩展 Proxy 吗?

javascript - 如何将外部 REST API 数据作为记录数组传递到模型?

javascript - 调整浏览器大小时保持视频的宽高比

javascript - 密码与 Angular.js 匹配

带有 block 作用域的 Javascript 默认参数仅在 iOS 上失败

javascript - 如何在其实例上访问 es-2015 类方法?

javascript - 代理 : Calling static methods of target's parent when using a proxy object