Несколько маленьких полезных приемов в 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;  
        }  
  
    }  
} 

 

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




Рекомендуем почитать

 

Добавить комментарий


Ваше имя:


Комментарий:


Введите: Картинка