JQuery plugin - change depth

I am currently working with a plugin with a parameter variable that is pretty deep (3-4 levels in some places). Following the generally accepted JQuery Plugin pattern, I have implemented an easy way for users to change settings on the fly using the following notation:

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

Here is code similar to what I'm using now for the options method.

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

Now consider that I have such a settings variable:

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

If I want to change the deep settings, I have to use the following notation:

 $('#element').plugin('option', 'another', { deep: false }); 

However, since in practice my settings can be 3-4 depth levels, I feel that the following notation will be more useful:

 $('#element').plugin('option', 'another.deep', false); 

However, I am not sure how much this is possible, and how to do it. As a first attempt, I tried to β€œcross” the corresponding option and set it, but if I set my move variable, it will not set what it refers to in the initial setting.

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

To say this in another way: setting opt after passing, the value that it actually refers to in the settings variable does not change after this code.

I apologize for the long question, any help is appreciated. Thanks!


EDIT

As a second attempt, I can do this with eval() as follows:

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

But I really would like to see if anyone can show me a way not to use eval. Since this is a user input line, I would prefer not to run eval() , because it could be anything. Or let me know if I'm paranoid and this should not cause problems at all.

+6
source share
3 answers

The problem you're working with comes down to the difference between variables pointing to objects and variables for other types, such as strings. 2 variables can point to the same Object , but not to the same 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' 

Your workaround code works fine until the last iteration of the loop, in which the opt point is a variable containing the same value as deep inside the settings.opt.another object. Instead, shorten the short loop and use the last levels element as key , e.g.

  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' 

At this point, opt is a pointer to the same Object as settings.another and k is a String with a value of 'deep'

+2
source

What about using eval rather than a workaround?

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

Will the built-in jQuery $().extend() not be what you need?

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

* note that the second method signature with the first true method performs deep merging ...

0
source

Source: https://habr.com/ru/post/903311/


All Articles