简洁的方法来null检查一个深层嵌套的对象?

时间:2017-08-07 14:21:56

标签: javascript

浏览器的JavaScript

我需要测试一个深度嵌入的属性不是null,如果这个条件是true,那么要改变它的属性。但任何其父母也可以null。因此,我要检查链中的每个项目...因此,我写了这样丑陋的代码:

if(window[rootNamespace].vm.tech && 
    window[rootNamespace].vm.tech.currentWorkType &&
    window[rootNamespace].vm.tech.currentWorkType.currentVariant &&
    window[rootNamespace].vm.tech.currentWorkType.currentVariant.currentVersion &&
    window[rootNamespace].vm.tech.currentWorkType.currentVariant.currentVersion.currentWorkSection &&
    window[rootNamespace].vm.tech.currentWorkType.currentVariant.currentVersion.currentWorkSection.currentStageSet){

  window[rootNamespace].vm.tech.currentWorkType.currentVariant.currentVersion
    .currentWorkSection.currentStageSet.selectedEntity = item;
}

是否有较短的检查方法?

5 个答案:

答案 0 :(得分:1)

语法明智我不这么认为,但我建议至少重构。

var getCurrentStageSet = function(window){
   return window[rootNamespace].vm.tech && 
    window[rootNamespace].vm.tech.currentWorkType &&
    window[rootNamespace].vm.tech.currentWorkType.currentVariant &&
    window[rootNamespace].vm.tech.currentWorkType.currentVariant.currentVersion &&
    window[rootNamespace].vm.tech.currentWorkType.currentVariant.currentVersion.currentWorkSection &&
    window[rootNamespace].vm.tech.currentWorkType.currentVariant.currentVersion.currentWorkSection.currentStageSet
}

var setSelectedEntity = function(currentStageSet, item){
    currentStageSet.selectedEntity = item;
}

通过抽象这个逻辑,你的实际属性集将更具可读性和可重用性:

var currentStageSet = getCurrentStageSet(window);
if (currentStageSet){
   setSelectedEntity(currentStageSet, item);
}

答案 1 :(得分:1)

(我是提出try-catch方法的原始海报,但根据对该帖子的讨论,你担心性能。这是另一种方法。)

您可以使用原型方法来实现访问子属性的安全方法。这是一个可以安全地测试嵌套属性是否存在的方法:

// Indicates whether an object has the indicated nested subproperty, which may be specified with chained dot notation 
// or as separate string arguments.
Object.prototype.hasSubproperty = function() {
    if (arguments.length == 0 || typeof(arguments[0]) != 'string') return false;  
  var properties = arguments[0].indexOf('.') > -1 ? arguments[0].split('.') : arguments;    
  var current = this;
  for(var x = 0; x < properties.length; x++) {
    current = current[properties[x]];
    if ((typeof current) == 'undefined') return false;
  }  
  return true;
};

A full set of methods can be found here, with sample code.

Timings可以在这里运行,并指出使用 try-catch方法在抛出错误时可能会比原始方法运行几个数量级,但是否则非常快。原型方法更通用,可以产生更具声明性的风格,同时提供比try-catch未命中更好的性能,但显然不如手工制作每次if语句和/或try-catch而不会错过。

我也blogged about this approach

答案 2 :(得分:0)

对于这样一个微不足道的,自包含的代码,只是捕获并忽略错误(可能是日志)可能并非不合理,例如。

try {
  if (window[rootNamespace].vm.tech.currentWorkType.currentVariant.currentVersion.currentWorkSection.currentStageSet) {
      window[rootNamespace].vm.tech.currentWorkType.currentVariant.currentVersion.currentWorkSection.currentStageSet = item;
  }
} catch (e) {
   // log the error but continue
}

不确定在这种类型的支票中还有什么可能真的出错,或者你可以专门捕捉TypeError,但不确定它真的会那么重要。

我一般不会建议赶上所有人,但在这种情况下,它似乎自足,不会成为巨大的风险。

除此之外的任何事情都需要努力,例如建立一个对象装饰器或一个流畅的接口类型解决方案,但对我来说似乎有点过分了。

答案 3 :(得分:-1)

您可以创建一些变量以使代码更具可读性

  var tech = window[rootNamespace].vm.tech;

  var workType, curVariant, curVer, curWorkSection;

  if(tech){
      workType = tech.currentWorkType
  }

  if(workType){
      curVariant = workType.currentVariant;
  }
  if(curVariant){
      curVer =curVariant.currentVersion;
  }
  if(curVer){
      curWorkSection = curVer.currentWorkSection;
  }
  if(curWorkSection && curWorkSection.currentStageSet){
      curWorkSection.currentStageSet.selectedEntity = item;
  }

答案 4 :(得分:-2)

这是基本JavaScript中最紧凑的语法。它通过使用错误捕获来避免所有空值检查。没有其他答案是紧凑的,因为语言只是缺少你在C#之后的功能。

显然,我被其他人的作者拒绝了,而不是紧凑的答案,但这仍然是唯一的单行答案。请注意,此处列出的其他方法可让您创建多个功能。 :|如果你想要紧凑,就是这样。

try { window[rootNamespace].vm.tech.currentWorkType.currentVariant.currentVersion
    .currentWorkSection.currentStageSet.selectedEntity = item; } catch (err) {}