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

Несколько маленьких полезных приемов в 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» специально для Временно.нет.

Расскажите друзьям

Оцените статью:
  • 1
  • 2
  • 3
  • 4
  • 5

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

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

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

Ну или:
myVar = myVar || ;
#
Alexey  
Alexey
Эх, в последней строке вырезалась концовка:
myVar = myVar || значение-по-умолчанию;
#
Alexey  
a13ks3y
Спасибо, действительно полезно.
#
a13ks3y
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.

#
Octane
Kykyryzo
всё таки javascript очень неоднозначный язык. не знаю даже нравится мне он или нет))
vasa_c
document.createDocumentFragment()
Разве перерисовка будет вызвана не после завершения выполнения потока?
B@rmaley.e>
Octane, спасибо, очень интересный прием.
#
B@rmaley.e>
Алина
ага прием действительно супер

Новый комментарий

как выглядит какой тег
жирный текст <b>жирный текст</b>
курсивный тект <i>курсивный тект</i>
зачеркнутый текст <s>зачеркнутый текст</s>
подчеркнутый текст <u>подчеркнутый текст</u>
ссылка <a href="адрес">ссылка</a>
function foo() { ... }
<pre><code>function foo() { ... } </code></pre>
разрешенные теги или посмотреть как будет выглядеть
как выглядит какой тег
жирный текст <b>жирный текст</b>
курсивный тект <i>курсивный тект</i>
зачеркнутый текст <s>зачеркнутый текст</s>
подчеркнутый текст <u>подчеркнутый текст</u>
ссылка <a href="адрес">ссылка</a>
function foo() { ... }
<pre><code>function foo() { ... } </code></pre>
разрешенные теги или посмотреть как будет выглядеть
counter strike mt2 silkroad pvp metin2 metin2 pvp knight pvp gm olarak başlayan pvpler pvp silkroad pvp serverler counter strike serverler msn show cam show görüntülü sohbet oyunlar suskunlar gazete oku