正在检查属性的属性是否存在
Checking if property of property exists
一般来说,如果我想检查obj.foo.bar
是否退出,我会这样做:
if(
typeof obj != "undefined" &&
typeof obj.foo !== "undefined" &&
typeof obj.foo.bar !== "undefined"
){ action() }
这是相当丑陋和重复,可悲的是,我不得不经常使用它。
我相信没有任何函数isDefined()
可以这样做,因为当if(isDefined(obj.foo.bar)){action()}
时,即使是空函数(function isDefined(){}
)也会抛出错误
那么,有没有什么聪明的方法可以检查obj.foo.bar
是否退出?
编辑:
- 使用字符串解析(或仅将变量作为字符串传递)的方法是非常有问题的,因为可能正在使用minimier
- CCD_ 6可用CCD_。这个解决方案仍然不能让我满意
编辑2-解决方案:
如这里建议的
var a = {
b: {
c: 'd'
}
};
function isDefined(fn) {
var value;
try {
value = fn();
} catch (e) {
value = undefined;
} finally {
return value !== undefined;
}
};
// ES5
console.log(
isDefined(function () { return a.b.c; }), //return true
isDefined(function () { return a.b.c.d.e.f; }) //returns false
);
// ES6 using the arrow function
console.log(
isset(() => a.b.c),
isset(() => a.b.c.d.e.f)
);
我批准了@T.J.Crowder的解决方案,而不是@somethinghere的解决方案。因为最终常规解决方案更短,而且try
catch
语句还有其他用途,可能会导致问题
你可以让它不那么难看,因为你不需要typeof
来完成大部分:
if (obj && obj.foo && typeof obj.foo.bar !== "undefined") {
action();
}
如果obj.foo.bar
不能是伪值(0
、""
、NaN
、null
、undefined
或false
),则最后一项也不需要typeof
:
if (obj && obj.foo && obj.foo.bar) {
action();
}
如果你真的想要一个isDefined
函数,你必须按照这个问题及其答案中的概述进行字符串解析,但如果你使用一个重命名(缩短)属性名的迷你程序,并且确实涉及字符串解析,那可能会有问题。
您实际上可以将其作为一个通用函数:
function isDefined(base){
// Run through any number of passed arguments, ignoring the first one (`base`)
for(var i = 1; i < arguments.length; i++){
// While running, see if they exist and assign it to base, then continue
base = typeof base[arguments[i]] != "undefined"
? base[arguments[i]] : null;
// if base is set to false break the loop as theres nothing deeper to find
if(!base) break;
}
// return the value that base was set to
return base;
}
然后这样称呼它:
var bar = {foo: {}};
console.log(isDefined(bar, 'foo')); ///= Will be bar[foo] (Object Object)
console.log(isDefined(bar, 'foo', 't')); // Will be 'null'
你总是需要传递一个参数才能使其工作,但如果你想要全局存在,你可以传递窗口对象。
function isDefined(base){
for(var i = 1; i < arguments.length; i++){
base = typeof base[arguments[i]] != "undefined"
? base[arguments[i]] : null;
if(!base) break;
}
return base;
}
var bar = {foo: {}};
document.write(isDefined(bar, 'foo') + " / " + isDefined(bar, 'foo', 't'));
如果您想先查看bar
是否存在,请尝试使用isDefined(window, 'bar', 'foo');
更新
我注意到设置为false
的值也会返回false,所以null是我们的救星。
更新2
既然你提出了minimier问题,有一种方法是半优雅的,可以进行单行部署,但你不能将其封装在一个函数中:
var bar = {};
try { var defined = typeof bar.foo !== "undefined"; } catch(e) { var defined = false; } // defined will be false
var bar = {foo:{}};
try { var defined = typeof bar.foo !== "undefined"; } catch(e) { var defined = false; } // defined will be true
令人讨厌的是,它需要在if之前执行,但它确实大大简化了if
:
var bar = {};
try { var defined = typeof bar.foo !== "undefined"; } catch(e) { var defined = false; }
if(defined){
// Code here
}
希望能有所帮助。
更新3
毕竟,有一种方法可以将其封装在一个函数中,隐藏得很深,但这里有一个直接链接到被低估的答案:javascript测试嵌套对象密钥的存在
关键是将值包装在一个函数中,该函数返回当时的值。它很聪明!
像这样的东西应该可以做到:
function isDefined(obj, keysString) {
//get all the keys
var keys = keysString.split('.');
var tmp = obj;
for(var i = 0; i < keys.length; i++) {
tmp = tmp[keys[i]];
//slowly construct your 'deep' object while checking if you can
if(typeof tmp === 'undefined') {
return false;
}
}
return true;
}
用法:
isDefined({test: {nested: true}}, 'test.nested'); //return true
isDefined({test: {nested: true}}, 'test.nested.supernested'); //return false
isDefined({test: {nested: true}}, 'test.othernested.supernested'); //return false
Js在此报价
小心使用可能会更改密钥名称的缩小程序。
- 检查对象的所有属性是否未定义
- 检查来自不同数组的两个元素的一个属性是否相等
- 正在检查属性的属性是否存在
- 在 Forerunner 数据库集合中创建主键时,key 属性是否可以位于集合对象的对象内部
- 使用 Chai - 如何检查对象属性是否包含 DOM 元素
- Ember 1.0 预发行版支持属性是否已更改
- VueJS:检查属性是否具有来自其他属性的值
- 创建nonce并将其输出为数据属性是否存在漏洞
- 检查数组中的对象属性是否与具有相同ID的另一个对象重复
- 如何在Ember.js中创建一个计算属性来查看单个EmberData属性是否脏
- Javascript-在检查对象属性是否存在时避免异步竞争条件
- 如何指定输入元素中允许的最大字符数 - 设置 maxlength 属性是否足够
- 如何检查主干模型中的嵌套属性是否已更改
- HTML 文本框值属性是否安全免受 XSS 攻击
- 在 HTML 定位点中指定“语言”属性是否会更改事件行为
- 在灯泡阶段检查对象属性是否存在
- 给定元素本身的 aria-live 属性是否可以使用 javascript 动态设置
- 立即调用的属性是否可以引用它所分配到的对象
- 检查 css 属性是否应用了 !重要属性
- 检查数据属性是否具有值