Подтвердить что ты не робот

Что такое использование реального мира для функции .toString() в javascript?

Я заметил в javascript, что если вы определите функцию, скажем myfunction(), а затем вызовите myfunction.toString(), вы получите текст источника для этой функции. Есть ли какое-нибудь интересное/реальное использование этого?

4b9b3361

Ответ 1

Ну, вы можете использовать его, чтобы легко переопределить функцию:

function x() { alert('asdf'); }
eval(x.toString().replace('asdf','hello'));
x();

Это будет предупреждать строку "привет" вместо строки "asdf".

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

Ответ 2

Это старый вопрос, но вот мои 2 цента.

Используя node.js, это становится полезным для создания функций на сервере, которые затем встраиваются в страницу и отправляются клиенту.

Например, механизм шаблонов dot.js работает, сначала компилируя шаблоны в функцию, которые затем могут быть выполнены для генерации HTML-кода.

например:

var compiled = dot.compile("<h1>{{=it.header}}</h1>");
var html_output = compiled({header: "hello world"});

Итак, если мы хотим использовать шаблоны в клиенте, не имея каждого клиента, который должен сначала скомпилировать их, мы можем предоставить им страницу, содержащую оцененный результат:

"var compiled = " + dot.compile("<h1>{{=it.header}}</h1>").toString();

который затем предоставит "скомпилированную" функцию на стороне клиента, для использования компиляции данных, таких как отправленные из ajax-запросов на клиентскую сторону HTML.

Ответ 3

Я использовал его для автоматического создания именованных версий функций. Например, если у вас есть функция

function f(a, b, c) {
    return a * b + c;
}

вы можете извлечь имена параметров из f.toString() и использовать его для генерации функции, которую вы можете вызвать следующим образом:

namedParametersF({ a: 2, b: 3, c: 4}); // f(2, 3, 4);

Вот реализация этой идеи:

// Get an array of parameter names from a function
Function.parameters = function(f) {
    // Find the parameter list in f.toString()
    var m = /function[^\(]*\(([^\)]*)\)/.exec(f.toString());
    if (!m) {
        throw new TypeError("Invalid function in parameters");
    }

    var params = m[1].split(',');
    for (var i = 0; i < params.length; i++) {
        // trim possible spaces
        params[i] = params[i].replace(/^\s*|\s*$/g, '');
    }
    return params;
};

// Convert f to a function that accepts named parameters
Function.withNamedParameters = function(f) {
    var params = Function.parameters(f);
    return function(args) {
        var argsArray = new Array(params.length);
        for (var i = 0; i < params.length; i++) {
            argsArray[i] = args[params[i]];
        }
        return f.apply(this, argsArray);
    };
};

У меня есть немного более гибкая реализация этого, которая может идти в другом направлении (Function.withPositionalParameters) на GitHub: http://gist.github.com/132782.

Ответ 4

Я думаю, что это по существу используется для целей отладки...

Ответ 5

Разрабатывая идею поднятую выше Джеймсом Вестгейтом, здесь приведен пример использования toString() для создания, отправки и получения веб-рабочего:

/*
 * @param fun the function to carry out in the web worker
 * @param mes the message to send to the web worker
 * @param com the function to do on completion
 * creates, dispatches & receives a web worker
 */
function wor(fun, mes, com) {
   var wor = new Worker(URL.createObjectURL(new Blob([
         'self.onmessage = ' + fun.toString()], {
         type: 'application/javascript'
   })));       
   wor.postMessage(mes);
   wor.onmessage = com;
}

Перевернув функцию в строку, мы можем использовать ее для создания функции в URL-адресе объекта, которая затем анализируется и выполняется при приеме данных.

Ответ 6

Один реальный пример представлен в Prototype, который использует это, чтобы определить имена аргументов методам в подклассах, чтобы увидеть если он должен сделать свой специальный суперкласс, обрабатывающий материал (который включает специальный аргумент $super).

Ответ 7

Angular JS использует этот шаблон, чтобы внедрить его встроенные службы. Все, что вам нужно сделать, это использовать имя службы (с префиксом "$" ) в качестве параметра вашей функции - например: "$ http".

См. точное использование в Github.

Ответ 8

Многострочные строки в источнике Javascript.

Как описано в этом сообщении в блоге от @tjanczuk, одним из массивных неудобств в Javascript является многострочная строка. Но вы можете использовать .toString() и синтаксис для многострочных комментариев (/* ... */) для получения тех же результатов.

Используя следующую функцию:

function uncomment(fn){
  return fn.toString().split(/\/\*\n|\n\*\//g).slice(1,-1).join();
};

... вы можете передать многострочные комментарии в следующем формате:

var superString = uncomment(function(){/*
String line 1
String line 2
String line 3
*/});

В оригинальной статье было отмечено, что поведение Function.toString() не стандартизировано и, следовательно, является дискретным по реализации, и рекомендуемое использование было для Node.js(где можно использовать интерпретатор V8); однако сценарий, который я написал, кажется, работает на каждом доступном мне обозревателе (Chrome 27, Firefox 21, Opera 12, Internet Explorer 8).

Ответ 9

Определения представления CouchDb принимают их map и reduce как строки. С помощью function.toString вы можете записать эти функции в качестве правильных функций (поэтому может помочь вам проверка IDE/синтаксиса), а затем конвертируйте их в строки при их вставке.

Ответ 10

Я считаю, что Visual Studio Intellisense использует это для поиска и анализа необязательных комментариев кодов XML для любых таких документированных функций, например ниже:

function areaFunction(radiusParam)
{
    /// <summary>Determines the area of a cicle based on a radius parameter.</summary>
    /// <param name="radius" type="Number">The radius of the circle.</param>
    /// <returns type="Number">Returns a number that represents the area.</returns>
    var areaVal;
    areaVal = Math.PI * radiusParam * radiusParam;
    return areaVal;
}

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

Ответ 11

В многооконных веб-приложениях, если вам нужно разделить функцию между окнами, которые будут выполняться позднее, но не может гарантировать, что владелец этой функции (окно, в котором она была определена) будет жива в время выполнения, вы можете сериализовать функцию с помощью toString(), сохранить ее в соответствующем окне и вызвать eval() на ней позже или в момент выполнения. Конечно, использование eval() имеет свои бородавки, но это похоже на законный прецедент (нам нужно повторно запустить механизм синтаксического анализа script, чтобы превратить сериализованную функцию обратно в исполняемый код).

Это единственный надежный способ не получить отказ в доступе к ошибкам в этом сценарии. В результате здесь используется контекст выполнения, теперь это окно, из которого мы вызываем eval(), а не область, из которой первоначально была определена функция, поэтому следует проявлять осторожность, чтобы не полагаться на переменные за пределами функции немедленной области действия.

Ответ 12

помимо полезности получения содержимого функции в виде строки или обеспечения того, что тип того, что вы работаете, является строкой (для не принудительных сравнений), проверьте необязательный параметр radix, который можно использовать.

radix Дополнительно. Определяет радиус для преобразования числовых значений в строки. Это значение используется только для чисел.

var a = 16;
a.toString(2)    // returns "10000"
a.toString(4)    // returns "100"
a.toString(8)    // returns "20"
a.toString(16)   // returns "10"
a.toString(32)   // returns "g"

Следующий пример иллюстрирует использование метода toString с аргументом radix. Возвращаемое значение функции, показанное ниже, представляет собой таблицу преобразования Radix.

function CreateRadixTable (){
   var s, s1, s2, s3, x;                    //Declare variables.
   s = "Hex    Dec   Bin \n";               //Create table heading.
   for (x = 0; x < 16; x++)                 //Establish size of table
   {                                        // in terms of number of
      switch(x)                             // values shown.
      {                                     //Set intercolumn spacing.
         case 0 : 
            s1 = "      ";
            s2 = "    ";
            s3 = "   ";
            break;
         case 1 :
            s1 = "      ";
            s2 = "    ";
            s3 = "   ";
            break;
         case 2 :
            s3 = "  ";
            break;
         case 3 : 
            s3 = "  ";
            break;
         case 4 : 
            s3 = " ";
            break;
         case 5 :
            s3 = " ";
            break;
         case 6 : 
            s3 = " ";
            break;
         case 7 : 
            s3 = " ";
            break;
         case 8 :
            s3 = "" ;
            break;
         case 9 :
            s3 = "";
            break;
         default: 
            s1 = "     ";
            s2 = "";
            s3 = "    ";
      }                                     //Convert to hex, decimal & binary.
      s += " " + x.toString(16) + s1 + x.toString(10)
      s +=  s2 + s3 + x.toString(2)+ "\n";

   }
   return(s);                               //Return entire radix table.
}

Ответ 13

Может использоваться как способ кодирования веб-рабочих без необходимости размещения функций в отдельных файлах.

Ответ 14

Вы можете использовать строение функции для включения функции в сгенерированную страницу с подсветкой синтаксиса функции в источнике. Я тоже это сделал с CoffeeScript, с функцией, написанной и выделенной как CoffeeScript, но рассматриваемой как функция JavaScript, так как она... одна. Или, поскольку он скомпилирован в один, когда компиляция остальной части CoffeeScript.

См. это в github:

        error_handling = ->
            d = document.createElement "div"
            d.className = "error bubble script-error"
            window.onerror = (error)->
                document.body.appendChild d
                d.style.position = "absolute"
                d.style.borderRadius = d.style.padding = 
                d.style.bottom = d.style.right = "5px"
                d.innerText = d.textContent = error

        body += """
            <script>~#{error_handling}()</script>
            <style>
                .error {
                    color: red;
                }
                .error.bubble {
                    background: rgba(255, 0, 0, 0.8);
                    color: white;
                }
                body {
                    font-family: Helvetica, sans-serif;
                }
            </style>
        """

Ответ 15

assert arg не null

exports.warnNull = function() {
  var func = arguments.callee.caller
  var args = func.toString().match(/function\s*\w*\((.*?)\)\s*/)[1].split(',').map(Function.prototype.call.bind(String.prototype.trim))
  var params = Array.prototype.slice.call(arguments)
  for (var i = 0; i < params.length; i ++) {
    if (!params[i]) {
      console.warn(gutil.colors.yellow('缺少变量 : ' + args[i]))
    }
  }
}

wrap long Строка

exports.controller = function(){
/*
app.controller('{{ controllerName }}', function({{ injects }}) {
  // ...
})
*/
}.toString().slice(16, -4)