2011-12-07 17 views
6

私は現在かなり深い(いくつかの場所で3-4レベル)の設定​​変数でプラグインを使っています。一般的に受け入れられているjQueryのプラグインのパターンに続いて、私は、次の表記法を使用してその場で設定を変更するユーザーのための簡単な方法を実装している:jQuery Plugin - 深刻なオプションの変更

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

は、私はオプションの方法のために今使っているものと同様のコードです。しかし、

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

:私は、次の表記を使用する必要がdeep設定を変更したい場合は

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

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

は今、私はそうのような設定変数を持っていることを考えます実際には私の設定は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変数にを意味し、このコードの実行後に変更されていません。

私は長い質問をお詫び申し上げますが、どんな助けもありがとうございます。ありがとう!


EDIT

私はそうのような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

問題は、オブジェクトを指し示す変数間の差にダウンしています文字列のような他の型の変数。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が同じ値を含む変数であるその時点で、ループの最後の反復まで素晴らしい作品としてdeepオブジェクト内にsettings.opt.another。代わりに、短いあなたのループをカットし、この段階ではopt

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' 

のように、keyとしてlevelsの最後の要素を使用することはsettings.anotherと同じObjectへのポインタで、kは値'deep'

+0

幻想的で、そこにある参照の混乱は、問題を曇らしていたものでした。私のためにそれをクリアしてくれてありがとう。私はあなたの答えのおかげで働く方法を今持っている。 – Chad

0

トラバーサルではなくevalを使用するのはどうですか?

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

    } 
}; 

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

Stringです私はこの方法でそれを使用すると、私のプラグインが注入されたjavascriptを受け入れるようになるので、ユーザ入力文字列に 'eval'を使用することを避けようとしていました。 – Chad

+0

ブラウザ側にはセキュリティはありません。ユーザーは任意のjを実行して任意のクエリを送信できます。 –

0

組み込みのjQuery $().extend()は、あなたが必要とするものではないでしょうか?

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

* trueの最初のagumentが深いマージを実行して第二の方法署名を注意してください...あなたがここに実行している

+0

本当ですが、ここで置き換えたい構文を使用する必要があることを意味します。目標は、関数の文字列引数にドット表記で変数にアクセスすることです。 –

+0

Danielと同様に、ユーザーがオブジェクトを渡す場合はextendメソッドを使用していますが、詳細設定のためにオブジェクトを渡す必要があります。私は彼らにも文字列のオプションを許可しようとしています。 – Chad

関連する問題