poniedziałek, 15 października 2012

[HTML|JS|CSS] JavaScript Patterns: Funkcje

Funkcje są powszechnie stosowane w języku JavaScript. W porównaniu z językami obiektowymi mamy dwie bardzo ważne cechy, o których nie należy zapominać: funkcje są obiektami i zapewniają osobny scope. Można je tworzyć dynamicznie, przypisywać do zmiennych, przekazywać jako argumenty funkcji i jako wartość zwracaną przez funkcję. Każda funkcja ma właściwość name, którą można wykorzystywać np. podczas debugowania.

var f1 = function(){};
function f2(){}
var f3 = function f3(){};

console.log(f1.name);
console.log(f2.name);
console.log(f3.name);

Konsola:

undefined
f2
f3

Poniżej kilka wzorców projektowych przydatnych przy pracy z funkcjami.

  • Callback

Przekazanie funkcji jako argumentu by wykonać pewne specyficzne operacje np. zapewniając dodatkowy scope.

var mycallback = function(msg){
 if(msg % 2 == 0){
  mycallback.counter++;
 }
};
mycallback.counter = 0;

var fun = function(fun){
 var j = 2;
 for (var i = 1; i < 100000; i++) {
  j += i;
  fun(j);
 }
};

fun(mycallback);
console.log('Operations finished');
console.log('Even numbers: ' + mycallback.counter);

  • Funkcja zwracająca funkcję

Funkcja może być zwracana przez inną funkcję. Zewnętrzna funkcja może się zająć pewną inicjalizacją, natomiast funkcja zwracana dokonywać modyfikacji danych.

function myfun(){
 var number = 0;
 return function(){
  number++;
  console.log(number);
 };
}

var myfunvar = myfun();
myfunvar();
myfunvar();
myfun()();

Konsola

1
2
1

  • Samo definiująca się funkcja

Bardzo użyteczny wzorzec dla opóźnionych inicjalizacji.

var sdfunc = function(){
 var name = "Mike";
 console.log('Initializing');
 sdfunc = function(){
  console.log('My name is ' + name);
 };
};

console.log('Before');
sdfunc();
sdfunc();

Konsola:

Before
Initializing
My name is Mike

  • Immediate functions

Gdy chcemy wykonać pewne operacje tylko raz i nie chcemy zaśmiecać globalnego scope nowymi zmiennymi.


(function(){
 var day = (new Date()).getDay();
 var days = ['pn','wt','sr','cz','pt','sb','nd'];
 console.log('Dzisiaj jest: ' + days[day - 1]);
})();

  • Memoization

Wzorzec używany do cache'owania wyników długich operacji, tak aby przeprowadzane były tylko raz, a przy kolejnych wywołaniach można było korzystać z uzyskanych już wyników.

var cfun = function(param){
 if(!cfun.cache[param]){
  var result = 2;
  console.log('Computing...');
  for (var i = 1; i < param; i++) {
   result += i;
  }
  cfun.cache[param] = result;
 }
 return cfun.cache[param];
};

cfun.cache = {};

console.log(cfun(55));
console.log(cfun(33));
console.log(cfun(55));

Konsola:


Computing...
1487
Computing...
530
1487

  • Currying

Nazwa wzorca pochodzi od nazwiska znanego matematyka Haskella Curry. Jego istotą jest transformacja funkcji, która przyjmuje wiele parametrów. Po transformacji będzie możliwe wywołanie funkcji jako łańcucha wywołań z pojedynczym argumentem.Szczegółowy opis tutaj.

var multiply = function(x,y){
 var oldy = y, oldx = x;
 if(typeof oldy === "undefined"){
  return function(newy){
   return oldx*newy;
  };
 }
 return x*y;
};

console.log(multiply(2,4));
var multiply5 = multiply(5);
console.log(multiply5(2));
console.log(multiply(3)(4));

Brak komentarzy:

Prześlij komentarz