【问题标题】:More Readable Way to Write Complex If Statement编写复杂 If 语句的更易读的方式
【发布时间】:2017-05-24 22:19:36
【问题描述】:

我正在为我的 Angular 项目编写用户定义的类型保护。

以下if 语句(由我的 cmets 标记)运行良好 — 但我不禁认为会有一种更易读的方式来编写它们。

以下首先检查传递给函数的Object 是否具有所需的道具(如果没有则提前退出)。

下一个(和第三个)if 语句检查属性 activity 的值是一个字符串。

第二个和第四个if 语句需要检查props createdAt 和updatedAt 的值是否是String 类型,或者它们是Objects 并且它们有自己的props .sv 谁的值是字符串timestamp。

import { GridMetadata } from './grid-metadata';

export function isGridMetadata(obj: any): obj is GridMetadata {
  [ 'activity', 'createdAt', 'totalReps', 'updatedAt' ].every((prop) => {
    if (obj.hasOwnProperty(prop) === false) return false;
  });

  if (typeof obj.activity !== 'string') return false;

  // TODO: Better way to write this?
  if (typeof obj.createdAt === 'string') {}
  else if (obj.createdAt.hasOwnProperty('.sv') && obj.createdAt['.sv'] === 'timestamp') {}
  else return false;

  if (typeof obj.totalReps !== 'number') return false;

  // TODO: Better way to write this?
  if (typeof obj.updatedAt === 'string') {}
  else if (obj.updatedAt.hasOwnProperty('.sv') && obj.updatedAt['.sv'] === 'timestamp') {}
  else return false;

  return true;
}

可能确实有更好更易读的方式来编写整个函数?!

【问题讨论】:

  • 首先你需要分离你的逻辑用例,然后你可能想对二进制用例使用三进制(只有一个 if 和 else),并为多个用例(多个 if)使用 switch case,这个这样您的代码将非常易读。只是想知道你为什么使用空语句?
  • 我认为您对every 语句有疑问。 return false 不返回您的 isGridMetadata 函数,它只返回传递给 every 的匿名函数。

标签: javascript angular if-statement


【解决方案1】:

首先,每个值都不会存储在任何地方。并且您可以直接退回支票:

var objHasPropertiesInTheList = [ 'activity', 'createdAt', 'totalReps', 'updatedAt' ].every((prop) => {
    return obj.hasOwnProperty(prop);
  });

如果对象中没有列表的所有这些属性,现在objHasPropertiesInTheList 将为 false。因此,如果没有所有属性,请在此处添加检查并执行您需要的操作。

然后这个:

if (typeof obj.createdAt === 'string') {}
  else if (obj.createdAt.hasOwnProperty('.sv') && obj.createdAt['.sv'] === 'timestamp') {}
  else return false;

可以很简单:

if (typeof(obj.createdAt) !== 'string' && obj.createdAt['.sv'] !== 'timestamp') {
  return false;
}

最后一个也一样:

if (typeof(obj.updatedAt ) !== 'string' && obj.updatedAt['.sv'] !== 'timestamp') {
  return false;
}

【讨论】:

    【解决方案2】:

    如果我没有犯错:

    if (typeof obj.activity !== 'string' ||
        (!typeof obj.createdAt === 'string' && !(obj.createdAt.hasOwnProperty('.sv') && obj.createdAt['.sv'] === 'timestamp') || 
        typeof obj.totalReps !== 'number' ||
        (!typeof obj.updatedAt === 'string' && !(obj.updatedAt.hasOwnProperty('.sv') && obj.updatedAt['.sv'] === 'timestamp')) {
        return false;
    } else {
        return true;
    }
    

    【讨论】:

    • 抱歉,如果我不正确,但我看不出这是如何工作的。我需要在循环内检查obj.hasOwnProperty(prop),否则prop 未定义。如果我处于循环中,该语句肯定会返回 false,因为即使满足该 prop 的条件,其他三个属性也不存在并因此失败?
    • 完成,现在应该没问题了
    【解决方案3】:

    我认为重写它的等效且更紧凑的方法是:

    function validateDateProperty(obj, dateProp) {
        const dateVal = obj[dateProp];
        return typeof dateVal === 'string' || (dateVal.hasOwnProperty('.sv') && dateVal['.sv'] === 'timestamp');
    }
    
    export function isGridMetadata(obj : any) : obj is GridMetadata {
        if !(['activity', 'createdAt', 'totalReps', 'updatedAt'].every(prop => obj.hasOwnProperty(prop))) {
            return false;
        }
        return (
            typeof obj.activity === 'string'
            && typeof obj.totalReps === 'number'
            && validateDateProperty(obj, 'createdAt')
            && validateDateProperty(obj, 'updatedAt')        
        );
    }

    【讨论】:

      猜你喜欢
      • 2010-11-22
      • 2015-03-06
      • 2022-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-25
      相关资源
      最近更新 更多