我使用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中有些相同吗?
答案 0 :(得分:0)
您可以使用有角度的$parse
$parse('contextmenu.isOpen').assign(storage, true);
$parse('contextmenu.top').assign(storage, 100);
或者,如果你已经变态,我至少知道两种方式
1)用Proxy(牺牲表现和browser support)来做:
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);