Najlepsze rozwiązania w JavaScript cz. 1.

OK

Poziom średnio-zaawansowany

Update 09-2014: uwaga – ten artykuł powstał oryginalnie kilka lat temu, jeszcze na starym blogu, więc może nieco odbiegać od dzisiejszych standardów dobrych i zalecanych rozwiązań.

Dzisiaj szef_kuchni.js poleca wpis z serii najlepszych rozwiązań w JavaScript. Ma on charakter czysto praktyczny. Przedstawiamy porady i znane bądź opracowane na potrzeby jakiegoś projektu rozwiązania problemów, tudzież po prostu triki.

Najlepsze rozwiązania w JavaScript

Przykład na pierwszy ogień – dynamiczne dodanie elementu do dokumentu (użycie DOM):

<div id="some_div">W tym elemencie dodamy kolejny...</div>
// dom_create_input.js
function createInput() {
    var input = document.createElement("input");
    input.name = "user_location"; // nazwa
    input.id = "user_location"; // id
    input.value = ""; // wartość
    input.style.width = "150px"; // opcje CSS

    // readonly, lub inne opcje ...

    document.getElementById("some_div").appendChild(input);
}

Kolejny trik to wysłanie formularz po kliknięciu w link.

Przykład – wysłanie formularza poprzez zwykły link:

<a href="javascript:document.forms[0].submit()">OK</a>

Jak ustawić szybko klasę CSS dla elementu w czystym JS?

Oto przykład:

var cn = "foobar";
document.getElementById("id_elementu").className = cn;

A jak używając operacji na DOM wyciągnąć zawartość tekstową elementu HTML?

Przykład – wyciąganie tekstu z elementów takich jak div, h1, itp.:

<h1 id="temat"> Test </h1>
var dTopic = document.getElementById('temat').firstChild.nodeValue;
alert(dTopic);

Kolejny przykład używany był w funkcjonalności związanej z wiadomościami pomiędzy użytkownikami wysyłanymi poprzez AJAX.

Kod ten pobierał treść wiadomości napisanej przez użytkownika celem dalszego przetworzenia, zapisania w bazie danych / wysłania. Chodziło o pobranie wszystkiego co napisał użytkownik z poziomu JavaScript, działające w wielu przeglądarkach (tak, to kod sprzed wielu lat).

Przykład – prawidłowe pobieranie danych z elementu jak p czy div (wszystkie childnodes):

var msg_el = "id_elementu_z_dlugim_tekstem";

var msg_buff = "";
if (document.getElementById(msg_el).hasChildNodes()) {
var ctmp = null;
var children = document.getElementById(msg_el).childNodes;

for (var i = 0; i < children.length; i++) {
    ctmp = children[i].nodeValue;
    if (ctmp == null)
        msg_buff += "<br />"; // null => < br / >
    else
        msg_buff += ctmp;
    }
}

Powyższe zadanie można uprościć, stosując funkcję InnerHTML z biblioteki Prototype JS:

var d = $(msg_el);
alert(d.innerHTML);

Przejdźmy dalej. Jak napisać najprostszy odpowiednik funkcji isset() w JS?

Przykładowo tak:

function isset(variable) {
    if  (variable == undefined) {
        return false;
    }

    return true;
}

Następny kod natomiast to implementacja isArray. Jest to ścisłe sprawdzenie, czy podany argument jest tablicą.

Przykład – sprawdzanie czy argument jest tablicą w JS:

// is_array JavaScript
var isArray = function(value) {
    return value && typeof value === 'object' &&
    typeof value.length === 'number' &&
    typeof value.splice === 'function' &&
    !(value.propertyIsEnumerable('length'));
};

// przykłady użycia:
isArray('x'); // false
isArray(1); // false
isArray(new Array()); // true

A teraz jeden z tych prostych trików, które lubię. Jest to zwięzły i szybki sposób na obejście błędów, np. gdy nie wiemy czy dany element istnieje. Tak zapisany kod pobiera wartość elementu (tutaj tablicy) i zwraca albo tę wartość albo wartość domyślną, którą zdefiniowaliśmy za operatorem logicznym OR (||).

Przykład – zwięzły zapis pobierania wartości lub wartości domyślnej:

var tablica = new Array(); // ...
var zmienna = tablica["jakas-nazwa"] || "(none)";
alert(zmienna);

Sprawdza się, dając elegancki wynik, nawet jeśli element tablicy (lub też obiektu) nie istnieje, a próbujemy się do niego odwołać.

Przejdźmy dalej.


Trochę matematyki i wyrażeń regularnych

Przy okazji, jeśli ktoś doczytał dotąd to wspomnę, że mile widziane są Wasze własne bądź znane z jakiegoś źródła, najlepsze rozwiązania w JavaScript. Można je śmiało wklejać jako komentarz.

Przykład – implementacja silni w JavaScript:

// silnia w JS
var factorial = function factorial(i, a) {
    a = a || 1;
    if (i < 2) {
        return a;
    }

    return factorial(i - 1, a * i);
};

alert(factorial(4)); // 24

Przypominamy przykład przedstawiony już podczas omawiania wyrażeń regularnych:

Przykład – parsowanie URL:

var parse_url = /^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)
(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/;

var url = "http://www.adres.com:80/skrypt?q#fragment";

var result = parse_url.exec(url);
var names = ['url', 'protokol', 'ukosniki', 'serwer', 'port',  
    'path', 'zapytanie', 'zakotwiczenie'];

var blanks = '              ';
var i;

for (i = 0; i < names.length; i += 1) {
    document.writeln(names[i] + ':' + blanks.
        substring(names[i].length), result[i]);
}

Kolej na dość ciekawy i praktyczny przykład użycia wyrażeń regularnych do formatowania ułamków jako liczb rzeczywistych.

Przykład – formatowanie ułamków jako liczb rzeczywistych w JavaScript:

function ulamki(txt) {
    txt = txt.replace(/^ */, "");
    txt = txt.replace(/ *$/, "");
    txt = txt.replace(/(([0-9]+) *\/ *([0-9]+)).*/, "($2/$3)");
    txt = txt.replace(/ /, "+");
    
    return(eval(txt));
}

// przykłady użycia
alert(ulamki("1/4"));         // 0.25
alert(ulamki(" 1 / 4 "));     // 0.25
alert(ulamki(" 10 /80 "));    // 0.125
alert(ulamki("2 3/8"));       // 2.375
alert(ulamki("1 2/5 cala"));  // 1.4

Następny przykład to symulacja „varargs” czyli tzw. zmiennej listy argumentów funkcji, na pewno znanej programistom takich języków jak C.

Przykład – zmienna lista argumentów w JavaScript:

// va_args JS
var sum = function() {
    var i, sum = 0;
    for (i = 0; i < arguments.length; i += 1) {
        sum += arguments[i];
    }
    
    return sum;
};

alert(sum(4, 8, 15, 16, 23, 42));  // 108

Niektórzy wiedzą, inni się domyślają, że liczby (zmienne typu Number) w JavaScript mają natywną metodę toString(), która konwertuje je na ciąg znaków (typ String).

Przykład – toString dla liczb (konwersja liczby na łańcuch w JavaScript):

var number = 5;
alert(typeof number); // number
number = number.toString(); // "5"
alert(typeof number); // string

// nadpisanie metody - modyfikacja działania
Number.prototype.toString = function() {
    return String(this + 1);
};

var nv = number.toString();
alert(nv); // "6"

W przykładzie został także pokazany przykład nadpisania wbudowanej metody. W tym konkretnym przypadku do wartości liczbowej najpierw jest dodane 1, a następnie całość jest konwertowana na typ String.

A na deser: sortowanie po ludzku, czyli porządkowanie naturalne w JavaScript.

Przykład – porządkowanie naturalne:

var m = ['aa', 'bb', 'a', 8, 4, 16, 15, 23, 42];
m.sort(function(a, b) {
    if (a === b) {
        return 0;
    }

    if (typeof a  === typeof b) {
        return a < b ? -1 : 1;
    }

    return typeof a < typeof b ? -1 : 1;
});

// m wynosi [4, 8, 15, 16, 23, 42, 'a', 'aa', 'bb']
alert(m.toString());

Podsumowanie

To wszystko jeśli chodzi o pierwszą część z serii: Najlepsze rozwiązania w JavaScript. Jak widać niektóre z nich były rozwiązaniami problemów napotkanych w prawdziwych projektach.

Jeśli jakieś rozwiązanie będzie przydatne dla choćby jednego Czytelnika, to ja uważam swoje zadanie na dziś za wykonane.

Dziękuję za uwagę.

Programista WWW i aplikacji mobilnych z wieloletnim doświadczeniem, początkujący bloger. Pasjonat programowania, nowych technologii, e-commerce, a także sportu i motoryzacji.

Twitter LinkedIn Google+ Skype Xing 

Podaj dalej: Share on Facebook0Tweet about this on TwitterShare on Google+1Share on LinkedIn1Share on Tumblr0Digg thisEmail this to someonePin on Pinterest1
Możesz skomentować leave a response, lub podać trackback z własnej strony.
  • Fajny tekst, ale wydaje mi się, że lepiej byłoby rozbić to na wiele mniejszych artykułów. Łatwiej potem komuś linkować rozwiązanie jego problemu.

    Miałbym pewną uwagę. Jaki sens ma kod isset … Właśnie odpaliłem w firebugu coś takiego:

    alert(isset(aaa)); // aaa niezadeklarowana

    W wyniku: „ReferenceError: aaa is not defined”

  • Hello,

    co do errora – zgadza się…

    samego isset() zdarzyło mi się potrzebować – ale użyłem wersji pro tzn. implementacji z biblioteki phpjs:

    http://phpjs.org/functions/isset/

    Co ciekawe dla takiego przypadku i ta implementacja, czyli:

    function isset () {
      // http://kevin.vanzonneveld.net
      // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
      // +   improved by: FremyCompany
      // +   improved by: Onno Marsman
      // +   improved by: Rafał Kukawski
      // *     example 1: isset( undefined, true);
      // *     returns 1: false
      // *     example 2: isset( 'Kevin van Zonneveld' );
      // *     returns 2: true
      var a = arguments,
        l = a.length,
        i = 0,
        undef;
    
      if (l === 0) {
        throw new Error('Empty isset');
      }
    
      while (i !== l) {
        if (a[i] === undef || a[i] === null) {
          return false;
        }
        i++;
      }
      return true;
    }
    
    alert(isset(aaa));
    

    zachowuje się tak samo jak ta prosta, przestawiona w artykule.

    Jaki jest sens – w tym przypadku, o ile pamiętam, kod wykonywał sprawdzanie czy istnieje zadany element – tak jak używa się tego w PHP.

    Na szybko przepisywaliśmy jakiś kod z PHP na JS, wiadomo że można to w JS przerobić samemu w taki czy inny sposób, ale inaczej jest kiedy czas nagli… wiadomo jak to bywa, szczególnie lata temu, gdy nie brakowało ambicji, ale brakowało doświadczenia.

    Generalnie powiedziałbym że to bardziej ciekawostka, i jakaś alternatywa dla specyficznych przypadków.

    A choć biblioteka phpjs jest ambitna, to wiadomo ze w samym JS sporo kwiatków jest posadzonych i kwitnie 🙂

    A co do rozbicia na mniejsze arty – jest to jakiś pomysł, ale nie chciałem się rozdrabniać za bardzo.
    Może jak się tego nazbiera więcej, to stworzymy jakiś leksykon rozwiązań…

    Pozdrowienia