Pokazywanie postów oznaczonych etykietą funkcja. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą funkcja. Pokaż wszystkie posty

wtorek, 28 stycznia 2014

recursiveEach

recursiveEach - rekursywna iteracja po obiekcie. Funkcja do prawidłowego działania wymaga również 2 innych funkcji znajdujących się na tym blogu: getType oraz each.
Funkcję można dodatkowo rozbudować. Np. idealnie byłoby, gdyby w docelowej funkcji zamiast samej wartości klucza zwracała tablicę stringów wskazujących na ścieżkę do tego klucza w głównym obiekcie.

var recursiveEach = function recur(obj, fn, depth) {
  if (typeof depth === 'undefined')
    depth = -1;

  var res = {};

  if (getType(obj) === 'Object' && depth !== 0) {
    each(obj, function (el, key) {
      res[key] = recur(el, fn, depth - 1);
    });
    return res;
  }
  return fn(obj);
};

var getType = function (obj) {
  return ({}).toString.call(obj).slice(8, -1);
};

var each = function (obj, fn) {
  var res = {};
  for (var i in obj) {
    if (obj.hasOwnProperty(i)) {
      res[i] = fn.call(obj, obj[i], i);
    }
  }
  return res;
};

Przy pomocy tej funkcji łatwo zaimplementować funkcję flatten. Do funkcji flatten można przekazać zarówno obiekt jak i tablicę.
var flatten = function(obj) {
  var res = [];
  recursiveEach(obj, function(val) {
    res.push(val);
  });
  return res;
};

niedziela, 29 września 2013

DialogsControl - kontrolowanie domyślnych okien dialogowych

Prosta funkcja/klasa pozwalająca kontrolować (udawać) okna dialogowe.
Przy pomocy metody disable możemy wyłączyć wyświetlanie wszystkich okien dialogowych. oba parametry tej metody pozwalają ustawić wartości zwracane przez funkcje confirm oraz prompt. Domyślne ich wartości to odpowiednio true oraz '' (pusty string).
Metoda restore pozwala przywrócić domyślne wartości tych funkcji czyli oryginalne okna dialogowe w obiekcie window. Domyślne pod warunkiem, że nie były one modyfikowane przez inny skrypt.

var DialogsControl = function(w){
  w = w || window;
  var d = {
    alert: w.alert,
    confirm: w.confirm,
    prompt: w.prompt
  };

  return {
    disable: function(confirmRet, promptRet){
      if (typeof confirmRet === 'undefined')
        confirmRet = true;
      if (typeof promptRet === 'undefined')
        promptRet = '';
      w.alert = function(){};
      w.confirm = function(){return confirmRet;};
      w.prompt = function(){return promptRet;};
    },
    restore: function(){
      w.alert = d.alert;
      w.confirm = d.confirm;
      w.prompt = d.prompt;
    }
  };    
};

Gotowy kod z przykładami wywołania można przetestować tutaj http://jsfiddle.net/a8BvR/

czwartek, 12 września 2013

waitFor - zaczekaj na pojawienie się obiektu

Funkcja, która w bardzo prymitywny sposób czeka na pojawienie się oczekiwanego obiektu w bliżej nie określonym czasie. Czasami takie coś może się przydać jeśli inny skrypt tworzy obiekty i nie wiemy kiedy się pojawią.

var waitFor = function(obj, srcArr, fn, opt){
  opt = opt || {t: 50};

  (function callee(){
    var tmp = obj;
    var tid = setTimeout(callee, opt.t);
    for (var i = 0; i < srcArr.length; ++i) {
      if (typeof tmp[srcArr[i]] !== 'undefined') {
        tmp = tmp[srcArr[i]];
      } else {
        return;
      }
    }
    clearTimeout(tid);
    fn(tmp, obj);
  })();
};
Poniżej przykład użycia:
waitFor(window, 'abc.def'.split('.'), function(data, obj){
  alert('jest: ' + data);
});

setTimeout(function(){
  window.abc = {};
  
  setTimeout(function(){
    window.abc.def = 'obiekt/dane';
  }, 1e3);
}, 1e3);

sobota, 3 marca 2012

Array unique - czyli pozbywamy się duplikatów

Funkcja jako argument przyjmuje tablicę z danymi dowolnego typu. W rezultacie funkcja zwraca tablicę zawierającą tylko unikalne elementy tablicy źródłowej.
var unique = function(arr){
  return arr.filter(function(el, i){
    return arr.indexOf(el, i+1) === -1;
  });
};
Poniżej zamieszczam funkcję robiącą to samo co powyższa funkcja z drobnym wyjątkiem. Poniższa funkcja zawiera dwa dodatkowe wykonania funkcji reverse co pozwoliło na zachowanie naturalnej kolejności elementów występujących w tablicy. Pierwsze wystąpienie danego elementu pozostaje w tym samym miejscu, kolejne wystąpienia tego samego elementu są ignorowane. W poprzedniej wersji funkcji to ostatni element zostałby zachowany.
var unique = function(arr){
  return arr.reverse().filter(function(el, i){
    return arr.indexOf(el, i+1) === -1;
  }).reverse();
};

let unique = [...new Set(myArray)];

środa, 22 lutego 2012

getType - sprawdzenie typu, pewniejsze od typeof

Poniżej zamieszczam funkcję zwracającą typ danej. Funkcja w przeciwieństwie do operatora typeof znacznie skuteczniej oddaje typ przekazanej danej. Pomysł został zaczerpnięty z serwisu JavaScript Garden. Funkcja do sprawdzenia typu wykorzystuje generyczną funkcję toString podstawowego obiektu.
var getType = function(obj){
  return ({}).toString.call(obj).slice(8, -1);
};
Poniżej szybkie sprawdzenie różnic funkcji getType oraz operatora typeof. Pomaga on uświadomić sobie, z jakimi problemami mamy do czynienia, jeśli używamy operatora typeof.
[{}, [], '', 0, 1/0, false, function(){}, /./, null, undefined].map(function(obj){
  return [getType(obj), typeof obj];
});
Tak naprawdę operator typeof JavaScriptu ma tylko jedno uzasadnione zastosowanie.
typeof variable === 'undefined';

niedziela, 12 czerwca 2011

Domyślne parametry funkcji

Funkcja i domyślne jej parametry w JavaScript? JavaScript nigdy nie oferował mechanizmu nadawania domyślnych wartości niezdefiniowanym parametrom przy jej wywołaniu.

Można sobie z tą niedogodnością poradzić w całkiem prosty sposób i wiele osób tak to właśnie robi. Poniżej zamieszczam kawałek kodu.

var fn = function(a, b, c){
  a = a || 25;
  b = b || [2, 5];
  c = c || 'domyslny';
  alert(
    'liczba: ' + a + '\n' +
    'tablica: ' + b + '\n' +
    'string: ' + c
  );
};

fn(5, [1,2,3], 'test');
fn(5, [1,2,3]);
fn(5);
fn();

Działa całkiem nieźle. Co jednak jeśli wywołamy funkcję w poniższy sposób?

fn(0);

Funkcja wyświetla 25. Przecież wysłaliśmy 0 (zero). Dzieje się tak, ponieważ poniższa konstrukcja traktuje liczbę 0 jako wartość false, dlatego do zmiennej a przypisywana jest alternatywna wartość 25.

a = a || 25;

Skoro znamy już problemy wynikające z powyższych konstrukcji przejdźmy do rozwiązania problemu w inny, bardziej elegancki sposób.
Poniżej zamieszczam funkcję która pozwala ze zwykłej funkcji stworzyć funkcję przyjmującą domyślne parametry. Kod zawiera również funkcję testową oraz kilka jej wywołań.

Function.prototype.params = function(){
  var that = this,
      arg = [].splice.apply(arguments, [0, arguments.length]);
  return function(){
    return that.apply(this, [].splice.apply(arguments, [0]).concat(
        arg.slice(arguments.length)
      )
    );
  };
};

var test = function(a, b){
  alert(
    a + '\n' +
    b
  );
}.params(11, 22);

test(1, 2);
test(1);
test();

Stworzenie funkcji z domyślnymi parametrami jest teraz dziecinnie proste. Wystarczy zadeklarować dowolną funkcję a zaraz za nią wywołać naszą metodę z argumentami, które mają być domyślne.
Warto pamiętać o tym, że powyższe udogodnienie będzie spowalniać działanie skryptu. Każde wywołanie zwróconej funkcji powoduje wywołanie kilku dodatkowych instrukcji. Nadużywanie tego udogodnienia może okazać się nierozsądne, w szczególności w przypadku prostych, wielokrotnie powtarzanych funkcji.