Java Script
Как бы учебник
- Операторы JavaScript
- Массивы JavaScript
- Объекты JavaScript
- Особенности функций в JavaScript
- ООП JavaScript - наследование
- Область видимости переменной в Javascript
- Клиентский (браузерный) JavaScript
- JavaScript Strict Mode
- Масштабируемые JavaScript приложения
- 10 несуразностей и секретов JavaScript
- Используем console на полную
Крайне полезная информация
Это надо обработать
- Тесты производительности циклов, работы с массивами и т.д.
- JavaScript Гарден
- Модульный подход в JavaScript
- Случайное перемешивание массива
- Javascript наследование для чайников
- Операторы, их особенности в JS
- JavaScript Comparison and Logical Operators
- Путь асинхронного самурая
- «Лапша» из callback-ов — будьте проще
- Как избавиться от пристрастия к синхронности
- Спагетти в последовательном вызове асинхронных функций. Теория и практика
- javascript - XMLHttpRequest в цикле
- javascript - XMLHttpRequest подробный анализ примера
- Многопоточный яваскрипт
- работаем с объектами в примерах
- 10 лучших функций на JavaScript - в комментах тьма полезностей
- ОПТИМИЗИРУЕМ JS
- http://pyramidin.narod.ru/clientref13/ -очень хорошо описаны функции, их стандартные методы, свойства и использование
- Побитовые или поразрядные операции в конце для js
- Прототипы в JavaScript
- Стыкуем компоненты в JavaScript
- Стыкуем асинхронные скрипты
- GCC: интеграция с Google Closure Library
- 3d -javascipt
- свой Uploader с нуля
- document-write
- создаем элементы DOM
- Заполнение массива одинаковыми значениями
- Производительность простых и сложных конструкций в JavaScript
обработка событий в примерах
Контекст
- Ключевое слово this в javascript — учимся определять контекст на практике
- Привязка контекста (this) к функции в javascript и частичное применение функций
- Правильный захват контекста в Javascript
- JavaScript: что делает Function.call.apply(…)?
- Стратегия (шаблон проектирования)
Библиотеки
- JavaScript-фреймворк qooxdoo 1.6 - новое слово в вебинтерфейсах
Несколько интересных проектов с помощью которых можно динамически создавать векторные рисунки.
- Статья - Пробуем ремесло рисования с помощью ArtisanJS
- Страница разработчика ArtisanJS
- Высокопроизводительная библиотека динамического рисования Html5 - полностью самодостаточная
- Кросс-браузерное решение
- Поддерживается как свободное рисование так и работа с векторными формами
Полезные трюки
http://habrahabr.ru/post/155093/
Как работает Array.prototype.slice.call
Для того, чтобы из аргументов JavaScript функции "отрезать" первые Х значений, используется метод:
Array.prototype.slice.call(arguments, X);
Например такая функция вернет "3,4":
(function(){ var args = Array.prototype.slice.call(arguments, 2); alert(args); // Returns: 3,4 })(1, 2, 3, 4);
Таким образом, такой подход используется когда нужно срезать входящие параметры функции JavaScript.
Array.prototype.concat.apply
Для объединения более двух массивов используется concat().
var a = [1, 2], b = ["x", "y"], c = [true, false]; var d = a.concat(b, c); console.log(d); // [1, 2, "x", "y", true, false];
For concatenating just two arrays, using push.apply() can be used instead for the case of adding elements from one array to the end of another without producing a new array. With slice() it can also be used instead of concat() but there appears to be no performance advantage from doing this.
var a = [1, 2], b = ["x", "y"]; a.push.apply(a, b); console.log(a); // [1, 2, "x", "y"];
Современный метод bind
В современном JavaScript для привязки функций есть метод bind. Он поддерживается большинством современных браузеров, за исключением IE<9, но легко эмулируется.
Этот метод позволяет привязать функцию к нужному контексту, и даже к аргументам.
Синтаксис bind:
var wrapper = func.bind(context[, arg1, arg2...])
- func Произвольная функция
- wrapper Функция-обёртка, которую возвращает вызов bind. Она вызывает func, фиксируя контекст и, если указаны, первые аргументы.
- context Обертка wrapper будет вызывать функцию с контекстом this = context.
- arg1, arg2, … Если указаны аргументы arg1, arg2... — они будут прибавлены к каждому вызову новой функции, причем встанут перед теми, которые указаны при вызове.
Простейший пример, фиксируем только this:
function f() { alert(this.name); } var user = { name: "Вася" }; var f2 = f.bind(user); f2(); // выполнит f с this = user
Использование для привязки метода sayHi к новому объекту User:
function User() { this.id = 1; this.sayHi = function() { alert(this.id); }.bind(this); } var user = new User(); setTimeout(user.sayHi, 1000); // выведет "1"
Object.defineProperty или как сделать код капельку лучше
оригинал статьи тоже ребята старались
Этот краткий пост-заметку или температурный бред (в Одессе похолодало, да) хочу посвятить такой прекрасной функции, как Object.defineProperty (и Object.defineProperties). Активно использую её уже около двух месяцев, так как поддержка старых браузеров (в том числе и IE8) в проекте, который я сейчас реализую, не требуется (завидуйте).
Как положено статье на хабре, приведу краткое описание того, что она делает. Object.defineProperty добавляет новое свойство, обладающее неким нестандартным для обычного свойства поведением, и принимает три аргумента:
- Объект, который мы модифицируем, добавляя новое свойство
- Свойство (строка), которое, собственно, хотим добавить
- Дескриптор: объект, содержащий «настройки» нового свойства, например аццессоры (геттер, сеттер)
Дескриптор может содержать следующие свойства:
- value (любое значение: строка, функция...) — значение, которое получит определяемое свойство объекта (геттер и сеттер в данном случае определить нельзя)
- writable (true/false) — можно ли перезаписать значение свойства (аццессоры тоже не доступны)
- get (функция) — геттер (value и writable определить нельзя)
- set (функция) — сеттер (value и writable определить нельзя)
- configurable (true/false) — можно ли переопределить дескриптор (использовать Object.defineProperty над тем же свойством)
- enumerable (true/false) — будет ли свойство перечисляться через for..in и доступно в Object.keys (плохая формулировка)
var o = {}; Object.defineProperty(o, "a", {value : 37, writable : true, enumerable : true, configurable : true}); var bValue; Object.defineProperty(o, "b", {get : function(){ return bValue; }, set : function(newValue){ bValue = newValue; }, enumerable : true, configurable : true});
Лучше меня объяснит MDN Object/defineProperty. Благо, даже английский знать не надо, и так всё понятно.
Если нужно определить сразу несколько свойств, можно использовать Object.defineProperties, который принимает два аргумента: объект, требующий изменений и объект с определяемыми ключами. MDN: Object/defineProperties.
// Код сперт с MDN Object.defineProperties(obj, { "property1": { value: true, writable: true }, "property2": { value: "Hello", writable: false } // etc. etc. });
Теперь соль. Чего я вообще решил это запостить?
Так как в упомянутом выше проекте мне приходится использовать defineProperty не просто активно, а очень активно, код стал, мягко говоря, некрасивым. Пришла в голову простейшая идея (как я до этого раньше-то не додумался?), расширить прототип Object, сделав код сильно компактнее. Плохой тон, скажете вы, засерать прототип Object новыми методами.
Откуда вообще взялось это мнение? Потому что все объекты унаследуют это свойство, которое, при обычной модификации прототипа, становится перечисляемым в for..in. На душе становится тепло, когда вспоминаешь о том, что я описал выше, а именно, о свойстве дескриптора enumerable. Действительно, расширив прототип таким образом:
Object.defineProperty( Object.prototype, 'logOk' { value: function() { console.log('ok') }, enumerable: false });
все объекты получат этот метод, но, при этом, он будет неперечисляемым (не нужно каждый раз использовать hasOwnProperty для проверки, есть ли такое свойство):
var o = {a: 1, b: 2} for( var i in o ) console.log( i, o[ i ] ); > a 1 > b 2 o.logOk(); > ok
Собственно то, ради чего я тут графоманю.
Во-первых определим метод define, чтоб каждый раз не вызывать перегруженную, на мой взгляд, конструкцию. Во-вторых определим метод extendNotEnum, который расширяет объект неперечисляемыми свойствами.
Object.defineProperties( Object.prototype, { define: { value: function( key, descriptor ) { if( descriptor ) { Object.defineProperty( this, key, descriptor ); } else { Object.defineProperties( this, key ); } return this; }, enumerable: false }, extendNotEnum: { value: function( key, property ) { if( property ) { this.define( key, { value: property, enumerable: false, configurable: true }); } else { for( var prop in key ) if( key.hasOwnProperty( prop ) ){ this.extendNotEnum( prop, key[ prop ] ); } } }, enumerable: false } });
Использование:
var o = { a: 1 }; o.define( 'randomInt', { get: function() { return 42; } }); o.extendNotEnum({ b: 2; }); for( var i in o ) console.log( i, o[ i ] ); > a 1 > randomInt 42 console.log( o.b ); > 2
И пошла… Еще два удобных метода:
Object.prototype.extendNotEnum({ extend: function() { var args = Array.prototype.slice.call( arguments ); args.unshift( this ); return $.extend.apply( null, args ); // если jQuery надоест, можно просто переписать под себя }, each: function( callback ) { return $.each( this, callback ); // аналогично } }); o.extend({c: 3}); // тупо добавляет новые свойства в объект o.each(function( key, value ) { // просто повторяет механизм $.each, перебирая все ключи и свойства });
Добавлять новые свойства можно до бесконечности, никто вам за это руку не откусит.
Вывод
Играйте в Денди, пишите на Javascript, который становится всё лучше и лучше.
комментарии
Еще один финт ушами для тех, кто определяет свойства прототипа только однажды, после определения функции-конструктора:
// запускается в консоли
Object.defineProperty( Object.prototype, 'awesomeprototype', {
set: function( object ) {
for( var prop in object ) {
Object.defineProperty( this.prototype, prop, {
value: object[ prop ],
enumerable: false
});
}
}
});
var X = function() {}
X.awesomeprototype = {
method: function() { alert( 'ok' ) }
};
var x = new X
x.method()
Стоит отметить что в литералах объектов свойства можно задавать через геттер и сеттер:
var o = { __someProperty : 42, get someProperty() { return this.__someProperty; }, set someProperty(v) { this.__someProperty = v; } }; o.someProperty; // 42 o.someProperty = 56; o.someProperty; // 56
Ну это так, к слову :)
deferred
- Асинхронные API и объект Deferred в деталяхGitHub
- Объект Deferred.
- Асинхронное программирование: концепция Deferred
- Deferred: все подробности
Шаблонизация в JavaScript
DOM
dom2json
http://coderepos.org/share/browser/lang/javascript/dom2json/dom2json.js?rev=30780 skips empty attributes that IE implicitly adds
/* * $Id: dom2json.js,v 0.2 2008/06/15 07:04:10 dankogai Exp dankogai $ */ (function(){ dom2json = function(dom){ var type = dom.nodeType; if (type == 3) return dom.nodeValue; if (type == 1){ var json = []; json.push(dom.nodeName); var attrs = dom.attributes; if (attrs.length){ var attr = {}; for (var i = 0, l = attrs.length; i < l; i++){ attr[attrs[i].name] = attrs[i].value; } if (0 /*@cc_on +1@*/){ attr['style'] = dom.style; } json.push(attr); } if (! dom.hasChildNodes()) return json; var kids = dom.childNodes; for (var i = 0, l = kids.length; i < l; i++){ var kjson = arguments.callee(kids[i]); if (kjson) json.push(kjson); } return json; } }; json2dom = function(json){ var i = 0; var tag = json[i++] var dom = document.createElement(tag); if (json[i].constructor == Object){ var attr = json[i++]; for (var name in attr){ dom.setAttribute(name, attr[name]); } } for (var l = json.length; i < l; i++){ dom.appendChild( json[i].constructor == Array ? arguments.callee(json[i]) : document.createTextNode(json[i]) ); } return dom; } })();
обход дерева DOM
/** * Рекурсивное перечисление дочерних элементов * * @param DomNode node * Родительский элемент, чьи дочерние узлы нужно перечислять. * * @return void */ function enumChildNodes(node) { // если нам передали элемент if (node && 1 == node.nodeType) { // берем его первый дочерний узел var child = node.firstChild; // пока узлы не закончились while (child) { // если этот узел является элементом if (1 == child.nodeType) { // что-то делаем с найденным элементом alert('элемент ' + child.tagName); // рекурсивно перечисляем дочерние узлы enumChildNodes(child); }; // переходим к следующему узлу child = child.nextSibling; }; }; }; // перечисляем содержимое body enumChildNodes(document.body);
Обход child nodes (потомков) определнного элемента в Javascript
JavaScript на заметку Комментировать Речь о том как корректно обойти элементы потомки DOM для данного элемента, простите за тафтологию
var object = document.getElementById('el'); for (var childItem in object.childNodes) { if (object.childNodes[childItem].nodeType == 1) object.childNodes[childItem].style.color = '#FF0000';
В данном примере мы берем некоторый элемент с id = 'el' и проходим по массиву его потомков (childNodes), при этом проверяем nodeType потомка, чтобы он был элементом страницы и если так, то окрашиваем его в КРАСНЫЙ цвет.
В принципе на базе этой конструкции можно организовать рекурсивный обход дерева всех потомков заданного элемента, если конечно возникнет такая необходимость, но пока я представляю только упрощенный вариант.
Здесь следует обратить внимание на проверку свойства nodeType == 1, дело в том что без этой проверки в обработку попадут и разрывы строк, т.е. символы "\n", которые тоже воспинимаются как ноды. Т.е. например конструкция вида:
так быстрее и меньше кода
var object = document.getElementById(‘el’).getElementsByTagName(‘*’); for(var i=0;object[i];i++){ object[i].style.color = ‘#FF0000′;
Sun, getElementsByTagName не поддерживает ИЕ, смысл его использовать?
К сожалению заметил, что данная конструкция в Opera выполняется некорректно (цикл for проходится два раза), никто с таким не встречался? Где-то всё же закралась моя ошибка или это ошибка браузера (проверял в 9.20, 9.50, 10.20), замечу, что в остальных браузерах всё выполняется верно.
var object = document.getElementById(‘el’); for (var childItem in object.childNodes) { } var object=document.getElementById(‘el’); for(var i=0;i<object.childNodes.length;i++) { if (object.childNodes[i].nodeType == 1) { // тут что-либо делаем } }