Зомби зомби зомби. © Народная мудрость
Developers! Developers! Developers! Developers! © Stiven Ballmer
Речь в сегодняшней статье пойдёт в основном о яваскриптах, потому что именно их я преподавала, на момент написания, стажёру нашей компании. Поэтому статья носит методологический характер.
Что такое объект?
Поскольку яваскрипт, в общем-то объектно-ориентированный язык, мы повторяли определение, что же такое объект в программировании и в яваскриптах в частности? Поискав для сравнения определения в интернете я ничего хорошего не нашла. Во всех источниках упоминается полнейшая чушь, что становится конечно понятно откуда берётся каша в головах студентов, соискателей, и стажёров. Потому что, вместо того чтобы делать знания простыми и понятными методологисты переписывают одни и те же книжки каждый раз только запутывая формулировки. Впрочем к концу, я думаю вы запутаетесь сами =). Пока процитирую некоторые определения из википедии:
Объект — Сущность в адресном пространстве вычислительной системы, появляющаяся при создании экземпляра класса или копирования прототипа (например, после запуска результатов компиляции и связывания исходного кода на выполнение).
Википедия
Заметьте, в довольно простое определения навязали адресное пространство, компиляцию, классы и прототипы. Это всё равно что спросить что такое птица, а в ответ получить что это сущность употребимая в пищу и вылупляющаяся из яиц!
Объект — некоторая сущность в виртуальном пространстве, обладающая определённым состоянием и поведением, имеет заданные значения свойств (атрибутов) и операций над ними (методов). Как правило, при рассмотрении объектов выделяется то, что объекты принадлежат одному или нескольким классам, которые в свою очередь определяют поведение (являются моделью) объекта. Время с момента создания объекта (конструкция) до его уничтожения (деструкция) называется временем жизни объекта
Я не читала таких определений, когда начала изучать яваскрипты, поэтому интуитивно они представляются совсем по другому. Это понятие класса должно строится на понятии объекта, а не понятие объекта строится на понятии класса.
Объект — это сущность, которой можно посылать сообщения, и которая может на них реагировать, используя свои данные. Данные объекта скрыты от остальной программы. Сокрытие данных называется инкапсуляцией.
Опять таки. В определении говорится об инкапсуляции. А что если данные объекта не скрыты? Впрочем, поскольку моя статья про яваскрипты, данное определение вообще никакой смысловой нагрузки не несёт.
Объект в программировании, это такая штука, которая не всегда может иметь визуальное представление, типа кнопки или поля. Скорее наоборот.
Представь себе массив — упорядоченный набор переменных. Каждая переменная в обычном массиве может содержать строку, число, (любую типизированную переменную) или другой массив. Поэтому моё определение звучит так:
Объект — это массив, который может содержать в качестве переменных, кроме всего прочего, функции или другие объекты.
Такое определение я призываю запомнить стажёров, потому что это именно то, с чем мы работаем в яваскриптах.
Справедливости ради, хочется так же отметить определение из англоязычной версии. Оно довольно хорошее.
The programming construct that combines data with a set of methods for accessing and managing those data is called an object. © en.wikipedia.org
Т. е. данные, и набор функций (методов) для работы с этими данными называются объектом.
Такой вариант так же допустим для запоминания. А теперь мне хочется рассказать почему яваскрипт это целиком объектно-ориентированный язык, и какие сложности в обучении ему возникают.
Объекты в Javascript
Теперь внимание, дальше вы можете запутаться!
В яваскриптах — почти всё является объектами, но не всё называется объектами. Число — или строковая переменная (или сущность) — не называются сами по себе объектами! Но по факту — являются ими.
Например у числа или строки могут быть встроенные функции. Т. е. функция.split например — аналог строковой функции explode в php и т. п.
var a = 'te.st';
var b = a.split('.'); // в b - будет массив из значений te и st
Чтобы понять сказанное выше утверждение, приведу такой аналог: «насекомые и птицы — не называются животными, хотя по факту являются ими». Т. е. вы видите на улице собаку или слона и говорите «О, какое животное». А когда видите птицу, говорите «какая птица», хотя из биологии это тоже царство животных. А собаки или слоны относятся к млекопитающим. Так и тут, когда вы видишь число или строку — нет нужды говорить «о, какой объект». Лучше сказать какая строка или какое число. А вот когда вы видите, например, документ html — document, или его тело — document.body — тут уж можно сказать «какой объект», просто потому что он уже и не число и не строка.
Далее, небольшая тонкость касающаяся массивов. В яваскриптах есть названия для классов объектов — строка, число, массив и, внимание(!), Объект. Так и приходится писать объект объект.
новый массив можно создать например как:
a = new Array(); или в сокращённой нотации a = [];
новый Объект (буду писать с большой буквы), можно создать так:
a = new Object(); или в сокращённой нотации a = {};
Индексы массива [] в яваскрипте могут быть только числовыми. Индексами объекта - что угодно кроме чисел (их можно конвертировать в строки). Пример:
var a = {'my_func': function(){ do_something; } };
Обращу внимание, что функция будет доступна как элемент массива: a['my_func'](); и как метод объекта a.my_func(); — в принципе равнозначно, как кому нравится.
Теперь внимание — массив, может содержать индексы элементов, т. е. на какой позиции какая переменная находится. В яваскриптах массив может содержать только ЧИСЛОВЫЕ индексы. В то время как объект — может содержать любые индексы переменных.
Индексы в записи Объекта пишут так index:value, однако это не подходит для записи массива (спасибо SelenIT в комментариях), поэтому запись
a= [1:'something', 2:'something']; — НЕ верно
a= ['first':'something', '2':'something']; — НЕ верно
a= {'first':'something', '2':'something'}; — верно
Но можно создать такой объект
var a = {'вася':'Пупкин'};
и обращаться к нему как к массиву
alert(a['вася']));
Подробнее об этом написано в моей статье «Javascript — работа с массивами и объектами» (09.2009).
Теперь я расскажу о функциях. Функции — так же как и строки, и числа, и Объекты, являются в какой-то степени объектами. Они, согласно моему определению «объект — это данные + функции» — могут содержать набор данных, и (!) функций.
Отличия от строк — и т. п. — в том что чтобы вызвать внутреннюю функцию функции, или же переменную объявленную внутри функции необходимо вызвать саму функцию, объявляются внутри с помощью кодового слова this. Вся эта конструкция выглядит так:
function test(){
// do_something;
this.x = 5;
}
тогда a = test().x; // равно 5
функция при этом выполняется, и может что-то делать:
<script>
function test(){
// do_something;
alert('test');
this.x = 5;
}
a = test().x;
</script>
присвоит переменной число 5 — и покажет alert().
Ссылки на объекты
В заключение, мне хочется в очередной раз рассказать об одной особенности языка Javascript связанной с операцией присваивания.
Когда происходит присвоение переменной строки, числа или логической переменной, это создаёт копию этого значения. В то время как присваивание переменной массива или объекта создаёт ссылку на это значение. Это вызывает путаницу, т. к. оказывается что изменение одной копии массива изменяет и вторую когда не надо, и наоборот когда надо присваивание свойства элемента переменной не изменит его с изменением этого свойства.
Пример:
a=document.title; // Присваиваем переменной a - значение заголовка документа
a='test'; // присваиваем переменной другое значение, заголовок документа не меняется
a=document; // присваиваем переменной значение документа
a.title='test'; // присваиваем заголовку значение - меняется заголовок окна.
Об этом, и о том как копировать объекты и массивы, так же написано в моей прошлой статье «Javascript — работа с массивами и объектами».
P.S. Так же очень хочу сказать что Джон Ресиг (создатель jquery если кто не в курсе), недавно выступил с отличной и правильной идеей преподавания javascript в качестве первого языка программирования. Пожалуйста прочитайте его статью: Яваскрипт как первый язык программирования.В ней он так же затрагивает некоторые вопросы методологии, и как и я подчёркивает то, что в яваскриптах всё, включая функции является объектами. Цитирую:
Function Declarations
Perhaps the most interesting change that we can make is a rather subtle one, but it's eschewing normal function declarations for creating anonymous functions and assigning them to a variable.
// Don't do this:
function getData() { }
// Do this instead:
var getData = function() { };
There are a number of good habits that are instilled when you use this particular technique.
Makes it easier to understand "functions as an object". I've found that when you show new developers a function being assigned to a variable it suddenly becomes much more obvious that a function is actually an object and can be manipulated as such (and that a function can be passed as an argument to another function). Thus students are advanced along the path towards a better understanding of functional programming.
С удовольствием выслушаю ваши замечания по теме.