Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.191.216.163] |
|
Сообщ.
#1
,
|
|
|
Здрасте всем, есть код, но не работает, возникает ошибка.
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 выловить не удалось, там тоже эксэпшен. |
Сообщ.
#2
,
|
|
|
У тебя shelby в друзьях у shelby, потому что friends - это элемент его "прототипа", т.е. принадлежит сразу всем. По-этому, рекурсивно вызывается тустринг: gregory[shelby[shelby[shelby[...]]]]
|
Сообщ.
#3
,
|
|
|
Цитата Serafim @ У тебя shelby в друзьях у shelby, потому что friends - это элемент его "прототипа", т.е. принадлежит сразу всем. По-этому, рекурсивно вызывается тустринг: gregory[shelby[shelby[shelby[...]]]] Спс a выход есть из этого? ща просто нет под рукой компа. |
Сообщ.
#4
,
|
|
|
Я уже писал тебе об этом, но ты ответил "нет, не хочу использовать классы", так что нет. Перебирай каждое поле и копируй руками.
Добавлено О, можно вот так например: 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()); |
Сообщ.
#5
,
|
|
|
нашел косяк в реализации функции toString:
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(). заменил на s += this.friends[i].name + ', '; все выводит, да еще определил в каждом объекте свое поле friends: 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: [] } }); спс за уточнения еще раз Цитата Serafim @ твой код немного мне не понятен, видимо ECMAScript 6-7? |
Сообщ.
#6
,
|
|
|
Вот ES6:
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()); |
Сообщ.
#7
,
|
|
|
Serafim, а что значит вот это заклинание?
Цитата Serafim @ [Symbol.toPrimitive]() { return this.toString(); } |
Сообщ.
#8
,
|
|
|
У тебя же в коде много недоработок:
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, а что значит вот это заклинание? Ну это декларация значения в качестве имени метода =) Например: const NAME = 'asdasd'; class Some { [NAME]() { return 23; } } (new Some).asdasd(); // 23 Добавлено Ну или даже вот так: 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); } |
Сообщ.
#9
,
|
|
|
Цитата Serafim @ Ну это декларация значения в качестве имени метода =) А что в данном случае даст Symbol.toPrimitive? |
Сообщ.
#10
,
|
|
|
Цитата Астарот @ А что в данном случае даст Symbol.toPrimitive? возможность кастовать объект к примитиву =) Т.е. всякие number\string\etc - это объекты, но при передаче куда-то они ведут себя как примитивы, т.е. передаются по значению, а не по ссылке, за это отвечает этот символ Добавлено https://developer.mozilla.org/ru/docs/Web/J...bol/toPrimitive |
Сообщ.
#11
,
|
|
|
Ну и наркомания
|
Сообщ.
#12
,
|
|
|
наркомания - это вот это писать:
Цитата Cfon @ 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.'; } Вместо `${this.name} is a ${this.age} years old. [${this.friends.map(i => i.name).join(', ')}] are his friends.` |
Сообщ.
#13
,
|
|
|
Serafim при всем уважении, ну нет такого синтаксиса в моих умных книжках по js
|
Сообщ.
#14
,
|
|
|
Сообщ.
#15
,
|
|
|
Цитата Serafim @ ну не знаю предложи лучше вот я например ща читаю книжку "Сильные стороны Javascript" Дугласа крокфорда 2012 года издание |
Сообщ.
#16
,
|
|
|
Всё что угодно, не более 1-2х летней давности. 2012ый год - это древность, чего и требовалось доказать
|
Сообщ.
#17
,
|
|
|
Цитата Serafim @ ну это я для примера привёл, еще я читаю "JavaScript для профессионалов" николаса закаса 2015 года издание, но и там не использует твой синтаксис и ты предлагаешь мне не изучать язык по таким авторитетным авторам с их богатым опытом, только из-за того что это старый стандарт? моё мнение такое, что лучше для начала почитать эти "устаревшие" издания и потом если есть необходимость изучить новый стандарт по документации той же мозилы, чем сразу копаться в документации без нужного опыта в программировании на js |
Сообщ.
#18
,
|
|
|
Окок, просто учитывай, что сейчас так мало кто пишет
|
Сообщ.
#19
,
|
|
|
Цитата Serafim @ Окок, просто учитывай, что сейчас так мало кто пишет А я буду так писать |