jQuery插件-深度选项修改

jQuery Plugin - Deep option modification

本文关键字:选项 修改 深度 插件 jQuery      更新时间:2023-09-26

我目前正在工作的插件设置变量是相当深(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(),因为它可以是任何东西。或者让我知道我是否偏执,这应该不会引起任何问题。

您在这里遇到的问题归结为指向对象的变量和指向其他类型(如字符串)的变量之间的差异。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是一个变量,在对象settings.opt.another中包含与deep相同的。相反,缩短循环并使用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是指向与settings.another相同的Object的指针,k是值为'deep'

String

使用eval而不是遍历如何?

var settings = {
opt: false,
   another: {
 deep: true,
   }
};
var x = "settings.another";
eval(x).deep = false;
alert(settings.another.deep);

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

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

*注意true的第一个参数的第二个方法签名执行深度合并…