设置其子项的值时创建父对象

时间:2016-06-15 14:16:05

标签: javascript php angularjs

我使用AngularJS,我有一个名为storage的工厂,用于在控制器和指令之间共享一些数据。

ell.on('contextmenu', function(event){
    scope.$apply(function(){
        event.preventDefault();
        storage.contextmenu.isOpen = true;
        storage.contextmenu.top     = 100;
        storage.contextmenu.left    = 200;
    });
});

问题是,第一次上下文菜单未定义。但我不想在这里设置,因为contextmenu可能有其他属性,并且他们有参考。

是的,我知道,如果我使用if语句,我可以解决这个问题:

ell.on('contextmenu', function(event){
    scope.$apply(function(){
        event.preventDefault();

        if(typeof storage.contextmenu == 'undefined'){
            storage.contextmenu = {}
        }

        storage.contextmenu.isOpen = true;
        storage.contextmenu.top     = 100;
        storage.contextmenu.left    = 200;
    });
});

但我想知道是否有一个getter重载解决方案来默认执行此操作。因此,当我第一次设置isOpen的值并且contextmenu未定义时,而不是js抛出错误,它将contextmenu设置为一个对象并将isOpen设置为true?

在php __get()函数中做了魔术,在js中有些相同吗?

1 个答案:

答案 0 :(得分:0)

您可以使用有角度的$parse

$parse('contextmenu.isOpen').assign(storage, true);
$parse('contextmenu.top').assign(storage, 100);

或者,如果你已经变态,我至少知道两种方式

1)用Proxy(牺牲表现和browser support)来做:

here test example

function pathBuilder(src, path) {
    path = path || [];
    src = src || {};
    return new Proxy(src, {
        get: function (target, name) {
            function isenum(name) {// is property enumerable, including inherited props
                for (var n in src) {
                    if (n === name) return true;
                }
                return false;
            }

            var val;
            if (isenum(name)) {
                val = ({}).valueOf.call(src[name]); // converting primitive type to object
            }
            else if (!(name in src)) {
                val = {};
            }
            else {
                return src[name];
            }
            path.push({
                obj: src,
                prop: name
            });
            return pathBuilder(val, path);
        },
        set: function (target, name, val) {
            src[name] = val;
            var p, current = src;
            while (path.length) {
                p = path.pop();
                p.obj[p.prop] = current;
                current = p.obj;
            }
        }
    });
}


var o1 = {};
var o2 = {someprop: 'sdasdasd'};
var p1 = pathBuilder(o1);
var p2 = pathBuilder(o2);

p1.a.b.c = 12;
console.log(o1);
console.log(JSON.stringify(o1)); // {"a":{"b":{"c":12}}}

p2.someprop.foo.bar = 'value';
console.log(o2); // someprop converts from primitive string to String object
                 // to perform assignment of foo property
console.log(p2.someprop.foo.bar);// "value"
console.log(JSON.stringify(o2)); // {"someprop":"sdasdasd"}

我做了回购https://github.com/forceuser/access-deep

2)制作自定义代码tranfromer(例如Babel插件),用条件分配替换所有代码(不支持动态属性)

例如:

obj.foo.bar = 1;

转换为:

(obj.foo = obj.foo || {})&&(obj.foo.bar = 1);