【问题标题】:Shorthand creation of object chains in JavascriptJavascript中对象链的速记创建
【发布时间】:2014-02-18 11:18:33
【问题描述】:

我想知道是否有更短的方法可以实现以下目标:

App.Plugins = App.Plugins || {};
App.Plugins.SomePlugin = App.Plugins.SomePlugin || {};
App.Plugins.SomePlugin.Models = App.Plugins.SomePlugin.Models || {};
App.Plugins.SomePlugin.Views = App.Plugins.SomePlugin.Views || {};
App.Plugins.SomePlugin.Collections = App.Plugins.SomePlugin.Collections || {};

据我所知,这种格式很好,如果我弄错了,请告诉我,我只是想知道是否有更好的方法来对我的单例进行初始设置。

提前谢谢...

【问题讨论】:

  • 您可以编写一个方法来为您解决这些问题:buildTree(App, 'Plugins', 'SomePlugin', 'Models') 等可以像 mkdir -p 一样工作
  • 当然,但是考虑到执行此操作的频率很低,并且为了保持代码简单,它没有上面的意义。我想知道是否有一些单线,但我认为没有

标签: javascript semantics


【解决方案1】:

您可以执行以下操作:

function defaults(obj, prop) {
    return obj[prop] = obj[prop] || {};
}
defaults(App, 'Plugins');
defaults(App.Plugins, 'SomePlugin');
defaults(App.Plugins.SomePlugin, 'Models');
defaults(App.Plugins.SomePlugin, 'Views');
defaults(App.Plugins.SomePlugin, 'Collections');

【讨论】:

  • 我考虑过创建一个函数来做到这一点,事实上,虽然这与问题中提供的手动方法一样多的代码行,但它也增加了另一个潜在的故障点,我相信答案我的问题可能是否定的。不过感谢您的回复。
  • 如果您担心“故障点”,您就没有很好的测试套件。也许你需要先解决这个问题。
  • 您应该将其改写为“没有测试套件”,我刚刚加入了这个项目,它在我的优先级列表中排名第一!事实是,我认为这不会比最初的方法增加任何价值,但我接受它作为一个完全有效的答案,感谢您的洞察力
【解决方案2】:

我不明白你为什么要这样做

无论如何,一种更短的写法是:

App={
 Plugins:{
  SomePlugin:{
   Models:{},
   Views:{},
   Collections:{}
  }
 }
}

然后考虑函数

function defaults(obj, prop) {
    return obj[prop] = obj[prop] || {};
}

使用会返回错误

defaults(App.Plugins.AnotherPlugin,'Models')

检查这很痛苦:

var x={};
if(App&&
   App.Plugins&&
   App.Plugins.AnotherPlugin&&
   App.Plugins.AnotherPlugin.Models
){
 x=App.Plugins.AnotherPlugin.Models
}
console.log(x);

解决办法是

var x={};
try{x=App.Plugins.AnotherPlugin.Models}catch(e){}
console.log(x)

这不会给你任何错误

但你不能简单地设置它。

编辑

评论回答

然后,您应该从不确定的地方开始检查。在您的情况下,您只需要检查另一个插件是否存在。您可能已经有 App 和 App.Plugins。所以您不需要 App=App||{},而只需要 App.Plugins.AnotherPlugin

!App.Plugins.AnotherPlugin||App.Plugins.AnotherPlugin=NewPlugin

或函数

function addPlugin(name,newPlugin){
 !App.Plugins[name]||App.Plugins[name]=newPlugin
}

定义你自己的标准...我的意思是如果对象不存在,为什么要返回它?

如果它不存在,你无论如何都不能做任何事情。

再一次,最大的问题是检查它是否存在......就像我上面已经描述的那样,它是 try catch。

EDIT2

检查此功能。

function def(a,b,c,d){
 c=b.split('.');
 d=c.shift();
 a[d]||(a[d]={});
 !(c.length>0)||def(a[d],c.join('.'));
}

用法:

var A={};
def(A,'B.C.D.E.F')
//this transforms your {}
//to 
A:{
 B:{
  C:{
   D:{
    E:{
     F:{
     }
    }
   }
  }
 }
}

http://jsfiddle.net/5NgWL/

创建你的插件:

var App={}
def(App,'Plugins.SomePlugin.Models')
def(App.Plugins.SomePlugin,'View')
// &/or
def(App,'Plugins.SomePlugin.Collections')

【讨论】:

  • 我这样做的原因是 App 对象在执行我的代码时已经存在,我正在为我的应用程序组件添加额外的容器。我绝对对您对此提出的任何批评感兴趣
  • 花了我一段时间来创建一个自定义函数,但它现在就在这里......检查一下。
  • 同意评论回答,在这个阶段这是代码中唯一采用这种方法的地方,应用程序已经过验证,但其余的都没有。展望未来,我会让 App.Plugins 检查链上更高的位置,因为各个插件不需要关心自己。
  • 对于优雅的功能也 +1。被接受为最有力和最有见地的答案。
【解决方案3】:

可能会用到

function namespace(path) {
    var segments = path.split('.'),
        result = {};

    function define(name, obj) {

        if (name === '.') {
            return obj;
        } 

        !obj[name] && (obj[name] = {});
        return define(segments.shift(), obj[name]);
    }

    segments.push('.'); //add stop symbol;
    define(segments.shift(), result);

    return result;
}

namespace('App.Plugins.SomePlugin.Collections').controller = function() {}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-07
    • 1970-01-01
    • 2011-11-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-09
    • 2023-03-11
    相关资源
    最近更新 更多