Объекты Javascript в примерах
Объекты (они же - ассоциативные массивы, хэши) и работа с ними в Javascript - реализованы не так, как в большинстве языков. С этим связано много ошибок и непоняток.
В этой статье описаны базовые свойства объектов javascript, создание и изменение, перечисление свойств и т.п.
Объект в javascript представляет собой обычный ассоциативный массив или, иначе говоря, "хэш". Он хранит любые соответствия "ключ => значение" и имеет несколько стандартных методов.
Метод объекта в javascript - это просто функция, которая добавлена в ассоциативный массив. Далее - подробнее.
Следующие два варианта создания объекта эквивалентны:
// эквивалентные записи
var o = new Object()
var o = {}
Есть два синтаксиса добавления свойств в объект. Первый - точка, второй - квадратные скобки:
// эквивалентные записи
o.test = 5
o["test"] = 5
Квадратные скобки используются в основном, когда название свойства находится в переменной:
var name = 'test'
o[name] = 5
Здесь имя свойства "test" является ключом в ассоциативном массиве, по которому лежит значение 5.
Доступ к свойству осуществляется точно так же:
alert(o.test)
alert(o['test'])
Если у объекта нет такого свойства, то результат будет 'undefined'
var o = {}
alert(o.nosuchkey) // => undefined
Никакой ошибки при обращении по несуществующему свойству не будет, просто вернется специальное значение undefined.
Проверка глобальной переменной
В javascript нельзя проверить существование глобальной переменной простым if:
if (x) { ... }
Если x не определен, то конструкция if (x) вызовет ошибку javascript.
Распространенное решение - использовать typeof:
if (typeof x != 'undefined') { ... } // или typeof(x)
Однако зная, что глобальная переменная в javascript - всего лишь свойство объекта window - мы можем записать проще:
if (window.x) { ... } // правильный аналог if(x)
// или
if (window.x !== undefined) // аналог typeof x ..
Все свойства объектов - public, т.е при определении свойства никак нельзя ограничить доступ к свойству. В javascript есть специальные выверты для создания private свойств, связанные с замыканиями. Они рассмотрены вместе с наследованием объектов.
Удаляет свойство оператор delete:
o.test = 5
delete o.test
o['bla'] = true
Свойства можно указывать непосредственно при создании объекта, через список в фигурных скобках вида {..., ключ : значение, ...}:
var o = {
test: 5,
bla: true
}
Получившийся объект можно изобразить так:

Как и в других языках, у объектов javascript есть методы.
Например, создадим объект rabbit с методом run
var rabbit = {}
rabbit.run = function(n) {
alert("Пробежал "+n+" метров!")
}
Добавление метода в объект - просто присвоение функции function(n) { ... } свойству rabbit.run.
Теперь можно запускать
var rabbit = {}
rabbit.run = function(n) {
alert("Пробежал "+n+" метров!")
}
rabbit.run(5) // Пробежал 5 метров
rabbit.run(7) // Пробежал 7 метров
Здесь не идет речь о классах, создании экземпляров и тому подобном. Просто - в любой объект в любое время можно добавить новый метод или удалить существующий.
Javascript - очень динамический язык, не правда ли?
Обычно хочется, чтобы метод не просто вызывался из объекта, но имел доступ к самому объекту, мог менять находящиеся в нем данные.
Для этого используется ключевое слово this:
for(var key in obj) {
… obj[key] …
}
В отличие от многих языков, this никак не привязано к объекту, а обозначает просто объект, вызвавший функцию.
Например,
function this1() {
var vasya = { name:'Вася' }
var petya = { name:'Петя' }
sayName = function() {
alert("Я - "+ (this.name ? this.name : 'безымянный') )
}
vasya.sayName = sayName
// один и тот же метод в двух объектах
petya.sayName = vasya.sayName
// тут - this будет petya
petya.sayName() // Я - Петя
// тут - this будет vasya
vasya.sayName() // Я - Вася
// а тут - вызывается метод глобального объекта window, у которого нет имени
sayName() // Я - безымянный
}
Запустить this1()
Более подробно о том, как работает this можно почитать в этой статье.
Для перебора всех свойств объекта используется специальный вид конструкции for, for..in:
for(var key in object) {
// key - название свойства
// object[key] - значение свойства
...
}
Например,
var o = {a:5, b:true}
for (var key in o) {
alert(key+':'+o[key])
}
Запустить
Это уже выходит за рамки текущей статьи, но вообще - существует еще одна форма перебора свойств, которая более надежна, особенно если используется библиотека типа prototype.
for(prop in object) {
if (!object.hasOwnProperty(prop)) continue
//...
}
Эта форма отфильтровывает свойства, которые принадлежат не самому объекту, а его прототипу. Поэтому она работает, даже если в прототип Object добавлены новые свойства.
Более элегантный вариант записи:
for(prop in object) if (object.hasOwnProperty(prop)) {
//...
}
|
А почему ничего не сказано про прототипы (aka классы)?
function a () { // объявляем класс
}
// добавляем метод для прототипа
a.prototype.b = function () {
alert ('test');
}
// создаем объект
var a = new a();
Извиняюсь, сам дурак
Хорошие статьи. Коротко, самое важное, без утаревших приемов, и всякой лабуды. Но я, собственно, по поводу Доступ к объекту из метода.
Раньше, было не нужно, а сейчас потребовалось, из повешанного на объект метода, получить ссылку не на объект его вызвавший, а на объект, на котором висит сам метод. Вроде вот он рядом :-), а как достать? Понимаю, что можно использовать прототип, но это нарушит всю задуманную задачу. Перекопал сегодня пол Интернета, но как то не смог ни чего найти. Такое чувство, что есть какая то простейшая возможность, но я её упустил.
Сам метод генерится динамически, и я, в принципе, могу жестко забить ссылку на объект, но это вроде не этично. :-)
Что есть "объект, на котором висит сам метод"?
Что есть "объект, на котором висит сам метод"?Извините, пару дней сюда заглядывал, ответов не было... и теперь только сейчас.
Например, есть элемент div c id="div", вешаем метод таким образом:
document.getElementById('div').metod = function() { alert('Ok!'); };
потом назначаем этот метод обработчиком события click.
document.get.ElementsByTagName('body')[0].onclick = document.getElementById('div').metod;
Так "не принято", но мне нужно именно так.
И теперь, нужно из самого метода получить ссылку на DIV, на котором он висит.
document.get.ElementsByTagName('body')[0].onclick = function() { document.getElementById('div').metod; }В тему: в javascript, в отличие от C/Java/... методы НЕ висят на объектах. Контекст вызова метода целиком зависит от того, как его вызвали.
Вот
как можно исползоват функции php в javascript
РНР это серверные скрипты... JavaScript это клиентская часть. Можно вызвать через AJAX сам РНР скрипт и результат его работы получить через XML (или в HTML на худой конец). А дальше делай с этими данными все что нужно.
Думаю гораздо удобней будет получить результат ввиде JSON строки.
А можно ли изменит порядок свойств объекта? Можно ли с объектом работать как с массивом т.е. использовать теже методы предусмотренные для объект Array?
Ну, ладно с предыдущим вопросом я разобрался. Ввод: нельзя. Другой ворос, можноли получить как-нибудь ссылку на свойство объекта, именно ссылку.
интересная статья. Много полезного узнал. Но вот интересно как можно вызывать метод объекта через setTimeout? Странно, вызов происходит, только метод не может получить доступ к свойствам объекта.
В примере ниже вызван метод объекта "metod" с правильным this
.... var self = this setTimeout(function() { self.method() }, 1000) ...То есть, правильный указатель this передается через замыкание. Очень распространенный трюк.
Почему, когда я пытаюсь объявить объект Google maps в глобале,
ничего не происходит?
var map = new google.maps.Map2(document.getElementById("map")); function mapsLoaded() { map.setCenter(new google.maps.LatLng(37.4419, -122.1419), 13); //Не работает }Если Array является объектом (встроенным) со свойствами constructor,length,prototype,concat,join etc..., то почему я не могу перечислить его свойства путем :
for (var key in Array) { alert(key+':'+ Array.prototype.hasOwnProperty(key)+'&') }или
for (var key in Array) { alert(key+':'+ Array.hasOwnProperty(key)+'&') }?
Array - это один объект (конструктор/функция), а Array.prototype - это другой объект, у каждого свои свойства, которые могут иметь атрибут DontEnum, что исключает их перечисление.
Хорошо, поправлюсь :
Вначале наведенные ответом вопросы : а как понять(узнать), какие атрибуты установлены у данного свойства ? И как вообще установить эти атрибуты ?
И собственно сам вопрос :
Если Array является объектом (встроенным) со свойствами constructor,length,prototype,concat,join etc..., то почему я получаю эти свойства у его прототипа, а не у него самого :
alert(Array.prototype.hasOwnProperty("join") ) // -1 alert(Array.hasOwnProperty("join")) // 0Тем более, что сказано в документации :
Этот метод не проверяет наличие свойства по цепочке прототипов; указанным свойством должен обладать именно сам объект. А пример выше показывает, что именно сам объект не обладает свойством, а обладает, наоборот, - прототип.
Короче , путаница получается - распутайте, плз.
Еще пример для размышления :
alert(Object.hasOwnProperty("prototype")) // -1 alert(Object.prototype.hasOwnProperty("prototype")) // 0Обратитесь к стандарту: http://javascript.ru/ecma/part12#a-12.6.4.
Там описано, как работает цикл
for .. in. Обратите внимание на шаг 5.Перечисляются только те свойства, у которых нет атрибута
DontEnum.Большинство свойств у родных объектов яваскрипт имеют
DontEnum, и поэтому не будут перечисляться в циклеfor..in.Атрибут
DontEnumне проверяется при прямом обращении, поэтомуArray.prototype.joinвыдаст, что метод все-таки есть.[quote]Атрибут DontEnum[/quote] Да про него уже скзали выше. Интересуют ответы на "наведенные вопросы" см выше по поводу аттрибутов ?!
А ответ на этот вопрос тоже должен быть не такой, как я понял , а такой :
alert(Array.hasOwnProperty("join")) // false, потому , что Array здесь ошибочно употреблен в качестве объекта типа Array, в то время , как в такой нотации он является объектом типа Function, т.к. возвращает ссылку на конструктор Array.
alert(Array.prototype.hasOwnProperty("join") ) // trueпотому , что Array.prototype здесь возвращает ссылку на прототип объектов,имеющих тип Array, который уже обладает этим собственным свойством.
Кстати, для
var a = new Array(); alert(a.hasOwnProperty("join")) // =falseпотому, что объект a действительно не имеет собственного Own свойства "join" , оно для этого объекта берется из его прототипа (на прототип объекта a указывает свойство prototype его конструктора Array.prototype),
У класса Array есть свой, "статический", метод join:
И в чём принципиальная разница между a и b в следующем коде.
var a = new Object(); function myFunc(){}; var b = new MyFunc();Я так понимаю ссылкой prototype (или [[prototype]]) и как следствие набором свойств и методов. Или ещё чем...? И можно ли сказать, что b создается как и а, но после создания b вызывается ещё и MyFunc() (с this указывающем на b)
Как я полагаю, Вы сами ответили на свой вопрос. Мне кажется, что все именно так.
Very good post, thanks a lot.
Подскажите пожалуйста!!!
Есть такой когд (смотреть ниже), где нужно передать id в функцию clickFunction().
В результате получаю null. Пробовал ввести id напрямую, т. е. "list", браузер не выводит вообще ничего.
<html> <head> <script type="text/javascript"> function clickFunction(elemId){ alert(elemId); } var getId = document.getElementById("list"); var altF = new clickFunction(getId); </script> <title></title> </head> <body> <ul id="list"> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> </ul> </body> </html>P.S.: заранее приношу ивинения, если пишу не туда.
Я "чайник"
<html>
<head>
<title></title>
</head>
<body>
<ul id="list">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</body>
</html>
<script type="text/javascript">
var getId = document.getElementById("list");
function clickFunction(elemId){
alert(elemId.id);
}
var altF = new clickFunction(getId);
</script>
Прошу прощения, читать так:
alert(elemId.nodeName);
var getId = document.getElementById("list");
function clickFunction(elemId){
alert(elemId.id);
}
var altF = new clickFunction(getId);
Прошу прощения если не заметил, но по-моему у вас нигде не написано, что объекты в Javascript передаются и копируются по ссылке.
И было бы интересно увидеть функцию clone, которая делала бы копирование объектов по значению.
function clone(obj){
var newObj = {}, i;
for(i in obj)
newObj[i] = obj[i];
return newObj;
}
TODO: Добавить рекурсивое клонирование
В этой функции есть ряд недостатков, аккуратнее с ней.
Не перепутан ли в статье этот пример:
Для этого используется ключевое слово this:
for(var key in obj) { … obj[key] … }И хотел спросить. Так я обращаюсь к свойствам объекта из метода:
var obj = { property : 0, a : 0, b : 0, c : 0 } obj.method = function(n) { this.property = n * this.a + ( this.b + n ) / this.c; }Возможно ли обращение без this?
Обращение к свойствам объекта из метода без
thisневозможно.Не нашел на сайте, где можно посмотреть как можно сделать так чтобы при наведении мыши на страницу происходило какое-то действие. Подскажите.
Извиняюсь за глупый вопрос)
var o = {} //создали объект o['test'] = 5 //добавили свойство alert(o['test']) //выводит 5Подскажите почему если вместо alert(o['test']) прописать alert(o.test) то будет выведено undefined. Ведь сказано что o - это объект, а test - его свойсто. Тоесть у него же есть свойство.
Если я создаю объект с несколькими свойствами и присваиваю в качестве значений, например, Image при создании объекта в память будет загружены изображения для каждого указанного свойства или свойствам будут присвоены только ссылки на Imagе. Т.е. интересует вопрос выделения памяти под объект в этом случае.
var img = new Image ();
img.src = "/forum/a.jpg";
var o = { b1: img, b2: img, b3: img }
в опере 9.6 баг нашел.
в мазиле и в ие можно так делать:
var a=new Array()
a['top']='dfgd.kfg'
a['bottom']='dfgkldfg'
a['dfgqwdf']='dfl.kgdfg'
а потом обращатся двумя способами:
var c=a.top // c='dfgd.kfg'
var c=a['top'] // c='dfgd.kfg'
так вот в опере работает только второй способ.
Отправить комментарий
Приветствуются комментарии:- Полезные.
- Дополняющие прочитанное.
- Вопросы по прочитанному. Именно по прочитанному, чтобы ответ на него помог другим разобраться в предмете статьи. Другие вопросы могут быть удалены.
P.S. Лучшее "спасибо" - не комментарий, как все здорово, а рекомендация или ссылка на статью.Для остальных вопросов и обсуждений есть форум.