你能帮助我做一个简写函数来判断对象属性是否存在吗?在99%的情况下,我想用它来检查返回的json对象是否包含指定的属性。请注意,无法保证必须定义任何父属性甚至json对象本身。
我正在以这种方式思考:
function propertyExists(<property>) {
// property is something like data.property.property
return typeof(data) !== "undefined" && typeof(data.property) !== "undefined" && typeof(data.property.property) !== "undefined";
}
我不知道如何以动态方式编写它以检查所有父属性。 in-parameter也应该只是对“data.property.property”的引用,而不是字符串,所以我不知道如何在其中找到父属性。
答案 0 :(得分:4)
这是我从一个项目中找到的函数,它告诉你是否定义了一个属性(包括它的所有父属性,如果有的话):
function isDefined(target, path) {
if (typeof target != 'object' || target == null) {
return false;
}
var parts = path.split('.');
while(parts.length) {
var branch = parts.shift();
if (!(branch in target)) {
return false;
}
target = target[branch];
}
return true;
}
它应该像这样使用:
var data = { foo: { bar: 42 } };
isDefined(data, "foo"); // true
isDefined(data, "foo.bar"); // true
isDefined(data, "notfoo"); // false
isDefined(data, "foo.baz"); // false
您可以轻松调整此值以返回值本身(或null
),而不是true
/ false
。
更新:在阅读了有关该问题的评论后,我搜索了Javascript in
运算符,并将typeof
测试替换为该值。现在,代码写成“它的意图是什么”。
答案 1 :(得分:2)
允许JSON属性包含{"a.b": 42}
中的点,这使得点串不适合对象的“深度引用”。
isDefined({"a.b": 42}, 'a.b') // false
isDefined({"a": 42}, 'a.b') // TypeError
因此,数组可能是参考或索引的更好选择
function hasProperty(value, index) {
if (index instanceof Array) {
return index.length === 0 ||
(hasProperty(value, index[0])
&& hasProperty(value[index[0]], index.slice(1)));
}
return value.hasOwnProperty(index);
}
它的用法如下:
hasProperty(42, []); // true
hasProperty(42, ['a']); // false
hasProperty(42, ['a']); // false
hasProperty({a: 42}, 'a'); // true
hasProperty({a: 42}, ['a']); // true
hasProperty({a: 42}, ['a', 'b']); // false
hasProperty({a: {b: 42}}, ['a', 'b']); // true
hasProperty({"a.b": 42}, ['a.b']); // true
hasProperty([1,2,3], 2); // true
hasProperty([1,2,3], 3); // false
hasProperty({a: {b: [1,2,3]}}, ['a', 'b', 2]); // true
请注意,由于使用了原型函数hasProperty
,hasOwnProperty
会忽略原型中的属性。
答案 2 :(得分:1)
我目前无法找到其他帖子,请确保以下内容正确:
function checkAccess(obj, path) {
var path = path.split('.');
var prop;
for (var i=0, iLen=path.length; i<iLen; i++) {
if (obj !== null && typeof obj == 'object') {
prop = path[i];
if (prop in obj) {
obj = obj[prop];
}
} else {
return false
}
}
return true;
}
var o = {foo:{bar:null}};
alert(checkAccess(o, 'foo.bar')); // true
alert(checkAccess(o, 'foo.bar.baz')); // false
请注意,这应该适用于JSON,但如果涉及到主机对象,则所有投注均已关闭,因为 typeof 无法保证返回 object (或任何内容)那种情况。如果您需要测试主机对象,可能try..catch
可能是最强大的解决方案,除非您确信正在测试的对象将返回预期结果。
try {
alert( o.foo.bar.baz);
} catch(e) {
alert( 'oops');
}
如果你想使用单个参数,那么我将假设基础对象是一个全局属性:
var checkAccess = (function(global) {
return function (expr) {
var path = expr.split('.');
var obj, prop;
if (path.length) {
obj = global[path.shift()];
for (var i=0, iLen=path.length; i<iLen; i++) {
if (obj !== null && typeof obj == 'object') {
prop = path[i];
if (prop in obj) {
obj = obj[prop];
}
} else {
return false
}
}
return true;
}
return false;
}
}(this));
请注意,上述内容只是意味着尝试访问路径不会返回错误,并不意味着它将返回一个值(可能是未定义的,null或其他内容)。