web-dev-qa-db-ja.com

JavaScript:渡された変数の引数値と名前を取得

私がやりたいのは、関数に渡される変数の名前を取得することですその変数の値、そして1つの変数だけを渡す必要があります関数。そう:

var x = "anything";

function showName() {

}

showName(x);

または

showName("x");

返される結果:「x =何でも」。

現在、変数を2回指定する必要があります。

showName("x", x);

私が渡す変数の名前と値を取得するために。

ShowNameのプロトタイプの引数の名前ではなく、呼び出し元の関数の変数の名前に興味があることに注意してください。また、渡された変数はローカルである可能性があるため、変数を見つけるためにウィンドウオブジェクトを使用できません。

46
Peleg

簡単な答えは、できないということです。

長くて邪悪な答えは、ある種の本当の意地悪さを伴う缶です。また、別の関数から呼び出された場合にのみ機能します。

役立つ2つの興味深い属性があります。

arguments.callee呼び出し元

fnが次のようなことをする場合:

(function(){
  var showMe = function(s){
    alert(arguments.callee.caller.toString().match(/showMe\((\S)\)/)[1] + 
    ' = '+ s)
  }
  x = 1
  showMe(x)
})()

Arguments.callee.caller.toString()。match(..)[1]は、呼び出し元の関数で呼び出されているshowMeを探し、その値と値を出力します。

しかし、showMe(x)の最初の呼び出しにしかヒットしないため、これはまだかなり制限されています。そのため、2つの呼び出しがある場合、機能しません。

しかし、これらの不可解なもので遊ぶのは楽しかったです。

59
BaroqueBobcat
var x = "anything";

function showName(s) {
    alert(s + " = " + eval(s));
}

showName("x");

推奨されていませんが、あります。

8
RedFilter

戦略1:

関数の呼び出し中にデータ構造を制御できる場合は、名前と値を組み合わせてキーとして名前をエンコードする辞書を渡すことができます。ステルス中括弧に注意してください。

var foo = "bar";
yourfunction({foo});

次のようなJavaScriptディクショナリを渡します。

{foo : "bar"}

いつ yourfunction(が実行され、名前と値が次のようにアンパックされます。

yourfunction = function(dict) { 
    var name = Object.keys(dict)[0];
    var value = dict[name];
    console.log(name);        //prints foo
    console.log(value);       //prints bar
}

戦略2:

グローバルスコープで名前と値のペアのそのままのリストを維持できる場合は、リフレクションとイントロスペクションを設定および取得に常に使用できます。次に例を示します。

var my_global_stack = [];

yourfunction = function() { 

    //Chomp the stack
    var dict = my_global_stack.pop();

    //The name is the key at index 0
    var name = Object.keys(dict)[0];

    //Fetch the value by keyname:
    var value = dict[name];

    console.log(name);       //prints foo
    console.log(value);      //prints bar
}


foo = "bar";
my_global_stack.Push({foo});
yourfunction();

戦略3:

ユーザーの敵対的な入力が問題にならない場合は、eval(は、指定された変数名の値を再検出します。次に例を示します。

yourfunction = function(somevariable) { 
    console.log(somevariable);          //prints foo
    console.log(eval(somevariable));    //prints bar
}

foo = "bar";
yourfunction("foo");

人々は言います eval(は、悪意のあるユーザーがメモリ内のfooの値をいつでも上書きできる場合、OSコマンドインジェクションを実行し、必要なコマンドを実行できるため、悪意があります。
http://cwe.mitre.org/top25/#Guidance

6
Peleg

ハッシュを作成して渡すことができます:

var x = {a: 1,b:2}
function showVars(y) {
    for (var z in y) { alert(z + " is " + y[z]); }
}
showVars(x);

これは必ずしも変数の名前を表示するわけではありませんが、キーと値のペアを許可します。

2
DGM

これは、デバッグに使用するものです。グローバル変数、eval、arguments.callee、arguments.callerはありません:

_var Helpers = (function () {
    // ECMAScript 5 strict mode
    'use strict';

    var Module = {};

    Module.debug = function () {
        var i;

        for (i = 0; i < arguments.length; i++) {
            console.log(arguments[i] + ':', this[arguments[i]]);
        }
    };

    Module.SomeObject = function SomeObject() {
        this.someMember = 1;
        this.anotherMember = 'Whatever';

        Module.debug.call(this, 'someMember', 'anotherMember');

        var privateMember = {
            name: 'Rip Steakface',
            battleCry: 'Raaaaaaaaahhhhhhhhhrrrrrrrrrg!'
        };

        Module.debug.call(privateMember, 'name', 'battleCry');
    };

    return Module;
}());
_

なぜこれをしたいのか疑問に思っている人にとっては、複数の変数とその名前を効率的に記録する方法にすぎません。

Module.debug.call(obj, 'hair.fluffiness')のように、ネストされたメンバーをログに記録したい場合は、次のように関数を変更できます。

_Module.debug = function () {
    var i, j, props, tmp;

    for (i = 0; i < arguments.length; i++) {
        tmp = this;
        props = arguments[i].split('.');

        for (j = 0; j < props.length; j++) {
            tmp = tmp[props[j]];
        }

        console.log(arguments[i] + ':', tmp);
    }
};
_

残念ながら、オブジェクトのメンバーではない複数のプライベート変数を効率的にログに記録する方法は見つかりません。 var roll = 3, value = 4; Module.debug.call(???);

2
David Kennedy

直接 JavaScriptから必要なものを取得できるかどうかわからない実行時)。

あなたはcanですが、ちょっとしたことをしますdifferent名前付き引数を渡すことができます。匿名オブジェクトを作成し、関数に渡します:

function showNames(o)
{
    for( var ix in o )
    {
       alert( ix + ":" + o[ix] );
    }
}

var z = { x : "Anything" }
showNames( z );
// or
showNames( { a : "ay", b : "bee", c: "see" } )

オブジェクトのプロパティを反復するには、次のような機能スタイルを好む傾向があります。

Array.iteri = function(o, f)
{
    for(var i in o) { f(i, o[i]) }
}

function showNames(o)
{
    Array.iteri( o, function(i,v)
    {
        alert( i + ": " + v )
    });
}
showNames( { a : "ay", b : "bee", c: "see" } )
1
James Hugard

以下のコードは、できる限り最善の方法です。残念ながら、関数内のローカル変数は非表示のCallオブジェクトのプロパティなので、aがウィンドウオブジェクトのプロパティであるwindow [a]のようなJavascriptからはアクセスできません。

x = "this is x";
var say = function(a) {
    document.write(a + " = " + window[a]);
}
say("x");

var wrapper = function () {
    var x = "this is x";
    document.write(x + " = " + eval("x"))
}
wrapper()
1
Anon