Javascript jQuery插件-深度选项修改
我目前正在开发一个带有设置变量的插件,该变量相当深(有些地方有3-4个级别)。遵循普遍接受的jQuery插件模式,我为用户实现了一种简单的方法,使用以下符号动态修改设置:Javascript jQuery插件-深度选项修改,javascript,jquery,jquery-plugins,javascript-objects,Javascript,Jquery,Jquery Plugins,Javascript Objects,我目前正在开发一个带有设置变量的插件,该变量相当深(有些地方有3-4个级别)。遵循普遍接受的jQuery插件模式,我为用户实现了一种简单的方法,使用以下符号动态修改设置: $('#element').plugin('option', 'option_name', 'new_value'); $('#element').plugin('option', 'another', { deep: false }); 下面是与我现在使用的options方法类似的代码 option: function
$('#element').plugin('option', 'option_name', 'new_value');
$('#element').plugin('option', 'another', { deep: false });
下面是与我现在使用的options方法类似的代码
option: function (option, value) {
if (typeof (option) === 'string') {
if (value === undefined) return settings[option];
if(typeof(value) === 'object')
$.extend(true, settings[option], value);
else
settings[option] = value;
}
return this;
}
现在考虑一下我有一个设置变量,比如SO:
var settings = {
opt: false,
another: {
deep: true
}
};
如果我想更改deep
设置,我必须使用以下符号:
$('#element').plugin('option', 'option_name', 'new_value');
$('#element').plugin('option', 'another', { deep: false });
然而,由于在实践中,我的设置可以是3-4级,我觉得以下符号更有用:
$('#element').plugin('option', 'another.deep', false);
然而,我不确定这有多可行,也不知道如何着手去做。作为第一次尝试,我尝试“遍历”到有问题的选项并对其进行设置,但如果我设置遍历变量,则不会设置它在原始设置变量中引用的内容
option: function (option, value) {
if (typeof (option) === 'string') {
if (value === undefined) return settings[option];
var levels = option.split('.'),
opt = settings[levels[0]];
for(var i = 1; i < levels.length; ++i)
opt = opt[levels[i]];
if(typeof(value) === 'object')
$.extend(true, opt, value);
else
opt = value;
}
return this;
}
但我真的很想看看是否有人能告诉我一种不使用eval的方法。因为它是一个用户输入字符串,所以我不希望对它运行
eval()
,因为它可以是任何东西。或者让我知道我是否有妄想症,这应该不会引起任何问题。使用eval而不是遍历怎么样
var settings = {
opt: false,
another: {
deep: true,
}
};
var x = "settings.another";
eval(x).deep = false;
alert(settings.another.deep);
内置jQuery
$().extend()
是否正是您所需要的
*请注意,第二个方法签名的第一个参数为
true
执行深度合并…您在这里遇到的问题归结为指向对象的变量和其他类型(如字符串)的变量之间的差异2个变量可以指向相同的对象
,但不能指向相同的字符串
:
var a = { foo: 'bar' };
var b = 'bar';
var a2 = a;
var b2 = b;
a2.foo = 'hello world';
b2 = 'hello world';
console.log(a.foo); // 'hello world'
console.log(b); // 'bar'
在循环的最后一次迭代之前,遍历代码一直运行良好,此时opt
是一个变量,它包含与对象settings.opt.other
中的deep
相同的值。相反,缩短循环,使用levels
的最后一个元素作为键,如
var settings = {
another: {
deep: true
}
};
var levels = 'another.deep'.split('.')
, opt = settings;
// leave the last element
var i = levels.length-1;
while(i--){
opt = opt[levels.shift()];
}
// save the last element in the array and use it as a key
var k = levels.shift();
opt[k] = 'foobar'; // settings.another.deep is also 'foobar'
在此阶段,opt
是指向与设置相同的对象的指针。另一个和k
是一个字符串,其值为'deep'
,我试图避免在用户输入字符串上使用eval
,因为以这种方式使用它会使我的插件接受注入的javascript…无论如何,浏览器端没有安全性。用户可以运行他们想要的任何js并发送任何查询。是的,但这意味着他必须使用他希望在这里替换的语法。目标是在函数的字符串参数中使用点符号访问这些变量。正如Daniel所说,如果用户传递对象,我将使用extend方法,但是他们必须传递对象以进行深度设置。我也在尝试允许他们选择字符串。太棒了,引用上的混乱是问题的症结所在。谢谢你帮我澄清;多亏了你的回答,我现在有了一个工作方法。