繁体   English   中英

Javascript - 检查 object 具有所需属性的优雅方法

[英]Javascript - elegant way to check object has required properties

我正在寻找一种好的/优雅的方法来验证 javascript object 是否具有所需的属性,到目前为止,这就是我所拥有的:

var fields = ['name','age','address'];
var info = {
  name: "John Doe",
  age: "",
  phone: "123-456-7890"
}


var validateFields = function(o, required_fields) {
  required_fields.forEach(function(field){
    if(o.hasOwnProperty(field)){
      if(o[field]){
        console.log(field + ": " + o[field]);
      }else{
        console.log(field + " exists but is empty");
      }
    }else{
      console.log(field + " doesn't exist in object");
    }
  });
}

validateFields(info, fields);

在普通的 javascript 中有更有效/更优雅的方法吗?

编辑:好的,我很高兴我问了,因为我完全错过了一堆可能的条件,比如零。

随着 window 的优雅,这是如何验证 function 的? 还有其他我应该检查的情况吗?

var fields = ['name','age','address'];
var info = {
  name: "John Doe",
  age: 0,
  address: false,
  phone: "123-456-7890"
}


var validateFields = function(o, required_fields, null_valid, zero_valid, empty_valid) {
  var invalid_fields = [];
  required_fields.forEach(function(field){
    if(field in o){
      switch(o[field]){
        case '':
          console.log(field + " exists but is empty");
          if(!empty_valid){
            invalid_fields.push(o[field]);
          }
          break;
        case undefined:
          console.log(field + " exists but is undefined");
          invalid_fields.push(o[field]);
          break;
        case null:
          console.log(field + " exists but is null");
          if(!null_valid){
            invalid_fields.push(o[field]);
          }
          break;
        case 0:
          console.log(field + " exists and the value is 0");
          if(!zero_valid){
          }
          invalid_fields.push(o[field]);
          break;
        default:
          console.log(field + ": " + o[field]);
          break;
      }
    }else{
      console.log(field + " doesn't exist in object");
      invalid_fields.push(o[field]);
    }
  });

  return invalid_fields;
}


var invalid = validateFields(info, fields, true, true, false);
console.log(invalid);
if(invalid.length >0){
  console.log("ERROR: Missing fields");
}else{
  console.log("Fields are valid");
}

如果您想要“优雅”,那么您正在寻找的称为schema

 var schema = { name: function (value) { return /^([AZ][az\\-]* )+[AZ][az\\-]*( \\w+\\.?)?$/.test(value); }, age: function (value) { return !isNaN(value) && parseInt(value) == value && value >= 18; }, phone: function (value) { return /^(\\+?\\d{1,2}-)?\\d{3}-\\d{3}-\\d{4}$/.test(value); } }; var info = { name: "John Doe", age: "", phone: "123-456-7890" }; function validate(object, schema) { var errors = Object.keys(schema).filter(function (key) { return !schema[key](object[key]); }).map(function (key) { return new Error(key + " is invalid."); }); if (errors.length > 0) { errors.forEach(function (error) { console.log(error.message); }); } else { console.log("info is valid"); } } validate(info, schema);

要解决@AndreFigueiredo 的迂腐问题,您还可以检查object包含该属性:

 var schema = { name: function (value) { return /^([AZ][az\\-]* )+[AZ][az\\-]*( \\w+\\.?)?$/.test(value); }, age: function (value) { return !isNaN(value) && parseInt(value) == value && value >= 18; }, phone: function (value) { return /^(\\+?\\d{1,2}-)?\\d{3}-\\d{3}-\\d{4}$/.test(value); } }; schema.name.required = true; schema.age.required = true; var info = { // name: "John Doe", age: "", phone: "123-456-7890" }; function validate(object, schema) { var errors = Object.keys(schema).map(function (property) { var validator = schema[property]; return [property, !validator.required || (property in object), validator(object[property])]; }).filter(function (entry) { return !entry[1] || !entry[2]; }).map(function (entry) { if (!entry[1]) return new Error(entry[0] + " is required."); else return new Error(entry[0] + " is invalid."); }); if (errors.length > 0) { errors.forEach(function (error) { console.log(error.message); }); } else { console.log("info is valid"); } } validate(info, schema);


更新

这是一个使用 ECMAScript 6 版本功能的现代化解决方案,包括解构箭头函数Object.entries()模板文字for...of

 const schema = { name: value => /^([AZ][az\\-]* )+[AZ][az\\-]*( \\w+\\.?)?$/.test(value), age: value => parseInt(value) === Number(value) && value >= 18, phone: value => /^(\\+?\\d{1,2}-)?\\d{3}-\\d{3}-\\d{4}$/.test(value) }; let info = { name: 'John Doe', age: '', phone: '123-456-7890' }; const validate = (object, schema) => Object .keys(schema) .filter(key => !schema[key](object[key])) .map(key => new Error(`${key} is invalid.`)); const errors = validate(info, schema); if (errors.length > 0) { for (const { message } of errors) { console.log(message); } } else { console.log('info is valid'); }

以及分别执行requiredvalidate检查的版本:

 const schema = { name: value => /^([AZ][az\\-]* )+[AZ][az\\-]*( \\w+\\.?)?$/.test(value), age: value => parseInt(value) === Number(value) && value >= 18, phone: value => /^(\\+?\\d{1,2}-)?\\d{3}-\\d{3}-\\d{4}$/.test(value) }; schema.name.required = true; schema.age.required = true; let info = { // name: 'John Doe', age: '', phone: '123-456-7890' }; const validate = (object, schema) => Object .entries(schema) .map(([key, validate]) => [ key, !validate.required || (key in object), validate(object[key]) ]) .filter(([_, ...tests]) => !tests.every(Boolean)) .map(([key, invalid]) => new Error(`${key} is ${invalid ? 'invalid' : 'required'}.`)); const errors = validate(info, schema); if (errors.length > 0) { for (const { message } of errors) { console.log(message); } } else { console.log('info is valid'); }

我认为您应该更关心检查它的正确方法是什么,而不是最优雅的方法。 我将删除 Todd Moto 关于此问题的一篇非常好的帖子的链接: 请看一看

简而言之,您的代码应如下所示:

 var validateFields = function(o, required_fields) {
  required_fields.forEach(function(field){
    if(field in o){
      if((typeof o[field] != 'undefined')){
        console.log(field + ": " + o[field]);
      }else{
        console.log(field + " exists but is undefined");
      }
    }else{
      console.log(field + " doesn't exist in object");
    }
  });
}

注意:检查它是否有值时要小心,javascript 中的许多表达式都是假的(例如 0、假等)但都是有效值。

您可以使用https://github.com/jquense/yup来解决您的问题。

import * as yup from 'yup';

let schema = yup.object().shape({
  name: yup.string().required(),
  age: yup.number().required().positive().integer(),
  address: yup.string().required(),
});

var info = {
  name: "John Doe",
  age: "",
  phone: "123-456-7890"
}

// check validity
schema
  .isValid(info)
  .then(function (valid) {
    valid; // => false
  });

这不仅仅是检查字段的存在,它还确保数据类型正确,例如年龄是非负数。

我会真正检查空字符串,因为0是假的,但是一个值而不是空。

 function validateFields(object, keys) { keys.forEach(function (k) { if (k in object) { console.log(k + ": " + object[k]); if (object[k] === '') { console.log(k + " exists but is empty"); } return; } console.log(k + " doesn't exist in object"); }); } var fields = ['name', 'age', 'address', 'zeroString', 'zeroNumber'], info = { name: "John Doe", age: "", phone: "123-456-7890", zeroString: '0', zeroNumber: 0 }; validateFields(info, fields);

这是一个函数,它将通过将对象的键与字符串数组进行比较来检查对象是否包含所有必需的键。 由于它通过比较长度进行验证,因此顺序不同或对象是否包含附加信息都无关紧要。

const hasRequiredKeys = (object, requiredKeys) => {
  return Object.keys(object).filter(key => requiredKeys.includes(key)).length === requiredKeys.length
}

用法

exempleUsage(username: string, password: string) {
  checkRequiredProperties({username, password})
  return this.apiService.post(`/.../...`)
}

帮手

const isEmpty = (v) => (!v && v !== false && v !== 0);

const handleErrorForCB = (error, errorCB) => {
  if (!errorCB) throw error;
  errorCB(error);
};

export function hasProperty(o, p) {
  return !isEmpty(_.get(o, p));
}

export function checkRequiredProperties(o, properties = Object.keys(o), errorCB) {
  const errors = properties.filter(p => !hasProperty(o, p));
  if (errors.length > 0) handleErrorForCB(new Error("Missing properties: " + errors), errorCB);
}

export function checkFoundProperties(o, properties = Object.keys(o), errorCB) {
  const errors = properties.filter(p => !hasProperty(o, p));
  if (errors.length > 0) handleErrorForCB(new Error("Not found: " + errors), errorCB);
}

您可以执行以下操作

  const checkObj = (obj, fields) => {
  const isObject = 'object' === typeof obj && null != obj;
  const objectSize = Object.keys(obj).length;

  if(false === isObject || fields.length !== objectSize) return false;

  let i = objectSize;
  while(-1 < --i) {
    if(fields[i] !== Object.keys[i]) return false;
  }
  return true;
}

如果您愿意,您可以验证字段数组Array.isArray(fields)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM