代码之家  ›  专栏  ›  技术社区  ›  tmim

可以在javascript中创建隐藏属性吗

  •  23
  • tmim  · 技术社区  · 16 年前

    我想创建一个具有隐藏属性的对象(在 for (var x in obj

    5 回复  |  直到 16 年前
        1
  •  50
  •   Tim Down    7 年前

    这在ECMAScript 3中是不可能的(在2010年提出这个问题时,主流浏览器都实现了这一点)。但是,在所有主流浏览器的当前版本实现的ECMAScript 5中,可以将属性设置为不可枚举:

    var obj = {
       name: "Fred"
    };
    
    Object.defineProperty(obj, "age", {
        enumerable: false,
        writable: true
    });
    
    obj.age = 75;
    
    /* The following will only log "name=>Fred" */
    for (var i in obj) {
       console.log(i + "=>" + obj[i]);
    }
    

    这适用于当前浏览器:请参见 http://kangax.github.com/es5-compat-table/ 有关旧浏览器中兼容性的详细信息。

    Object.defineProperty 允许正常分配(这是 false 默认情况下)。

        2
  •  17
  •   GregRos    8 年前

    for ... in 循环。

    现在是经典的不可枚举属性

    与以前版本的ECMAScript一样,您可以使用 Object.defineProperty 创建未标记的特性的步骤 enumerable . 这使得在使用某些方法(例如 环路和 Object.keys

    Object.defineProperty(myObject, "meaning of life", {
        enumerable : false,
        value : 42
    });
    

    Object.getOwnPropertyNames 函数,它甚至返回不可枚举的属性。当然,你仍然可以通过它的键来访问这个属性,理论上,这只是一个任何人都可以构建的字符串。

    A(不可枚举) symbol

    在ES6中,可以使用新基元类型的键创建属性-- . 此类型由Javascript本身使用 for ... of

    Symbols

    你创造了一个 符号 使用 Symbol

    let symb = Symbol("descriptive text");
    

    你可以用 函数定义以符号作为键的特性。

    let theSecretKey = Symbol("meaning of life");
    Object.defineProperty(myObject, theSecretKey, {
        enumerable : false,
        value : 42
    });
    

    除非有人得到对那个符号对象的引用,否则他们不能按键查找属性的值。

    let theSecretKey = Symbol("meaning of life");
    myObject[theSecretKey] = 42;
    

    具有此键类型的属性永远不会显示在中 循环等,但仍然可以是可枚举和不可枚举的,如 Object.assign 对不可枚举属性的工作方式不同。

    Object.getOwnPropertyNames对象 不会让你 对象的键,但名称类似 Object.getOwnPropertySymbols 会成功的。

    弱映射基本上是 Map

    它们的主要设计目的是允许在不实际修改对象的情况下扩展对象。

    let weakMap = new WeakMap();
    

    并使用要延伸的对象作为关键点。然后这些值将是一组属性,可以是 {} 对象,或以 地图 数据结构。

    weakMap.set(myObject, {
        "meaning of life" : 42
    });
    

    weakMap 实例 和

    当然,这其中最大的缺陷是,它没有创建实际的属性。所以它不参与原型链之类的。

    (*)这是个谎言。

        3
  •  11
  •   Jack Wilsdon HelloWorld    10 年前

    function secret() {
      var cache = {};
      return function(){
        if (arguments.length == 1) { return cache[arguments[0]];}
        if (arguments.length == 2) { cache[arguments[0]] = arguments[1]; }
      };
    }
    var a = secret();
    
    a.hello = 'world';
    a('hidden', 'from the world');
    

    如果你是一个真正的职业选手,你可以这样做!

    var a = new (secret())();
    
    a.hello = 'world';
    a.constructor('hidden', 'from the world');
    

    现在如果你看一只萤火虫,它将是一个物体。。。但你更清楚!;—)

        4
  •  0
  •   johannesvalks    9 年前
    var Foo=function(s){
        var hidden
        this.setName=function(name){theName=name}
        this.toString=function(){return theName}
        this.public=s
    }
    var X=new Foo('The X')
    X.setName('This is X')
    X // returns 'This is X'
    X.public // returns 'The X'
    X.hidden // returns 'undefined'
    
        5
  •  0
  •   Ritesh kumar    8 年前

    试试这个:

    Object.defineProperty(
        objectName,
        'propertiesName', {
            enumerable: false
        }
    )
    
        6
  •  0
  •   Aronanda    6 年前

    下面是一个使用代理对象的解决方案。

    事件发射器示例:

    class Event {
      constructor(opts = {}) {
        this.events = new Map
        this.proxy = new class {}
        Object.defineProperty(this.proxy, 'on', { value: this.on.bind(this) })
        Object.defineProperty(this.proxy, 'emit', { value: this.emit.bind(this) })
        Object.defineProperty(this.proxy, 'length', { get: () => this.length })
        Object.defineProperty(this.proxy.constructor, 'name', {
          value: this.constructor.name
        })
        return new Proxy(this.proxy, {})
      }
      on(topic, handler) {
        if (!this.events.has(topic))
          this.events.set(topic, new Set)
        this.events.get(topic).add(handler)
        return this.remove.bind(this, topic, handler)
      }
      emit(topic, ...payload) {
        if (!this.events.has(topic))
          return
        const set = this.events.get(topic)
        for (const fn of set)
          fn(...payload)
      }
      remove(topic, handler) {
        if (!this.events.has(topic))
          return
        const set = this.events.get(topic)
        if (set.has(handler))
          set.delete(handler)
      }
      get length() {
        return this.events.size
      }
    }
    

    更新: events .

    let Event = 
    class Event {
      on(topic, handler) {
        if (!events.has(topic))
          events.set(topic, new Set)
        events.get(topic).add(handler)
        return this.remove.bind(this, topic, handler)
      }
      emit(topic, ...payload) {
        if (!events.has(topic))
          return
        const set = events.get(topic)
        for (const fn of set)
          fn(...payload)
      }
      remove(topic, handler) {
        if (!events.has(topic))
          return
        const set = events.get(topic)
        if (typeof handler === 'undefined')
          return events.delete(topic)
        if (set.has(handler))
          set.delete(handler)
      }
      get length() {
        return events.size
      }
    }
    let events
    Event = new Proxy(Event, {
      construct (target, args, self) {
        events = new Map
        return Reflect.construct(target, args, self)
      }
    })
    

    以下是我使用此概念开发的功能更全面的事件发射器的要点: https://gist.github.com/aronanda/18b6397c355da88ca170d01e0cc02628