英文:
calculate an object property based on the value of another property of the same object
问题
I need to find out the value of "name" inside on the obj object. How can I find it without function invocation?
我需要找到 obj 对象内的 "name" 的值。如何在不调用函数的情况下找到它?
I wanna use just obj.isActive
not obj.isActive()
我只想使用 obj.isActive
而不是 obj.isActive()
If use an IFEE:
如果使用立即调用函数表达式(IFEE):
I get:
我得到:
return this.name.length > 4;
^
TypeError: Cannot read properties of undefined (reading 'length')
return this.name.length > 4;
^
TypeError: Cannot read properties of undefined (reading 'length')
英文:
I need to find out the value of "name" inside on the obj object. How can I find it without function invocation?
I wanna use just obj.isActive
not obj.isActive()
let obj = {
name: "X Æ A-12 Musk",
isActive: function () {
return this.name.length > 4;
},
};
// and after a while I need to check if is active:
console.log(obj);
// {
// name: 'X Æ A-12 Musk',
// isActive: [Function: isActive] <--------- NOT COOL !
// }
If use an IFEE:
let obj = {
name: "X Æ A-12 Musk",
isActive: (function () {
return this.name.length > 4;
})(),
};
I get:
return this.name.length > 4;
^
TypeError: Cannot read properties of undefined (reading 'length')
答案1
得分: 3
如果你不想将 isActive 调用为函数,你可以使用一个 getter。
const obj = {
name: "X Æ A-12 Musk",
get isActive () {
return this.name.length > 4;
},
};
console.log(obj.isActive);
英文:
If you do not want to have to call isActive as a function, you can use a getter.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const obj = {
name: "X Æ A-12 Musk",
get isActive () {
return this.name.length > 4;
},
};
console.log(obj.isActive);
<!-- end snippet -->
答案2
得分: 1
- 使用代理来拦截属性访问:
如果您无法修改对象本身,您可以将其包装在代理中,并将代理传递给库。
let obj = {
name: "X Æ A-12 Musk",
isActive: function () {
return this.name.length > 4;
},
};
const proxy = new Proxy(obj, {
get(target, prop) {
if (prop === 'isActive') {
return target?.isActive?.();
}
return target[prop];
}
});
console.log(proxy.isActive); // true
console.log(proxy.name); // "X Æ A-12 Musk"
console.log(proxy);
/*
{
"name": "X Æ A-12 Musk",
"isActive": true
}
*/
这可以泛化为在目标上调用任何getter函数,如果它在目标上存在:
let obj = {
name: "X Æ A-12 Musk",
isActive: function () {
return this.name.length > 4;
},
};
const proxy = new Proxy(obj, {
get(target, prop) {
const x = target[prop];
return typeof x === 'function' ? target[prop]() : x;
}
});
console.log(proxy.isActive); // true
console.log(proxy.name); // "X Æ A-12 Musk"
console.log(proxy);
/*
{
"name": "X Æ A-12 Musk",
"isActive": true
}
*/
注意:这里我使用了 target[prop]()
而不是 x()
,因为调用未关联的函数 x()
存在作用域影响,可能会导致错误或意外的结果(这也是使您的IIFE出现问题的相同问题)。
- 使用
Object.defineProperty
来建立getter。
再次,我不清楚为什么您无法直接在对象字面量上放置一个getter,所以我不知道这是否可行。
let obj = {
name: "X Æ A-12 Musk",
isActive: function() {
return this.name.length > 4;
},
};
Object.defineProperty(obj, "isActive", {
get() {
return this.name.length > 4
}
})
console.log(obj);
/*
{
"name": "X Æ A-12 Musk",
"isActive": true
}
*/
英文:
It's not clear from your question why you can do an IIFE but not a getter, but here are some other potential workarounds.
1. Use a Proxy to intercept the property accessor:
If you can't modify the object itself you could wrap it in a Proxy, and pass the proxy to the library.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
let obj = {
name: "X Æ A-12 Musk",
isActive: function () {
return this.name.length > 4;
},
};
const proxy = new Proxy(obj, {
get(target, prop) {
if (prop === 'isActive') {
return target?.isActive?.();
}
return target[prop]
}
});
console.log(proxy.isActive); // true
console.log(proxy.name); // "X Æ A-12 Musk"
console.log(proxy);
/*
{
"name": "X Æ A-12 Musk",
"isActive": true
}
*/
<!-- end snippet -->
This could be generalized to invoke any getter function if it's present on the target:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
let obj = {
name: "X Æ A-12 Musk",
isActive: function () {
return this.name.length > 4;
},
};
const proxy = new Proxy(obj, {
get(target, prop) {
const x = target[prop];
return typeof x === 'function' ? target[prop]() : x;
}
});
console.log(proxy.isActive); // true
console.log(proxy.name); // "X Æ A-12 Musk"
console.log(proxy);
/*
{
"name": "X Æ A-12 Musk",
"isActive": true
}
*/
<!-- end snippet -->
Note: I'm invoking target[prop]()
instead of x()
here because invoking the disassociated function x()
has scope implications that could produce errors or unexpected results.(The same issue that makes your IIFE blow up.)
2. Use Object.defineProperty
to establish the getter.
Again, it's not clear to me why you can't put a getter on the object literal directly, so I don't know if this is viable either.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
let obj = {
name: "X Æ A-12 Musk",
isActive: function() {
return this.name.length > 4;
},
};
Object.defineProperty(obj, "isActive", {
get() {
return this.name.length > 4
}
})
console.log(obj);
/*
{
"name": "X Æ A-12 Musk",
"isActive": true
}
*/
<!-- end snippet -->
答案3
得分: 1
与ray的答案类似,可以尝试如下方式:
let obj = {
name: "test"
};
Object.defineProperty(obj, "isActive", {
get: function() {
return obj.name.length > 3;
}
});
console.log(obj.isActive); // 输出:true
如果有帮助,并且您经常使用它,可以创建一个辅助函数:
function defineIsActive(object, condition) {
Object.defineProperty(object, "isActive", {
get: function() {
return condition;
}
});
}
let obj = {
name: 'test'
}
// 然后像这样使用它:
defineIsActive(obj, obj.name.length > 3)
console.log(obj.isActive)
英文:
Similarly to ray's answer, what about something like this:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
let obj = {
name: "test"
};
Object.defineProperty(obj, "isActive", {
get: function() {
return obj.name.length > 3;
}
});
console.log(obj.isActive); // Output: true
<!-- end snippet -->
If it helps, and you were to use it constantly, you could create a helper function:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
function defineIsActive(object, condition) {
Object.defineProperty(obj, "isActive", {
get: function() {
return condition
}
});
}
let obj = {
name: 'test'
}
// And simply use it like so:
defineIsActive(obj, obj.name.length > 3)
console.log(obj.isActive)
<!-- end snippet -->
答案4
得分: 1
> 我无法向该对象添加更多属性。
你可以创建一个以原始对象为原型的包装对象,并在前者中定义 getter。
<!-- 开始代码片段: js 隐藏: false 控制台: true babel: false -->
<!-- 语言: lang-js -->
let obj = {
name: "X Æ A-12 Musk",
isActive: function () {
return this.name.length > 4;
},
};
function makeWrapper (obj) {
let wrapper = Object.create(obj);
Object.defineProperty(wrapper, 'isActive', {
get () { return obj.isActive(); },
enumerable: true
});
return wrapper;
}
let obj2 = makeWrapper(obj);
console.log(obj2);
<!-- 结束代码片段 -->
英文:
> I cannot add more properties to that object
You can create wrapper object prototyped by the original object, and define getter in the former.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
let obj = {
name: "X Æ A-12 Musk",
isActive: function () {
return this.name.length > 4;
},
};
function makeWrapper (obj) {
let wrapper = Object.create(obj);
Object.defineProperty(wrapper, 'isActive', {
get () { return obj.isActive(); },
enumerable: true
});
return wrapper;
}
let obj2 = makeWrapper(obj);
console.log(obj2);
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论