将 undefined 作为对象处理

Handle undefined as an object

是否有一种技术/框架,可以在将新对象作为对象处理时创建并将其存储到未定义的变量中?

F.e。写作

some.thing = 7;

给出错误描述,无法设置未定义的(某些)属性。

所以现在,我们要回去写

some = {};
some.thing = 7;

这看起来 几乎 对我来说是不必要的,因为很明显,我想使用一些作为对象。


这样会很舒服:

hospitals.sectors.doctors = [];
hospitals.sectors.doctors[ 0 ].age = 32;

这看起来比

更高效、更简单
hospitals = {};
hospitals.sectors = {};
hospitals.sectors.doctors = [];
hospitals.sectors.doctors[ 0 ] = {};
hospitals.sectors.doctors[ 0 ].age = 32;

您可以编写自己的处理程序来完成这项工作

function createObjectProperty(objNameString, objPropertyString, objValueString) {
window[objNameString] = {};
window[objNameString][objPropertyString] = objValueString;
return window[objNameString];}

var test = createObjectProperty("some", "thing", 7);
alert(test.thing);

调用看起来像:

createObjectProperty("some", "thing", 7);

并提示“7”。您还可以在创建新对象之前检查它是否存在。我会遍历对象并收集所有属性,检查重复项并在需要此类功能时附加我的新属性+值。否则新对象将覆盖旧对象。希望这就是您正在寻找的东西

工作fiddle(更新):

https://jsfiddle.net/a922bopj/1/

如果您尝试将 7 分配给 some.thing 并且 some 应该 事先声明,请使用 Cory 的建议var some = { thing: 7 };.

如果您尝试将 7 分配给 some.thing 并且 some 可能 已经是 declared/defined(或者即使它已声明,可能会或可能不会设置为 undefined),使用

(some = (some || {})).thing = 7;

或(一个更具可读性的解决方案,虽然不是一个班轮)

some = (some || {});
some.thing = 7;

我的解决方案的一个警告是,如果未提前声明,您可能会在 some 上获得不需要的范围。未定义但仍声明的示例(因此范围将是预期的):

function assignThing(some) {
    (some = (some || {})).thing = 7; /* one liner solution */
    return some;
}

var foo = assignThing(); /* the parameter 'some' is undefined, but declared */

var bar = assignThing({}); /* the parameter 'some' is defined
                            * (though empty) and declared */

(baz = (baz || {})).thing = 7; /* Unless you have this declared
                                        * elsewhere this *should* be the
                                        * global scope */

var foobar; /* declared, not defined */
(foobar = (foobar  || {})).thing = 7; /* now defined */

编辑:创建了一个像 anddoutoi 建议的名称空间解决方案。 第一个用法示例 (hospitals) 使用第三个参数的可选性质,默认为 "undefined".

第二个示例 (hospitals2) 通过未定义。

第三个例子(hospitals3)传递了另一个对象(我碰巧是内联创建的)。

对于您(OP)提供的示例,我的 hospitals 示例最接近完全匹配。除了使用规范名称字符串 + 函数之外,我不知道有什么方法可以自动神奇地创建对象层次结构。

function create(canonicalPropertyName, value, root) {
    root = (root || {});
    var names = canonicalPropertyName.split(".");
    var current = root;

    for (var i = 0; i < names.length; i++) {
        /* Ensure the property exists */
        current[names[i]] = (current[names[i]] || (i < names.length - 1 ? {} : []));

        /* We're recursing down the object tree */
        current = current[names[i]];
    }

    return root;
}

var hospitals = create("sectors.doctors", []);
hospitals.sectors.doctors[ 0 ] = {};
hospitals.sectors.doctors[ 0 ].age = 32;
console.log(hospitals);

var hospitals2 = create("sectors.doctors", [], undefined);
hospitals2.sectors.doctors[ 0 ] = {};
hospitals2.sectors.doctors[ 0 ].age = 32;
console.log(hospitals2);

var hospitals3 = create("sectors.doctors", [], { name: "City Hospital" });
hospitals3.sectors.doctors[ 0 ] = {};
hospitals3.sectors.doctors[ 0 ].age = 32;
console.log(hospitals3);

许多框架都有一个 namespace() method/function 可以帮助您实现您想要的。

示例:

Ext.ns('hospitals.sectors.doctors') = [];
var doctors = Ext.ns('hospitals.sectors.doctors');
doctors[0] = {
    age : 32
};

我自己不喜欢这种模式,因为它增加了不必要的依赖和工作。