На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: ElcnU, ANDLL, fatalist
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> ошибка исполнения кода , объекты, наследование, прототипы
    Здрасте всем, есть код, но не работает, возникает ошибка.
    ExpandedWrap disabled
      var main = (function () {
          var Person = {
              name: null,
              age: null,
              friends: [],
              toString: function () {
                  var s = '[';
                  for (var i = 0; i < this.friends.length; ++i) {
                      s += this.friends[i] + ', ';
                  }
                  if (this.friends.length) {
                      s = s.slice(0, s.length - 2);
                  }
                  s += ']';            
                  return this.name + ' is a ' + this.age + ' years old. ' +
                      s + ' are his friends.';
              }
          };
       
          var gregory = Object.create(Person, {
              name: { value: 'Gregory' },
              age: { value: 42 }        
          });
            
          var shelby = Object.create(Person, {
              name: { value: 'Shelby' },
              age: { value: 27 }      
          });
       
          gregory.friends.push(shelby);    
          console.log(gregory.toString());
      })();

    вылазит ошибка: 'Out of stack space'
    в среде vs2013 выловить не удалось, там тоже эксэпшен.
    Сообщение отредактировано: Cfon -
      У тебя shelby в друзьях у shelby, потому что friends - это элемент его "прототипа", т.е. принадлежит сразу всем. По-этому, рекурсивно вызывается тустринг: gregory[shelby[shelby[shelby[...]]]]
        Цитата Serafim @
        У тебя shelby в друзьях у shelby, потому что friends - это элемент его "прототипа", т.е. принадлежит сразу всем. По-этому, рекурсивно вызывается тустринг: gregory[shelby[shelby[shelby[...]]]]

        Спс a выход есть из этого? ща просто нет под рукой компа.
          Я уже писал тебе об этом, но ты ответил "нет, не хочу использовать классы", так что нет. Перебирай каждое поле и копируй руками.

          Добавлено
          О, можно вот так например:
          ExpandedWrap disabled
            let Person, gregory,
                bind = function (fn, me) {
                    return function () {
                        return fn.apply(me, arguments);
                    };
                };
             
            Person = (function () {
                Person.prototype.name = null;
             
                Person.prototype.age = null;
             
                Person.prototype.friends = [];
             
                function Person(name, age) {
                    this.name          = name;
                    this.age           = age;
                    this.toString      = bind(this.toString, this);
                    this.toLocalString = bind(this.toLocalString, this);
                    this.addFriend = bind(this.addFriend, this);
                }
             
                Person.prototype.addFriend = function (friend) {
                    this.friends.push(friend);
                };
             
                Person.prototype.toString = () => `${this.name} is a ${this.age} years old. [${this.friends.join(', ')}] are his friends.`;
             
                Person.prototype.toLocaleString      = () => this.toString();
                Person.prototype.valueOf             = () => this.toString();
                Person.prototype[Symbol.toPrimitive] = () => this.toString();
             
                return Person;
            })();
             
            gregory = new Person('Gregory', 42);
             
            gregory.addFriend(new Person('Shelby', 27));
             
            console.log(gregory.toString());
          Сообщение отредактировано: Serafim -
            нашел косяк в реализации функции toString:
            ExpandedWrap disabled
                      toString: function () {
                          var s = '[';
                          for (var i = 0; i < this.friends.length; ++i) {
                              s += this.friends[i] + ', '; //<-- тут видимо идет рекурсивный вызов toString()
                          }
                          if (this.friends.length) {
                              s = s.slice(0, s.length - 2);
                          }
                          s += ']';            
                          return this.name + ' is a ' + this.age + ' years old. ' +
                              s + ' are his friends.';
                      }

            согласно твоему замечанию в строке отмеченой комментом идет скрытый рекурсивный вызов toString().
            заменил на
            ExpandedWrap disabled
              s += this.friends[i].name + ', ';

            все выводит, да еще определил в каждом объекте свое поле friends:
            ExpandedWrap disabled
                  var gregory = Object.create(Person, {
                      name: { value: 'Gregory' },
                      age: { value: 42 },
                      friends: { value: [] }
                  });    
               
                  var shelby = Object.create(Person, {
                      name: { value: 'Shelby' },
                      age: { value: 27 },
                      friends: { value: [] }
                  });

            спс за уточнения еще раз :victory:
            Цитата Serafim @

            твой код немного мне не понятен, видимо ECMAScript 6-7? :)
            Сообщение отредактировано: Cfon -
              Вот ES6:

              ExpandedWrap disabled
                class Person {
                  constructor(name, age) {
                    this.friends = [];
                    [this.name, this.age] = [name, age];
                  }
                 
                  addFriend(p) {
                    this.friends.push(p);
                  }
                 
                  toString() {
                    return `${this.name} is a ${this.age} years old. [${this.friends.join(', ')}] are his friends.`
                  }
                 
                  toLocaleString() { return this.toString(); }
                  valueOf() { return this.toString(); }
                  [Symbol.toPrimitive]() { return this.toString(); }
                }
                 
                gregory = new Person('Gregory', 42);
                 
                gregory.addFriend(new Person('Shelby', 27));
                 
                console.log(gregory.toString());
                Serafim, а что значит вот это заклинание?
                Цитата Serafim @
                [Symbol.toPrimitive]() { return this.toString(); }
                  У тебя же в коде много недоработок:
                  1) Для всех функций "function" в ES5 нужен бинд контекста в обязательном порядке, иначе при потере this будет ссылаться в другое место (будешь постоянно ловить ошибки "call to X of undefined", например).
                  2) Object.create создаёт новый объект, используя старый в качестве основы. У тебя прототип поля friends является общим, по-этому добавляя в друзья кого-то ты его добавляешь сразу всем существующим "персонам" - это ошибка логики.
                  3) У тебя в коде нет хотя бы минимальных инвариантов. Конструктор должен выполнять обязанность контракта дефолтных значений объекта.
                  4) Используя Object.create - ты используешь уже ES6, не понятно почему тогда не использовать метод join у массива, который был ещё в ES5 или даже 4ке
                  5) Ты забыл локальный метод приведения к строке (toLocaleString), метод каста к математическим выражениям (а-ля перегрузка: valueOf) и приведение объекта к примитивному значению (toPrimitive), по-этому "toString" будет нормально работать только в случае интерполяции и сложения N строк. Остальные случаи буду косячить или приводит к сериализации в "[Object Person]"
                  6) и т.д.

                  Добавлено
                  Цитата Астарот @
                  Serafim, а что значит вот это заклинание?

                  Ну это декларация значения в качестве имени метода =) Например:
                  ExpandedWrap disabled
                    const NAME = 'asdasd';
                     
                    class Some {
                      [NAME]() { return 23; }
                    }
                     
                    (new Some).asdasd(); // 23


                  Добавлено
                  Ну или даже вот так:
                  ExpandedWrap disabled
                    class UsersRepository {
                        users = [];
                     
                        add(user) {
                            this.users.push(user);
                            return this;
                        }
                     
                        *[Symbol.iterator]() {
                            yield* this.users;
                        }
                    }
                     
                    let users = new UsersRepository()
                        .add({name: 'Vasya'})
                        .add({name: 'Petya'});
                     
                    for(let user of users) {
                        console.log(user);
                    }
                  Сообщение отредактировано: Serafim -
                    Цитата Serafim @
                    Ну это декларация значения в качестве имени метода =)

                    А что в данном случае даст Symbol.toPrimitive? :scratch:
                      Цитата Астарот @
                      А что в данном случае даст Symbol.toPrimitive?

                      возможность кастовать объект к примитиву =) Т.е. всякие number\string\etc - это объекты, но при передаче куда-то они ведут себя как примитивы, т.е. передаются по значению, а не по ссылке, за это отвечает этот символ

                      Добавлено
                      https://developer.mozilla.org/ru/docs/Web/J...bol/toPrimitive
                        Ну и наркомания :crazy:
                          наркомания - это вот это писать:
                          Цитата Cfon @
                          ExpandedWrap disabled
                             toString: function () {
                                        var s = '[';
                                        for (var i = 0; i < this.friends.length; ++i) {
                                            s += this.friends[i] + ', '; //<-- тут видимо идет рекурсивный вызов toString()
                                        }
                                        if (this.friends.length) {
                                            s = s.slice(0, s.length - 2);
                                        }
                                        s += ']';            
                                        return this.name + ' is a ' + this.age + ' years old. ' +
                                            s + ' are his friends.';
                                    }

                          Вместо
                          ExpandedWrap disabled
                            `${this.name} is a ${this.age} years old. [${this.friends.map(i => i.name).join(', ')}] are his friends.`
                          :lol:
                            Serafim при всем уважении, ну нет такого синтаксиса в моих умных книжках по js :D
                              Вывод: у тебя книжки - говно мамонта ;)

                              Прикреплённый файлПрикреплённый файл123123.jpg (339,48 Кбайт, скачиваний: 399)
                                Цитата Serafim @
                                Вывод: у тебя книжки - говно мамонта ;)

                                Прикреплённый файлПрикреплённый файл123123.jpg (339,48 Кбайт, скачиваний: 399)

                                ну не знаю предложи лучше ;)
                                вот я например ща читаю книжку "Сильные стороны Javascript" Дугласа крокфорда 2012 года издание
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0586 ]   [ 19 queries used ]   [ Generated: 28.03.24, 11:52 GMT ]