45 Типсов-Триксов и Практик JavaScript

в 13:18, , рубрики: javascript, перевод, метки: ,

Одним вечером делать нечего, листая белые страницы интернета, в поисках чего бы такого мне почитать на сон грядущий, наткнулся я на одну занимательную статейку – на неизвестном мне ресурсе, от автора которого знать не знаю, слыхать не слыхал. Чтиво оказалось довольно интересным, с учетом того, что близко по роду деятельности, по форме и ее содержанию.
Правда, не очень во всем согласился с автором непосредственно в излагаемом материале, к тому же много затрагивается базисных вещей, но подумал, что она заслуживает внимания населения – кому вчитываться лень, но любит чтобы кратко, с толком, с расстановкой и по делу без лишней литературщины.
Естественно, что все ниже изложенное отнюдь не есть истина последней инстанции, как на библии, на ней клясться я бы не советовал. Но может быть кто-то откроет какие вещи с новой стороны, а кто – то покритикует, высказав свое ЧСВешное: «Фи фи фи, фа фа фа!».
Однако обо всем по порядку в моем своевольном от лица первого…

Кадр первый, вступительный

Как вы знаете, JavaScript номер один среди прочих языков программирования в мире: это язык для веба, язык для написания мобильных приложений ( прим. – опустил слово hybrid: mobile hybrid apps ) c PhoneGap и Appcelerator, для разработок на серверной стороне c NodeJS и Wakanda, и множества других применений. Это также отправная точка для многих новичков в мир программирования: может использоваться как для вывода простого alert в браузере, так и для управления роботом( с использованием  nodebot, nodruino).

Разработчики с отличным знанием JavaScript, которые пишут понятный и производительный код, одни из самых востребованных на рынке труда.
В этой статье мне хотелось бы ознакомить с различными трюками и практиками, которые должны быть известны каждому JavaScript разработчику в независимости от внутренностей браузера ( browser/engine ), а также интерпретатора серверного кода javascript( Server Side JavaScript interpreter ).

Все примеры кода были протестированы в Google Chrome version 30, который
использует V8 JavaScript Engine (V8 3.20.17.15).

Кадр второй, поучительно-советовательный

1 — Не забывайте ключевое слово `var`, когда присваиваете значение переменной
первый раз :

Присвоение не объявленной ранее переменной приведет к тому, что данная переменная будет создана в глобальном пространстве. Избегайте этого.
(прим. — автор намекает, что когда вы создаете переменные, то можете
забыть ключевое слово, соответственно, создадите лишнюю переменную в
глобальном пространстве window)

2 — Используйте `===` вместо `==` :
Применение `==(!=)` производит преобразование типов, если это необходимо. Тогда как `===` не делает такого преобразования. Данный
оператор сравнивает не только значения, но также и типа, что разрешается быстрее, чем `==`. Примеры:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        [10] === 10    // is false
        [10]  == 10    // is true
        '10' == 10     // is true
        '10' === 10    // is false
         []   == 0     // is true
         [] ===  0     // is false
         '' == false   // is true but true == "a" is false
         '' ===   false // is false
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

3 — `undefined, null, 0, false, NaN, ''` :
Все вышеперечисленное всегда будет ложью в логических выражениях

4 — Не забывайте `;` :
Использование `;` для завершения выражений является хорошей практикой. Вы не будете предупреждены, если пропустите ее, так как JavaScript парсер вставит ее за вас.

5 — Объект через конструктор :

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        function Person(firstName, lastName){
            this.firstName =  firstName;
            this.lastName = lastName;
        }

        var Saad = new Person("Saad", "Mousliki");
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

6 — Будьте осторожны, когда используете `typeof, instanceOf, constructor` :

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var arr = ["a", "b", "c"];
        typeof arr;   // return "object"
        arr  instanceof Array // true
        arr.constructor();  //[]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

7 — Используйте self-calling функции :
Часто их называют самовызывающимися анонимными функциями (Self-Invoked Anonymous Function) или немедленно вызываемым выражением функции (Immediately Invoked Function Expression (IIFE)). Это функция, которая запускается, непосредственно при создании и имеет следующую форму:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        (function(){
            // some private code that will be executed automatically
        })();
        (function(a,b){
            var result = a+b;
            return result;
        })(10,20);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

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

8 — Получение произвольного значения массива :

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var items = [12,548,'a',2,5478,'foo',8852,'Doe',2145,119];
        var randomItem = items[Math.floor(Math.random() * items.length)];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

9 — Получение произвольного числа в определенном диапазоне :
Данный пример может использован, когда необходимо сгенерировать какие-либо фейковые данные, чтобы протестировать что-нибудь, к примеру, зарплаты, находящиеся между минимальными и максимальным значением:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var x = Math.floor(Math.random() * (max - min + 1)) + min;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

10 — Генерация численного массива от 0 до max :

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var numbersArray = [] , max = 100;
        // numbers = [0,1,2,3 ... 100]
        for( var i=1; numbersArray.push(i++) < max;);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

11 — Генерация произвольного набора символов :

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        function generateRandomAlphaNum(len) {
            var rdmstring = "";
            for( ; rdmString.length < len; rdmString  += Math.random().toString(36).substr(2));
            return  rdmString.substr(0, len);
        }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

12 — Перемешивание массива :

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var numbers = [5, 458 , 120 , -215 , 228 , 400 , 122205, -85411];
        numbers = numbers.sort(function(){ return Math.random() - 0.5});
        /* the array numbers will be equal for example to [120, 5, 228, -215, 400, 458, -85411, 122205]  */
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

13 — Функция `trim()` для строк :
Классическая функция `trim()`, которая есть в Java, C#, PHP и многих других языках программирования, которая удаляет пробельные символы, не содержится в JavaScript. Однако можно добавить ее к объекту `String`:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        String.prototype.trim = function(){
            return this.replace(/^s+|s+$/g, "");
        };
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

(прим. — не удержался, но странно, что автор использует данный прием,
как бы `trim()`есть уже в JavaScript)

14 - Добавить один массив к другому :

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var array1 = [12 , "foo" , {name "Joe"} , -2458];

        var array2 = ["Doe" , 555 , 100];
        Array.prototype.push.apply(array1, array2);
        /* array1 will be equal to  [12 , "foo" , {name "Joe"} , -2458 , "Doe" , 555 , 100] */
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

15 — Преобразовать объект `arguments` в массив :

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var argArray = Array.prototype.slice.call(arguments);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

16 – Проверка является ли заданный аргумент числом :

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        function isNumber(n){
            return !isNaN(parseFloat(n)) && isFinite(n);
        }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

17 – Проверка является ли заданный аргумент массивом :

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        function isArray(obj){
            return Object.prototype.toString.call(obj) === '[object Array]' ;
        }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Замечание, если метод `toString()` переопределен, то результат будет не такой какой ожидается при использовании данного трюка.
Или воспользоваться…

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        Array.isArray(obj); // its a new Array method
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Вы также можете использовать `instanceof`, если не работаете с множеством фреймов. Однако, если вы используете много контекстов, то
получите неправильный результат:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var myFrame = document.createElement('iframe');
        document.body.appendChild(myFrame);

        var myArray = window.frames[window.frames.length-1].Array;
        var arr = new myArray(a,b,10); // [a,b,10]

        // instanceof will not work correctly, myArray loses his constructor
        // constructor is not shared between frames
        arr instanceof Array; // false
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

18 – Получить максимальное, минимальное значение численного массива :

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var  numbers = [5, 458 , 120 , -215 , 228 , 400 , 122205, -85411];
        var maxInNumbers = Math.max.apply(Math, numbers);
        var minInNumbers = Math.min.apply(Math, numbers);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

19 – Делаем массив пустым :

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var myArray = [12 , 222 , 1000 ];
        myArray.length = 0; // myArray will be equal to [].
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

20 – Не используйте `delete` для того, чтобы удалить из массива :
Используйте `split` вместо `delete`, чтобы удалить запись из массива. Использование `delete` не удаляет, а заменяет элемент на `undefined`.
Вместо этого…

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var items = [12, 548 ,'a' , 2 , 5478 , 'foo' , 8852, , 'Doe' ,2154 , 119 ];
        items.length; // return 11
        delete items[3]; // return true
        items.length; // return 11
        /* items will be equal to [12, 548, "a", undefined × 1, 5478, "foo", 8852, undefined × 1, "Doe", 2154,       119]   */
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Используйте вот это…

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var items = [12, 548 ,'a' , 2 , 5478 , 'foo' , 8852, , 'Doe' ,2154 , 119 ];
        items.length; // return 11
        items.splice(3,1) ;
        items.length; // return 10
        /* items will be equal to [12, 548, "a", 5478, "foo", 8852, undefined × 1, "Doe", 2154,       119]   */
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Однако `delete` следует использовать для удаления свойств объекта.

21 – Урезаем массив, используя `length` :
Как в предыдущем примере с пустым массивом, для урезания массива воспользуемся свойством `length`:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var myArray = [12 , 222 , 1000 , 124 , 98 , 10 ];
        myArray.length = 4; // myArray will be equal to [12 , 222 , 1000 , 124].
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Бонус, если установить значение длины массив больше его текущей, то длина массива будет изменена, а новые значения будут установлены
как `undefined`. Свойство длины массива не только для того, чтобы его считывать.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        myArray.length = 10; // the new array length is 10
        myArray[myArray.length - 1] ; // undefined
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

22 – Использование логических `AND/ OR` для условных выражений :

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var foo = 10;
        foo == 10 && doSomething(); // is the same thing as if (foo == 10) doSomething();
        foo == 5 || doSomething(); // is the same thing as if (foo != 5) doSomething();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Логическое `OR` может быть также использовано, чтобы установить значение по умолчанию для аргумента функции.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        Function doSomething(arg1){
            Arg1 = arg1 || 10; // arg1 will have 10 as a default value if it’s not already set
        }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

23 – Используйте `map()`метод, чтобы пройти циклом по массиву :

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var squares = [1,2,3,4].map(function (val) {
            return val * val;
        });
        // squares will be equal to [1, 4, 9, 16]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

24 – Округление числа до N чисел после запятой :

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var num =2.443242342;
        num = num.toFixed(4);  // num will be equal to 2.4432
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

25 – Проблема плавающих точек :

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        0.1 + 0.2 === 0.3 // is false
        9007199254740992 + 1 // is equal to 9007199254740992
        9007199254740992 + 2 // is equal to 9007199254740994
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Почему так происходит? 0.1 + 0.2 равняется 0.30000000000000004. Что вам необходимо знать так это то, что все числа в JavaScript с плавающей точкой внутри представляются как 64 битные в двоичном виде по стандарту IEEE 754.
Если хотите больше примеров - посмотрите данный блог.
Вы можете использовать методы `toFixed()` и `toPrecision()`, чтобы избежать подобных проблем.

26 – Проверяйте свойства объекта, когда пользуетесь `for-in` циклом :
Данный пример кода может быть использован, чтобы избежать итераций по свойствам прототипа объекта.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        for (var name in object) {
            if (object.hasOwnProperty(name)) {
                // do something with name
            }
        }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

27 – Оператор запятая :

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var a = 0;
        var b = ( a++, 99 );
        console.log(a);  // a will be equal to 1
        console.log(b);  // b is equal to 99
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

28 – Кешируйте переменные, которые необходимы для вычислений или запросов :
На примере jQuery селекторов, мы можем закешировать их результат — DOM элементы.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var navright = document.querySelector('#right');
        var navleft = document.querySelector('#left');
        var navup = document.querySelector('#up');
        var navdown = document.querySelector('#down');
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

29 – Проверьте аргумент прежде, чем отправить его в isFinite()` :

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        isFinite(0/0) ; // false
        isFinite("foo"); // false
        isFinite("10"); // true
        isFinite(10);   // true
        isFinite(undifined);  // false
        isFinite();   // false
        isFinite(null);  // true  !!!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

30 – Избегайте отрицательных индексов в массивах :

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var numbersArray = [1,2,3,4,5];
        var from = numbersArray.indexOf("foo") ;  // from is equal to -1
        numbersArray.splice(from,2);    // will return [5]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Убедитесь, что аргументы передаваемые `indexOf` не отрицательны.

31 – Сериализация и десериализация (для JSON) :

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var person = {name :'Saad', age : 26, department : {ID : 15, name : "R&D"} };
        var stringFromPerson = JSON.stringify(person);
        /* stringFromPerson is equal to "{"name":"Saad","age":26,"department":{"ID":15,"name":"R&D"}}"   */
        var personFromString = JSON.parse(stringFromPerson);
        /* personFromString is equal to person object  */
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

32 – Избегайте `eval()` или `Function` конструктора :
Использование `eval` или `Function` конструктора дорогостоящая операция так как каждый раз они вызывают преобразование исходного кода в исполняемый движком javascript.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var func1 = new Function(functionCode);
        var func2 = eval(functionCode);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

33 – Избегайте `with` (Хорошая штука) :
Использование `with` определяет переменную в глобальное пространство. Если какая-либо переменная будет иметь такое же имя, тогда это создаст определенные проблемы, так как может произойти затирание значения.

34 – Избегайте `for-in` циклов для массивов :
Вместо…

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var sum = 0;
        for (var i in arrayNumbers) {
            sum += arrayNumbers[i];
        }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

…лучше это…

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var sum = 0;
        for (var i = 0, len = arrayNumbers.length; i < len; i++) {
            sum += arrayNumbers[i];
        }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Бонус, присвоение для `i` и `len` будет произведено лишь однажды так как это первое выражение конструкции цикла. Это быстрее, чем …

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        for (var i = 0; i < arrayNumbers.length; i++)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Почему? Длина массива `arrayNumbers` вычисляется при каждой итерации цикла.

35 – Передавайте функции, а не строки для `setTimeout()` и `setInterval()` :
Если вы передаете строки в `setTimeout()` или `setInterval()`, то они будут обрабатываться также как и с использованием `eval`, это медленно.

Вместо использования…

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        setInterval('doSomethingPeriodically()', 1000);
        setTimeOut('doSomethingAfterFiveSeconds()', 5000);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

…используйте…

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        setInterval(doSomethingPeriodically, 1000);
        setTimeOut(doSomethingAfterFiveSeconds, 5000);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

36 – Используйте `switch/case` вместо серии из `if/else` :
Использование `switch/case` работает быстро, когда более двух условий, это более элегантно и лучше для организации кода. Избейгате этого
выражения, когда имеется более 10 условных выражений.

37 – Используйте `switch/case` выражение с численными диапазонами :
Использование `switch/case` выражения с численным диапазоном делает возможным следующий трюк.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        function getCategory(age) {
            var category = "";
            switch (true) {
                case isNaN(age):
                    category = "not an age";
                    break;
                case (age >= 50):
                    category = "Old";
                    break;
                case (age <= 20):
                    category = "Baby";
                    break;
                default:
                    category = "Young";
                    break;
            };
            return category;
        }
        getCategory(5);  // will return "Baby"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

38 – Создать объект, чей прототип — это задаваемый объект :
Возможно создать функцию, что создает объект, чьим прототипом будет является объект, который передается в аргументе функции…

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        function clone(object) {
            function OneShotConstructor(){};
            OneShotConstructor.prototype= object;
            return new OneShotConstructor();
        }
        clone(Array).prototype ;  // []
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

39 – HTML escaper :

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        function escapeHTML(text) {
            var replacements= {"<": "<", ">": ">","&": "&", """: """};
            return text.replace(/[<>&"]/g, function(character) {
                return replacements[character];
            });
        }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

40 – Избегайте использования `try-catch-finally` внутри циклов :
`try-catch-finally` создает новую переменную в текущем пространстве выполнения каждый раз, когда срабатывает исключение и оно связывается с переменной.

Вместо этого…

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var object = ['foo', 'bar'], i;
        for (i = 0, len = object.length; i <len; i++) {
            try {
                // do something that throws an exception
            }
            catch (e) {
                // handle exception
            }
        }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

…используйте это…

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var object = ['foo', 'bar'], i;
        try {
            for (i = 0, len = object.length; i <len; i++) {
                // do something that throws an exception
            }
        }
        catch (e) {
            // handle exception
        }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

41 – Устанавливайте задержки для `XMLHttpRequests` :
Вы можете потерять соединение, если XHR занимает слишком большое время (как пример, сетевые проблемы), используйте `setTimeout()` с вызовами
XHR.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var xhr = new XMLHttpRequest ();
        xhr.onreadystatechange = function () {
            if (this.readyState == 4) {
                clearTimeout(timeout);
                // do something with response data
            }
        }
        var timeout = setTimeout( function () {
            xhr.abort(); // call error callback
        }, 60*1000 /* timeout after a minute */ );
        xhr.open('GET', url, true);

        xhr.send();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Как бонус, вам следует избегать синхронных запросов Ajax.

42 – Deal with WebSocket timeout
Обычно, когда соединение установлено, сервер может сбросить соединение по тайм-ауту после 30 секунд неактивности. Фаервол может также после определенного периода сбросить соединение по тайм-ауту из-за неактивности.
Данную проблему можно решить путем посылок пустых сообщений серверу. Чтоб сделать это, следует добавить две функции в ваш код: одна, чтобы поддерживать соединение и другая, чтобы отменить эту поддержку.
Используя данный трюк, вы будете управлять тайм-аутом.

Добавляем `timerID`…

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var timerID = 0;
        function keepAlive() {
            var timeout = 15000;
            if (webSocket.readyState == webSocket.OPEN) {
                webSocket.send('');
            }
            timerId = setTimeout(keepAlive, timeout);
        }
        function cancelKeepAlive() {
            if (timerId) {
                cancelTimeout(timerId);
            }
        }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

`keepAlive()` следует добавить в конец `onOpen()` метода для webSocket
соединения и `cancelKeepAlive()` в конец `onClose()` метода.

43 – Помните, что примитивы работают быстрее, чем вызовы функций.
Воспользуйтесь VanillaJS

Для примера, вместо этого…

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var min = Math.min(a,b);
        A.push(v);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

…используйте это…

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var min = a < b ? a b;
        A[A.length] = v;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

44 – Не забывайте пользоваться инструментами по форматированию и стилистике кода.
Используйте JSLint и минимизацию (JSMin, для примера) перед тем, как код начнет жить.

45 – JavaScript просто шиииикааарен: Best Resources To Learn JavaScript.

Заключение

Естественно, есть множество советов и трюков и практик. Поэтому, если вам есть, что добавить, получить какую-то обратную связь или внести корректировки — пишите в комментариях.

Ссылочки

При написании данной статьи я использовал свои примеры для кода, однако некоторые примеры были навеяны из других статей и форумов:

А вот и сказочки конец....

Каждый по-разному может относиться к тому, что написано и изложено в этом материале. Достаточно он был хорош или нет, насколько глубоко раскрыты были вопросы, освещены результаты, насколько умны и интересны были примеры.
Моя задача, как транслятора, была в том, чтобы доставить его на суд говорящей, кипящей от работы синапсов общественности. А уж зачем ему конкретно это надо — каждый решает за себя.
Кто захочет поговорить с автором, почитать комментарии — пройдите по ссылочкам. Пробегитесь по оригинальной статье. Надеюсь, что моя скромная копия принесла вам пользы, не отняла много времени.

Спасибо за внимание!

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Оригинал текста
Автор оригинального текста: Саад Муслики (Смотреть героя)
*Декабрь 23, 2013*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Автор: tap043k

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js