JavaScript Александр Березневатый, Senior Java Developer & Team Lead
> new Array() + new Array() = ?
> new Array() + new Array() =
> new Array() + new Object() = ?
> new Array() + new Array() = > new Array() + new Object() = [object Object]
> new Array() + new Array() = > new Array() + new Object() = [object Object] > 0 == ?
> new Array() + new Array() = > new Array() + new Object() = [object Object] > 0 == => true > 0 == 0 ?
> new Array() + new Array() = > new Array() + new Object() = [object Object] > 0 == => true > 0 == 0 => true > 0 == false ?
> new Array() + new Array() = > new Array() + new Object() = [object Object] > 0 == => true > 0 == 0 => true > 0 == false => true > '0' == false ?
> new Array() + new Array() = > new Array() + new Object() = [object Object] > 0 == => true > 0 == 0 => true > 0 == false => true > '0' == false => true > 0 == ' \r \t \n \t ?
> new Array() + new Array() = > new Array() + new Object() = [object Object] > 0 == => true > 0 == 0 => true > 0 == false => true > '0' == false => true > 0 == ' \r \t \n \t => true > NaN == NaN ?
> new Array() + new Array() = > new Array() + new Object() = [object Object] > 0 == => true > 0 == 0 => true > 0 == false => true > '0' == false => true > 0 == ' \r \t \n \t => true > NaN == NaN => false
План дня > История Web (продолжение) > Синтаксис > Работа с DOM > Good Parts & Bad Parts > Libraries > Performance notes > Домашнее задание
Цели > Общее понимание языка > Часто встречающиеся сложности > Заинтересовать в изучении > Best practice
Жалобы > Программирование в браузере это ужас > JS тормозит > я плохо знаю JS > JS просто большая куча ошибок
История: JavaScript > Разработан за две недели > Много чего бездумно скопировано > Пострадал в результате войны браузеров > Стандартизируется ECMA + W3C
Синтаксис
Синтаксис: Объекты > неупорядоченный набор свойств > var x = new Object() > var y = {};
Синтаксис: JSON > очень краткий и емкий формат > {}, [] > свойства в кавычках
Синтаксис: JSON { status : success result : [ 12, 22, { id: 45, name: Alex } ] }
Синтаксис: Функции > функция тоже объект > ключевое слово function > аргументы и локальные переменные
Синтаксис: Функции var myFunc = function(arg0, arg1) { arguments[0] === arg0;//true arguments[2] === 3;//true }; myFunc(1, 2, 3);
Синтаксис: Функции function iter(fn, array) { for (var i = 0; i < array.length; i++) { fn(array[i]); } }; iter(function(el){ alert(el); }, [1, 2, 3, 4]);
Синтаксис: Глобальный контекст > глобальные переменные это свойства объекта window > ключевое слово var > ключевое слово delete
Синтаксис: Видимость переменных > ключевое слово var (продолжение) > цепочки скоупов > ключевое слово with
Синтаксис: Видимость переменных
Синтаксис: Контекст > ключевое слово this > варианты контекста > методы call и apply
Синтаксис: Контекст function myFunc() { console.log(this); } var obj = { method : myFunc }; myFunc(); // this === window obj.method(); // this === obj obj.method.call(document); // this === document obj.method.apply(console); // this === console
Синтаксис: Прототипы и наследование > наследуются объекты > цепочки свойств > перезапись и удаление свойств
Синтаксис: Прототипы и наследование var x = { name: Alex }; var y = {}; assert(y.name === undefined); y.prototype = x; assert(y.name === x.name); y.name = Sasha; assert(y.name === Sasha); assert(x.name === Alex);
Синтаксис: Прототипы и наследование var JSProgrammer = { skills: javascript }; var LuxoftJsProgrammer = function(name, city) { this.name = name; this.city = city || unknown; }; LuxoftJsProgrammer.prototype = JSProgrammer; var me = new LuxoftJsProgrammer(Alex); assert(me instanceof LuxoftJsProgrammer);
Синтаксис: Прототипы и наследование
Синтаксис: eval() == evil > вызывется в той же области видимости > хуже по производительности > потенциальная дыра в безопасности > используйте заменители когда это возможно
Синтаксис: strict mode > "use strict"; > запрещает «скрытые» ошибки > улучшает безопасность кода > не разрешает пользоваться «неправильными» инструментами
Синтаксис: Вопросы
Работа с DOM
Document > > document.getElementById(myElementId); > document.getElementsByTagName(div); > xpath
Live collections var divs = document.getElementsByTagName(div); for (var i = 0; i < divs.length; i++) { var el = divs[i]; el.parentNode.removeChild(el);// хитрая ошибка }
Node > Document, Element, TextNode > appendChild/removeChild > firstChild/lastChild > childNodes > getAttribute/setAttribute
Window > setTimeout/clearTimeout > концепция кадров > Некоторый контроль над браузером > alert/confirm/prompt
События > addEventListener/attachEvent > фазы просачивания и перехвата > удаление обработчиков > не используйте html аттрибуты!
События
function on(el, event, fn) { if (el.addEventListener) { el.addEventListener(event, fn, false); } else if (el.attachEvent) { el.attachEvent(on + event, fn); } else { // выдать ошибку – странный браузер } on(element, click, function() { alert(Hi); });
События element.addEventListener(click, function() { alert(hi); }, false); // … // скрытая ошибка element.removeEventListener(click, function() { alert(hi); }, false);
События var listener = function() { alert(hi); }; element.addEventListener(click, listener, false); // … element.removeEventListener(click, listener, false);
Стили > element.style.borderBottom = 1px solid red; > document.defaultView (хорошие браузеры) > element.currentStyle (только IE)
Reflow for (var i = 0; i < array.length; i++) { element.innerHTML += array[i]; // возможен reflow if (element.offsetWidth > 50) { // тут уж точно reflow // do something }
AJAX > Asynchronous JavaScript And XML > Баги и особенности в разных браузерах > Используйте библиотечные реализации
Comet > server push > Периодически опрашиваем сервер > Помним о висячих соединениях
DOM: Вопросы
Best practices
Bad parts > Глобальные переменные > Оператор + > typeof > with и eval > Ложные массивы > == и != > false, null, undefined, NaN > Автоматическая вставка ;
Bad parts function myFunc() { return { ok: true }; }
Bad parts function myFunc() { return { ok: false }; }
Bad parts function myFunc() { return; // упс { ok: false }; }
Bad parts function myFunc() { return; { // блок ok: false }; }
Bad parts function myFunc() { return; { ok: false // label }; }
Bad parts function myFunc() { return; { ok: false // бессмысленный оператор }; }
Bad parts function myFunc() { return; { ok: false; }; }
Bad parts function myFunc() { return; { ok: false; }; // пустой оператор }
Bad parts function myFunc() { return; // код недостижим, но JS промолчит { ok: false; }; }
Bad parts
Good parts > функции, замыкания > операторы || и && > JSON, {}, [] > динамические объекты и типы > JSLint
Good parts
Патерны: локальная глобальность (function(window, undefined) { var document = window.document, navigator = window.navigator, location = window.location; // ваш код }) (window);
Патерны: синглетон var singleton = (function() { var privateVar = 3; return { publicFn: function(arg) { return arg + privateVar; } }; }) (); singleton.publicFn(5);
Патерны: callback Array.prototype.each = function(fn) { for (int i = 0; i < this.length; i++) { fn.call(this, this[i], i); } }; var myNumbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; myNumbers.each(function(el, i) { // this === myNumbers });
Патерны: условные операторы function(arg1, arg2) { var name = arg1 || arg2 || unknown; // вместо: var other = arg1; if (!other) { other = arg2; } if (!other) { other = unknown; }
Патерны: длинный список параметров // кривовато: function fn(arg1,arg2, arg3, arg4, arg5, arg6 …); // лучше: function fn(cfg) { cfg.arg1, cfg.arg2… } fn({ arg1: ss });
Патерны: полиморфные функции function ajax(url, fn) { var method = get; if (typeof(url) !== string) { method = url.method; fn = url.fn; url = url.url; } // do ajax … } ajax(myUrl, myCallback); ajax({ method: post, url: myUrl, fn: myCallback });
Патерны: цепочечные вызовы var obj = { initialize : function() { return this; }, animate : function() { return delayController; } }; obj.initialize().animate().oncomplete(function(){ // работа по завершению анимации });
Performance > контролируйте reflow > помните о живых колекциях > осторожно работайте с DOM > пользуйтесь DocumentFragment > используйте локальные переменные > сжимайте свой код обфускатором
Отладка > FireBug, Draggonfly, WebInspector > IE: Visual Studio, Companion.JS, DebugBar > debugger > console.log() > Старые добрые window.alert()
Best Practices: Вопросы
Libraries: JQuery > Легковесная, простая, мощная > Основана на селекторах близких к CSS > Практикует «ненавязчивость»
Libraries: JQuery $(#myButtonId).click( function(){ $.ajax(/myActionUrl).done(function(response) { var el = $( ); el.html(response); $(#results).append(el); });
Libraries: ExtJS > Тяжелая библиотека компонентов > Легка в освоении > Хорошая архитектура > Много компонентов out-of-box
Libraries: ExtJS Ext.create('Ext.window.Window', { title: 'Hello', height: 200, width: 400, layout: 'fit', items: { xtype: 'grid', border: false, columns: [{header: 'World'}], store: Ext.create('Ext.data.ArrayStore', {}) } }).show();
Libraries > Dojo > Prototype > SmartClient > GWT
Что упустили? > Наследование (подробнее) > Детали синтаксиса > Система типов > Многое другое
Что почитать? > Дэвид Флэнаган: JavaScript. Подробное руководство > JavaScript: The Good Parts. Douglas Crockford > High Performance JavaScript. Nicholas C. Zakas > boosting-tips-from-nicholas-zakas > > >
Что посмотреть? > The Good Parts. > Speed up you javascript > 10 things Ive learned from jquery source
Вопросы
Домашнее задание > прикручиваем джаваскрипт к нашему toprankу > используем JQuery