Где формируется объект data js. Предопределенные объекты языка JavaScript. Исходное значение value

22 ответа

Отборочные

JavaScript имеет только один тип данных, который может содержать несколько значений: Объект . Массив - это особая форма объекта.

(Plain) Объекты имеют вид

{key: value, key: value, ...}

Массивы имеют форму

Оба массива и объекты отображают структуру key -> value . Ключи в массиве должны быть числовыми, тогда как любая строка может использоваться как ключ в объектах. Пара ключей-значений также называется "свойствами" .

Доступ к свойствам можно получить либо с помощью точечной нотации

Const value = obj.someProperty;

или нотация , если имя свойства не будет действительным JavaScript имя идентификатора , или имя - это значение переменной:

// the space is not a valid character in identifier names const value = obj["some Property"]; // property name as variable const name = "some Property"; const value = obj;

По этой причине элементы массива могут быть доступны только с использованием скобок:

Const value = arr; // arr.5 would be a syntax error // property name / index as variable const x = 5; const value = arr[x];

Подождите... как насчет JSON?

JSON - это текстовое представление данных, подобно XML, YAML, CSV и другим. Чтобы работать с такими данными, сначала необходимо преобразовать их в типы данных JavaScript, то есть массивы и объекты (и как это было объяснено). Как разбирать JSON объясняется в вопросе Parse JSON в JavaScript? .

Дополнительный материал для чтения

Как получить доступ к массивам и объектам является фундаментальным знанием JavaScript, и поэтому рекомендуется прочитать Руководство по JavaScript MDN , особенно разделы

Доступ к вложенным структурам данных

Вложенная структура данных представляет собой массив или объект, который относится к другим массивам или объектам, т.е. его значения представляют собой массивы или объекты. К таким структурам можно получить последовательное применение точечной или скобкой.

Вот пример:

Const data = { code: 42, items: [{ id: 1, name: "foo" }, { id: 2, name: "bar" }] };

Предположим, мы хотим получить доступ к name второго элемента.

Вот как мы можем сделать это шаг за шагом:

Как мы видим, data - это объект, поэтому мы можем получить доступ к его свойствам с помощью точечной нотации. Доступ к свойству items осуществляется следующим образом:

Data.items

Значение представляет собой массив, для доступа к его второму элементу мы должны использовать нотацию в виде скобок:

Data.items

Это значение является объектом, и мы снова используем точечную нотацию для доступа к свойству name . Поэтому мы в итоге получаем:

Const item_name = data.items.name;

В качестве альтернативы мы могли бы использовать условное обозначение для любого из свойств, особенно если имя содержало символы, которые сделали бы его недопустимым для использования точечной нотации:

Const item_name = data["items"]["name"];

Я пытаюсь получить доступ к свойству, но получаю только undefined назад?

В большинстве случаев, когда вы получаете undefined , объект/массив просто не имеет свойства с этим именем.

Const foo = {bar: {baz: 42}}; console.log(foo.baz); // undefined

В качестве альтернативы for...in с hasOwnProperty вы можете использовать Object.keys для получить массив имен свойств:

Object.keys(data).forEach(function(prop) { // `prop` is the property name // `data` is the property value });

Массивы

Чтобы перебрать все элементы массива data.items , мы используем цикл for:

For(let i = 0, l = data.items.length; i < l; i++) { // `i` will take on the values `0`, `1`, `2`,..., i.e. in each iteration // we can access the next element in the array with `data.items[i]`, example: // // var obj = data.items[i]; // // Since each element is an object (in our example), // we can now access the objects properties with `obj.id` and `obj.name`. // We could also use `data.items[i].id`. }

Можно также использовать for...in для итерации по массивам, но есть причины, по которым этого следует избегать: Почему "для (элемент var в списке)" с массивами, считающимися плохими практика в JavaScript? .

При увеличении поддержки браузера ECMAScript 5 метод массива forEach становится интересным альтернатива:

Data.items.forEach(function(value, index, array) { // The callback is executed for each element in the array. // `value` is the element itself (equivalent to `array`) // `index` will be the index of the element in the array // `array` is a reference to the array itself (i.e. `data.items` in this case) });

В средах, поддерживающих ES2015 (ES6), вы также можете использовать цикл for...of , который не только работает для массивов, но и для любого iterable :

For (const item of data.items) { // `item` is the array element, **not** the index }

В каждой итерации for...of непосредственно дает нам следующий элемент итерации, нет никакого "индекса" для доступа или использования.

Что делать, если "глубина" структуры данных мне неизвестна?

В дополнение к неизвестным ключам, "глубина" структуры данных (например, сколько вложенных объектов) она имеет, также может быть неизвестна. Как получить доступ к глубоко вложенным свойствам, как правило, зависит от точной структуры данных.

Но если структура данных содержит повторяющиеся шаблоны, например. представление двоичного дерева, решение обычно включает в себя рекурсивно доступ каждый уровень структуры данных.

Вот пример, чтобы получить первый лист node двоичного дерева:

Function getLeaf(node) { if (node.leftChild) { return getLeaf(node.leftChild); // x > 0)) // false, because 3^2 is greater than 5 console.log(arr.every(x => Math.pow(x, 2) < 5)) // true, because 2 is even (the remainder from dividing by 2 is 0) console.log(arr.some(x => x % 2 === 0)) // false, because none of the elements is equal to 5 console.log(arr.some(x => x === 5))

Array.prototype.find() и Array.prototype.filter()

Методы find() возвращают первый элемент, который удовлетворяет предоставленной функции обратного вызова. Метод filter() возвращает массив всех элементов, который удовлетворяет предоставленной функции обратного вызова.

Const arr = // 2, because 2^2 !== 2 console.log(arr.find(x => x !== Math.pow(x, 2))) // 1, because it the first element console.log(arr.find(x => true)) // undefined, because none of the elements equals 7 console.log(arr.find(x => x === 7)) // , because these elements are greater than 1 console.log(arr.filter(x => x > 1)) // , because the function returns true for all elements console.log(arr.filter(x => true)) // , because none of the elements equals neither 6 nor 7 console.log(arr.filter(x => x === 6 || x === 7))

Array.prototype.map()

Метод map() возвращает массив с результатами вызова предоставленной функции обратного вызова для элементов массива.

Const arr = console.log(arr.map(x => x + 1)) // console.log(arr.map(x => String.fromCharCode(96 + x))) // ["a", "b", "c"] console.log(arr.map(x => x)) // (no-op) console.log(arr.map(x => Math.pow(x, 2))) // console.log(arr.map(String)) // ["1", "2", "3"]

Array.prototype.reduce()

Метод reduce() уменьшает массив до одного значения, вызывая предоставленную функцию обратного вызова с двумя элементами.

Const arr = // Sum of array elements. console.log(arr.reduce((a, b) => a + b)) // 6 // The largest number in the array. console.log(arr.reduce((a, b) => a > b ? a: b)) // 3

Метод reduce() принимает необязательный второй параметр, который является начальным значением. Это полезно, когда массив, на который вы вызываете reduce() , может иметь нуль или один элемент. Например, если бы мы хотели создать функцию sum() , которая принимает массив в качестве аргумента и возвращает сумму всех элементов, мы могли бы написать это следующим образом:

Const sum = arr => arr.reduce((a, b) => a + b, 0) console.log(sum()) // 0 console.log(sum()) // 4 console.log(sum()) // 7

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

const data = { code: 42, items: [{ id: 1, name: "foo" }, { id: 2, name: "bar" }] }; const { items: [, { name: secondName }] } = data; console.log(secondName);

В приведенном выше примере создается переменная с именем secondName из ключа name из массива, называемого items , одинокая, говорит, пропускает первый объект в массиве.

Примечательно, что это, вероятно, слишком велико для этого примера, так как простой массив доступа легче читать, но он пригодится при разрыве объектов в целом.

Это очень краткое введение в ваш конкретный прецедент, деструктурирование может быть необычным синтаксисом, чтобы привыкнуть к нему. Я бы порекомендовал вам прочитать документацию по назначению Mozilla Destructuring Assignment, чтобы узнать больше.

Чтобы получить доступ к вложенному атрибуту, необходимо указать его имя, а затем выполнить поиск по объекту.

Если вы уже знаете точный путь, вы можете жестко закодировать его в своем скрипте следующим образом:

Data["items"]["name"]

это тоже работает -

Data.items.name data["items"].name data.items["name"]

Когда вы не знаете точного имени заранее, или пользователь предоставляет вам имя. Затем требуется динамический поиск по структуре данных. Некоторые предположили, что поиск может быть выполнен с использованием цикла for , но существует очень простой способ обхода пути с использованием Array.reduce .

Const data = { code: 42, items: [{ id: 1, name: "foo" }, { id: 2, name: "bar" }] } const path = [ "items", "1", "name"] let result = path.reduce((a,v) => a[v], data)

Путь - это способ сказать: сначала возьмите объект с ключевыми items , который оказывается массивом. Затем возьмите 1 элемент -st (0 индексных массивов). Последнее, возьмите объект с name ключа в этом элементе массива, который является строкой bar .

Если у вас очень длинный путь, вы можете даже использовать String.split чтобы сделать все это проще -

"items.1.name".split(".").reduce((a,v) => a[v], data)

Это просто обычный JavaScript, без использования сторонних библиотек, таких как jQuery или lodash.

Использование JSONPath будет одним из самых гибких решений, если вы хотите включить библиотеку: https://github.com/s3u/JSONPath (node и браузер)

Для вашего случая использования путь json:

$..items.name

Var secondName = jsonPath.eval(data, "$..items.name");

Var ourStorage = { "desk": { "drawer": "stapler" }, "cabinet": { "top drawer": { "folder1": "a file", "folder2": "secrets" }, "bottom drawer": "soda" } }; ourStorage.cabinet["top drawer"].folder2; // Outputs -> "secrets"

//parent.subParent.subsubParent["almost there"]["final property"]

В основном, используйте точку между каждым потомком, который разворачивается под ним, и когда у вас есть имена объектов, состоящие из двух строк, вы должны использовать нотацию ["obj Name"]. В противном случае достаточно точки;

добавим, что доступ к вложенным массивам будет происходить так:

Var ourPets = [ { animalType: "cat", names: [ "Meowzer", "Fluffy", "Kit-Cat" ] }, { animalType: "dog", names: [ "Spot", "Bowser", "Frankie" ] } ]; ourPets.names; // Outputs "Fluffy" ourPets.names; // Outputs "Spot"

Еще один полезный документ, описывающий описанную выше ситуацию: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Basics#Bracket_notation

Доступ к собственности с помощью точечного хождения: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors#Dot_notation

Если вы ищете один или несколько объектов, которые соответствуют определенным критериям, у вас есть несколько вариантов, используя query-js

//will return all elements with an id larger than 1 data.items.where(function(e){return e.id > 1;}); //will return the first element with an id larger than 1 data.items.first(function(e){return e.id > 1;}); //will return the first element with an id larger than 1 //or the second argument if non are found data.items.first(function(e){return e.id > 1;},{id:-1,name:""});

Есть также single и singleOrDefault они работают так же, как first и firstOrDefault соответственно. Разница лишь в том, что они будут бросать, если найдено более одного совпадения.

для дальнейшего объяснения query-js вы можете начать с этого поста

Старый вопрос, но как никто не упоминал lodash (просто подчеркивание).

Если вы уже используете lodash в своем проекте, я думаю, что это элегантный способ сделать это в сложном примере:

Get(response, ["output", "fund", "data", "0", "children", "0", "group", "myValue"], "")

то же самое, что:

Response.output.fund.data.children.group.myValue

Разница между первой и второй опцией заключается в том, что в Оптим 1 , если у вас есть одно из отсутствующих свойств (undefined), в пути вы не получите ошибку, он возвращает вы третий параметр.

Для фильтра массива lodash есть _.find() , но я бы предпочел использовать регулярный filter() . Но я все же считаю, что вышеприведенный метод _.get() очень полезен при работе с действительно сложными данными. В прошлом я столкнулся с действительно сложными API-интерфейсами, и это было удобно!

Я надеюсь, что это может быть полезно для тех, кто ищет варианты для обработки действительно сложных данных, которые подразумевает название.

Что такое библиотека JavaScript, которая предоставляет целый беспорядок полезных помощников functional programming без расширения каких-либо встроенных объектов.

Решение: var data = { code: 42, items: [{ id: 1, name: "foo" }, { id: 2, name: "bar" }] }; var item = _.findWhere(data.items, { id: 2 }); if (!_.isUndefined(item)) { console.log("NAME =>", item.name); } //using find - var item = _.find(data.items, function(item) { return item.id === 2; }); if (!_.isUndefined(item)) { console.log("NAME =>", item.name); }

Доступ к динамически многоуровневому объекту.

Var obj = { name: "salut", subobj: { subsubobj: { names: "I am sub sub obj" } } }; var level = "subobj.subsubobj.names"; level = level.split("."); var currentObjState = obj; for (var i = 0; i < level.length; i++) { currentObjState = currentObjState]; } console.log(currentObjState);

Статья, в которой рассмотрим, какие в jQuery существуют методы для работы с data-атрибутами и внутренним хранилищем Data.

Назначение HTML 5 data-атрибутов

В HTML5 к любому элементу документа можно добавить пользовательские атрибуты. Назначение данных атрибутов веб-разработчик определяет самостоятельно, но в большинстве случаев они предназначены для хранения некоторой информации, которую затем можно использовать в скриптах JavaScript. Пользовательские атрибуты всегда начинаются с data-* :

Работа с data-атрибутами посредством методов attr и removeAttr

Выполнение действий над атрибутами data в jQuery обычно осуществляется с помощью методов: attr и removeAttr .

// получить значение атрибута data у первого элемента текущего набора $("селектор").attr("data-*"); // добавить или изменить значение атрибута data у всех выбранных элементов $("селектор").attr("data-*","значение"); // удалить значение атрибута data у всех найденных элементов 1 способ - с помощью attr $("селектор").attr("data-*",null); 2 способ - с помощью removeAttr $("селектор").removeAttr("data-*");

Например, выведем значение data-атрибутов элемента div с id="phone-1" в консоль браузера:

// получим значения data-атрибутов var phoneInfo = "Наименование: " + $("#phone-1").attr("data-name") + "; Цена: " + $("#phone-1").attr("data-price"); // вывести значения в консоль console.log(phoneInfo);

Данный метод (attr) возвращает значение data-атрибута в виде строки.

Например, добавим атрибут data-year к вышеприведённому элементу:

$("#phone-1").attr("data-year", 2016);

Более детально разобраться, как работать с данными методами можно в статье jQuery - Работа с атрибутами HTML элементов .

jQuery - data-атрибуты и метод data

Метод data используется в jQuery не для общения с data-атрибутами. Его основное предназначение - это чтение данных из внутреннего хранилища jQuery ($.cache) или запись в него некоторой информации.

Внутреннее хранилище jQuery - это некий контейнер, в который можно помещать произвольную информацию, связанную с определённым DOM-элементом текущей страницы.



Но, тем не менее, данный метод может выполнять чтение HTML5 data-атрибутов, и помещать их во внутреннее хранилище. Это случается только в том случае, если в хранилище jQuery нет ключа с именем, равным имени data-атрибута. В противном случае вы получите значение из хранилища $.cache .

Таким образом работать с data-атрибутами посредством метода data имеет смысл только в том случае, если дальнейшая работа с ними будет вестись через хранилище jQuery.

Пример, в котором рассмотрим, как метод data работает с data-атрибутом:

// это действие поместит data-атрибут price в хранилище (если его нет в хранилище) $("#book-1").data("price"); //значение 420 руб. // изменим значение data-атрибута price элемента с помощью attr $("#book-1").attr("data-price","513 руб."); // прочитаем значение price (т.к. данное значение есть в хранилище $.cache, то оно будет взято из него) $("#book-1").data("price"); //значение 420 руб. // удалим ключ price, который связан с элементом book-1, из хранилища $("#book-1").removeData("price"); // прочитаем значение price (т.к. данного значения нет в хранилище jQuery, то оно будет взято из data-атрибута и помещено в $.cache) $("#book-1").data("price"); //значение 513 руб.

В методе data ключ соответствует имени data-атрибута без приставки data- .

// если у элемента div с id="pencil" нет ключа color в хранилище jQuery, то прочитаем значение атрибута data-pencil и поместим его значение в $.cache $("#pencil").data("color");

Кроме этого, если в окончании имени data-атрибута (после data-) содержится дефисы ("-"), то при обращении к нему с помощью метода data буквы стоящие перед дефисом должны быть заменены на заглавные, а сами дефисы убраны. Например, имя атрибута data-last-name должно быть указано в методе data как lastName .

Ещё один момент при работе с методом data заключается в том, что когда jQuery разбирает значение data-атрибута, то он пытается привести его значение (строку) к соответствующему типу JavaScript (булевскому значению, числу, объекту, массиву или null). Например, значение "420" преобразуется в число 420. Если значение data-атрибута является объектом (начинается с " { ") или массивом (начинается с " [ "), то jQuery использует для разбора значения метод parseJSON . Это означает то, что содержимое атрибута должно иметь валидный JSON синтаксис (включая указания имен свойств в двойных кавычках). Но если попытка разобрать значение data-атрибута окажется не удачной, то оно останется в исходном в виде (т.е. в виде строки).



В итоге, метод data используется для выполнения следующих операций (в зависимости от указанных аргументов):

1. Получение значения ключа, связанного с элементом, из внутреннего хранилища jQuery:

$("селектор").data("ключ");

Данный вариант метода data выполняет одно из следующих действий:

  • Чтение data-атрибута (имя которого соответствует указанному ключу) у первого элемента текущего набора, помещение его в хранилище, и возвращение значение этого ключа в качестве результата. Данное действие данный метод выполняет только в том случае, если у элемента есть data-элемент соответствующий ключу и в контейнере $.cache у данного элемента нет записи с указанным ключом.
  • Получает значение указанного ключа из хранилища jQuery. Это действие метод data выполняет только в том случае, если в $.cache у элемента есть указанный ключ.
  • возвращает значение undefined или пустой объект, если ни одно из вышеперечисленных действий не выполняется.

Если в результате выборки $("селектор") возвращается несколько элементов, то данный метод возвращает значение только для первого элемента из полученного набора.

2. Получение всех данных в виде объекта JavaScript из хранилища jQuery, связанных с указанным элементом:

// вызов метода data осуществляется без аргументов $("селектор").data();

Более детально этот вариант метода data осуществляет следующее:

  • Автоматически помещает data-атрибуты во внутреннее хранилище jQuery. Это действие он выполняет только для тех data-атрибутов, имён (ключей) которых нет на текущий момент в хранилище jQuery.
  • Возвращает объект, состоящий из пар ключ-значение, связанных с текущим элементом.
  • 3. Метод data применяют не только для чтения значений, но и для записи данных (ключ-значение), ассоциированных с некоторым элементом DOM во внутреннее хранилище jQuery.

    // 1 вариант (сохранить указанную пару ключ-значение для каждого выбранного элемента): $("селектор").data(ключ,значение); // ключ (строка) // значение (данные любого типа) // 2 вариант (установить набор пар ключ-значение (объект) для всех найденных элементов): $("селектор").data(obj); // obj - объект JavaScript, содержащий пары ключ-значение

    Пример работы с методом data:

    //помещение в хранилище jQuery ключа price со значением 550 $("#book-js").data("price",550); // прочитать информацию, связанную с элементом #book-js из хранилища (автоматическое помещение data-атрибута name в хранилище) $("#book-js").data(); // получим значение ключа price элемента #book-js $("#book-js").data("price"); // 550 // получим значение ключа price элемента #book-js $("#book-js").data("name"); // "JavaScript"

    Методы для работы с data-хранилищем jQuery

    Рассмотрим, какие ещё есть методы в jQuery для работы с data хранилищем кроме data .

    Метод removeData

    Данный метод предназначен для удаления данных, связанных с определённым элементом, из внутреннего хранилища jQuery. Данный метод не работает с data-атрибутами, поэтому все соответствующие ключу data-атрибуты удалены не будут.

    Синтаксис метода removeData:

    // 1 вариант - без параметров (удаляет все данные, связанные с текущим элементом, из внутреннего контейнера jQuery. Если в результате выборки будет возвращено несколько элементов, то метод removeData выполнит своё действие (удаление данных из $.cache) для каждого элемента. $("селектор").removeData(); // 2 вариант - со строковым параметром, содержащим название ключа, который необходимо удалить у всех найденных элементов $("селектор").removeData("ключ"); // 3 вариант - предназначен для удаления несколько пар данных, связанных с элементом, из внутреннего хранилища jQuery $("селектор").removeData("ключ1 ключ2 ..."); // 4 вариант - аналогичен 3 варианту, только ключи указываются посредством массива $("селектор").removeData(["ключ1","ключ2",...]);

    Удалим несколько пар ключ-значений, ассоциированных с элементом с id="book-js" из хранилища jQuery:

    // чтение всех ключ у элемента #book-js (автоматическое помещение data-атрибутов в data-контейнер jQuery) $("#book-js").data(); // удаление 2 ключей, связанных с #books-js из data-контейнера jQuery $("#book-js").removeData(["price","name"]);

    Функция $.data()

    Данная функция выполняет действия аналогичные методу data , но в отличие от него работает на более низком уровне. Поэтому в большинстве случаев используют именно метод data , т.к. он является более удобным инструментом для работы с внутренним хранилищем jQuery.

    Данная функция предназначена только для работы с jQuery хранилищем и в отличие от метода $("селектор").data() не извлекает данные из HTML 5 data-атрибутов.

    Синтаксис функции jQuery.data() :

    // 1 вариант - сохранение информации в jQuery хранилище $.data(element,key,value); // element - DOM-элемент, с которым будет связана пара ключ-значение // key - ключ (строка), который будет ассоциироваться со значением // value - значение (любой тип данных за исключением undefined) // 2 вариант - получение информации из jQuery хранилища $.data(element,key); // element - DOM-элемент, ассоциированный с данными // key - название, с которым связано искомое значение // 3 вариант - возвращение всех данных связанных с указанным элементом из data-хранилища $.data(element); // element - DOM-элемент, связанный с данными

    Пример использования функции $.data() для сохранения информации, связанной с определённым DOM-элементом, в хранилище jQuery:

    // сохранение в хранилище информации, связанной с элементом id="book-html" $.data(document.getElementById("book-html"),"name","HTML в действии"); // добавление ещё одной порции информации, связанной с этим же элементом $.data(document.getElementById("book-html"),"price","760"); "760" // получение данных из хранилища jQuery, связанных с элементом id="book-html", в виде объекта var obj = $.data(document.getElementById("book-html")); // получения значения name объекта var name = obj.name; // получения значения price объекта var price = obj.price;

    Функция $.removeData()

    Эта функция также как и метод removeData применяется для удаления данных из внутреннего хранилища jQuery.

    $.removeData() является низкоуровневой функцией, также как и $.data() . Поэтому более удобным вариантом является использование метода data() вместо функции $.data() .

    Использование функции jQuery.removeData() :

    // 1 вариант - удаление всей информации из хранилища связанной с указанным элементом $.removeData(element); // element - DOM-элемент, с которым связаны данные, подлежащие удалению // 2 вариант - удаляет пару ключ-значение из набора данных связанных с указанным элементом $.removeData(element,key); // element - DOM-элемент, ассоциированный с данными // key - ключ, определяющий набор информации (ключ-значение), который необходимо убрать из data-контейнера jQuery

    Демонстрация использования функции removeData:

    // помещение атрибутов data в хранилище jQuery $("#book-css").data(); // получения ключа price из хранилища jQuery $("#book-css").data("price"); // 1170 // получения ключа name из хранилища jQuery $("#book-css").data("name"); // "CSS для профессионалов" // удаление из хранилища ключа price $.removeData(document.getElementById("book-css"),"price"); // при получении несуществующего ключа элемента получаем значение undefined $.data(document.getElementById("book-css"),"price"); //undefined

    Функция $.hasData()

    Эта функция определяет, имеет ли элемент, какие-либо данные во внутреннем хранилище jQuery.

    Применение $.hasData() :

    $.hasData(element); // element - DOM-элемент, который нужно проверить на наличие данных в $.cache

    Функция hasData возвращает true , если в хранилище есть какие-либо данные связанные с указанным элементом. В противном случае данная функция возвращает false .

    Внутреннее хранилище $.cache используется также самой библиотекой jQuery. Один из примеров - это использование его для хранения кода обработчиков событий jQuery.



    Пример использования функции hasData:

    // проверка данных во внутреннем хранилище связанных с элементом #book-css $.hasData(document.getElementById("book-css")); //false // поместим значение во внутреннее хранилище $("#book-css").data("name","CSS для профессионалов"); // проверка данных во внутреннем хранилище связанных с элементом #book-css $.hasData(document.getElementById("book-css")); //true // удалим значение из внутреннего хранилища $.removeData(document.getElementById("book-css")); // проверка данных во внутреннем хранилище связанных с элементом #book-css $.hasData(document.getElementById("book-css")); //false

    Разобраться, как работать в jQuery с data-атрибутами, которые появились в спецификации языка HTML5, можно в статье "jQuery – Методы attr и removeAttr" . Эти методы (attr и removeAttr) используются не только для управления data-атрибутами, но и любых других атрибутов HTML элементов.

    В этой главе:

    В языке JavaScript имеется ряд предопределенных объектов, которыми можно пользоваться при написании сценариев. К ним относятся такие объекты, как Array, Boolean, Date, Function, Math, Number, RegExp и String, а так же примитивный объект Object. В ранних версиях языка в него были также включены объекты документа (window, document), однако сейчас они исключены из ядра языка JavaScript, и относятся к определению объектной модели документа (DOM), о которой речь пойдет позже. Тем не менее, некоторые свойства этих объектов (document и window) нам уже знакомы.

    Впрочем, вернемся к встроенным объектам JavaScript в современном понятии. Все встроенные объекты, кроме Math и Date, имеют такие свойства, как constructor и prototype. Они используются для добавления новых свойств к существующим объектам, и описываются в контексте объекта Function.

    Объект Object

    Все объекты языка JavaScript являются наследниками объекта Object. Следовательно, все свойства и методы этого объекта имеются и у любого другого объекта JavaScript.

    Для объекта Object определено всего 2 свойства – constructor и prototype. Свойство constructor определяет функцию, создающую прототип объекта – именно всю функцию целиком, а не только ее название. Иначе говоря, рассмотрим вариант, когда определен некоторый объект test и создан экземпляр этого объекта tmp:

    Function test(version) { this.version = version; } tmp = new test(1);

    В таком случае, воспользовавшись свойством constructor, можно увидеть исходный код объекта test (рис. 4.6):

    Alert(tmp.constructor);

    Рис. 4.6.

    Для этого свойства, правда, имеется одно ограничение: оно не может вывести код встроенных объектов языка JavaScript: в таких случаях выводимая информация ограничивается именем функции прототипа и строкой «».

    Что касается свойства prototype, то оно позволяет получить доступ к функции прототипа текущего объекта. Использование этого свойства дает возможность изменять характеристики прототипа объекта. Например, можно добавить новое свойство для объекта типа test, воспользовавшись свойством prototype:

    Test.prototype.comment = "Новое свойство comment";

    Теперь все объекты типа test, включая уже созданный экземпляр tmp, будут иметь свойство comment, в чем несложно убедиться, применив такую проверку:

    Alert(tmp.comment);

    Более того, подобным образом допускается модернизировать и встроенные объекты JavaScript. Например, если нам требуется добавить к массивам такое свойство, как описание, то можно это сделать (разумеется, только в рамках текущего сценария!), сославшись на прототип объекта Array и добавив к нему соответствующее свойство:

    Array.prototype.description = "";

    Что касается методов, то их для объекта Object определено несколько больше – целых 5 штук. Это toSource, toString, watch, unwatch и valueOf, их краткое описание приведено в таблице 4.10.

    Методы toString и valueOf применимы практически ко всем встроенным объектам JavaScript, и, как правило, вызываются интерпретатором автоматически, когда возникает необходимость произвести преобразование. Что касается метода toSource, то он, фактически, просто выполняет работу для свойства constructor.

    Оставшиеся методы watch и unwatch – фирменные расширения, введенные еще в браузер Netscape 4 (сейчас поддерживаются так же Mozilla), – предназначены для отладки сценариев. Поскольку в рамках настоящего издания вопрос отладки программ рассматривается не будет, то и описывать эти методы нет смысла. Но на всякий случай, можете взять себе на заметку, что в Sea Monkey (но не в браузере Firefox) имеется отладчик сценариев – JavaScript Debugger.

    Объект Array

    Переменные-массивы содержат упорядоченные наборы значений, для удобства представленные в виде одной переменной. Мы не раз уже сталкивались с массивами (вспомните хотя бы массивы аргументов), теперь пришло время разобраться со всеми их свойствами и тонкостями применения.

    В отличие от других языков программирования, JavaScript не имеет такого типа данных, как массив. Но это ограничение обходится благодаря тому, что можно использовать предопределенный объект массива – Array. Для создания объекта-массива можно использовать один из следующих вариантов синтаксиса:

    ИмяМассива = new Array(элемент1, элемент2, ... элементN) ИмяМассива = new Array(ДлинаМассива)

    В первом случае перечисляются все составляющие массива, во втором – просто указывается количество элементов. Допускается также использование литералов при объявлении массива:

    Computers = ["PC", "Mac", "Sun"];

    Для заполнения элементов массива значениями, как и вообще для обращения к элементам массива, можно использовать индекс элемента. При этом следует учитывать, что индекс элементов массива начинается с нуля:

    Var colors = new Array(3); colors = "Красный"; colors = "Синий"; colors = "Зеленый";

    Довольно часто бывает удобно использовать предоставляемою языком JavaScript возможность заполнения массива непосредственно при его объявлении:

    Var colors = new Array("Красный","Синий","Зеленый");

    Чтобы узнать длину массива (количество элементов, из которых состоит массив), следует использовать свойство length:

    Var NumColors = colors.length;

    Помимо свойства length, в JavaScript предусмотрен также целый ряд других свойств и методов для работы с массивами. В частности, к числу свойств объекта Array, помимо length, относятся универсальные для всех объектов constructor и prototype, а так же предназначенные для использования массивов совместно с регулярными выражениями свойства index и input.

    Что касается методов, то помимо стандартных toSource, toString и valueOf, массивы наделены еще десятком собственных, перечисленных в таблице 4.11.

    Таблица 4.11. Методы объекта Array Метод Описание
    concat Объединяет два массива, и возвращает новый
    join Объединяет все элементы массива в одну строку
    pop Удаляет последний элемент из массива, и возвращает его
    push Добавляет один или более элементов в конец массива и возвращает его новую длину
    reverse Перемещает элементы массива таким образом, что первый становится последним, и наоборот
    shift Удаляет первый элемент массива и возвращает его
    slice Удаляет часть элементов массива, и возвращает новый массив
    splice Добавляет и (или) удаляет элемент из массива
    sort Сортирует элементы массива по алфавиту
    unshift Добавляет один или более элементов в начало массива, и возвращает новую длину массива (в MSIE 5.5 и 6 этот метод ничего не возвращает)

    Рассмотрим некоторые методы подробнее. Так, используя метод concat можно объединить 2 массива в одном:

    Var a = new Array("A1", "A2"); var b = new Array("B1", "B2"); var ab = a.concat(b);

    Здесь переменная ab станет массивом, содержащим все 4 элемента двух склеиваемых массивов. Если теперь к такому массиву применить метод join, то результатом будет строка, содержащая все элементы этого массива, перечисленные через запятую:

    Str = ab.join(); // получим str = "A1,A2,B1,B2"

    Что касается метода pop, то применив его к этому же массиву, мы получим в «B2» качестве ответа, а массив будет урезан до трех первых значений. А метод shift, наоборот, возвращает первый элемент (в нашем случае – «A1») и делает то же самое с массивом с той лишь разницей, что оставшиеся элементы сдвигаются вперед.

    Чтобы лучше понять, как работают эти и другие методы с массивами, обратимся к следующему примеру, приведенному в листинге 4.3.

    Листинг 4.3. Работа с массивами

    Этот же пример можно посмотреть в файле array.html, заодно можно будет просмотреть все результаты его работы в браузере (см. рис. 4.7).

    Рис. 4.7. Результат применения метода splice: возвращаемый массив и изменения

    Массивы также могут быть многомерными, т.е. элементом массива может быть другой массив. В таком случае для обращения к элементу массива используют следующий синтаксис:

    Array2D="Элемент 0,0" Array2D="Элемент 0,1" ... Array2D[N][N]="Элемент N,N"

    Пример заполнения и вывода двумерного массива можно найти в файле arrays.html, там же находится и интерактивный пример практически для всех методов массива.

    Объект Boolean

    Объект Boolean – оболочка для одноименного типа данных. Для определения объекта типа Boolean используется следующий синтаксис:

    BooleanObj = new Boolean(значение)

    Здесь значение – инициализирующее выражение, которое, в случае необходимости, будет приведено к true или false. Если вы укажете такое значение, как 0, null, false, NaN, undefined, или пустую строку, то результатом инициализации объекта типа Boolean будет false, а в случае любого другого значения – true.

    Не следует путать примитивные логические значения true и false с типами данных true и false объекта Boolean. Например, если объявить переменную x и присвоить ей значение объекта Boolean, инициализированного при помощи значения false, она все равно при сравнении будет представлять собой значение истины (true):

    X = new Boolean(false); // при сравнении if (x) получим true

    В то же время, если просто присвоить переменной примитивный тип данных false, то она именно его и получит:

    X = false; // при сравнении if (x) получим false

    Что касается применения этого объекта, на практике, то его можно использовать, в качестве функции для того, чтобы преобразовывать значения любых других типов в булевские:

    A = 100; x = Boolean(a); // x получит true if (x) {...}

    Но, на самом деле, вряд ли вы это будете делать, поскольку при необходимости подобные преобразования производятся интерпретатором JavaScript автоматически – в примере выше можно было бы сразу написать «if(a)…», а необходимое в данном случае преобразование будет сделано в любом случае.

    Объект Date

    Для работы с датами в языке JavaScript не предусмотрено специального типа данных, однако, как и в случае с массивами, имеется специальный объект Data. Для создания объекта даты можно воспользоваться любым из следующих способов:

    New Date() new Date(Миллисекунды) new Date("Дата_в_виде_строки")

    В первом случае создается объект Date с текущим временем, во втором – следует указать количество миллисекунд, прошедших с 1 января 1970 года. Если указывается дата в виде строки, то она должна быть вида «Feb 28, 2005». Допустимо также задать дату, используя целочисленные значения для года, месяца, дня и т.п.:

    New Date(Год, Месяц, День [, Час, Минута, Секунда, Миллисекунда])

    Разумеется, в этом случае можно избегать указывания секунд и миллисекунд, тем более что миллисекунды даже не поддерживались в старых версиях браузеров. Кроме того, в JavaScript до версии 1.3 не поддерживаются даты ранее 1 января 1970 года. Что касается формата значений, которые указывают в строке, то год – это любое 4-значное число (если указать 2-значное, то к нему добавится 1900), месяц число – от 0 (январь) до 11 (декабрь), а день – от 0 до 31. Соответственно, значения времени так же ограничены: для часов это будет целое от 0 до 23, для секунд и минут – от 0 до 59, а для миллисекунд – от 0 до 999. Таким образом, чтобы в качестве значения объекта типа Date указать 9 мая 2005 года, следует написать:

    Var anyday = new Date (2005, 5, 9);

    А если нужно получить текущее значение даты и времени, то никаких параметров не требуется вовсе:

    Var now = new Date();

    Начиная с JavaScript 1.3, диапазон дат может находиться в пределах 100 миллионов дней до и после 01.01.1970 (в сумме это почти 550 тысяч лет!). В этой же версии появилось требование всегда указывать год в четырехзначном формате, во избежание ошибок, связанных со сменой столетий.

    Для работы с объектом Date предусмотрено 2 свойства – constructor и prototype, а так же множество методов, позволяющих выделять нужную часть даты (год, месяц, число, время), выводить ее в том или ином формате и т.д. Все они перечислены в таблице 4.12.

    Таблица 4.12. Методы объекта Date Метод и его синтаксис Описание
    getDate() Возвращает день месяца в локальном времени
    getDay() Возвращает день недели в локальном времени
    getFullYear() Возвращает год в локальном времени
    getHours() Возвращает текущее время (часы) в локальном времени
    getMilliseconds() Возвращает текущее время (миллисекунды) в локальном времени
    getMinutes() Возвращает текущее время (минуты) в локальном времени
    getMonth() Возвращает текущее время (месяц) в локальном времени
    getSeconds() Возвращает текущее время (секунды) в локальном времени
    getTime() Возвращает текущее время в виде количества в локальном времени
    getTimezoneOffset () Возвращает смещение времени в минутах относительно времени по Гринвичу в локальном времени
    getUTCDate() Возвращает день месяца в универсальном времени
    getUTCDay() Возвращает день недели в универсальном времени
    getUTCFullYear() Возвращает год в универсальном времени
    getUTCHours() Возвращает текущее время (часы) в универсальном времени
    getUTCMilliseconds() Возвращает текущее время (миллисекунды) в универсальном времени
    getUTCMinutes() Возвращает текущее время (минуты) в универсальном времени
    getUTCMonth() Возвращает текущее время (месяц) в универсальном времени
    getUTCSeconds() Возвращает текущее время (секунды) в универсальном времени
    getYear() Устаревший. Возвращает год в коротком (двухзначном) формате в универсальном времени
    parse(строка_даты) Возвращает количество миллисекунд, прошедших с 1 января 1970 года до значения, указанного в параметре, в локальном времени
    setDate(день) Устанавливает день месяца в локальном времени
    setFullYear(год) Устанавливает год в локальном времени
    setHours(часы) Устанавливает время (часы) в локальном времени
    setMilliseconds (миллисекунды) Устанавливает время (миллисекунды) в локальном времени
    setMinutes(минуты) Устанавливает время (минуты) в локальном времени
    setMonth(месяц) Устанавливает время (месяц) в локальном времени
    setSeconds (секунды) Устанавливает время (секунды) в локальном времени
    setTime (миллисекунды) Устанавливает время в миллисекундах для определенной даты в локальном времени
    setUTCDate(день) Устанавливает день месяца в универсальном времени
    setUTCFullYear (год) Устанавливает год в универсальном времени
    setUTCHours(часы) Устанавливает время (часы) в универсальном времени
    SetUTCMilliseconds(миллисекунды) Устанавливает время (миллисекунды) в универсальном времени
    setUTCMinutes (минуты) Устанавливает время (минуты) в универсальном времени
    setUTCMonth(месяц) Устанавливает время (месяц) в универсальном времени
    setUTCSeconds (секунды) Устанавливает время (секунды) в универсальном времени
    setYear(год) Устаревший. Устанавливает год в локальном времени, в качестве значения года допустим двузначный формат
    toGMTString() Устаревший. Преобразует дату в строку, соответствующую времени по Гринвичу
    toLocaleString() Возвращает дату и время в виде строки, соответствующей по формату установкам локальной системы
    toLocaleDateString() Возвращает дату в виде строки, соответствующей по формату установкам локальной системы
    toLocaleTimeString() Возвращает время в виде строки, соответствующей по формату установкам локальной системы
    toSource() Возвращает объект даты в представлении литерала
    toString() Возвращает объект даты в представлении строки
    toUTCString() Преобразует дату в строку в формате, соответствующему универсальному времени
    UTC(параметры) Возвращает количество миллисекунд, прошедших с 1 января 1970 года в универсальном времени. В качестве параметров указывают год, месяц и день, а также (опционально) – часы, минуты, секунды и миллисекунды
    valueOf() Возвращает дату в виде примитивного значения

    Несмотря на такое обилие методов, работать с объектом Date достаточно просто: следует только понять принцип наименования методов:

    • методы, начинающиеся с «set», предназначены для установки даты и времени в объектах Date;
    • методы, начинающиеся с «get», предназначены для извлечения даты, времени или их частей из объектов Date;
    • методы, начинающиеся с «to», возвращают дату и время (или их части) в виде строковых значений;
    • методы, содержащие «UTC», отличаются от аналогичных только тем, что работают с форматом универсального времени (т.е. отображает время по Гринвичу, с учетом смещения относительно текущего часового пояса).

    Таким образом, остается только добавлять к get или set название необходимой части даты или времени, чтобы получить или установить нужный параметр, при необходимости используя еще и UTC. Ну а когда требуется получить результат в «человеческом» виде, используют методы to. Так же следует запомнить, что для работы с годом надо всегда использовать только полноформатные функции (т.е. getFullYear или getUTCFullYear, а не getYear).

    Строковое представление даты в JavaScript имеет следующий формат:

    ДеньНедели Месяц Число Год Часы:Минуты:Секунды GMT±Смещение

    Чтобы наглядно увидеть представление дат, а заодно и рассмотреть, как это работают функции вроде toString, рассмотрим то, что все они возвращают на вывод. При этом первое, что может прийти на ум для просмотра работы той или иной функции – это использовать вывод текста в документ:

    Document.writeln(DateObject.toString()); document.writeln(DateObject.toGMTString()); // и т.д.

    Но, на самом деле, поскольку функций много, было бы хорошо предварительно писать, что за действие было выполнено:

    Document.writeln("DateObject.toString()" + DateObject.toString());

    А теперь вновь подумаем о том, сколько же строк мы хотим вывести таким способом на самом деле. Даже если учитывать возможности метода «скопируй и вставь», поддерживаемого всеми текстовыми редакторами, это не застрахует от ошибок, подобных такой:

    Document.writeln("DateObject.toLocaleString()" + DateObject.toString());

    Но, как гласит девиз IBM, люди должны думать, а машины – работать. Так что подумаем, как заставить работать компьютер, заодно избавив себя от необходимости вводить лишние байты кода, для чего обратимся к листингу 4.4.

    Листинг 4.4. Вывод разных типов дат и функция eval

    Методы объекта Date

    Прежде всего, в нем определена функция printDate, которая, собственно и выводит в документ дату в том или ином виде. Вернее, она выводит дату в нашем случае, но в принципе она может выводить все, что угодно – главное, чтобы принимаемый ею аргумент был законченным фрагментом кода JavaScript. При этом сначала код выводится как есть (т.е. печатается строковая переменная в исходном виде), а затем выводится результат выполнения, для чего используется функция eval. В результате, написав один раз такую функцию, можно в дальнейшем по ходу всего документа обращаться к ней, избавив себя от необходимости дважды вводить практически один и тот же текст.

    Вслед за функцией вывода расположено создание объекта типа Date, которому присваивается значение 2005 год, 3 месяц (апрель, т.к. январь – нулевой), 1 число, 14 часов, 30 минут, 45 секунд. Далее открывается на запись документ и последовательно вызывается функция printDate для 6 различных методов объекта Date. Результатом работы данного сценария будет 6 строк, содержащих пары значений из метода и результата его работы, разделенных двоеточием (рис. 4.8).

    Рис. 4.8. Вывод одной и той же дата различными методами

    Следует отметить, что метод toSource, выводящий дату во внутреннем представлении программы, поддерживается только Mozilla-браузерами. Кроме того, формат вывода дат всеми остальными методами так же может несколько различаться в разных браузерах. Вы можете загрузить такой пример в различные программы просмотра и самостоятельно посмотреть, что они выдадут (файл date.html).

    Объект Function

    Предопределенный объект Function определяет строку кода на JavaScript, которая должна быть исполнена, как функция. Для объявления объекта Function используется следующий синтаксис:

    ИмяФункции = new Function([аргумент1, аргумент2, ...аргументN], ТелоФункции)

    В данном случае в качестве имени функции может быть использовано имя любой переменной, или свойство уже существующего объекта. Также возможно указывать объект типа Function в качестве значения для обработчика событий объекта. Допустим, если мы хотим сделать собственный обработчик события типа «завершение загрузки документа» (document.onload), то можем написать так:

    Document.onload = new Function([Аргумент1, ...аргументN], ТелоФункции);

    Аргументы в данном случае – это параметры, передаваемые функции, ну а тело функции – собственно код, который должен быть выполнен при обращении к данному объекту-функции. Например, можно написать такой вариант объекта, который будет использоваться для возведения числа в квадрат:

    Var SquareObj = new Function("x", "return x*x");

    Здесь SquareObj – имя переменной, x – принимаемый аргумент, а «return x*x» – тело функции. Обратите внимание на тот факт, что не только тело функции, но и принимаемые ей аргументы заключены в кавычки, а также и на то, что имя типа объекта, как это принято в JavaScript, пишется с большой буквы (Function).

    Использование созданных таким способом переменных аналогично использованию переменных любых других типов:

    Var a = 5 + SquareObj(2); // получим 9

    Фактически, объект типа Function всегда можно представить и в виде обычной функции, объявленной при помощи ключевого слова function. Так, то же возведение во вторую степень можно описать так:

    Function SquareFunc(x) { return x*x; }

    Соответственно, и использовать объявленную таким методом функцию (в данном случае – именно функцию в «чистом» виде, а не процедуру), можно аналогичным способом:

    Var a = 5 + SquareFunc(2); // тоже получим 9

    Таким образом, присвоение переменной значения в виде функции с использованием объекта Function является аналогичным объявлению функции как таковой. Но при этом у этих подходов имеется и отличие: если SquareObj – это переменная, значение которой является ссылкой на объект, созданный при помощи объекта Function, то SquareFunc – это имя функции. Соответственно, при исполнении программы они ведут себя тоже по-разному: для объекта типа функция интерпретатор всякий раз, когда ему попадется переменная (в нашем случае – SquareObj) будет полностью оценивать весь код функции, а для объявленных обычным способом функций код оценивается лишь при первом проходе. Это отличие может быть непринципиальным, если функция выполняет разовую работу, однако использование переменных, созданных на основе объекта Function, существенно снижает эффективность работы программы в циклах. Поэтому на практике использование объектов-функций – большая редкость, но, тем не менее, иногда они могут быть удобны, например, для добавления методов другим объектам.

    Объект Function имеет стандартные для JavaScript свойства constructor и prototype, а так же ряд собственных:

    Arguments – массив, соответствующий параметрам функции arguments.callee – соответствует телу функции. arguments.caller (устаревшее) – указывает на имя функции, из которой произошло обращение к объекту; arguments.length – указывает на число параметров функции. length – указывает на количество аргументов, ожидаемых функцией (а не на поступившее их число, как в случае с argument.length);

    ВНИМАНИЕ
    Все свойства arguments могут быть видны только «изнутри» функции, причем, начиная с JavaScript 1.4, arguments более не является свойством объекта Function, а является самостоятельной локальной переменной, неявно присутствующей в любой функции. Фактически, для Function остается всего 1 собственное свойство – length.

    Кроме свойств, у объекта Function имеется несколько методов. Так, метод apply позволяет применить метод одного объекта к другому, а метод call – вызывать метод иного объекта в контексте текущего. К сожалению, реализация этих методов на практике явно оставляет желать лучшего. Так что остается лишь упомянуть про стандартные для JavaScript методы toString, toSource и valueOf, имеющиеся так же и у объекта Function.

    Объект Math

    Math – встроенный объект языка JavaScript, имеющий в качестве методов и свойств основные математические константы и функции. Например, свойство PI объекта Math содержит значение числа Пи (π), что приблизительно равно 3,1416, а метод sin возвращает синус указанного числа.

    Кроме числа π, объект Math имеет следующие свойства:

    • E – основа натуральных логарифмов (приблизительно 2,718)
    • LN10 – натуральный логарифм 10 (приблизительно 2,302)
    • LN2 – натуральный логарифм 2 (приблизительно 0,693)
    • LOG10E – десятичный логарифм E (приблизительно 0,434)
    • LOG2E – двоичный логарифм E (приблизительно 1,442)
    • SQRT1_2 – квадратный корень из 0,5 (приблизительно 0,707)
    • SQRT2 – квадратный корень из 2 (приблизительно 1,414)

    Поскольку все свойства объекта Math являются предопределенными константами, то создавать другие объекты типа Math не только не требуется, но и недопустимо, а обращаться к ним надо всегда одним и тем же способом, например:

    Var CircleLength = diameter * Math.PI;

    Помимо свойств, для объекта Math определены также методы, соответствующие основным математическим функциям. Все они перечислены в таблице 4.13.

    Таблица 4.13. Математические методы JavaScript Метод и его синтаксис Описание
    abs(число) Возвращает абсолютное значение аргумента
    atan2(y, x) Возвращает число в диапазоне от -? до?, представляющее угол (в радианах) между осью X и точкой (x,y). Обратите внимание, что первым аргументом является Y-координата
    exp(число) Возвращает E в указанной степени (экспонентный логарифм)
    ceil(число), floor(число) Возвращает значение, являющееся ближайшим большим (ceil) или меньшим (floor) целым числом
    min(число1, число2), max(число1, число2) Возвращают меньшее (min) или большее (max) число из двух сравниваемых аргументов
    sin(число),cos(число), tan(число),asin(число), acos(число),atan(число) Возвращают результат выполнения стандартных тригонометрических функций – синуса, косинуса, тангенса, арксинуса, арккосинуса и арктангенса
    pow(база, экспонента) Возвращает базу в степени экспоненты
    random() Возвращает псевдослучайное число от 0 до 1
    round(число) Возвращает значение, округленное до ближайшего целого
    sqrt(число) Возвращает квадратный корень числа

    Как и в случае со свойствами, для использования методов объекта Math следует ссылаться непосредственно на сам объект, а не на его копии. Для примера напишем функцию, которая будет возвращать диаметр исходя их площади круга:

    Function CircleDiam(Square) { Radius = Math.sqrt(Square / Math.PI) ; }

    Чтобы воспользоваться ею на практике, можно прибегнуть к помощи методов prompt и alert:

    Var sq = prompt("Введите площадь",1); var di = CircleDiam(sq); alert("Диаметр окружности: "+di);

    Работу этих и других методов объекта Math можно посмотреть в файле math.html.

    Объект Number

    Объект Number является объектным представлением простых числовых типов. Он имеет специальные свойства для числовых констант, – таких, как «максимальное число», «не число» и «бесконечность». Для создания нового объекта типа Number используют следующий синтаксис:

    New Number(Значение)

    На практике использование объекта Number чаще всего сводится к использованию его констант при проверке аргументов на допустимость и отслеживания ошибок времени выполнения. Например, чтобы проверить, является значение переменной числом или нет, можно использовать такой способ:

    If (x!=Number.NaN);

    В данном случае условие будет истинным, если переменная x содержит число, поскольку она сравнивается со специальным значением – NaN, означающим «не число». Помимо NaN, можно использовать и другие специальные значения – все они являются свойствами объекта Number:

    • MAX_VALUE – максимальное возможное число
    • MIN_VALUE – минимальное возможное число
    • NaN – не число (Not a Number)
    • NEGATIVE_INFINITY – «отрицательная бесконечность», специальное значение, возвращаемое в случае переполнения
    • POSITIVE_INFINITY – «положительная бесконечность», специальное значение, возвращаемое в случае переполнения

    Все эти свойства являются константами, поэтому для их использования создавать новый объект типа Number не требуется. Помимо вышеперечисленных свойств, для Number определены так же стандартные свойства constructor и prototype

    Кроме свойств, объект Number, разумеется, имеет и методы. Помимо стандартных методов toSource, toString и valueOf, в JavaScript 1.5 появились 3 новых собственных метода объекта Number – toExponential, toFixed и toPrecision. Все они предназначены для преобразования чисел в строки на основе того или иного формата. Так, метод toExponential преобразует число в строку в виде числа с экспонентой, метод toFixed – в строку, содержащую число с фиксированным количеством знаков после запятой, а метод toPrecision использует один из этих способов, в зависимости от числа и выделенного количества знаков.

    Исследуем с эти методы подробнее, для чего рассмотрим их синтаксис:

    Метод([ЧислоЗнаков])

    Очевидно, что для всех методов число знаков обозначает число знаков после запятой, однако если для метода toFixed значением по умолчанию (т.е. если ничего не указано) будет 0, то для toExponential и toPrecision – количество знаков, необходимое для вывода числа полностью. Чтобы лучше разобраться с работой и отличиями всех этих методов, рассмотрим их на примере листинга 4.5:

    Листинг 4.5. Методы toExponential, toFixed и toPrecision

    Методы объекта Number

    Здесь мы вновь (как и в листинге 4.4) воспользовались функцией, выводящей сначала выражение, а затем – результат его интерпретации, только назвали ее в данном случае printNumber. Далее следует собственно объявление переменной, над которой будут производиться вычисления. В данном случае мы объявили ее как объект типа Number, хотя, на самом деле, можно было бы ограничиться и простым объявлением переменной (x = 12.45678). Наконец, документ открывается для записи и в него сначала выводится значение переменной x без каких-либо явных преобразований (но мы уже знаем, что на самом деле тут автоматически применяется метод toString()), после чего все три исследуемых метода вызываются сначала без указания числа знаков, а затем – с параметрами 2 и 4. Результатом работы этого сценария будет 10 строк, содержащих пары «выражение: результат обработки» (рис. 4.9).

    Рис. 4.9.

    В заключение остается еще раз отметить, что данные методы появились лишь в JavaScript 1.5 и, соответственно, не работают в браузерах Netscape 4, MSIE 4/5 и Opera до версии 7.0. В то же время, они обеспечивают более гибкие возможности форматирования чисел при выводе, чем, скажем, метод round() объекта Math.

    2011-08-01 // Есть вопросы, предложения, замечания? Вы можете

    До создания HTML5 работать с атрибутами в HTML элементах, мягко говоря, не доставляло удовольствия. Приходилось использовать такие атрибуты, как rel или class . А некоторые разработчики даже создавали свои атрибуты.

    Но дело координально изменилось когда HTML5 предоставил нам возможность использования своих data атрибутов. Теперь довольно легко можно сохранять дополнительные данные стандартными средствами.

    Как же работают дата атрибуты?

    Название говорит само за себя. Дата атрибуты хранят в себе какие-то данные, заданные вами. Они всегда начинаются с приставки data- и заканчиваются чем то более понятным для разработчика (по спецификации допускаются только символы нижнего регистра и дефисы). Элемент может содержать в себе любое количество дата атрибутов.

    Пример использования атрибутов для хранения данных о пользоватле:

  • Calvin
  • Конечно, эти данные не слишком помогают конечному пользователю, так как он их попросту не видит, но дата атрибуты очень широко используются в современных веб технологиях.

    Приведем пример кнопки для удаления чего-либо на вашей странице:

    Delete

    Все необходимые параметры у вас под рукой и готовы для отправки в скрипт бекэнда. Никаких больше rel атрибутов или обработки ID или необходимого действия из других атрибутов.

    Что можно хранить?

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

    Чтение/запись атрибутов средствами javascript

    Вернемся к примеру с кнопкой и посмотрим как нам получить доступ к нужным атрибутам.

    // Это кнопка var button = document.getElementById("your-button-id"); // Получаем значение var cmd = button.getAttribute("data-cmd"); var id = button.getAttribute("data-id"); // Изменяем значение button.setAttribute("data-cmd", yourNewCmd); button.setAttribute("data-id", yourNewId);

    Довольно просто, не так ли? Теперь просто передавайте параметры cmd и id вашему приложению и выполняйте необходимый ajax запрос.

    Чтение/запись дата атрибутов при помощи jQuery.

    Приведем аналог на jQuery:

    // Получаем значение var cmd = $("#your-button-id").attr("data-cmd"); var id = $("#your-button-id").attr("data-id"); // Изменяем значение $("#your-button-id") .attr("data-cmd", yourNewCmd) .attr("data-id", yourNewId);

    Не путайте с методом data() . Хотя у них есть что-то общее, в целом это абсолютно разные вещи. Даже если вы не полностью знакомы с этими методами, просто используйте attr() .

    Использование dataset API

    HTML5 даже предлагает нам API для работы с data атрибутами, хотя IE10 и ниже не поддерживает его.

    Опять таки пример с кнопкой, но на этот раз при помощи dataset API:

    // Это кнопка var button = document.getElementById("your-button-id"); // Получаем значение var cmd = button.dataset.cmd; var id = button.dataset.id; // Изменяем значение button.dataset.cmd = yourNewCmd; button.dataset.id = yourNewId;

    Обратите внимание на отсутсвие приставки data и дефисов. Так же как и при работе со свойтсвами CSS в JavaScript вам потребуется "горбатый" регистр. Dataset API переводит имена атрибутов таким образом что data-some-attribute-name в HTML превращается в dataset.someAttributeName в JavaScript.

    Что можно делать с дата атрибутами

    Приведенные примеры - это только фундамент. Вы можете выполнять гораздо более сложные операции с дата атрибутами. Давайте рассмотрим несколько примеров.

    Фильтрация

    Допустим вы работаете со списком элементов и вам необходимо отфильтровать их по ключевому слову. Разместите ключевые слова в data атрибутах и при помощи небольшого итерационного скрипта обработайте их.

    • Ford
    • Chevrolet
    • ...

    Пример “на коленке”:

    $("#filter").on("keyup", function() { var keyword = $(this).val().toLowerCase(); $(".cars > li").each(function() { $(this).toggle(keyword.length < 1 || $(this).attr("data-models").indexOf(keyword) > -1); } ); } );

    Стилизация

    Конечно стили лучше применять посредством классов, но тоже самое можно сделать и при помощи data атрибутов. Вот так можно применить стиль к элементам, имеющим определенный data атрибут, независимо от его значниния. Сначал взглянем на HTML:

    А теперь CSS:

    { background: red; }

    Но как же учитывать значение атрибута? Вот так можно применить стиль ко всем элементам с атрибутом data-warning чье значение содержит в себе слово error:

    { color: red; }

    Настройка

    Известный фреймворк Bootstrap применяет data атрибуты для настройки своих JavaScript плагинов. Пример всплывающего окна:

    Popover on top

    Лучший способ хранить данные

    Дата атрибуты очень распространены в веб технологиях. Но самое важное то, что они полностью поддерживаются старыми браузерами и все глубже и глубже проникают в веб стандарты. А так стандарт HTML уже утверждён, то работать с ними можно уже сегодня и не бояться, что вдруг они пропадут завтра.

    В языке JavaScript имеется три типа объектов: встроенные объекты, объекты браузера и объекты, которые программист создает самостоятельно (рис. 2.1).

    Рис. 2.1. Объекты в сценариях JavaScript

    Каждый из этих типов имеет свое назначение и свои особенности.

    Встроенные объекты

    Ниже мы перечислили встроенные объекты, свойства и методы которых доступны в сценариях JavaScript без предварительного определения этих объектов:

    Здесь символом * отмечены встроенные объекты, определенные в языке Microsoft JScript версии 3.0. Эта версия реализована в браузере Microsoft Internet Explorer версии 4.0.

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

    Как работать со встроенными объектами?

    Достаточно просто. Программа создает реализации (instance) объектов, а затем обращается к свойствам и методам объектов.

    В качестве примера, имеющего практическое значение, рассмотрим документ HTML, в котором отображается текущая дата и время. Исходный текст этого документа вы найдете в листинге 2.1.

    Листинг 2.1. Файл chapter2/date/date.html

    Show date and time Show date and time

    Здесь сценарий JavaScript создает объект Data, применяя для этого ключевое слово new, знакомое всем поклонникам языка С++, и конструктор Date без параметров:

    var dt; dt = new Date();

    Создаваемый таким образом объект Data инициализируется текущей локальной датой, установленной у пользователя (а не на сервере Web, с которого был загружен соответствующий документ HTML).

    В следующей строке формируется текстовая строка даты:

    szDate = "Date: " + dt.getDate() + "." + dt.getMonth() + "." + dt.getYear();

    Значение календарного числа, номера месяца и года здесь получается при помощи методов getDate, getMonth и getYear, соответственно. Эти методы вызываются для объекта dt, содержащего текущую дату.

    Текстовая строка даты выводится в документ HTML с помощью метода write, определенного в объекте document:

    document.write(szDate);

    Этот способ мы уже использовали в примерах сценариев, приведенных в первой главе нашей книги.

    Заметим, что объект Date содержит также информацию о текущем времени. Эта информация извлекается для отображения с помощью методов getHours, getMinutes и getSeconds (соответственно, часы, минуты и секунды):

    document.write("Time: " + dt.getHours() + ":" + dt.getMinutes() + ":" + dt.getSeconds());

    Внешний вид документа HTML при его просмотре в окне браузера Microsoft Internet Explorer версии 4.0 показан на рис. 2.2.

    Рис. 2.2. Просмотр локальной даты и времени

    Применение других встроенных объектов мы продемонстрируем позже по мере изучения материала.

    Объекты браузера

    С точки зрения сценария JavaScript браузер представляется иерархически организованным набором объектов. Обращаясь к свойствам и методам этих объектов можно выполнять различные операции над окном браузера, загруженным в это окно документом HTML, а также над отдельными объектами, размещенными в документе HTML. Например, можно создавать новые окна браузера, загружая в них документы HTML, динамически формировать текст документа HTML, обращаться к полям форм, определенных в документе HTML и так далее.

    Объекты браузера являются тем интерфейсом, с помощью которого сценарий JavaScript взаимодействует с пользователем и документом HTML, загруженным в окно браузера, а также с самим браузером. В сценариях JavaScript вы не можете создавать новые классы на базе классов, соответствующих этим объектам, однако свойства и методы объектов браузера вам доступны.

    Иерархия объектов браузера

    Иерархия объектов браузера схематически показана на рис. 2.2.

    Рис. 2.2. Иерархия объектов браузера

    Объект window находится в корне иерархии. Когда в окно браузера загружается документ HTML, внутри этого объекта создаются другие объекты - document, parent, frame, location и top.

    Если в окно браузера загружается документ HTML с фреймами, то для каждого фрейма создается отдельное окно, причем это окно создается как объект window.

    Объект document содержит в себе другие объекты, состав которых полностью определяется документом HTML, загруженным в окно браузера. Это могут быть формы, ссылки на другие документы HTML или локальные ссылки внутри одного документа, объекты, определяющие адрес URL документа и так далее.

    Если в документе имеются формы, то они также представляются в виде иерархического набора объектов. Объект-форма может содержать в себе такие объекты, как кнопки, переключатели, поля для ввода текстовой информации.

    Обращаясь к свойствам перечисленных выше объектов, сценарий JavaScript может определить различные характеристики документа HTML, такие как, например, заголовок. Ему доступны все ссылки, размещенные в документе, а также содержимое полей форм, определенных в документе HTML.

    События, связанные с объектами

    Сделаем еще одно очень важное замечание относительно объектов браузера.

    С каждым таким объектом связывается определенный набор событий, обработка которых возможна в сценарии JavaScript.

    Например, с объектом window связаны события onLoad и onUnload. Первое из этих событий возникает, когда браузер завершает загрузку окна и всех расположенных в нем фреймов (если эти фреймы определены в окне). Второе событие возникает, когда пользователь завершает работу с документом, закрывая окно браузера или переключаясь на другой документ.

    Сценарий JavaScript может, например, при обработке события onLoad выводить для пользователя приветственное сообщение или запрашивать дополнительную информацию. При завершении работы с окном (когда возникает событие onUnload) сценарий может освобождать какие-либо ресурсы, связанные с этим окном, или выводить сообщение на экран монитора.

    С другими объектами браузера также связаны события. Мы расскажем о них при описании этих объектов.

    Объекты на базе классов, создаваемых программистом

    Многочисленные книги для начинающих, посвященные языку программирования С++, предлагают представить себе класс как структуру данных, где помимо обычных полей определены функции-методы для работы с этими данными. Так вот, в языке JavaScript для создания собственных классов используется прямо противоположный метод.

    Класс JavaScript создается как функция, в которой определены свойства, играющие роль данных. Что же касается методов, то они тоже определяются как функции, но отдельно.

    Приведем конкретный пример.

    Пусть нам нужно создать класс, предназначенный для хранения записи воображаемой телефонной базы данных. В этом классе нам нужно предусмотреть свойства для хранения имени, фамилии, номера телефона, адреса, а также специального признака для записей, закрытых от несанкционированного доступа. Дополнительно требуется разработать методы, предназначенные для отображения содержимого объекта в табличном виде, как это показано на рис. 2.3.

    Рис. 2.3. Просмотр содержимого записей

    Прежде всего займемся созданием собственного класса с названием myRecord. Пусть пока в нем не будет методов, мы добавим их позже.

    Искомый класс создается следующим образом:

    function myRecord(name, family, phone, address) { this.name = name; this.family = family; this.phone = phone; this.address = address; this.secure = false; }

    Нетрудно заметить, что описание нашего класса есть ни что иное, как функция конструктора. Параметры конструктора предназначены для установки свойств объекта при его создании на базе класса.

    Свойства определяются простыми ссылками на их имена с указанием ключевого слова this. Это ключевое слово здесь указывает, что в операторе выполняется ссылка на свойства того объекта, для которого вызван конструктор, то есть для создаваемого объекта.

    Обратите внимание, что наш конструктор инициализирует свойство с именем secure, записывая в него значение false. Соответствующий параметр в конструкторе не предусмотрен, что вполне допустимо.

    Как пользоваться определенным классом?

    На базе этого класса вы можете создать произвольное количество объектов. Ниже мы привели фрагмент сценария JavaScript, где на базе класса myRecord создается два объекта rec1 и rec2:

    var rec1; var rec2; rec1 = new myRecord("Иван", "Иванов", "000-322-223", "Малая Большая ул., д. 225, кв. 226"); rec2 = new myRecord("Петр", "Петров", "001-223-3334", "Большая Малая ул., д. 552, кв. 662"); rec2.secure = true;

    Объекты создаются при помощи оператора new, знакомого тем, кто составлял программы на языках С++ и Java. Здесь мы передаем конструктору параметры для инициализации свойств создаваемых объектов.

    Что же касается свойства с именем secure, то в объекте rec2 оно инициализируется уже после создания последнего. В него записывается значение true. Мы не изменяли свойство secure объекта rec1, поэтому в нем хранится значение false.

    Теперь наша задача - добавление в определенный нами класс новых методов с именами printTableHead, printTableEnd и printRecord. Первые два из этих методов выводят в документ HTML, соответственно, начальный и конечный фрагмент таблицы, а третий - строки таблицы, отражающие содержимое записей.

    В сокращенном виде новое определение класса myRecord представлено ниже:

    function printTableHead() { . . . } function printTableEnd() { . . . } function printRecord() { . . . } function myRecord(name, family, phone, address) { this.name = name; this.family = family; this.phone = phone; this.address = address; this.secure = false; this.printRecord = printRecord; this.printTableHead = printTableHead; this.printTableEnd = printTableEnd; }

    Здесь перед определением конструктора мы расположили определения для функций-методов нашего класса. Кроме этого, в конструктор добавлено определение новых свойств:

    this.printRecord = printRecord; this.printTableHead = printTableHead; this.printTableEnd = printTableEnd;

    После такого определения класса вы можете создавать объекты и обращаться к определенным методам:

    rec1.printTableHead(); rec1.printRecord(); rec1.printTableEnd(); rec2.printTableHead(); rec2.printRecord(); rec2.printTableEnd();

    Возвращаясь к документу, показанному выше на рис. 2.3, приведем его полный исходный текст (листинг 2.2).

    Листинг 2.2. Файл chapter2/NewObject/NewObject.html

    Просмотр записей Просмотр записей

    Определение нового класса myRecord и его методов мы расположили в области заголовка документа HTML, как это принято делать.

    Метод printTableHead выводит в документ HTML заголовок таблицы. Внешний вид этого заголовка зависит от содержимого свойств объекта.

    Прежде всего метод printTableHead проверяет свойство secure, получая его значение при помощи ключевого слова this:

    var szSec = ""; if(this.secure) szSec = " (Secure)"; else szSec = " (Unsecure)".fontcolor("red");

    Здесь это ключевое слово означает, что необходимо использовать свойство того объекта, для которого был вызван метод printTableHead.

    Если содержимое свойства secure равно true, в текстовую переменную szSec записывается строка " (Secure)". Если же оно равно false, в эту переменную заносится строка " (Unsecure)", причем для строки устанавливается красный цвет.

    Так как в JavaScript все текстовые строки (в том числе и литералы) являются объектами встроенного класса String, то для них можно вызывать определенные в этом классе методы. В частности, метод fontcolor позволяет установить цвет строки, чем мы и воспользовались.

    Далее метод printTableHead выводит в документ HTML оператор

    с параметром BORDER, с которого начинается определение таблицы, имеющей рамку. Надпись над таблицей задается с помощью динамически формируемого оператора . В эту надпись включается имя и фамилия, извлеченные из соответствующих свойств объекта, для которого был вызван метод printTableHead. Затем этот метод выводит надписи для столбцов таблицы.

    Метод printTableEnd выводит в документ HTML оператор

    , завершающий определение таблицы, а также пустой параграф для отделения таблиц, следующих друг за другом:

    function printTableEnd() { document.write(""); document.write("

    "); }

    Последний метод, определенный в нашем классе, называется printRecord. Он печатает содержимое первых четырех свойств объекта как строку таблицы, определенной в документе HTML только что описанной функцией printTableHead.

    Обратите внимание, что содержимое свойств объекта печатается наклонным шрифтом, для чего мы вызываем метод italics:

    document.write("Name:" + this.name.italics() + "");

    Определение класса myRecord мы уже описали выше.

    Перейдем теперь ко второй части нашего сценария, расположенной в теле документа HTML.

    Здесь мы создаем два объекта rec1 и rec2 на базе класса myRecord, а затем устанавливаем свойство secure объекта rec2 в состояние true.

    Как видите, применение собственного класса позволили сильно упростить задачу инициализации и отображения содержимого записей нашей воображаемой телефонной базы данных. Фактически мы свели эту задачу к вызовам нескольких методов, определенных заранее в нашем классе.