Как стать автором
Обновить

Комментарии 81

Всё-таки пример с ассоциативными массивами не совсем корректен. Есть порядковые массивы, которые по совместительству, так же как и многое другое, являются объектами.
Совершенно аналогично будет:

var MyObject = new Number();
MyObject["id"] = 5;
MyObject["name"] = "SampleName";
Ага, добавил.

var MyObject = new Number();
MyObject["id"] = 5;
MyObject["name"] = "SampleName";


пацталом :D зачем писать, если не разбираешься в предмете?
Великолепно! В закладки, да и кармы прибавил :)
Стоящая работа — добавил кармы. Огромное спасибо!
В javascript нет никаких ассоциативных массивов! Что вы такое городите?
Это название приёма
Ассоциативный массив — это такой тип данных, хэш-таблица. Для создания хэшей в javascript используется Object. Использование Array в вашем случае — не пришей кобыле хвост. Почитайте первый комментарий от gro.

К примеру, для того, чтобы определить количество элементов массива, есть Array#length. А в вашем случае как определить?
Это эмуляция отсутствующего типа данных.
В избранном! Кармы, к сожалению, пока добавить не могу (
var MyObject = new Object();
var MyObject = new Array();
var MyObject = new Number();

Какая нафиг разница? Почему просто не написать, что что угодно из этого может выступать ассоциативным массивом? И что для них тоже используется литеральная нотация? Только запутываете читателей.
Это все - хеши
Именно так.
Людям, которым понравилось, или впервые увидели, думаю будет занятно почитать Дмитрия Котерова:
http://dklab.ru/chicken/nablas/39.html
Хороший пост, спасибо.
Хорошая статья, спасибо!
ИМХО, каждую статью о ООП наужно начинать с того, что в JS нет наследования на основе классов, а есть делегирование на основе прототипов. Не надо даже пытаться их равнять. Так проще читающим. Вроде "забудь о том, что знаешь о ООП, тут оно другое!"
А здесь вообще про ООП практически ничего нет. Здесь есть работа с объектами.
Простите а "работа с объектами" это разве не ООП? :) Как минимум полиморфизм тут представлен. Ничего не сказано про и инкапсуляцию, наследование (которых по сути и нет в JS) и создание классов - это да, хотя пример "класса" (конструктора) все таки присутствует.
Инкапсуляция и наследование "по сути" есть в JS. А вот "классов" нет.
Это почему инкапсуляции нету? Объект сам по себе суть "купсула" независимо от языка и подхода.
Инкапсуляция это, когда у объекта есть свойства к которым только он имеет доступ, то есть доступ к этим свойствам можно получить только через специальные методы (set/get) или не получить вообще.
определение с вики:
Инкапсуля
(отчего-то обрезалось)
Инкапсуляция — свойство языка программирования, позволяющее объединить данные и код в объект и скрыть реализацию объекта от пользователя. При этом пользователю предоставляется только спецификация (интерфейс) объекта. Пользователь может взаимодействовать с объектом только через этот интерфейс.
Во-первых, она есть в JS, ссылку дал Дед Мороз.
Во-вторых, инкапсуляция в своей основе — объединение вместе данных и кода, обрабатывающего их. Сокрытие это дополнительная фишка в некоторых реализациях ООП, к самой сути инкапсуляции отношения не имеет.
Python, например, весь из себя объектный, намного более чем то же C++, а сокрытия там вообще никакого нет.
Вот не соглашусь с вами. В примере DeadMoroz'а используются замыкания, и для каждого экземпляра будут создаваться свои экземпляры метода (функции). Таким образом, получаем больший расход памяти и потерю скорости на создании методов (особенно если методов много). К тому же совсем не используется механизм прототипов, и мы не сможем "унаследовать" новый "класс" от данного. Ну и еще неприятный момент - невозможность расширить ваш класс/конструктор (хотя конечно есть пара тройка извращенных способов).
И все таки инкапсуляцию - это скрытие реализации объекта, так чтобы никто не мог поменять критическое свойство или прочитать его - случайно или намерено. В следующей версии JS как раз такая возможность появится (создавать приватные свойства и методы).
Отсутствие сокрытия - скорее зло чем добро, потому как "разломать" объект (сложнее чем набор свойств) ни составляет труда, и все зависит от программиста. И часто бывает что "ломают" объекты случайно, и только потому что какое нибудь свойство не скрыто, а его меняют.
Да, использование замыканий это неуклюжая калька с "обычного" ООП.
В "обычном" ООП "физически" объект ни от чего не защищён. Он защищён "условно". Ничто не мешает добавить условность и в js. Например, обычное соглашение об именах: префикс "__" для защищённых объектов. "Ошибиться" и сломать "случайно" какое-нибудь object.__protectedProperty невозможно.
* замыканий для защиты свойств.
Как это физически не защищён? Он защищен на уровне компилятора/интерпретатора обычно (кроме страшных хаков). Насколько "физичнее" по вашему должна быть защита?
"Условная защита" значит, что народ _договорился_ не трогать защищённые члены.
А чтобы _случайно_ не накосячить, проверку возложили на компилятор. Проверку.
Если же кто-то _захочет_ поломать объект, он его поломает.
И, раз уж защита строится на договорённости, почему в js должно быть по-другому?
Как "случайно не накосячить" я уже привёл пример.
А в чем неуклюжесть? Кроме шуток.
lahmatiy написал чуть выше, в первом абзаце.
Для методов да. Для свойств вполне.
Если пытаться дословно перенести "классическое" ООП на "прототипное", пытаясь использовать прототипы точно так же как классы, а замыкание только для закрытия свойств в том же виде, в каком это присутствует в классах.
Однако, если отрешится от всего что мы прочитали в книжке "ООП на C++" и попытаться осознать парадигму JS с самого начала, то окажется, что там есть и инкапусляция, и полиморфизм, и наследование. И использовать их очень удобно и на скорость и память это не слишком влияет. Только писать код нужно совершенно по другому.
Отсутствие сокрытия - скорее зло чем добро

Это тема для длительных дискуссий (и их тьма). И я здесь скорее на вашей стороне. Однако, это не относится к тому факту, что инкапсуляция без сокрытия, это та же инкапсуляция.
Перечитал, что написал :) Второй абзац должен был заканчиваться чем то вроде "в каком присутствует в классах, то, действительно, получится полная фигня".
Все что в JavaScript - это объекты, и работать надо с ними так же как с объектами, т.е. тут нету массивов, строк и т.п.

например: var myString = "я строчка";
так вот myString это тоже объект, который имеет свои методы и может быть расширен новыми вашими методами, за это я кстати и люблю JS.
Покажите пример расширения примитивной строчки (именно данной переменной, а не прототипа String)
естественно я имел ввиду String, не надо придираться. В любом случае
при записи var myString = "я строчка"; myString сразу становится объектом String, который и можно расширять (естественно через prototype)

пример:
String.prototype.getBold = function() {
return "<b>" + this + "</b>";
}

var myString = "test";

document.write(myString.getBold());
Не становится.
myString содержит примитивное значение.
При использовании с ним "объектного синтаксиса" (myString.getBold) создается "объект-над-примитивом", который и используется.
Например, установить свойство для myString не получится:
myString.x = 10;
alert(myString.x); // undefined
ну я писал про методы и не свойства, в любом случае данный пример можно осуществить следующим образом:

String.prototype.x = null;
String.prototype.SetX = function(intValue) {
String.x = intValue;
}

String.prototype.GetX = function() {
return String.x;
}

var myString = "test";
myString.SetX(13);

alert(myString.GetX());

Кстати такой вид записи был бы правильнее, чем прямой доступ к свойству x.
Правильный, неправильный, это с какой точки посмотреть. У вас всё равно идет прямой доступ к свойству GetX :)
Да и ваш пример опять таки не показывает того, что вы хотите показать. Вы ставите свойство на прототип, то есть на все строки, а не на конкретную.
Смысл в том, что за озарением "в JS всё объекты" у изучающего должно через какое-то время идти "неа, не всё в JS объекты".
ну так правильно, я работаю со String, поэтому и GetX будет у всех строк. Но все же var myString = "test"; тут myString все же объект, потому что как минимум у него есть свойство length.
Если же нужно расширять функционал именно для myString, то и создавать тогда myString необходимо по другому;
Да, создавать нужно так, как показал lahmatiy чуть ниже.
Вот именно там переменная содержит ссылку на объект. Если вы утверждаете, что в вашем случае так же получается объект, то объясните разницу в поведении этих двух примеров.
У myString нет свойства length, оно есть у объекта-над-примитивом, появляющегося только в момент выполнения операции.
а какая разница когда и как обрабатывается свойство length? если бы myString был обычной строкой в полном этом понимании, то не о какой length речи бы и не шло. Другое дело, что примитив myString тоже видимо что то типа объекта, только ущербного :)

Думаю вы поняли меня, я понял вас, в любом случае ваши знания о JS больше моих, поэтому я приму к сведению весь наш спор :) . Поставил бы + да не могу, первый день тут :)
Просто данная тема кажется элементарной, а подобный спор спором о терминах или вообще не о чем.
Однако, большинство программистов, когда начинают более-менее глубоко разбираться в JS, из за неполного понимания подобных фишек набивают себе много шишек ). Чему во многом способствуют авторы большинства книг. Чего только стоит их опусы про "примитивы передаются по значению, а объекты по ссылкам".
Да, тут поможет только
var myString = new String('some str');
или
var myString = new Object('some str');
только в этом случае typeof myString будет возвращать 'object' и в этом случае проверить что это строка можно только myString.constructor === String
Вот что с людьми делают фреймворки (prototype, jQuery etc) - они не знаю основные принцы построения объектов в JavaScript :( хотя тут скорее не построение, а обычная работа с объектами.

Замечания:
1. my_object.property == null проверяет не присутствие свойства, а равно ли null (или undefined) свойство property объекта my_object.

var my_object = { property: null };
my_object.property == null; // вернет true: свойство и правда равно null
'property' in my_object; // вернет true: это свойство есть у объекта
'absent' in my_object; // вернет false: этого свойства нет у объекта

таким образом проверка существования свойства производится не сравнением свойства с null, а конструкцией 'property_name' in object
(данная конструкция не работает в старых версиях IE, если не ошибаюсь до версии 5.5)

2. delete может удалять и свойства и сами объекты. По сути имена объектов/свойств это всего лишь ссылки, так что в данном случае удаляется ссылка на объект (ассоциация с объектом), а если ссылок на объект больше нет, то и сам объект разрушается (срабатывает сборщик мусора).

var a = { p: 'value' };
var b = a;
alert(typeof a); // object
alert(typeof b); // object
delete a;
alert(typeof a); // undefined
alert(typeof b); // object
delete b;
alert(typeof a); // undefined
alert(typeof b); // undefined


3. Нет разницы между следующими записями
my_object.name = 'value';
my_object["name"] = 'value';
вторая запись используется только тогда, когда имя свойства противоречит правилам именования переменных, т.е. содержит символы не разрешенные в именах переменных (то есть символы за исключением a-z, A-Z, 0-9, _ (знак подчеркивания), $ (знак доллара) ) или имя свойства начинается с цифры.
Вы пишите "значения соотвествуют object['name'] == object.name"
это то же самое что написать object == object, странно будет тут получить false.

4. Конструкции new String(), new Boolean(), new Number() создают объекты типа 'object', так что получается такая картина

var str1 = new String('str');
var str2 = 'str';
var str3 = str2;
typeof str1; // object
typeof str2; // string
str1 == str2; // true - примитивные значения равны
str1 === str2; // false - эти переменные ссылаются разные объекты
str2 === str3; // true - эти переменные ссылаются на один объект

в тоже время только new Function() возвращает объект типа function
так что будьте осторожны, лучше использовать "скрытые" конструкторы (как в случае с str2).

и т.д.

ЗЫ:
Instance != инстанция
Instance == экземпляр класса (объекта)
>2. delete
Вот вы пример пишите, а проверить? Там везде будет object. Удалять можно только свойства объектов, но не переменные.
Вернее можно удалить "глобальные" переменные, объявленные без "var", так как они и не переменные на самом деле, а свойства глобального объекта.
Да, Вы правы. Проверял в консоле firebug, и он немного "обманул". Глобальные объекты удаляются (как удаление свойства у window), хотя у IE есть известная проблема с этим (там не всегда можно удалить).
Конструкция new String() создает объект именно "типа" String. "Наследованный" от Object, но не тождественный ему. В нем содержится предопределенный набор методов для работы со строками, не имеющийся в Object и неявная связь ([[Value]]) с примитивными значением.
Отличный коментарий :)

Я даже задумался над тем чтобы написать статейку про "замыкания" (closures). Чтобы затем в итоге получить такой дополняющий пост.
Если осилю, дам знать ;)

А так конечно, нового мало в статье написано, но при наличии богатых коментариев даже неновый и не эксклюзивный материал приносит неплохую пользу!
Так что, автор, если в следующий раз будете сомневаться писать или нет, то пишите :)
Уж, на нынче подхламленном хабре хуже от этого точно не станет :D
Пишите, тема довольно сложная, потому как многие часто используют неправильно/неоправданно (спасибо prototype за bind) и ловят неожиданные результаты (ошибки/неправильную работу), не понимая почему так.
Тут уже выше давали ссылку на статью Котерова по этой теме: Большие хитрости JavaScript
Ниачом! Профессионалы будут плеваться (собственно что и происходит, и я их поддерживаю), а новичков только запутает. Правильно советовали люди выше — читайте наблы Димы Котерова, он как никто хорошо объяснил в своих статьях что есть объекты в JavaScript и как с ними работать.
Да. Если не считать множества неточностей и вообще ошибок в его объяснении.
ну раз речь об объектах пошла, то можно сказать пару слов про закрытые функции и свойства :)

myClass = function () {
var _privateProperty = '';
var _privateFunction = function() {
}

this.publicGetter = function() {
return _privateProperty;
}

this.publicCallPrivate = function() {
return _privateFunction();
}

}
Ну так скажите пару слов :)
Хотя бы дайте ключевое слово ("замыкание"), чтобы начинающим читателям было куда копать :)
пардон, если подробнее, то ява скрипт поддерживает такой механизм как "замыкания"

за счёт которого можно реализовать закрытые и открытые методы "классов"
подробнее: теория, для javascript можно изучить вопрос здесь, издесь
поразительно! статья об Обьектах в JS и ни одного слова " prototype ". *откашливаецо*
за что я люблю хабру, так это за то, что кроме полезной статьи (такие бывают :)) в комментах пишут ооочень много полезного (иногда больше полезного чем в самой статье), так что товарищи, читаем комменты и мотаем на ус.
вы б ее в коллективный блог добавили...
Перенёс.
а ваша статья на мой взгляд лучше :) гораздо :)

хотя рулит конечно же крокфорд%))
НЛО прилетело и опубликовало эту надпись здесь
Котеров не писал не здоровой херни. Он написал статьи, которые вызвали интерес к JS среди широких кругов. А так как в них были фактические ошибки, то они породили интересные дискуссии, в следствии которых у многих так же повысилось знание JS.
Так и данная статья, возможно не несет конечного знания, но породило достаточно интересную беседу, после бесконечных матерных частушек и остальных "служить ли ИТшникам в армии".
Вы бы могли бы присоединиться к ней и просветить все 80% дебилов насчет этого удивительного языка.
НЛО прилетело и опубликовало эту надпись здесь
Ваш ответ фееричен. Он совершенно точно отражает ваш статус на данном ресурсе и репутацию.
НЛО прилетело и опубликовало эту надпись здесь
Своя не значит. Но получить усредненное представление о собеседнике по ней можно.
НЛО прилетело и опубликовало эту надпись здесь
Как самоцель — торчать на сайте, только ради набирания этих цифорок, чтобы потом ими мерятся с другими, мне не интересно.
Но как побочное явление, позволяющая сделать первое мнение о собеседнике, очень полезно. Например, первое мнение о вас подтвердилось со всей точностью. Вы из тех людей, про которых дедушка Фрейд говорил, что их в детстве напугали большим членом.
Статья, конечно, хорооошая... но не для тех, кто давно кодит на JS, а так... для тех, кто на нем не кодит и кодить не будет :). Пусть дивятся и радуются.

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

AJAX в действии (Дейв Крейн, Эрик Паскарелло, Даррен Джеймс)

http://www.internet-technologies.ru/books/book_194.html


Обратите внимание на приложения в конце книги. Там коротко и ясно описано: что такое обьекты в JS, как их создавать и многое другое.
Всё новое - хорошо забытое старое. Ничего нового в статье не увидел.
ага ;)
this[block ? 'block_fields' : 'fields'][name_fields[i]][disable ? 'disable' : 'enable']();
К чему вы это?
Опять пропагандируете тернарный оператор? :)
%) ну что поделаешь. В даном случае просто как пример того, что не только дотнотация this.that.do() в ходу...
т.е. вместо if (block) { this.block_fields() } else { this.fields() } можно использовать лаконичное this[block ? 'block_fields' : 'fields'](); А можно и не использовать (для тех, кто не любит читать тернарные операторы)!
мой код и так сложно читать, а если я начну писать так, что я стану незаменимым работником :)
;) ну дык, совмещение работы и развлечения (решение логических задачек на скорость)
НЛО прилетело и опубликовало эту надпись здесь
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.