17 декабря 2007 в 11:01

JavaScript. Создание объектов

JavaScript предоставляет разработчикам возможность создавать объекты и работать с ними. Для этого существуют следующие приёмы:
  • Оператор new
  • Литеральная нотация
  • Конструкторы объектов
  • Ассоциативные массивы



Используем оператор new



Это, наверное, самый легкий способ создания объекта. Вы просто создаете имя объекта и приравниваете его к новому объекту Javascript.


//Создаем наш объект
var MyObject = new Object();
//Переменные
MyObject.id = 5; //Число
MyObject.name = "Sample"; //Строка
//Функции
MyObject.getName = function()
{
    return this.name;
} 


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


//Используем наш объект
alert(MyObject.getName()); 


Литеральная нотация



Литеральная нотация является несколько непривычным способом определения новых объектов, но достаточно легким для понимания. Литеральная нотация работает с версии Javascript 1.3.


//Создаем наш объект с использованием литеральной нотации
MyObject = {
    id : 1,
    name : "Sample",
    boolval : true,
    getName : function()
    {
        return this.name;
    }
} 


Как видите, это довольно просто.


Объект = {
идентификатор : значение,
...
} 


И пример использования:


alert(MyObject.getName()); 


Конструкторы объектов



Конструкторы объектов — это мощное средство для создания объектов, которые можно использовать неоднократно. Конструктор объекта — это, по сути, обычная функция Javascript, которой так же можно передавать различные параметры.


function MyObject(id, name)
{

} 


Только что мы написали конструтор. С помощью него мы и будем создавать наш объект.


var MyFirstObjectInstance = new MyObject(5,"Sample");
var MySecondObjectInstace = new MyObject(12,"Othe Sample"); 


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


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


function MyObject(id, name)
{
    //Значения переданные пользователем
    this._id = id;
    this._name = name;
    //Значение по умолчанию
    this.defaultvalue = "MyDefaultValue"; 
} 


Аналогичным образом мы можем создавать и функции.


function MyObject(id,name)
{
    this._id = id;
    this._name = name;
    this.defaultvalue = "MyDefaultValue"; 
    
    //Получение текущего значения
    this.getDefaultValue = function()
    {
        return this.defaultvalue;
    }
    
    //Установка нового значения
    this.setDefaultValue = function(newvalue)
    {
        this.defaultvalue = newvalue;
    }
    
    //Произвольная функция
    this.sum = function(a, b)
    {
        return (a+b);
    }
} 



Ассоциативные массивы



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


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



Для обхода таких объектов можно использовать такой цикл:


for (MyElement in MyObject)
{
    //Код обхода
    //В MyElement - идентификатор записи
    //В MyObject[MyElement] - содержание записи
}



По материалу подготовлена небольшая схема.





Вы можете её посмотреть в форматах: PNG SVG


Огромное спасибо gro за помощь.
Даня Вершинин @dinamyte
карма
344,9
рейтинг 0,0
Похожие публикации
Самое читаемое Разработка

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

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

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

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


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

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

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

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

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

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

        var myString = "test";

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

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

                    Думаю вы поняли меня, я понял вас, в любом случае ваши знания о JS больше моих, поэтому я приму к сведению весь наш спор :) . Поставил бы + да не могу, первый день тут :)
                    • 0
                      Просто данная тема кажется элементарной, а подобный спор спором о терминах или вообще не о чем.
                      Однако, большинство программистов, когда начинают более-менее глубоко разбираться в JS, из за неполного понимания подобных фишек набивают себе много шишек ). Чему во многом способствуют авторы большинства книг. Чего только стоит их опусы про "примитивы передаются по значению, а объекты по ссылкам".
          • 0
            Да, тут поможет только
            var myString = new String('some str');
            или
            var myString = new Object('some str');
            только в этом случае typeof myString будет возвращать 'object' и в этом случае проверить что это строка можно только myString.constructor === String
  • +2
    Вот что с людьми делают фреймворки (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 == экземпляр класса (объекта)
    • 0
      >2. delete
      Вот вы пример пишите, а проверить? Там везде будет object. Удалять можно только свойства объектов, но не переменные.
      Вернее можно удалить "глобальные" переменные, объявленные без "var", так как они и не переменные на самом деле, а свойства глобального объекта.
      • 0
        Да, Вы правы. Проверял в консоле firebug, и он немного "обманул". Глобальные объекты удаляются (как удаление свойства у window), хотя у IE есть известная проблема с этим (там не всегда можно удалить).
    • 0
      Конструкция new String() создает объект именно "типа" String. "Наследованный" от Object, но не тождественный ему. В нем содержится предопределенный набор методов для работы со строками, не имеющийся в Object и неявная связь ([[Value]]) с примитивными значением.
    • 0
      Отличный коментарий :)

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

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

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

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

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

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

        за счёт которого можно реализовать закрытые и открытые методы "классов"
        подробнее: теория, для javascript можно изучить вопрос здесь, издесь
  • +1
    поразительно! статья об Обьектах в JS и ни одного слова " prototype ". *откашливаецо*
  • 0
    за что я люблю хабру, так это за то, что кроме полезной статьи (такие бывают :)) в комментах пишут ооочень много полезного (иногда больше полезного чем в самой статье), так что товарищи, читаем комменты и мотаем на ус.
  • +3
    Я смотрю, http://sphere.habrahabr.ru/blog/28641.ht… прошла лесом.
    • +1
      вы б ее в коллективный блог добавили...
      • 0
        Перенёс.
    • 0
      а ваша статья на мой взгляд лучше :) гораздо :)

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

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

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

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


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

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