分配对象属性(在循环中)并包含 setter 会导致未定义的值
Assigning object properties (in a loop) and including a setter results in undefined values
这是我第一次尝试使用 Javascript 的 Object.defineProperty
and/or defineProperties
,显然我做错了。我将一个 cfg 对象传递给一个 Javascript 函数构造函数,然后在该构造函数中循环遍历配置和
- 在每个 cfg 键上调用 Object.defineProperty
- 正在分配
this[key] = cfg[key]
然而,每个 this[key]
都以 undefined
作为它的值出现。我已经尝试了一些不同的事情,例如将 writable
属性设置为 true,但得到一个错误,表明这与 set/function
冲突。我也尝试使用 Object.defineProperties
得到相同的结果。我不认为这是 this
的范围问题,甚至在 setter 上使用 .bind(this)
可以肯定,但无济于事。代码可以是 运行 at https://repl.it/@dexygen/js-define-properties,我将其包含在内联下方。当然,预期结果而不是 undefined
是 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];
}
*/
}
当您使用 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
}
};
由setter
或getter
设置或获取的属性必须有不同的属性名称,例如_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);
}
为什么漂亮干净的传统 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 ) );
我想感谢第一位发表评论的人,但他拒绝回答,所以我不仅根据他的评论发表自己的评论(事实上我没有提供 getter
或多或少是我从 setter
回来 undefined
的原因),但也解决了其他一些答案提出的问题,一个是对我的用例的质疑,我在 [= =13=].
工作代码在这里: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);
}
这是一个替代方案 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);
}
这是我第一次尝试使用 Javascript 的 Object.defineProperty
and/or defineProperties
,显然我做错了。我将一个 cfg 对象传递给一个 Javascript 函数构造函数,然后在该构造函数中循环遍历配置和
- 在每个 cfg 键上调用 Object.defineProperty
- 正在分配
this[key] = cfg[key]
然而,每个 this[key]
都以 undefined
作为它的值出现。我已经尝试了一些不同的事情,例如将 writable
属性设置为 true,但得到一个错误,表明这与 set/function
冲突。我也尝试使用 Object.defineProperties
得到相同的结果。我不认为这是 this
的范围问题,甚至在 setter 上使用 .bind(this)
可以肯定,但无济于事。代码可以是 运行 at https://repl.it/@dexygen/js-define-properties,我将其包含在内联下方。当然,预期结果而不是 undefined
是 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];
}
*/
}
当您使用 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
}
};
由setter
或getter
设置或获取的属性必须有不同的属性名称,例如_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);
}
为什么漂亮干净的传统 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 ) );
我想感谢第一位发表评论的人,但他拒绝回答,所以我不仅根据他的评论发表自己的评论(事实上我没有提供 getter
或多或少是我从 setter
回来 undefined
的原因),但也解决了其他一些答案提出的问题,一个是对我的用例的质疑,我在 [= =13=].
工作代码在这里: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);
}
这是一个替代方案 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);
}