Javascript 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

我目前正在开发一个带有设置变量的插件,该变量相当深(有些地方有3-4个级别)。遵循普遍接受的jQuery插件模式,我为用户实现了一种简单的方法,使用以下符号动态修改设置:

$('#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方法,但是他们必须传递对象以进行深度设置。我也在尝试允许他们选择字符串。太棒了,引用上的混乱是问题的症结所在。谢谢你帮我澄清;多亏了你的回答,我现在有了一个工作方法。