jQuery插件 - 深度选项修改

时间:2011-12-07 17:58:32

标签: javascript jquery jquery-plugins javascript-objects

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

$('#element').plugin('option', 'option_name', 'new_value');

以下代码类似于我现在使用的选项方法。

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;
}

现在考虑我有一个像这样的设置变量:

var settings = {
    opt: false,
    another: {
        deep: true
    }
 };

如果我想更改deep设置,我必须使用以下表示法:

$('#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;
}

换句话说:通过在遍历后设置opt,在settings变量中实际引用的设置在此代码运行后保持不变。

我为长期问题道歉,任何帮助表示赞赏。谢谢!


修改

作为第二次尝试,我可以使用eval()这样做:

option: function (option, value) {
    if (typeof (option) === 'string') {
        var levels = option.split('.'),
            last = levels[levels.length - 1];

        levels.length -= 1;

        if (value === undefined) return eval('settings.' + levels.join('.'))[last];

        if(typeof(value) === 'object')
            $.extend(true, eval('settings.' + levels.join('.'))[last], value);
        else 
            eval('settings.' + levels.join('.'))[last] = value;
    }

    return this;
}

但我真的很想看看是否有人能告诉我使用eval的方法。由于它是用户输入字符串,我宁愿不在其上运行eval(),因为它可能是任何东西。或者让我知道,如果我是偏执狂,它应该不会引起任何问题。

3 个答案:

答案 0 :(得分:2)

您遇到的问题归结为指向对象的变量与其他类型(如字符串)的变量之间的差异。 2个变量可以指向相同的Object,但不能指向相同的String

  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是一个变量,在对象{{1}内包含与deep相同的 }}。相反,缩短你的循环并使用settings.opt.another的最后一个元素作为levels,如

key

在此阶段, 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相同的Object的指针,而settings.anotherk,其值为String < / p>

答案 1 :(得分:0)

如何使用eval而不是遍历?

var settings = {
opt: false,
   another: {
 deep: true,

   }
};

var x = "settings.another";
eval(x).deep = false;
alert(settings.another.deep);

答案 2 :(得分:0)

内置的jQuery $().extend()不完全是你需要的吗?

http://api.jquery.com/jQuery.extend/

*请注意第一个true的第一个方法签名执行深度合并...