分配对象属性(在循环中)并包含setter会导致未定义的值

时间:2017-11-18 14:35:29

标签: javascript object defineproperty

这是我第一次尝试使用Javascript' Object.defineProperty和/或defineProperties,显然我完全错误地做了这件事。我将一个cfg对象传递给一个Javascript函数构造函数,然后在该构造函数中循环遍历该配置并

  1. 在每个cfg键上调用Object.defineProperty
  2. 分配this[key] = cfg[key]
  3. 然而,this[key]每个undefined都会显示writable的值。我尝试了一些不同的操作,例如将set/function属性设置为true,但出现了与Object.defineProperties冲突的错误。我也尝试使用this来获得相同的结果。我不认为它是.bind(this)的范围问题,甚至在设置者身上使用undefined来确定,但无济于事。代码可以在https://repl.it/@dexygen/js-define-properties运行,我将其包含在内联下方。当然,而不是this.foo的预期结果是cfg.foo,例如将包含字符串' foo'从let myObj = new ObjInstance({ foo: 'foo', bar: 'bar', baz: 'baz' }); function ObjInstance(cfg) { for (let key in cfg) { Object.defineProperty(this, key, { configurable: true, enumerable: true, // writable: true, // throws error in conjunction with set function set: (function(val) { console.log('this[' + key + ']: ' + this[key]); //undefined :( }).bind(this) }); console.log('cfg[key]: ' + cfg[key]); this[key] = cfg[key]; } console.log(this); console.log('this.foo: ' + this.foo); /* // if you comment this in, comment out the above for loop let objProperties = {} for (let key in cfg) { objProperties[key] = { configurable: true, enumerable: true, set: (function(val) { console.log('this[' + key + ']: ' + this[key]); }).bind(this) } } for (let key in cfg) { console.log('cfg[key]: ' + cfg[key]); this[key] = cfg[key]; } Object.defineProperties(this, objProperties); for (let key in cfg) { console.log('cfg[key]: ' + cfg[key]); this[key] = cfg[key]; } */ } 传递到对象构造函数

    MeshFilter

4 个答案:

答案 0 :(得分:0)

使用setter或getter时,它不能具有与返回属性相同的属性名称。你似乎尝试做这样的事情:

var obj = {
  set a(param){
    console.log(this.a); //setter try to set a setter
  },
  get a(){
    return this.a;  //RangeError: Maximum call stack
  }
};

settergetter设置或获取的属性必须具有不同的属性名称,例如_foo

let myObj = new ObjInstance({
    foo: 'foo',
    bar: 'bar',
    baz: 'baz'
});

console.log(myObj);

function ObjInstance(cfg) {
    for (let key in cfg) {
      Object.defineProperty(this,key, {
          configurable: true,
          enumerable: true,
          set:(val)=>{
            this[`_${key}`] = key;
          },
          get:()=>{
            return this[`_${key}`];
          }
      });
      console.log('cfg[key]: ' + cfg[key]);
      this[key] = cfg[key];
    }
    console.log(this);
    console.log('this.foo: ' + this.foo);
}

或者您可以将值存储在getter中,如下所示:

let myObj = new ObjInstance({
    foo: 'foo',
    bar: 'bar',
    baz: 'baz'
});

console.log(myObj);

function ObjInstance(cfg) {
    for (let key in cfg) {
      Object.defineProperty(this,key, {
          configurable: true,
          enumerable: true,
          get:()=>{
            return key;
          }
      });
      console.log('cfg[key]: ' + cfg[key]);
      this[key] = cfg[key];
    }
    console.log(this);
    console.log('this.foo: ' + this.foo);
}

答案 1 :(得分:0)

我要感谢第一个发表评论的人,但他拒绝回答,所以我不仅根据他的评论发布我自己的评论(事实上我没有或多或少提供getter这是我从undefined获得setter的原因,但也解决了其他一些问题提出的问题,一个是对我的用例的质疑,我在评论中提到了setter

此处的工作代码:https://repl.it/@dexygen/javascript-defineProperty-working

let myObj = new ObjInstance({
    foo: 'foo',
    bar: 'bar',
    baz: 'baz'
});

function ObjInstance(cfg) {
    for (let key in cfg) {
      this[key] = cfg[key];

      Object.defineProperty(this, key, {
          configurable: true,
          enumerable: true,
          set: function(val) {
              cfg[key] = val;
              // additionally plan to emit an event
          },
          get: function() {
              return cfg[key];
          }
      });
    }

    console.log('this.foo: ' + this.foo);
    this.foo = 'foobarbaz';
    console.log('this.foo: ' + this.foo);
}

答案 2 :(得分:0)

这是另一种JavaScript向后兼容的等价物

function Handle( O ) {

var arr = [];

   for( var p in O ) {
    arr.push(
    ["get "+p+"(){ return O['"+p+"']; }, set "+p+"(x){ O['"+p+"'] = x; /*your emitter*/ }" ]
    );
   }
    return Function("O", "return {"+arr.join()+"}" )(O);
}

答案 3 :(得分:-1)

为什么一个漂亮而干净的传统JavaScript对你不起作用?

var myObj = new ObjInstance
(
  {
    foo: 'foo',
    bar: 'bar',
    baz: 'baz'
  }
);

function ObjInstance( cfg ) {
    for ( var key in cfg ) {
      this[ key ] = cfg[ key ];
    }
};

console.log( JSON.stringify( myObj ) );

myObj.bar = 'bar2';

console.log( JSON.stringify( myObj ) );