На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: ElcnU, ANDLL, fatalist
  
> Объекты и прототипы , Гений объясняет
    Здравствуйте всем,
    для тех кто путает объекты, прототипы, классы и не может разобраться что да как, Гений ща все разжует! :D

    итак объект создается с помощью литерала:
    ExpandedWrap disabled
      var o = {};

    добавляем свойства
    ExpandedWrap disabled
      o.prop1 = 'hello';
      o.prop2 = 100;
      o.prop3 = [1,2,3,4,5];
      o.prop4 = {};
      o.prop5 = function(){};
      // и т.д.

    у объекта есть скрытое свойство [[Prototype]]. Прототип это ссылка на другой объект, который используется движком JS. Доступ к нему закрыт (в ES3/ES5), но в ES6 доступ в нему можно получить через метод Object.setPrototypeOf, кроме того некоторые браузеры предоставляют доступ к прототипу через свойство __proto__.

    Устал печать пока все :writer:
      с нетерпением ждём продолжения книги. :whistle:
        Цитата Cfon @
        у объекта есть скрытое свойство [[Prototype]]

        Нету. Прототип есть только у функций и проч :whistle:
          Цитата K313 @
          с нетерпением ждём продолжения книги. :whistle:

          да дружище скоро будет :D

          Добавлено
          Цитата Serafim @
          Цитата Cfon @
          у объекта есть скрытое свойство [[Prototype]]

          Нету. Прототип есть только у функции :whistle:

          дружище ты меня удивляешь своим не знанием предмета!
          но ничего скоро я все разжую и объясню что там да как :D
            Даже не пойму, то ль это реально фейспалм, то ли просто троллинг :D
              Мы с такой скоростью подачи материала будем учиться до тришкиного заговения. ТС, можешь побыстрей новый материал выдавать? Но не очень быстро, а то я конспектирую.
              Сообщение отредактировано: MIF -
                Цитата MIF @
                Мы с такой скоростью подачи материала будем учиться до тришкиного заговения. ТС, можешь побыстрей новый материал выдавать? Но не очень быстро, а то я конспектирую.

                жди! :punish: :D
                  Продолжаю вещать! :D
                  JavaScript слаботизирован, т.е. тип переменной не указыватся и он может динамически меняться вовремя выполнения кода. В JavaScript существует несколько элементарных типов данных: числа(number), строки(string), логические(boolean), и объектный тип (object), кроме того есть еще тип undefined - означает не определенный тип. В ES6 появился новый тип symbol, думаете что это символьный тип? Ошибаетесь! Если в двух словах это тип который определяет некое уникальное значение :D
                  Тип переменной можно определить с помощью оператора typeof, например:
                  ExpandedWrap disabled
                    var i = 0, s = 'hi',
                        o1 = {}, o2;
                    typeof i; // 'number'
                    typeof s; // 'string'
                    typeof o1; // 'object'
                    typeof o2; // 'undefined'

                  К объектам относятся также функции, но они имеют тип 'function'
                  ExpandedWrap disabled
                    var foo = function() {};
                    typeof foo; // 'function'

                  Объекты представляют из себя коллекции свойств - пар: ключ/значение. В переменных хранятся только ссылки на объекты, а сами объекты хранятся в куче. Что это значит? Например:
                  ExpandedWrap disabled
                    var o1 = { a: 100 };
                    var o2 = o1;
                    o1 = { b: 200 };
                    console.log(o1); // { b: 200 }
                    console.log(o2); // { a: 100 }

                  Давайте проанализируем ,что тут происходит:
                  -- определяется переменная o1
                  -- создается объект в куче(со свойтсвом a и значением 100)
                  -- ссылка на этот объект записывается в o1;
                  -- определяется переменная o2 и связывается с объектом на который указывает o1;
                  -- создается новый объект со значением {b: 200}
                  -- ссылка на объект записывается в o1.
                  Что тут важно отметить, o1 больше не указывает на объект {a:100}, но o2 по-прежнему ссылается на {a:100}, т.е. операция o2 = o1 определяет не ссылку на o1, а новую связь с объектом {a:100}, поэтому после o1 = { b: 200 } ссылка o2 по-прежнему указывает на {a: 100}, а o1 -> {b:200}. Вооот! :D

                  Там еще есть ссылка на прототип, она неявно создается при создании объекта, т.е на самом деле будет что-то типа
                  ExpandedWrap disabled
                    { a: 100, __proto__: Object.prototype }

                  но об этом в след раз :writer:
                  to be continue...
                  Сообщение отредактировано: Cfon -
                    Продолжаю :writer:

                    В приведенном выше примере присутствует свойство __proto__, которому присвоено значение Object.prototype. Эту связь добавляет сам JavaScript. Что это означает?
                    Object это функция, которая уже определена в JavaScript, а у нее есть свойство prototype. Скажу больше, у каждой определяемой нами функции есть свойство prototype со значением { constructor: имя_функции }, где имя_функции это имя функции :D, в данном случае Object. Обратите внимание на название свойства constructor, по данной причине саму функцию часто называют конструктор. Свойство prototype это особое свойство функции, которое используется движком JavaScript при создании объекта через оператор new (пока я опущу его описание :D). Так вот в этом Object.prototype содержится ссылка на объект, в котором определены несколько методов:
                    -- toString, valueOf, haOwnProperty, isPrototypeOf и т.д.

                    Строка __proto__: Object.prototype добавляется неявно самим JavaScript. Свойство __proto__ используется для связывания объектов в цепочки, с помощью которых отслеживаются разрешения обращения к свойствам объекта. В нашем примере мы связали, точнее сам JavaScript связал :D, наш объект "o" с объектом Object.prototype через свойство __proto__. Не путайте __proto__ со свойством prototype функции! Это разные свойства, первое присутствует в объекте, второе в функции. Но оба они указывают на один и тот же объект в куче. Как работает цепочка прототипов? Например:
                    ExpandedWrap disabled
                      var o = {
                        a: 100
                      };
                      o.toString(); // [object Object]

                    Казалось бы в нашем объекте нет метода toString, но он есть в прототипе Object.prototype. Что делает JavaScript:
                    -- JavaScript ищет метод toString сначала в самом объекте "o",
                    -- не обнаружив его, переходит по ссылке __proto__ к объекту Object.prototype.
                    -- Тут он есть, происходит его вызов. Конец :D
                    В нашем случае цепочка короткая, но ее можно расширить, связать несколько объектов, например:
                    ExpandedWrap disabled
                      var o1 = { a: 100 };
                      var o2 = { b: 200, __proto__: o1 };
                      o2.b; // OK: 200
                      o2.a; // OK: 100
                      o2.toString(); // OK: [object Object]

                    Если запрашиваемого свойства не оказалось в текущем прототипе, то поиск продолжится дальше по цепочке пока не дойдет до Object.prototype, где его __proto__ равен null, на этом поиск закончится и произойдет ошибка TypeError:
                    ExpandedWrap disabled
                      o.foo(); // TypeError: o.foo is not a function

                    Здесь я несколько упростил, используя __proto__, как правило его лучше не трогать поскольку оно не стандатизировано, хотя вроде в ES6 уже стандартизировано :D. Как же тогда связывать объекты в цепочки? Для назначения объекта свойству __proto__ существует несколько способов,
                    кроме прямого обращения к __proto__, а именно:
                    -- свойство prototype функции, да-да то самое, что я упоминал выше :D
                    -- Object.create (ES5)
                    -- Object.setPrototypeOf (ES6)
                    например:
                    ExpandedWrap disabled
                      var o1 = { a: 100 };
                      var o2 = { b: 200 };
                      Object.setPrototypeOf(o2, o1);
                      o2.b; // OK: 200
                      o2.a; // OK: 100
                      o2.toString(); // OK: [object Object]

                    или
                    ExpandedWrap disabled
                      var o1 = { a: 100 };
                      var o2 = Object.create(o1, { value: {b: 200 }});

                    или
                    ExpandedWrap disabled
                      var o1 = { a: 100 };
                      function F() {}
                      F.prototype = o1; //<-- а вот ана prototype :D
                      var o2 = new F();
                      o2.b = 200;

                    В последнем примере как раз используется оператор new. Что он делает?
                    -- создает новый объект (пустой) и связывает его со ссылкой this (она используется внутри конструктора)
                    -- далее вызывает конструктор F (он у нас ничего не делает, но без него никак :D)
                    -- ссылка на F.prototype связывается с this.__proto__
                    -- и наконец ссылка на новый объект связывается с o2.
                    Обратите внимание объект o2 во втором и треьем примере не использует литерал. Я скажу больше эти способы практически одинаковые!
                    Object.create был введен в ES5 и реализован так же как в последнем случае, т.е. через временный конструктор F с добавлением разных проверок и передачи объекта инициализации.

                    На сегодня все! :gamer:
                    to be continue...
                    Сообщение отредактировано: Cfon -
                      Цитата Cfon @
                      Object это функция, которая уже определена в JavaScript, а у нее есть свойство prototype.


                      ExpandedWrap disabled
                        {}.protoype


                      Странно, у моего объекта нету protoype <_<

                      ExpandedWrap disabled
                        ({})()


                      И это не функция!

                      Обманщик! Дизлайк, отписка!!!111
                        Цитата Cfon @
                        Продолжаю верещать!

                        фиксед :whistle:
                          Цитата Serafim @
                          Цитата Cfon @
                          Object это функция, которая уже определена в JavaScript, а у нее есть свойство prototype.

                          ExpandedWrap disabled
                            {}.protoype

                          Странно, у моего объекта нету protoype <_<

                          {} это не функция, это же литерал объект :D
                          естествено у объекта нет никакого свойства prototype, у него есть __proto__, а вот у функции есть prototype.
                          читай внимательно я не обманщик, я Гений! :D

                          Добавлено
                          Цитата _lcf_ @
                          Цитата Cfon @
                          Продолжаю верещать!

                          фиксед :whistle:

                          пшол отседа пацан! :lool:
                          Сообщение отредактировано: Cfon -
                            Цитата Cfon @
                            естествено у объекта нет никакого свойства prototype



                            Но ведь же:
                            Цитата Cfon @
                            Object это функция, которая уже определена в JavaScript, а у нее есть свойство prototype.


                            1) typeof {} // "object"
                            2) Это объект, а объект - это функция, ты так написал.
                              Цитата Serafim @
                              Цитата Cfon @
                              естествено у объекта нет никакого свойства prototype

                              Но ведь же:
                              Цитата Cfon @
                              Object это функция, которая уже определена в JavaScript, а у нее есть свойство prototype.

                              1) typeof {} // "object"
                              2) Это объект, а объект - это функция, ты так написал.

                              не тупи, я написал не объект, а Object - это функция, что тут не ясно?
                                Цитата Cfon @
                                пшол отседа пацан!
                                ты для кого книгу пишешь? для самого себя? :whistle: Если народ твой метод изложения материала не понимает - значит хреновый из тебя писатель...

                                Прикладывай разукрашки, и понятнее будет и писанины будет меньше :popcorn:
                                например
                                user posted image

                                Добавлено
                                Цитата Cfon @
                                не тупи, я написал не объект, а Object - это функция, что тут не ясно?
                                Вот так ты и запутаешь всех своих дорогих читателей.

                                Ты же ещё не объяснил, что любые функции в javascript - это функции лижь с точки зрения пользователя, потому что их можно вызвать. А с точки зрения самого javascript - это объекты типа "function" :scratch:
                                Сообщение отредактировано: K313 -
                                  да пока материал сыроват, но я стараюсь!
                                  все для дорогих читателей :writer:
                                    скоро будет продолжение!
                                    пока времени нет писать :D
                                      Цитата Cfon @
                                      скоро будет продолжение!

                                      Ох ты ж блин, нет, только не это!

                                      Скрытый текст
                                      :D :lol:
                                      Сообщение отредактировано: Serafim -
                                        че реально отстой? :'(
                                        ну и фиг с вами! :D
                                          Цитата Cfon @
                                          че реально отстой?
                                          ну и фиг с вами!

                                          А как я тогда вбрасывать на вентилятор буду? :unsure: Только о себе и думаешь, игаизт!!1111 <_<
                                          Сообщение отредактировано: Serafim -
                                            Скрытый текст
                                            Цитата Cfon @
                                            че реально отстой? :'(
                                            ну и фиг с вами!

                                            Cfon, норм! Если хочешь, чтобы было супер - используй едионообразное оформление.
                                            Тогда тебе вообще цены не будет, а благодарных читателей наберешь :)
                                              Цитата JoeUser @
                                              Скрытый текст
                                              Цитата Cfon @
                                              че реально отстой? :'(
                                              ну и фиг с вами!

                                              Cfon, норм! Если хочешь, чтобы было супер - используй едионообразное оформление.
                                              Тогда тебе вообще цены не будет, а благодарных читателей наберешь :)

                                              Добре! :yes:
                                              будем думать :victory:

                                              А пока вот продолжение моего эпоса :D

                                              Из предыдущего раздела (см #9) стало ясно, что объектная система JavaScript не использует классы, как в других языках программирования (Java, C#, C++), для создания объектов. В JavaScript объекты создаются либо через литерал, например:
                                              ExpandedWrap disabled
                                                var o = {
                                                  a: 100,
                                                  foo: function(){},
                                                  // и тд
                                                };

                                              либо через оператор new и функцию-конструктор, например:
                                              ExpandedWrap disabled
                                                function O() {
                                                  this.a = 100;
                                                  this.foo = function(){};
                                                  // тд.
                                                }
                                                var o = new O();

                                              второй способ более много словен, поэтому обычно его редко используют в JavaScript, но именно он позволяет нам создавать объекты в стиле классических языков программирования.
                                              Давайте рассмотрим его поближе. В приведенном примере объявляется функции (конструктор), в которой ссылке this присваиваются различные свойства. Как было указано выше this это ссылка на объект, который будет присвоен ссылке this во время выполнения кода. Что это значит? Это значит, что значение this может меняться в зависимости от контекста, в котором выполняется данная функция, т.е. в контекcте оператора new this будет иметь значение ссылки на созданный объект. Это надо всегда помнить! Если же например, вызвать функцию O без new, то результат будет печален! Так как в таком контексте this будет указывать на глобальный объект window, в случае броузера, или global в случае NodeJS, это приведет к модификации эти глобальных объектов! Есть одно но, если выполнять вызов функции O в строгом режиме ('use strict', он введен в ES5), то this будет иметь значение undefined, что приведет к ошибке при выполнении кода обращения к this:
                                              ExpandedWrap disabled
                                                'use strict';
                                                // вызов без new!
                                                var o = O(); // TypeError: Cannot set property 'a' of undefined

                                              ОК, но в чем схожесть с классическими языками, кроме использования оператора new? Суть в том, что если нам надо создать множество объектов под копирку, то в случае литерала, придется либо дублировать код путем тупого ручного копирования кода :D (метод работает, но подвержен ошибкам), либо создавать так называемую функцию-фабрику, которая будет возвращать объекты при ее вызове, например:
                                              ExpandedWrap disabled
                                                function createPerson() {
                                                  return {
                                                    name: 'Gregory',
                                                    age: 42,
                                                    toString: function() {
                                                      return '[' + this.name + ' is '+ this.age + ' years old.]';
                                                    }
                                                  };
                                                }
                                                var person1 = createPerson(),
                                                    person2 = createPerson();
                                                person1.toString(); // '[Gregory is 42 years old.]'
                                                person2.toString(); // '[Gregory is 42 years old.]'

                                              Что то не так? Да! Наша функция штампует не только одинаковые объекты, но и одинаковые данные! Как быть? Все просто :D, надо предусмотреть возможность передачи данных в функцию через ее параметры, например:
                                              ExpandedWrap disabled
                                                function createPerson(name, age) {
                                                  return {
                                                    name: name,
                                                    age: age,
                                                    toString: function() {
                                                      return '[' + this.name + ' is '+ this.age + ' years old.]';
                                                    }
                                                  };
                                                }
                                                var person1 = createPerson('Gregory', 42),
                                                    person2 = createPerson('Miller', 30);
                                                person1.toString(); // '[Gregory is 42 years old.]'
                                                person2.toString(); // '[Miller is 30 years old.]'

                                              Все красиво все работает. Такой стиль кодирования использовался в ES3/ES5, но ES6 привнесла некоторые изменения синтаксиса, вот как тоже будет в ES6:
                                              ExpandedWrap disabled
                                                function createPerson(name, age) {
                                                  return {
                                                    name,
                                                    age,
                                                    toString() {
                                                      return `[${this.name} is ${this.age} years old.]`;
                                                    }
                                                  };
                                                }

                                              Короче не так ли? За объяснением отсылаю к книжке Николаса Закаса "ECMAScript 6 Руководство для разработчика" от 2017 года! Хотя на самом деле она написана им в 2016, а на дворе конец 2017, и есть уже стандарт ES8! :D
                                              Но я бы таки рекомендовал к чтению сей перл! :good:
                                              Вернемся к стилю классического кодирования. Наш пример будет выглядеть так:
                                              ExpandedWrap disabled
                                                function Person(name, age) {
                                                  this.name = name;
                                                  this.age = age;
                                                  this.toString = function() {
                                                      return '[' + this.name + ' is '+ this.age + ' years old.]';
                                                  };
                                                }
                                                var person1 = new Person('Gregory', 42),
                                                    person2 = new Person('Miller', 30);
                                                person1.toString(); // '[Gregory is 42 years old.]'
                                                person2.toString(); // '[Miller is 30 years old.]'

                                              Т.е. сходства с классическим стилем на лицо и на лице! :D
                                              Стоит отметить, что и в том в другом стиле есть недостатки. Какие? Смотрите сами и тут и там идет дублирование кода за счет создания дубликатов функций toString! Я уже обсуждал эту тему раньше вместе с чуваком под ником K313 :D, где как мне кажется мы пришли соглашению, что дублируется только объявление функции, а само тело создается в единственном экземпляре. Хотя в книжках про это не уточняется! Везде просто указывается, что такой способ создания объектов приводит к дублированию кода и все! Но фиг с ним не суть :D
                                              Как же таки избежать такого дублирования кода? Просто надо вынести объявление методов за пределы функций-фабрик/конструкторов, а внутри конструктора или фабрики присваивать только ссылку на метод, например:
                                              ExpandedWrap disabled
                                                function Person(name, age) {
                                                  this.name = name;
                                                  this.age = age;
                                                  this.toString = toString;
                                                }
                                                function toString() {
                                                   return '[' + this.name + ' is '+ this.age + ' years old.]';
                                                };

                                              Это работает но требует дополнительного контроля за кодом если необходимо создавать много таких методов. Логично следующее решение создать объект в котором определять эти методы, напрмер:
                                              ExpandedWrap disabled
                                                function Person(name, age) {
                                                  this.name = name;
                                                  this.age = age;
                                                  this.toString = personMethods.toString;
                                                }
                                                var personMethods = {
                                                  toString: function() {
                                                    return '[' + this.name + ' is '+ this.age + ' years old.]';
                                                  }
                                                // другие методы
                                                };

                                              Это работает, но в JavaScript уже есть нужный механизм и называется он да-да prototype! :D
                                              Он же [[Prototype]], он же __proto__, он же prototype :D. Первое это условное обозначение прототипа в спецификации JavaScript, второе это ссылка на прототип в объекте-экземпляре, ну а третье это ссылка на прототип в функции-конструкторе.

                                              Об этом уже в следующий раз! :thanks:
                                              To be continue...
                                              Сообщение отредактировано: Cfon -
                                                Цитата Cfon @
                                                Все красиво все работает. Такой стиль кодирования использовался в ES3/ES5, но ES6 привнесла некоторые изменения синтаксиса, вот как тоже будет в ES6:

                                                Неа, в ES6 будет:
                                                ExpandedWrap disabled
                                                  class Person {
                                                      constructor(name, age) {
                                                          [this.name, this.age] = [name, age];
                                                      }
                                                   
                                                      toString() {
                                                          return `[${this.name} is ${this.age} years old.]`;
                                                      }
                                                  }
                                                   
                                                  function createPerson(name, age) {
                                                    return new Person(name, age);
                                                  }
                                                  Цитата Serafim @
                                                  Цитата Cfon @
                                                  Все красиво все работает. Такой стиль кодирования использовался в ES3/ES5, но ES6 привнесла некоторые изменения синтаксиса, вот как тоже будет в ES6:

                                                  Неа, в ES6 будет:
                                                  ExpandedWrap disabled
                                                    class Person {
                                                        constructor(name, age) {
                                                            [this.name, this.age] = [name, age];
                                                        }
                                                     
                                                        toString() {
                                                            return `[${this.name} is ${this.age} years old.]`;
                                                        }
                                                    }
                                                     
                                                    function createPerson(name, age) {
                                                      return new Person(name, age);
                                                    }

                                                  да не торопи события! торопыга :D
                                                  о классах будет дальше!
                                                    Это просто ты медленный. :angry:

                                                    Добавлено
                                                    С другой стороны, кажется, что пример с пользователем на ES5 лучше всё же переписать как:
                                                    ExpandedWrap disabled
                                                      function Person(name, age) {
                                                        this.name = name;
                                                        this.age = age;
                                                      }
                                                       
                                                      Person.prototype.sayHello = function() {
                                                          return 'Hello, I am ' + this.toString();
                                                      }
                                                       
                                                      Person.prototype.toString = function() {
                                                          return '[' + this.name + ' is '+ this.age + ' years old.]';
                                                      }


                                                    А то ты везде упоминаешь прототип, но при этом воообще не используешь его, декларируя данные в конструкторе во время инстанциирования, а не в прототипе ;)
                                                    Сообщение отредактировано: Serafim -
                                                      Цитата Serafim @
                                                      А то ты везде упоминаешь прототип, но при этом воообще не используешь его, декларируя данные в конструкторе во время инстанциирования, а не в прототипе ;)

                                                      да я же хочу все постепенно объяснять и к прототипу я приду естественным путем! ;)
                                                        Cfon! я для твоей книги место нашёл ;) http://sources.ru/magazine/
                                                          Продолжаю верещать! :D
                                                          Итак, шо мы имеем рассказать? А вот шо! К примеру есть код:
                                                          ExpandedWrap disabled
                                                            function createPerson(name, age) {
                                                              return {
                                                                name: name,
                                                                age: age,
                                                                __proto: personMethods
                                                              };
                                                            }
                                                            var personMethods = {
                                                              toString: function() {
                                                                return '[' + this.name + ' is ' + this.age + ' years old.]';
                                                              }
                                                            };
                                                            var gregory = createPerson('Gregory', 42);
                                                            if (typeof gregory.__proto.toString === 'function') {
                                                              console.log(gregory.__proto.toString.call(gregory));
                                                            } else {
                                                              console.log(gregory.toString());
                                                            }
                                                            // [Gregory is 42 years old.]


                                                          Тут я сымитировал работу движка JavaScript с прототипом. Рассмотрим его. В функции createPerson я добавил свойство __proto, которому присвоил ссылку на объект personMethods. Этот объект содержит определения методов для работы с объектом возвращаемым функцией createPerson. В нашем случае имеется всего один метод toString. Далее создаем объект gregory и собственно имитируем работу движка JavaScript, которую он выполняет при обращении к свойствам объекта, т.е. производим поиск нужного свойства через так называемую цепочку прототипов. В нашем простом примере я ограничился одним уровнем, поиском только в объекте __proto для демки.

                                                          А вот как это будет выглядеть через настоящий прототип:
                                                          ExpandedWrap disabled
                                                            function createPerson(name, age) {
                                                              return {
                                                                name: name,
                                                                age: age,
                                                                __proto__: personMethods //<-- тут изменение
                                                              };
                                                            }
                                                            var personMethods = {
                                                              toString: function() {
                                                                return '[' + this.name + ' is ' + this.age + ' years old.]';
                                                              }
                                                            };
                                                            var gregory = createPerson('Gregory', 42);
                                                            console.log(gregory.toString()); // [Gregory is 42 years old.]


                                                          Всего одно изменение, я заменил __proto на __proto__, т.е. присвоил personMethods ссылке __proto__, которая является внутренним свойством объекта gregory и неявно присутствует в каждом объекте. Это и есть ссылка на прототип, которую неявно использует движок JavaScript, выполняя за нас поиск свойств и обращение к ним. Конечно явно трогать свойство __proto__ не стоит, поскольку оно является внутренним свойтсвом движка JavaScript. Для доступа к нему существует несколько легальных способов, я уже перечислял их выше, не поленимся и еще раз перечислим:
                                                          1. свойство prototype функции-конструктора и оператор new;
                                                          2. метод Object.create (доступен в ECMAScript 5);
                                                          3. метод Object.setPrototypeOf (доступен в ECMAScript 6).

                                                          Первый способ:
                                                          ExpandedWrap disabled
                                                            function Person(name, age) {
                                                              this.name = name;
                                                              this.age = age;
                                                            }
                                                            Person.prototype = { //<-- установка прототипа
                                                              constructor: Person,
                                                              toString: function() {
                                                                return '[' + this.name + ' is ' + this.age + ' years old.]';
                                                              }
                                                            };
                                                             
                                                            var gregory = new Person('Gregory', 42);
                                                            console.log(gregory.toString()); // [Gregory is 42 years old.]


                                                          Второй способ:
                                                          ExpandedWrap disabled
                                                            var createPerson = (function () {
                                                              var personMethods = {
                                                                toString: function(){
                                                                  return '[' + this.name + ' is ' + this.age + ' years old.]';
                                                                }
                                                              };
                                                              return function (name, age) {
                                                                var o = Object.create(personMethods); //<-- установка прототипа
                                                                o.name = name;
                                                                o.age = age;
                                                                return o;
                                                              };
                                                            })();


                                                          Ну и третий способ:
                                                          ExpandedWrap disabled
                                                            var createPerson = (function () {
                                                              var personMethods = {
                                                                toString(){
                                                                  return `[${this.name} is ${this.age} years old.]`;
                                                                }
                                                              };
                                                              return function (name, age) {
                                                                var o = { name,  age };
                                                                Object.setPrototypeOf(o, personMethods);  //<-- установка прототипа  
                                                                return o;
                                                              };
                                                            })();


                                                          Существует еще один. Какой? Догадайтесь :D
                                                          ExpandedWrap disabled
                                                            class Person {
                                                              constructor(name, age) {
                                                                this.name = name;
                                                                this.age = age;
                                                              }
                                                              toString() {
                                                                return `[${this.name} is ${this.age} years old.]`;
                                                              }
                                                            }
                                                             
                                                            var gregory = new Person('Gregory', 42);
                                                            console.log(gregory.toString()); // [Gregory is 42 years old.]

                                                          хз где тут установка прототипа :D или ее нет? :unsure:
                                                          Конечно же есть! Просто она скрыта от глаз движком JavaScript :)

                                                          Это долгожданый всеми синтаксис класса. Он появился в ES6. Если разобраться, то это те же яйца тока в профиль :D
                                                          Почему? Да патаму шо является той же самой формой функции-конструктора, что и первый способ!

                                                          Юзать синтаксис классов конечно удобно, но есть подводные камни, которые могут появиться, если не знать прототипов и сразу писать классы минуя изучение прототипов и функций-конструктора. Какие камни? Ну например шо вы скажите когда увидите такое?
                                                          ExpandedWrap disabled
                                                            var Person = (function () {
                                                              class Person {
                                                                constructor(name, age) {
                                                                  this.name = name;
                                                                  this.age = age;
                                                                }
                                                                toString() {
                                                                  return `[${this.name} is ${this.age} years old.]`;
                                                                }
                                                              }
                                                              return Person;
                                                            )();

                                                          Ага задумчиво да? :D Не?! :blink:
                                                          значит вы просто изучали как и я с ES3 :victory:

                                                          Всем удачи! :thanks:
                                                          Продолжение следует...

                                                          Добавлено
                                                          Цитата K313 @
                                                          Cfon! я для твоей книги место нашёл ;) http://sources.ru/magazine/

                                                          до книжке еще далеко :P
                                                          Сообщение отредактировано: Cfon -
                                                            Из выше сказанного можно сделать вывод, что прототип объекта используется для экономии памяти, через определения в нем методов, которые будут разделяться другими экземплярами объектов. Но это еще не все прототип можно использовать для расширения функциональности, известную в среде программистов как наследование. По большому счету он не отличается от того что мы делали раньше, т.е. любому прототипу объекта можно назначить любой другой объект, который будет его прототипом. Принцип простой, мы назначаем нужный объект прототипу целевого объекта, а дальше работает движок JavaScript его цепочка прототипов, т.е. когда идет обращение к свойствам (методам) объекта движок JavaScript ищет данное свойство сначала в самом объекте и если его не обнаружевает, то ищет далее по цепочке прототипов, в конце цепочки находится объект Object.prototype, у которого прототип установлен в null, в результате если свойство не обнаружено, то JavaScript выдает ошибку TypeError.
                                                            Пример позже приведу, т.к. в новогодние дни лень много писать :D
                                                            Сообщение отредактировано: Cfon -
                                                              Цитата Cfon @
                                                              для экономии памяти

                                                              JS экономный по памяти :lool:
                                                                Здрасте с Новым Годом! :D
                                                                  Новичок: "Чем отличается свойство prototype от __proto__?"
                                                                  Гений: "Тем что prototype это свойство функции, которое задействуется при вызове оператора new при создании объекта для инициализации как раз таки внутреннего свойства __proto__, которое создается движком JS для организации цепочки прототипов."

                                                                  Новичок: :wacko:
                                                                  Новичок: "Что такое цепочки прототипов?"
                                                                  Гений: "Я тебе потом скажу :D"
                                                                  Сообщение отредактировано: Cfon -
                                                                  0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                                  0 пользователей:


                                                                  Рейтинг@Mail.ru
                                                                  [ Script execution time: 0,0949 ]   [ 16 queries used ]   [ Generated: 29.03.24, 08:53 GMT ]