Техника локальных переменных Javascript - PullRequest
2 голосов
/ 23 января 2009

У меня простой вопрос, связанный с однострочным программированием. Первый пример:

function test(a)
{
   var b=a.toString();
   return b.replace("a","b");
}

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

function test(a)
{
   return (arguments[1]=a.toString()).doSomething().doSomethingMore(arguments[1]);
}

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

Вот более реальная проблема с проблемой сценария One-Line:

function (number,limiter)
{
return ((arguments[2] = number.toString().replace(
         new RegExp("(\\d+)(\\d{3})($|"+limiter+")"),
         '$1'+limiter+'$2$3')) == number) ?
            arguments[2] : 
            arguments.callee(arguments[2],limiter);
}

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

Ответы [ 6 ]

4 голосов
/ 23 января 2009

Ваш пример может чрезмерно усложнять простую операцию, но демонстрируемая вами техника называется методом «сцепления». Это совершенно правильная форма, и ее можно использовать для того, чтобы сделать код более читабельным, если промежуточные результаты не нужны или не имеют смысла.

Мой любимый пример этого - замечательный DateJs :

var nextTuesday = DateJs.today().next().tuesday();

var aBitLater = DateJs.now().addHours(1).addMinutes(30);

Конечно, это синтаксический сахар, и его можно было бы написать более многословно в виде отдельных выражений, но с осторожным наименованием метода вы можете заставить его читать как английский.

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

Ваш пример может быть немного надуманным, но если вы используете его там, где это имеет смысл, это полезный шаблон.

4 голосов
/ 23 января 2009

Вы без необходимости усложняете операцию. Вам не нужно ничего заявлять вообще.

function test(a) {
return a.toString().replace("a","b");
}

Это не должно сказываться на производительности или памяти.

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

Присвоение значения массиву arguments, как вы делаете, не имеет смысла, так как у каждой функции есть свой массив arguments. Чтобы ответить на ваш вопрос о сфере применения, Javascript scoping является лексическим; что-то, объявленное локально внутри функции, автоматически не доступно для вещей вне функции.

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

1 голос
/ 23 января 2009

«Во-первых, отладка вдвое сложнее, чем написание кода. Поэтому, если вы пишете код настолько умно, насколько это возможно, вы, по определению, недостаточно умны для его отладки». - Брайан В. Керниган

Я не стучу в тебя, я просто говорю, что будь осторожен, чтобы не переусердствовать.

0 голосов
/ 23 января 2009

~~ Дрожь ~~

Это напоминает мне awk, где нет способа иметь локальные переменные в функции, если вы не объявите дополнительные переменные в списке аргументов.

Если вам нужна локальная переменная, просто сделайте это.

0 голосов
/ 23 января 2009

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

Переменные - это просто ссылки на создаваемые вами объекты. Независимо от того, назначаете ли вы их обычной переменной или помещаете в массив, очистка будет одинаковой. Массив arguments и локальная переменная выйдут из области видимости, как только метод вернется, поэтому я не думаю, что вы увидите какую-либо разницу в поведении. (область действия массива arguments может отличаться, если метод вызывался с помощью команды apply (), но я не проверял это, чтобы быть уверенным).

0 голосов
/ 23 января 2009

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

return (arguments[1]=a.toString()).doSomething().doSomethingMore(arguments[1]);
// is this a or a.toString()? it's not clear at a glance -------------^
...