06DOMClosuresOOP.md 9.0 KB

Введение в DOM.

DOM (Document Object Model) - внутренние объекты и функции браузерного JS, которые позволяют работать с деревом тэгов текущей загруженной страницы. JS через это API имеет полный доступ ко всему тому, что есть в HTML и CSS.

Корень

Корнем дерева элементов DOM является объект document

#Поиск элементов

Что бы найти элемент, нужно обратится к методу document, или любого другого элемента, в который нужно что-то найти:

var el  = document.getElementById("someId"); //обратите внимания, без #
var el2 = document.querySelector("#someId"); //поиск по любому селектору, аналог jQuery
var el3 = document.querySelectorAll("a");    //поиск всех тэгов a

Создание элементов DOM

document.createElement("a"); //обратите внимание, без <>

Добавление элементов:

var tr = document.createElement("tr");
var td = document.createElement("td");
var td2 = document.createElement("td");

tr.appendChild(td); //добавление ячейки в конец строки таблицы.
tr.insertBefore(tr.childNodes[0],td2); //добавление ячейки перед первой ячейкой (в самое начало строки таблицы)

Ссылка на родительский элемент находится в свойстве parentElement:

tr.childNodes[0].parentElement == tr

Свойства объектов или наборов объектов элементов в DOM

  • value - свойство а не функция для значения поля ввода.
  • attributes - объект attributes с атрибутами html-тэга. Также есть 4 функции для работы с атрибутами:
    • hasAttribute - проверка на наличие атрибута
    • getAttribute - чтение
    • setAttribute - запись
    • removeAttribute - удаление
  • style - объект стиля элемента
  • innerHTML - строка вложенного HTML в элементе.
  • innerText - строка вложенного текста в элементе.

События

Каждый элемент DOM содержит множество свойств on..., в которые вы можете занести тот или иной обработчик события:

document.onmousemove = function(){
    document.write("mouse move <br/>");
}

Так же можно добавлять обработчики используя метод элемента addEventListener:

document.addEventListener("mousemove",function(){
    document.write("mouse move <br/>");
});

Нюансы

Элемент в дереве

может встречаться только один раз. Вы не можете вставить элемент дважды в дерево. Если вы хотите создать копию элемента в вашем DOM-дереве, используйте cloneNode.

HTML/CSS

Всё, что вы видели в HTML/CSS может быть установлено как свойства объекта-узла DOM и тут же будет отображено в браузере

children и childNodes

  • Узлами (Node) может быть любой текст в HTML, в том числе обычный текст и тот или иной тэг. Дочерние элементы каждого элемента находятся в псевдомассиве childNodes
  • В псевдомассиве children находятся только дочерние узлы-тэги, но без обычного текста. например

Задание Сделайте любое предыдущее задание по конструированию HTML используя DOM, а не конструирование строки. Проанализируйте отличия.

Замыкания, приватные методы и данные.

One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. -— Guy Steele on the design of Scheme

Closures are one of those few curious concepts that are paradoxically difficult because they are so simple. Once a programmer becomes used to a complex solution to a problem, simple solutions to the same problem feel incomplete and uncomfortable. But, as we will soon see, closures can be a simpler, more direct solution to the problem of how to organise data and code than objects. -- Doug Hoyte

Функция в JS находится сразу в двух контекстах: динамическом (this, значения параметров) и лексическом (переменные из более высоких областей видимости в месте определения функции). Динамический контекст - это контекст вызова функции - значение параметров и окружение на момент вызова; лексический контекст - контекст определения функции, её вложенности в другие области видимости, доступ к которым функция имеет и после окончания выполнения функций-владельцев этих областей видимости.

makeAdder

function makeAdder(x){
    function adder(y){
        return x + y;
    }
    return adder
}

var add5 = makeAdder(5);
var greeter = makeAdder("Hi, ");

alert(add5(2));
alert(greeter("John"));

В примере выше 5,"Hi, ", 2 и "John" находятся в динамическом контексте вызова функции. А вот значение x в adder находится в лексическом контексте. На момент запуска функций add5 и greeter функции makeAdder уже давно отработали, однако значение x и область видимости продолжают присутствовать в функциях add5 и greeter. Это называется замыканием - данные в локальной области видимости отработавшей функции и код, который использует эти данные впоследствии. В широком смысле замыкание является объектом, так как хранит в единой сущности код и данные.

В контексте JS замыкания очень удобны для огораживания кода, сохранения состояния переменных "на будущее", для функций обратного вызова. Так же замыкания удобны для организации приватных полей у объектов JS.

makeCounter


function makeCounter(){
    var counter = 0;

    return function(){
        return counter++;
    }
}

Функция выше создает счетчик, значение которого можно узнать из возвращаемой анонимной функции. При этом счетчик увеличится на 1. Если расширить функционал данного примера для чтения и декремента счетчика, получим, например:


function makeCounter(){
    var counter = 0;

    function inc(){
        return counter++;
    }

    function dec(){
        return counter--;
    }

    function read(){
        return counter;
    }

    return [inc,dec,read];
}

Результатом выполнения makeCounter будет массив функций. Однако намного более наглядным будет создание именованного массива, т. е. объекта:


function makeCounter(){
    var counter = 0;

    function inc(){
        return counter++;
    }

    function dec(){
        return counter--;
    }

    function read(){
        return counter;
    }

    return {inc: inc, dec: dec, read: read};
}