Вопрос по javascript – JavaScript: получить значение аргумента и имя пропущенной переменной [дубликат]

46

This question already has an answer here:

То, что я хочу сделать, это получить имя переменной, переданной функцииand ЗНАЧЕНИЕ этой переменной, и нужно передать только одну переменную в функцию. Так:

var x = "anything";

function showName() {

}

showName(x);

или же

showName("x");

Который вернется: "x = что-нибудь".

Прямо сейчас я должен указать переменную дважды:

showName("x", x);

Чтобы получить имя и значение переменной, которую я передаю.

Обратите внимание, что меня интересует не имя аргумента в прототипе showName, а имя переменной в вызывающей функции. Кроме того, передаваемая переменная может быть локальной, поэтому я не могу использовать объект окна, чтобы найти переменную.

stackoverflow.com/questions/1007981/… а такжеstackoverflow.com/questions/914968/… Paolo Bergantino
Если вы передаете словарь, как это:yourfunction({yourvariable});  затем встроенный словарь insta содержит пары ключ-значение, ключ - это имя, а значение - значение вашей переменной. Eric Leschinski

Ваш Ответ

7   ответов
2

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

Это не обязательно показывает имя переменной, но оно допускает пары ключ-значение, которые могут быть ближе к тому, что вам нужно.

это никогда не напечатает x = {a: 1, b: 2}, так что это не то, что нужно OP & quot;
@ally - я говорил концептуально, но большинство движков javascript (или могут) компилировать в промежуточный код для повышения производительности. AFAIK, только Chrome компилирует JavaScript прямо на ассемблере.
2

что я использую для отладки. Без глобальных переменных, без 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(???);

1

directly получите то, что вы хотите от 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" } )
@ally - я говорил концептуально, но большинство движков javascript (или могут) компилировать в промежуточный код для повышения производительности. AFAIK, только Chrome компилирует JavaScript прямо на ассемблере.
8
var x = "anything";

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

showName("x");

Не рекомендуется, но это так.

@BaroqueBobcat - вышеупомянутая функция прекрасно работает для меня. Если вы ищете граничные случаи, функция может быть легко изменена для строковой сортировки данных в зависимости от типа или значения. Например, пустой массив и пустая строка отображаются как пустые. Возможно, вы захотите обработать это по-другому или добавить дополнительную информацию о том, как лучше всего набирать текст. Цель этого примера не в том, чтобы быть пуленепробиваемым, а в том, чтобы продемонстрировать, что функция может получить как имя параметра, так и значение из одного скалярного параметра.
Как насчет х = 1; showName (x)?
1

что вы можете сделать. К сожалению, локальные переменные в функции являются свойствами скрытого объекта вызова, поэтому к ним нельзя получить доступ из Javascript, подобного window [a], где a является свойством объекта окна.

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()
57

Чем дольше, злой ответ, что вы можете с некоторой реальной мерзостью. И это работает только при вызове из другой функции.

Вам доступны два интересных атрибута, которые могут помочь

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). Поэтому, если к нему два вызова, он не сработает.

Но было весело играть с этими загадочными вещами.

+1, отвратительно и увлекательно.
Это будет ошибка в Firefox и Safari, когдаcaller являетсяnull
устарел с ECMAScript (ES5) :(
@Jhawins верно. Вероятно, есть обходной путь, если вы можете каким-то образом получить ссылку на строку источника.
5

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

Strategy 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();

Strategy 3:

Если пользовательский ввод не является проблемой, вы можете использоватьeval( чтобы восстановить значение заданного имени переменной, например:

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

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

Люди говорятeval( зло здесь, потому что если враждебный пользователь может перезаписать значениеfoo в любой момент в памяти, затем они могут выполнить инъекцию команд ОС и выполнить любую команду, какую захотят.
http://cwe.mitre.org/top25/#Guidance

Нет необходимости ни в ваших собственных глобальных переменных, ни в eval, как в моем ответе.

Похожие вопросы