这更像是一个一般实践问题。
我正在使用的语言是 Javascript。我有一个函数正在获取一个包含许多变量的对象(好的,只有 10 个变量)。确保此函数获取所有必需的变量并且它们都已设置的最佳方法是什么?
我知道,我知道,为什么不直接使用if
语句。这是 if 语句的一大块!随着我成长为一名程序员,我知道这可能不是最好的方法。我实际上正在寻找捷径。您将如何检查大量变量的存在值和非空白值?
这更像是一个一般实践问题。
我正在使用的语言是 Javascript。我有一个函数正在获取一个包含许多变量的对象(好的,只有 10 个变量)。确保此函数获取所有必需的变量并且它们都已设置的最佳方法是什么?
我知道,我知道,为什么不直接使用if
语句。这是 if 语句的一大块!随着我成长为一名程序员,我知道这可能不是最好的方法。我实际上正在寻找捷径。您将如何检查大量变量的存在值和非空白值?
这是处理验证的一种非常简洁的方法,我通常在检查表单输入中的必填字段时使用它。
var theObj = { /* object loaded from server */ }
function checkTheObj(testObj)
{
var requiredKeys = ['key1', 'key2', 'key3'];
for(var keyPos = 0; keyPos < requiredKeys.length; keyPos++)
{
if(typeof(testObj[requiredKeys[keyPos]]) == 'undefined')
{
return false;
}
}
return true;
}
if(checkTheObj(theObj))
{
//do stuff
}
您当然可以调整它以返回或抛出异常,告诉第一个缺失的字段(或使用内部数组返回所有缺失字段的列表)。
function objectHas(obj, properties) {
var len = properties.length
for (var i=0; i<len; i++) {
if (i in properties) {
if((!obj.hasOwnProperty(properties[i])) || (!obj.propertyIsEnumerable(properties[i]))) {
return false;
}
}
}
return true;
}
用法:
if(objectHas(user, ["email", "password", "phone"])) {
console.log("awesome");
}
这很简单,但可以完成工作。
编辑:在理想的世界中,您可以扩展 Object 原型以获得更简洁的语法,例如if(object.has(["a", "b", "c"])),但显然扩展 Object 原型是化身邪恶的,所以一个功能必须做:)
首先,您需要提高对这些语言的理解并学习正确的术语。
eval
代码可以有变量;这是一个不同(但相似)的概念。作为程序员,你应该已经知道可以循环执行重复性任务;ECMAScript 实现中的相关语句是for
、for
-in
和while
do
. 因此,您不必编写多个if
语句。
您可以通过两种方式访问对象的属性,其中属性名称property
是:
obj.property
obj["property"]
如果属性名称是标识符,即如果它遵循某些命名规则,则第二个等效于第一个。如果属性名称不是标识符或者它是变量,则必须使用第二个。这也表明所有属性名称都是字符串值。因此,您可以将属性的名称存储为变量或另一个属性的值,然后在属性访问器中访问该变量或属性。在下文中,属性名称 ( property
) 存储在变量中并从变量中使用:
var propertyName = "property";
obj[propertyName]
将其与循环结合使用,您可以迭代对象的某些属性。不幸的是,到目前为止提出的解决方案在两个方面存在缺陷: A for
-in
语句仅迭代对象的可枚举属性,并且它以任意顺序进行。此外,它还迭代可枚举的继承属性(这就是为什么一种解决方案需要hasOwnProperty()
调用的原因)。
以定义的顺序仅迭代对象的某些属性的简单、可靠且有效的方法如下所示:
var propertyNames = ['name1', 'name2', 'name3'];
for (var i = 0, len = propertyNames.length; i < len; ++i)
{
/* … */ myObject[propertyNames[i]] /* … */
}
这是因为propertyNames
引用了一个Array
实例,它封装了一个数组数据结构。数组的元素是具有从 0 到 65535 (2 32 -1)Array
的整数索引的实例的属性。因为索引不是标识符(它们以十进制数字开头),所以您必须使用括号属性访问器语法(有些人误解了这一点并将所有 ECMAScript 对象称为“数组”,甚至称它们为“关联数组”和“数组操作员”)。因此,在每次迭代中计算数组元素的值,每次增加 1。结果,在每个循环中访问具有该名称的属性。[…]
propertyNames[i]
i
myObject[propertyNames[i]]
现在,要确定该属性是否已设置,您需要定义它的含义。访问不存在的属性会产生undefined
值(而不是错误)。但是,现有属性也可以将undefined
值作为其值。
如果“未设置”意味着该对象没有该属性(但可以继承它),那么您应该使用hasOwnProperty()
Mahn 解决方案中使用的方法。
如果“未设置”意味着对象没有属性并且不继承它,那么您应该使用in
运算符,前提是该对象不是宿主对象(因为没有为它们指定运算符):in
if (propertyNames[i] in obj)
如果“未设置”意味着对象具有或继承了该属性,但该属性具有undefined
值,或者该对象既没有也没有继承该属性,那么您应该使用typeof
Bob Davies 和 aetaur 解决方案中使用的运算符(但后一种方法使用Array.prototype.every()
的兼容性较差;该方法在 ECMAScript 版本 5 之前未指定,并且在 IE/JScript < 9 中不可用)。
ECMAScript 版本 5.x 有第三个选项,该Object.keys()
方法(尽管它的名称)返回对实例的引用,该Array
实例包含参数的所有非继承属性的名称:
var propertyNames = Object.keys(obj);
/* continue as described above */
Object.keys()
如果它不是内置的,最好模拟它,因为这个算法经常有用。
variableNameList
如果(所需变量名称列表)中的所有变量都设置在 object 中,则此表达式返回 true o
:
variableNameList.every(function(varName){ return typeof o[varName] !== 'undefined'; });
您可以使用下划线_.all
函数代替 native every
,并使用下划线_.isUndefined
代替typeof ...
.