//4.6. Функции содержут параметр name function foo() {} // функция-­объявление var bar = function () {}; // функция-­выражение var baz = function baz() {}; // именованная функция-­выражение console.log(foo.name); // “foo” console.log(bar.name); // “” - В IE может отсуствовать это свойство console.log(baz.name); // “baz” //4.9. Можно передавать callback-функции другим функциям. при передачи указываются без круглых скобок var findNodes = function (callback) { // в данном примере передавать параметр callback в функцию findeNodes необязательно if(typeof callback !== 'function') { callback = false; } if(callback) { callback('param1'); } }; findNodes(function (a) { console.log(a); }); //4.10. Если в callback будут передавать обьект с методом, то надо поебать себе мозг var myapp = { color: 'green', paint: function (param) { console.log(this.color + ' ' + param); //в callback не будет this работать. //надо еще передать сам обьект } }; var findNodes = function (callback, obj) { //передача obj нужна для работы this // в данном примере передавать параметр callback в функцию findeNodes необязательно if(typeof callback !== 'function') { callback = false; } if(callback) { if(typeof obj === 'object') { callback.call(obj, 'param1'); //теперь this === obj } else { callback('param1'); } } }; findNodes(myapp.paint, myapp); //передача callback вместе с обьектом findNodes(function (a) { //передача обычной callback-фунции console.log(a); }); //4.11. Функция может возвращать другую функцию var setup = function () { var count = 0; return function () { return (count += 1); }; } var next = setup(); console.log( next() ); //1 console.log( next() ); //2 console.log( next() ); //3 //4.12. Самоопределяемые функции - функция может перезатерать себя. Во 2й раз будет вызываться уже другая ф-я var scareMe = function () { console.log("Boo!"); scareMe = function () { console.log("Double boo!"); }; }; scareMe(); // Boo! scareMe(); // Double boo! //4.15. НВФ может возвращать функцию, и хранить privat-переменые в замыкании var getResult = (function () { var res = 2 + 2; //сохранится как privat в замыкании return function () { return res; }; }()); console.log( getResult() ); //4.16. НВФ может использоваться в объектах var o = { message: (function () { var who = 'me', what = 'call'; return what + ' ' + who; }()), getMsg: function () { return this.message; } }; // пример использования usage console.log(o.getMsg()); //'call me' console.log(o.message); //'call me' //4.18. Немедленно вызываемые объекты (НВО) - ({ a: 'hello', init: function() { alert(this.a); } }).init(); ({ maxwidth: 'hello', init: function () { console.log(this.maxwidth); } }).init(); //4.21. Для кроссбраузерности, вместо ветвления кода и проверок на IE можно заранее реализовать один общий интерфейс var utils = { addListener: null, removeListener: null }; // реализация очереди событий. аргументы: element, event, function if (typeof window.addEventListener === 'function') { utils.addListener = function (el, type, fn) { el.addEventListener(type, fn, false); }; utils.removeListener = function (el, type, fn) { el.removeEventListener(type, fn, false); }; } else if (typeof document.attachEvent === 'function') { // IE utils.addListener = function (el, type, fn) { el.attachEvent('on' + type, fn); }; utils.removeListener = function (el, type, fn) { el.detachEvent('on' + type, fn); }; } else { // устаревшие броузеры. цепляем только одно событий utils.addListener = function (el, type, fn) { el['on' + type] = fn; }; utils.removeListener = function (el, type, fn) { el['on' + type] = null; }; } //пример вызова var elem = document.querySelector('input[type=submit]'); utils.addListener(elem, 'click', function () { alert(1); return false; }); //4.23. Кеширование (мемоизацию, memorization) любой фун-ции можно сделать по хешу входящих параметров var pow = function (base, exponent) { if(typeof pow.cache === 'undefined') { pow.cache = {}; } //делаем из arguments массив var array = Array.prototype.slice.call(arguments); //var array = [].slice.call(arguments); //менее производительно var key = JSON.stringify(array); //если нету в хэше, то считаем if(!pow.cache[key]) { var result = Math.pow(base, exponent); pow.cache[key] = result; console.log('from scratch'); } return pow.cache[key]; } console.log( pow(2, 3) ); //from scratch console.log( pow(2, 3) ); console.log( pow(2, 4) ); //from scratch //4.27. Если у нас в функцию часто передается один из параметров - можем использовать каррирование function curry(x, y){ if (typeof y === 'undefined') { // partial return function (y) { return x + y; }; } // полное применение return x + y; } console.log( curry(4, 5) ); // 9 console.log( curry(4)(5) ); // 9 //использование каррирования - сохранения параметра, который часто передаем var curry1 = curry(4); console.log( curry1(5) ); //9 console.log( curry1(6) ); //10