Несколько маленьких полезных приемов в JavaScript

22 февраля 2010, 13:10 Павел Марковнин JavaScript рейтинг +14-

Несколько маленьких полезных приемов в JavaScriptВсем привет!

Сегодня мы рассмотрим несколько полезных приемов при программировании на JavaScript. Эти приемы даже сниппетами назвать сложно, ведь некоторые из ни состоят из 2-3 символов, хотя некоторые разработчики (в том числе я сам ;-) часто используют вместо них намного более громоздкие конструкции.

Итак, поехали!

 

Конвертирование переменных

Как ни странно, но иногда для конвертирования переменных одного типа в другой используют конструкторы объектов типа Array() или Number(). На самом деле правильнее и лучше (с точки зрения производительности) использовать примитивные типы данных:

var myVar   = "3.14159",  
str = ""+ myVar,// в стринг (string)
int = ~~myVar, // в интеджер (integer)
float = 1*myVar, // во флоат (float)
bool = !!myVar, // в булен - все непустые строки и числа кроме 0 будут true
array = [myVar]; // в массив

Конвертирование в даты (new Date(myVar)) и регулярные выражения (new RegExp(myVar)) нужно делать с использованием конструкторов. Всегда используйте структуру /регулярное_выражение/флаги при создании регулярных выражений.

Конвертирование из десятичной в шестнадцатеричную и восьмеричную системы, и наоборот

Вы пишите отдельные функции для этого? На самом деле все преобразование можно сделать стандартными методами:

(int).toString(16);  // конвертирует десятичную (int) в шестнадцатеричную (hex): например, 12 => "C"
(int).toString(8); // конвертирует десятичную (int) в восьмеричную (octal): например, 12 => "14"
parseInt(string, 16) // конвертирует шестнадцатеричную (hex) в десятичную (int): например, "FF" => 255
parseInt(string, 8) // конвертирует восьмеричную (octal) в десятичную (int): например, "20" => 16

Замена всех вхождений подстроки в строку

Часто случается, что нужно заменить все вхождения какой-то строки в другую строку. Вместо громоздких конструкций лучше всего делать так:

var str = "foobarfoobar";
str.replace(/foo/g,"xxx");
// в итоге получиться str = "xxxbarxxxbar";

Еще несколько преобразований для числовых данных

В добавлении к предыдущим методам:

0xFF;                   // Объявление шестнадцатеричного, возвращает returns 255  
020; // Объявление восьмеричного, возвращает 16
1e3; // Эскпоненциальный, тоже что 1 * Math.pow(10,3), возвращает 1000
(1000).toExponential(); // Противоположное предыдущему, возвращает 1e3
(3.1415).toFixed(3); // Округление значения, возвращает "3.142"

Определение версии JavaScript

Вы знаете какую версию JavaScript поддерживает ваш браузер? Если нет, то можно посмотреть в Википедии.

Вот небольшой скрипт для определения версии JavaScript:

var JS_ver  = [];  

(Number.prototype.toFixed)?JS_ver.push("1.5"):false;
([].indexOf && [].forEach)?JS_ver.push("1.6"):false;
((function(){try {[a,b] = [0,1];return true;}catch(ex) {return false;}})())?JS_ver.push("1.7"):false;
([].reduce && [].reduceRight && JSON)?JS_ver.push("1.8"):false;
("".trimLeft)?JS_ver.push("1.8.1"):false;

JS_ver.supports = function() {
if (arguments[0])
return (!!~this.join().indexOf(arguments[0] +",") +",");
else
return (this[this.length-1]);
}

alert("Последняя поддерживаемая версия JavaScript: "+ JS_ver.supports());
alert("Поддержка версии 1.7 : "+ JS_ver.supports("1.7"));

Использование window.name для простейшей сессии

Записывая строковые переменные в переменную window.name, вы можете сохранять это значение в текущем окне до тех пор, пока оно не закрыто. Это очень полезно, например, для переключения между режимами отладки и тестирования.

Определение наличия переменной

Эта проблема может появиться либо при определении, есть ли переменная в принципе, либо при определении ее типа. Рассмотрим код:

// ПЛОХО: Это вызовет ошибку в коде, если переменная foo неопределена  
if (foo) {
doSomething();
}

// ХОРОШО: Это не вызовет ошибок, однако когда
// foo будет NULL или false, условие будет как true
if (typeof foo != "undefined") {
doSomething();
}

// ЛУЧШЕ: Опять же, никаких ошибок, и когда переменная
// будет NULL или false условие будет как false
if (window.foo) {
doSomething();
}

Однако, могут возникнуть ситуации, когда у нас есть более сложная структура и правильная проверка в этом случае должна выглядеть как-то так:

// УЖАСНО: нам нужно доказать наличие каждого объектаwe
// прежде чем мы будем уверены, что значение существует
if (window.oFoo && oFoo.oBar && oFoo.oBar.baz) {
doSomething();
}

Передача аргументов функции

Когда у какой-то функции есть как обязательные, так и необязательные аргументы, то ее вызов может выглядеть как-то так:

function doSomething(arg0, arg1, arg2, arg3, arg4) {  
...
}

doSomething('', 'foo', 5, [], false);

Хотя на самом деле всегда проще передавать только один объект вместо нескольких обычных аргументов:

function doSomething() {  
// Оставляем аргументы, если ничего не передано
if (!arguments[0]) {
return false;
}

var oArgs = arguments[0]
arg0 = oArgs.arg0 || "",
arg1 = oArgs.arg1 || "",
arg2 = oArgs.arg2 || 0,
arg3 = oArgs.arg3 || [],
arg4 = oArgs.arg4 || false;
}

doSomething({
arg1 : "foo",
arg2 : 5,
arg4 : false
});

Использование document.createDocumentFragment()

Часто возникает необходимость вставить несколько объектов в страницу. Однако, прямая их вставка в документ вызовет полную перерисовку всего документа, что плохо с точки зрения производительности. Вместо этого лучше использовать document.createDocumentFragment(), вызывая его только один раз в самом конце:

function createList() {  
var aLI = ["first item", "second item", "third item",
"fourth item", "fith item"];

// Создаем фрагмент
var oFrag = document.createDocumentFragment();

while (aLI.length) {
var oLI = document.createElement("li");

// Берем первый элемент массива и добавляем
// как текстовый узел в элемент LI
oLI.appendChild(document.createTextNode(aLI.shift()));
oFrag.appendChild(oLI);
}

document.getElementById('myUL').appendChild(oFrag);
}

Передача функции в метод replace()

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

var sFlop   = "Flop: [Ah] [Ks] [7c]";  
var aValues = {"A":"Ace","K":"King",7:"Seven"};
var aSuits = {"h":"Hearts","s":"Spades",
"d":"Diamonds","c":"Clubs"};

sFlop = sFlop.replace(/\[\w+\]/gi, function(match) {
match = match.replace(match[2], aSuits[match[2]]);
match = match.replace(match[1], aValues[match[1]] +" of ");

return match;
});

// строковая переменная sFlop теперь содержит:
// "Flop: [Ace of Hearts] [King of Spades] [Seven of Clubs]"

Метки внутри циклов

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

outerloop:  
for (var iI=0;iI<5;iI++) {
if (somethingIsTrue()) {
// Останавливаем внешний цикл
break outerloop;
}

innerloop:
for (var iA=0;iA<5;iA++) {
if (somethingElseIsTrue()) {
// Останавливаем внутренний цикл
break innerloop;
}

}
}

 

Нашли для себя что-то полезное? Отлично! Есть, что добавить — пишите в комментариях.

Перевод статьи «10 Small Things You May Not Know About Javascript» специально для Временно.нет.

Рекламное место, которое может стать вашим

Понравилась статья?

Тогда подпишись на обновления через RSS или воспользуйся
другими способами подписки.

Читать в Яндекс.Ленте Добавить в Google Добавить в Netvibes
  •  

Комментарии — 13

RSS
  • Аватарка
    22 февраля в 13:36 Порфирий
    Пиздатенько, спасибо
  • Аватарка
    22 февраля в 14:03 ]]>Андрей Петруша]]>
    И правда спасибо, иногда ищешь какую-то маленькую фигню (вроде "int = ~~myVar") - хрен найдёшь.
  • Аватарка
    22 февраля в 14:24 gm1
    для int есть parseInt.
    Метки - совсем плохо
  • Аватарка
    22 февраля в 14:26 demy
    Спасибо за то, что собрали все эти приемы в одном месте!
    Буду наверняка сюда иногда заходить!
  • Аватарка
    22 февраля в 14:28 ]]>remal]]>
    1*value - это, разве, преобразование не к int?
    А к double можно преобразовать при помощи 0.0+value

    if (undefined_var) { ... } лично у меня никогда ошибок не вызывало. Насколько я помню, в таком простом случае оператор if проверяет в т.ч. и на существование переменной.
  • Аватарка
    22 февраля в 15:15 Alexey
    Для несуществующих переменных можно делать так:
    myVar = myVar || {};

    Ну или:
    myVar = myVar || ;
  • Аватарка
    22 февраля в 15:16 Alexey
    Эх, в последней строке вырезалась концовка:
    myVar = myVar || значение-по-умолчанию;
  • Аватарка
    22 февраля в 15:20 a13ks3y
    Спасибо, действительно полезно.
  • Аватарка
    22 февраля в 16:36 Octane
    Тут обычная конкатенация строк, так как myVar — строка:
    	str     = ""+ myVar,//  в стринг     (string)


    Это просто инициализатор массива, никакого приведения типов здесь нет, только создается новый массив с одним элементом:
    	array   = [myVar];  //  в массив


    С числами всё таки лучше работать по человечески:
    var myVar = 3.14159,
        str = myVar.toString(), // приведение к типу string
        int = Math.round(myVar); // или Math.floor(…), округление до целых


    string к number можно приводить следующим образом:
    var myVar = "3.14159",
        num = +myVar; // или parseInt/parseFloat, приведение к типу number


    Кстати, еще можно быстро получить timestapm:
    var now = +new Date;


    Все числа хранятся в формате float64, т.е. 8 байт с плавающей точкой.
    Базовые типы: Строки, Числа, Boolean

    Для определения наличия свойств объектов (в том числе и window), можно воспользоваться оператором in.

  • Аватарка
    23 февраля в 10:19 ]]>Kykyryzo]]>
    всё таки javascript очень неоднозначный язык. не знаю даже нравится мне он или нет))
  • Аватарка
    25 февраля в 13:59 ]]>vasa_c]]>
    document.createDocumentFragment()
    Разве перерисовка будет вызвана не после завершения выполнения потока?
  • Аватарка
    26 февраля в 7:12 B@rmaley.e>
    Octane, спасибо, очень интересный прием.
  • Аватарка
    13 марта в 15:46 ]]>Алина]]>
    ага прием действительно супер
  • Эл. почта (используется для Граватарки)
  • Домашняя страница
  • Имя в Твиттере
  • Разрешенные теги Текст сообщения (надо бы заполнить это поле)
  • как выглядит какой тег
    жирный текст <b>жирный текст</b>
    курсивный тект <i>курсивный тект</i>
    зачеркнутый текст <s>зачеркнутый текст</s>
    подчеркнутый текст <u>подчеркнутый текст</u>
    ссылка <a href="адрес">ссылка</a>
    function foo() { ... }
    <pre><code>function foo() { ... } </code></pre>