首页 > JavaScript中使用多层级的对象属性有什么比较优雅的方式?

JavaScript中使用多层级的对象属性有什么比较优雅的方式?

比如有对象:

var a = {
        b:{
            c:{
                d:{
                }
            }
        }
    }

使用的时候比如
var param = a.b.c.d;
但是一旦其中c或者d不存在就会报错。
一般的方式是逐层检查,但是代码很不优雅。
有什么更好的方式呢?


层级能少当然好。

不过再怎么约定优化,多层级依然是会出现的.作为个体可能英明神武,群体内也总有些队友要呵呵的:)。何况,网络7层协议,哪位可以帮我减少一层呢。

所以,我们还是回到问题本身好点。

a.b.c.d 直达语义核心,很好。需要担心的异常情况,既然都说异常了,直接用异常处理即可。异常是分离正常代码和错误处理的好方法(好像废话


function d_value(){
try {
return a.b.c.d;
}
catch(err) {
result = nil;
}
}

80386 就已经直接支持异常了,没必要如同c一样,亦步亦趋的去检查了。这样的if ,? 样式的错误处理,该过时了。


拿我前幾天重構+擴充的辭典舉例,詞典的數據是高度層次化的,且每一層的數目不定,這時候代碼若不分層,將會成爲噩夢。

雖然我沒有像樓上那樣寫很多方法單獨處理每一層的數據,而是很瀟灑地寫了一個上百行的函數,但是由於技巧的使用,層與層之間的關係很清晰,基本獨立,也很容易重構成單獨的函數。這種寫法對於簡單的程序,或者剛開始寫的時候是再好不過了,開發效率非常高。

技巧就是:

var a = JSON.parse(text); // {b:{c:{}}}
// handle level a

var b = a.b;
if (b) {
    // handle level b

    var c = b.c;
    if (c) {
        // handle level c
    }
}

https://github.com/bumfo/moedict-server/blob/master/index.html?ts=4


  1. 使用 CoffeeScript: a?.b?.c?.d

  2. Source

    var level3 = (((test || {}).level1 || {}).level2 || {}).level3;

    function checkNested(obj /*, level1, level2, ... levelN*/) {
      var args = Array.prototype.slice.call(arguments),
          obj = args.shift();
    
      for (var i = 0; i < args.length; i++) {
        if (!obj || !obj.hasOwnProperty(args[i])) {
          return false;
        }
        obj = obj[args[i]];
      }
      return true;
    }
    
    var test = {level1:{level2:{level3:'level3'}} };
    
    checkNested(test, 'level1', 'level2', 'level3'); // true
    checkNested(test, 'level1', 'level2', 'foo'); // false
    
  3. brototype

    var myURL;
    if (Bro(app).doYouEven('config.environment.buildURL')) {
        myURL = app.config.environment.buildURL('dev');
    }
    

确定合理的数据结构

如果服务端给你的是像你描述的那样多层的数据结构,先问他一句:“非得这样吗?”
开发之前沟通充分,确定合理的数据结构,对于提高效率有事半功倍的作用。

不怕层级多,只要层级分明

在现实应用中,不能保证永远都能拿到“舒服”的数据结构,所以前端代码上也要想办法处理。以下是一些建议,供参考。

1. 不要频繁地跨层操作数据。

首先应该尽量避免用 a.b.c 这种方式访问对象的属性,这样的方式有这样几个缺点:

2. 为每一层数据设置专门的处理方法。

利用 JavaScript 面向对象的特性来编程,专门设置一个方法来处理对象的某个属性,确保其他地方在访问这个属性时,它的值一定符合某个约定的格式。
下面是一个简单的示例:
http://jsbin.com/lipeguvese/3/edit?js,console
直接把代码贴下面,方便大家批评修改:

javascriptvar Factory = function(data){
  this.initialize(data);
};
Factory.prototype = {
  initialize: function(data){
    this.data = data;
    this.setup();
  },
  setup: function(){
    var data = this.data,
        a = data.a,
        d = data.d,
        e = data.e;
    // 把 data.a 属性交给 handleA 处理
    this.handleA(data.a);
    // 对 data 的其他属性的处理
    d.push(4);
    d = d.slice(1);
    e = e.toUpperCase();
    data.e = e;
  },
  handleA: function(a){
    // 把 a.b 交给 handleB 处理
    this.handleB(a.b);
    // 对 a 的其他属性的处理
    // ...
  },
  handleB: function(b){
    // 把 b.c 交给 handleC 处理
    this.handleC(b.c);
    // 对 b 的其他属性的处理
    // ...
  },
  handleC: function(c){
    data.c = c + 100;
  },
  output: function(){
    console.log(this.data);
  }
};

// 假设约定的数据格式如下
var data = {
  a: {
    b: {
      c: 111
    }
  },
  d: [1,2,3],
  e: 'string property value'
};

// 处理数据
var f = new Factory(data);
f.output();
【热门文章】
【热门文章】