不使用eval,通过字符串名访问带名称空间的javascript对象
我遇到了需要从服务器访问javascript对象的情况。服务器返回函数或对象的字符串名,根据其他元数据,我将对对象进行不同的计算 最初我在评估(不使用eval,通过字符串名访问带名称空间的javascript对象,javascript,namespaces,eval,Javascript,Namespaces,Eval,我遇到了需要从服务器访问javascript对象的情况。服务器返回函数或对象的字符串名,根据其他元数据,我将对对象进行不同的计算 最初我在评估(eval([string])),一切都很好。最近,为了安全起见,我更新了函数,使其不使用eval,并且遇到了名称空间对象/函数的问题 具体来说,我尝试用窗口[name]替换eval([name]),以通过方括号语法从全局对象vseval访问对象 但我遇到了名称空间对象的问题,例如: var strObjName = 'namespace.serviceA
eval([string])
),一切都很好。最近,为了安全起见,我更新了函数,使其不使用eval
,并且遇到了名称空间对象/函数的问题
具体来说,我尝试用窗口[name]
替换eval([name])
,以通过方括号语法从全局对象vseval
访问对象
但我遇到了名称空间对象的问题,例如:
var strObjName = 'namespace.serviceArea.function';
// if I do
var obj = eval(strObjName); // works
// but if I do
var obj = window[strObjName]; // doesn't work
有谁能想出一个好的解决方案来避免使用
eval
和命名空间字符串吗?您可以在
上拆分并依次解析每个属性。只要字符串中的任何属性名称都不包含
字符,就可以:
var strObjName = 'namespace.serviceArea.function';
var parts = strObjName.split(".");
for (var i = 0, len = parts.length, obj = window; i < len; ++i) {
obj = obj[parts[i]];
}
alert(obj);
var strObjName='namespace.serviceArea.function';
var parts=strObjName.split(“.”);
对于(变量i=0,len=parts.length,obj=window;i
我想到了这个:
function reval(str){
var str=str.split("."),obj=window;
for(var z=0;z<str.length;z++){
obj=obj[str[z]];
}
return obj;
}
eval("window.this.that");
reval("this.that"); //would return the object
reval("this.that")(); //Would execute
函数reval(str){
var str=str.split(“.”),obj=window;
对于(var z=0;z,以下假设strObjName
的各部分由
分隔,并从窗口开始循环,直到到达所需的函数:
var strObjParts = strObjName.split('.');
var obj = window;
for(var i in strObjParts) {
obj = obj[strObjParts[i]];
}
我知道这个问题已经得到了询问者满意的回答,但是我最近遇到了这个问题,但是关于写入值。我提出了自己的静态类来处理基于字符串路径的读写操作。默认路径分隔符是
,但您可以将其修改为任何内容,例如/
。代码也被注释如果你想知道它是如何工作的
(function(){
var o = {}, c = window.Configure = {}, seperator = '.';
c.write = function(p, d)
{
// Split the path to an array and assaign the object
// to a local variable
var ps = p.split(seperator), co = o;
// Iterate over the paths, skipping the last one
for(var i = 0; i < ps.length - 1; i++)
{
// Grab the next path's value, creating an empty
// object if it does not exist
co = (co[ps[i]])? co[ps[i]] : co[ps[i]] = {};
}
// Assign the value to the object's last path
co[ps[ps.length - 1]] = d;
}
c.read = function(p)
{
var ps = p.split(seperator), co = o;
for(var i = 0; i < ps.length; i++)
{
co = (co[ps[i]])? co[ps[i]] : co[ps[i]] = {};
}
return co;
}
})();
(函数(){
var o={},c=window.Configure={},separator=';
c、 写入=函数(p,d)
{
//将路径拆分为数组并重新指定对象
//到局部变量
var ps=p.分离(分离器),co=o;
//在路径上迭代,跳过最后一个路径
对于(变量i=0;i
我编写了一个不同的解决方案,使用递归。我使用它来命名输入元素的name属性。例如,以下内容:
<input type="number" name="testGroup.person.age" />
因此,这里的目标是自动将输入元素中的值放入数据结构中的正确位置
我编写了这个小函数,用于根据传递给它的任何名称空间数组创建嵌套对象:
var buildObject = function ( obj, namespaceArray, pos ) {
var output = {};
output[namespaceArray[pos]] = obj;
if ( pos > 0 ) {
output = buildObject(output, namespaceArray, pos-1);
}
return output;
};
它是如何工作的?它从namespaceArray
数组的末尾开始,创建一个具有一个属性的对象,该属性的名称是namespaceArray
中最后一个插槽中的名称,其值是obj
。然后它递归,将该对象包装在其他对象中,直到用完为止namespaceArray
pos
中的名称是namespaceArray
数组的长度。您可以在第一个函数调用中计算出来,类似于if(typeof(pos)==“undefined”)pos=namespaceArray.length-1
,但是每次函数递归时都会有一个额外的语句进行求值
首先,我们将input
的name
属性拆分为一个围绕名称空间分隔符的数组,并获取输入的值:
var namespaceArray = inputElement.name.split("."),
obj = inputElement.value;
// Usually you'll want to do some undefined checks and whatnot as well
然后我们只需调用函数并将结果赋给某个变量:
var myObj = buildObject(obj, namespaceArray, namespaceArray.length - 1);
myObj现在看起来像这样:
{
testGroup: {
person: {
age: 25
}
}
}
此时,我使用jQuery的extend函数将该结构合并回原始数据对象:
data = $.extend(true, data, myObj);
然而,在无框架的JavaScript中合并两个对象并不是很困难,有很多方法可以很好地完成这项工作
我确信有更有效的方法来实现这一点,但这种方法很好地满足了我的需要。我的pastebin示例:
我喜欢你的代码,我用PHP做了很多类似的事情。
但在这里我觉得很难。。。
所以我使用了答案@LordZardeck()和@Alnitak()
这就是我所拥有的,只要使用它:
var someObject = {
'part1' : {
'name': 'Part 1',
'size': '20',
'qty' : '50'
},
'part2' : {
'name': 'Part 2',
'size': '15',
'qty' : '60'
},
'part3' : [
{
'name': 'Part 3A РУКУ!!!',
'size': '10',
'qty' : '20'
}, {
'name': 'Part 3B',
'size': '5',
'qty' : '20'
}, {
'name': 'Part 3C',
'size': '7.5',
'qty' : '20'
}
]
};
//var o = {}, c = window.Configure = {}, seperator = '.';
var c = function(){
this.o = {};
this.seperator = ".";
this.set = function(obj){
this.o = obj;
}
this.write = function(p, d) {
p = p.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
p = p.replace(/^\./, ''); // strip leading dot
// Split the path to an array and assaign the object
// to a local variable
var ps = p.split(this.seperator), co = this.o;
// Iterate over the paths, skipping the last one
for(var i = 0; i < ps.length - 1; i++)
{
// Grab the next path's value, creating an empty
// object if it does not exist
co = (co[ps[i]])? co[ps[i]] : co[ps[i]] = {};
}
// Assign the value to the object's last path
co[ps[ps.length - 1]] = d;
}
this.read = function(p) {
p = p.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
p = p.replace(/^\./, ''); // strip leading dot
var ps = p.split(this.seperator), co = this.o;
/*
for(var i = 0; i < ps.length; i++)
{
co = (co[ps[i]])? co[ps[i]] : co[ps[i]] = {};
}
*/
while (ps.length) {
var n = ps.shift();
if (n in co) {
co = co[n];
} else {
return;
}
}
return co;
}
};
var n = new c();
n.set(someObject);
console.log('whas');
console.log('n.read part.name', n.read('part1.name'));
n.write('part3[0].name', "custom var");
console.log('part1.name now changed');
n.write('part1.name', "tmp");
console.log('n.read part.name', n.read('part1.name'));
console.log('----');
console.log('before', someObject);
console.log('someObject.part1.name', someObject.part1.name);
console.log('someObject.part3[0].name', someObject.part3[0].name);
var someObject={
第一部分:{
“名称”:“第1部分”,
“大小”:“20”,
“数量”:“50”
},
第二部分:{
“名称”:“第2部分”,
“大小”:“15”,
“数量”:“60”
},
第三部分:[
{
“名称”:“第3A部分БУУУУ!!!”,
“大小”:“10”,
“数量”:“20”
}, {
“名称”:“第3B部分”,
“大小”:“5”,
“数量”:“20”
}, {
“名称”:“第3C部分”,
“大小”:“7.5”,
“数量”:“20”
}
]
};
//var o={},c=window.Configure={},separator=';
var c=函数(){
this.o={};
此.separator=“.”;
this.set=函数(obj){
这个。o=obj;
}
this.write=函数(p,d){
p=p.replace(/\[(\w+)\]/g,.$1');//将索引转换为属性
p=p.replace(/^\./,'');//带前导点
//将路径拆分为数组并重新指定对象
//到局部变量
var ps=p.split(本公司)
var someObject = {
'part1' : {
'name': 'Part 1',
'size': '20',
'qty' : '50'
},
'part2' : {
'name': 'Part 2',
'size': '15',
'qty' : '60'
},
'part3' : [
{
'name': 'Part 3A РУКУ!!!',
'size': '10',
'qty' : '20'
}, {
'name': 'Part 3B',
'size': '5',
'qty' : '20'
}, {
'name': 'Part 3C',
'size': '7.5',
'qty' : '20'
}
]
};
//var o = {}, c = window.Configure = {}, seperator = '.';
var c = function(){
this.o = {};
this.seperator = ".";
this.set = function(obj){
this.o = obj;
}
this.write = function(p, d) {
p = p.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
p = p.replace(/^\./, ''); // strip leading dot
// Split the path to an array and assaign the object
// to a local variable
var ps = p.split(this.seperator), co = this.o;
// Iterate over the paths, skipping the last one
for(var i = 0; i < ps.length - 1; i++)
{
// Grab the next path's value, creating an empty
// object if it does not exist
co = (co[ps[i]])? co[ps[i]] : co[ps[i]] = {};
}
// Assign the value to the object's last path
co[ps[ps.length - 1]] = d;
}
this.read = function(p) {
p = p.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
p = p.replace(/^\./, ''); // strip leading dot
var ps = p.split(this.seperator), co = this.o;
/*
for(var i = 0; i < ps.length; i++)
{
co = (co[ps[i]])? co[ps[i]] : co[ps[i]] = {};
}
*/
while (ps.length) {
var n = ps.shift();
if (n in co) {
co = co[n];
} else {
return;
}
}
return co;
}
};
var n = new c();
n.set(someObject);
console.log('whas');
console.log('n.read part.name', n.read('part1.name'));
n.write('part3[0].name', "custom var");
console.log('part1.name now changed');
n.write('part1.name', "tmp");
console.log('n.read part.name', n.read('part1.name'));
console.log('----');
console.log('before', someObject);
console.log('someObject.part1.name', someObject.part1.name);
console.log('someObject.part3[0].name', someObject.part3[0].name);
function getByNameSpace(namespace, obj) {
return namespace.split('.').reduce(function(a,b) {
if(typeof a == 'object') return a[b];
else return obj[a][b];
});
}
(function (s) {return s.split('.').reduce(function(p,n) { p[n] = p[n] || {}; return p[n];},window);})("some.cool.namespace");
window.ns = (function (s) {return s.split('.').reduce(function(p,n) { p[n] = p[n] || {}; return p[n];},window);})
ns("some.cool").namespace = 5;
if (5 != ns("some.cool.namespace")) { throw "This error can never happen" }