Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[54.224.52.210] |
|
Сообщ.
#1
,
|
|
|
Всем здрасте, новая трабла, след код выводит
Gregory is a 42 years old. undefined is a friend. почему "undefined"? var main = (function () { var createPerson = function (obj) { var person = {}; person.getName = function () { return obj.name; }; person.getAge = function () { return obj.age; }; person.addFriend = function (friend) { obj.friends.push(friend); }; person.toString = function () { var s = ''; var len = obj.friends.length; if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].name + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } return obj.name + ' is a ' + obj.age + ' years old. ' + s; }; return person; }; var gregory = createPerson({ name: 'Gregory', age: 42, friends: [] }); var shelby = createPerson({ name: 'Shelby', age: 27, friends: [] }); gregory.addFriend(shelby); //<-- тут добавляем объект shelby, но он не появляется в списке друзей console.log(gregory); // Gregory is a 42 years old. undefined is friend. console.log(shelby); // Shelby is a 27 years old. })(); |
Сообщ.
#2
,
|
|
|
s += obj.friends[i].name + ', '; Что за свойство name и откуда оно возьмется? |
Сообщ.
#3
,
|
|
|
Цитата AVA12 @ s += obj.friends[i].name + ', '; Что за свойство name и откуда оно возьмется? это свойтсво объекта obj, смотри что я передаю в createPerson: var gregory = createPerson({ name: 'Gregory', age: 42, friends: [] }); вот структура объекта { name: 'Gregory', age: 42, friends: [] } friends - массив объектов Добавлено а все разобрался ошибка восприятия заменил на getName терь все пучком person.toString = function () { var s = ''; var len = obj.friends.length; if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; //<-- тут заменил } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } return obj.name + ' is a ' + obj.age + ' years old. ' + s; }; вот так можно obj.name, а вот так уже нельзя obj.friends[i].name |
Сообщ.
#4
,
|
|
|
продолжаю тему, в предыдущем примере собственно наследования как такового и не было.
короче делаю функциональное наследование таким образом: var createJavaDrocher = function (obj) { var javaDrocher = createPerson(obj); //<-- получаем базовый объект person javaDrocher.getGrade = function () { return obj.grade; }; // переопределяем toString, но в нем надо вызвать toString объекта person! javaDrocher.toString = function () { return javaDrocher.toString() + ' The grade is ' + obj.grade + '.'; //<-- тут хз рекусия }; return javaDrocher; }; var gregory = createJavaDrocher({ name: 'Gregory', age: 42, grade: 10, friends: [] }); console.log(gregory.toString()); //<-- выводит ошибку: Out of stack space выхлоп: Out of stack space я так понял идет рекурсивный вызов toString(), вопрос в том как мне теперь быть? мне надо вызвать метод toString() базового объекта person, в переопеределяемом методе toString(). надеюсь нормально объяснил |
Сообщ.
#5
,
|
|
|
сам все порешал
решение гениальное! надо просто сохранить ссылку на базовый метод toString var createJavaDrocher = function (obj) { var javaDrocher = createPerson(obj); var toString = javaDrocher.toString; //<-- сохраняем ссылку на базовый toString javaDrocher.getGrade = function () { return obj.grade; }; javaDrocher.toString = function () { return toString() + ' The grade is ' + obj.grade + '.'; //<-- а тут вызываем его }; return javaDrocher; }; |
Сообщ.
#6
,
|
|
|
так все просто замечательно объекты создаются, наследуются, но одно маленькое но, в моем случае методы объектов дублируются в каждом вновь создаваемом объекте и как я понимаю расходуют впустую память, а хотелось бы чтобы они были в единственном экзампляре!
идеи есть? будем думать |
Сообщ.
#7
,
|
|
|
методы не дублируются, в объектах создаются ссылки на каждый метод
|
Сообщ.
#8
,
|
|
|
Цитата K313 @ методы не дублируются, в объектах создаются ссылки на каждый метод в каждом объекте созданном через createPerson или createJavaDrocher у каждого будет свой индивидуальный набор методов. |
Сообщ.
#9
,
|
|
|
так вот что я придумал, можно вынести реализацию методов в отдельный объект и потом дергать их из других объектов:
// это общий объект в котором реализованы методы var Person = { getName: function () { return this.name; }, getAge: function () { return this.age; }, addFriend: function (friend) { this.friends.push(friend); }, toString: function () { var s = ''; var len = this.friends.length; if (len > 0) { for (var i = 0; i < len; ++i) { s += this.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } return this.name + ' is a ' + this.age + ' years old. ' + s; } }; // тут мы дергаем методы из объекта Person var createPerson = function (obj) { var person = {}; person.getName = function () { return Person.getName.call(obj); //<-- тут можно было не заморачиваться и юзать obj.name }; person.getAge = function () { return Person.getAge.call(obj); }; person.addFriend = function (friend) { Person.addFriend.call(obj, friend); }; person.toString = function () { return Person.toString.call(obj); //<-- вместо большого кода мы просто дергаем метод toString из Person }; return person; }; var gregory = createPerson({ name: 'Gregory', age: 42, friends: [] }); var shelby = createPerson({ name: 'Shelby', age: 27, friends: [] }); console.log(gregory); console.log(shelby); два объекта юзают реализацию методов Person, таким нехитрым способом мы сократили объем памяти, которые будут занимать эти объекты конечно в данном гипотетическом случае это не видно, но если представить реальные объекты это будет заметно. пс. в случае с короткими метода такими как getName и тп, возможно не стоит заморачиваться, но ради соблюдения целостности интерфейса, можно и их перенести в общую реализацию. |
Сообщ.
#10
,
|
|
|
Цитата Cfon @ смысл ООП как раз в том, чтобы этого избежать. у каждого будет свой индивидуальный набор методов |
Сообщ.
#11
,
|
|
|
Цитата K313 @ Цитата Cfon @ смысл ООП как раз в том, чтобы этого избежать.у каждого будет свой индивидуальный набор методов дык избежал же не? ты ваще рубишь JavaScript или просто свои высеры сюда суешь? |
Сообщ.
#12
,
|
|
|
Агрессивность, самонадеянность и вульгарность - даже для пионЭра это перебор.
|
Сообщ.
#13
,
|
|
|
Цитата AVA12 @ Агрессивность, самонадеянность и вульгарность - даже для пионЭра это перебор. ну а че он туфту несет? где тут у меня ООП? наверное даже код не смотрел и пишет стандартные фразы! бесит! |
Сообщ.
#14
,
|
|
|
меня просто твоя гениальнось поразила
Цитата Cfon @ решение гениальное! надо просто сохранить ссылку на базовый метод toString и мне от зависти захотелось подосрать. А если серьёзно, то если бы я писал интерпретатор и компилятор для Javascript, то я бы на твоё объявление функции, создал в памяти блок с исполняемым кодом { телом твоей функции } плюс блок в памяти для всех объявленных переменных в теле функии ( каждая из которых позже при исполнении вызова функции, будут содержать ссылки на адреса в памяти, где хранятся их значения ). Затем, когда ты при каждом новом вызове createPerson внутри функции присваиваешь javaDrocher.toString = function () { return toString() + ' The grade is ' + obj.grade + '.'; //<-- а тут вызываем его }; Поэтому я и не пойму, где ты там память экономишь... |
Сообщ.
#15
,
|
|
|
Цитата K313 @ ясно, бла бла бла Добавлено Цитата K313 @ Поэтому я и не пойму, где ты там память экономишь... ну если ты не разбираешься в JavaScript, как я тебе могу объяснить где я там экономлю?! мы же на разных языках разговариваем |
Сообщ.
#16
,
|
|
|
Самоуверенный и упоротый, как Сифон (c)
|
Сообщ.
#17
,
|
|
|
Цитата Cfon @ тогда может хотя бы объяснишь, где там и что наследуется? Что у тебя и от кого gregory и shelby унаследовали? так все просто замечательно объекты создаются, наследуются |
Сообщ.
#18
,
|
|
|
Цитата K313 @ Цитата Cfon @ тогда может хотя бы объяснишь, где там и что наследуется? Что у тебя и от кого gregory и shelby унаследовали? так все просто замечательно объекты создаются, наследуются послушай чувачок ты думаешь я это сам придумал почитай Дугласа Крокфорда "Сильные стороны JavaScript" |
Сообщ.
#19
,
|
|
|
Цитата K313 @ я не буду в памяти создавать копию исполняемого кода функции javaDrocher.toString, у меня уже есть этот код в памяти в единственном экземпляре, Будешь. Чтобы не создавать - надо присобачивать его к прототипу. Добавлено var createPerson = function (obj) { obj.some = function() { return 23; } return obj; } console.assert(createPerson({a: 23}) === createPerson({a: 23})); // VM360:5 Assertion failed Добавлено Так что предлагаю не выпендриваться и засунуть эту свою книжку туда же, куда я рекомендовал раньше. На помойку т.е. |
Сообщ.
#20
,
|
|
|
Цитата Serafim @ var createPerson = function (obj) { obj.some = function() { return 23; } return obj; } console.assert(createPerson({a: 23}) === createPerson({a: 23})); // VM360:5 Assertion failed если надо проверить на равенство, то надо определить метод isEqual, который будет сравнивать значения свойств Цитата Serafim @ Так что предлагаю не выпендриваться и засунуть эту свою книжку туда же, куда я рекомендовал раньше. На помойку т.е. ща бегу выбрасывать, тока тапки одену |
Сообщ.
#21
,
|
|
|
Цитата Serafim @ Serafim, чувачок пытается сэкономить память путём выноса объявления функции в отдельный "класс". Я думаю, что с точки зрения С++ ( или на чём там javascript написан ) одно объявление функции - один исполняемый код этой функции в памяти. То есть в коде javascript, где бы объявление этой функции не находилось, память она должна пожирать одну и туже. Будешь. Чтобы не создавать - надо присобачивать его к прототипу. |
Сообщ.
#22
,
|
|
|
Цитата K313 @ Serafim, чувачок пытается сэкономить память путём выноса объявления функции в отдельный "класс". Я думаю, что с точки зрения С++ ( или на чём там javascript написан ) одно объявление функции - один исполняемый код этой функции в памяти. То есть в коде javascript, где бы объявление этой функции не находилось, память она должна пожирать одну и туже. старичок ну не спорь ты если не знаешь как устроен javascript! на С++ да там один метод так как классы, а тут извини объекты. можно юзать еще прототипы, но в моем случае они не используются! |
Сообщ.
#23
,
|
|
|
ну тык мне же тоже интересно, где я не прав
и каким образом ты экономишь память создав дополнительный класс/объект Person, а затем при каждом вызове метода объекта gregory или shelby делать лишний вызов метода в Person? |
Сообщ.
#24
,
|
|
|
Ну, ты еще спроси зачем он пытается "экономить память"
|
Сообщ.
#25
,
|
|
|
Цитата K313 @ ну тык мне же тоже интересно, где я не прав и каким образом ты экономишь память создав дополнительный класс/объект Person, а затем при каждом вызове метода объекта gregory или shelby делать лишний вызов метода в Person? Таким что если объектов будет например 1000, и методов в каждом объекте не как в мое примере один toString, то память экономится! Чувачок ты немного включай думалку |
Сообщ.
#26
,
|
|
|
Цитата Cfon @ Таким что если объектов будет например 1000, и методов в каждом объекте не как в мое примере один toString, то память экономится! Чувачок ты немного включай думалку И сколько ты на этом сэкономишь? Чувачок, ты точно тем делом занимаешься? |
Сообщ.
#27
,
|
|
|
Цитата Астарот @ много если будет много больших объектов. как думаешь сколько памяти занимает мой метод toString? |
Сообщ.
#28
,
|
|
|
Цитата Cfon @ много если будет много больших объектов. А у тебя много больших объектов? Вот правда-правда много? Цитата Cfon @ как думаешь сколько памяти занимает мой метод toString? Да плевать слюнями сколько он у тебя занимает, нахрена ты толком ничего не выучив оптимизацией занимаешься? |
Сообщ.
#29
,
|
|
|
ок, тогда на языке разукрашек
|
Сообщ.
#30
,
|
|
|
да-да живи с своем мире
JavaScript тебе не компилятор это интерпретатор, он берет строки кода и переводит по строчно, детали не знаю не интерисовался. еще раз методы в JavaScript в моем случае хранятся в каждом объекте. Добавлено Цитата Астарот @ Да плевать слюнями сколько он у тебя занимает, нахрена ты толком ничего не выучив оптимизацией занимаешься? я не учу оптимизацию цель была решить задачку, вот я ее и решил таким образом, если чето не нравится твое дело, сэр! |
Сообщ.
#31
,
|
|
|
Цитата Cfon @ спорить не буду, это лишь мои предположения... да-да живи с своем мире |
Сообщ.
#32
,
|
|
|
Цитата K313 @ спорить не буду, это лишь мои предположения... ну т.е. ты мне не веришь, что в каждом объекте есть полный набор методов, а не ссылки? когда я пишу функцию которая возвращает объект, например так var createObj = function(){ return { foo: function(){ } }; }; var obj1 = createObj(), obj2 = createObj() ... objN = createObj(); и вызываю ее n-е число раз то создается соответсвено n объектов, в каждом из которых есть свой метод foo. но можно создавать через так называемые прототипы: var Obj = function(){}; Obj.prototype.foo = function(){}; var obj1 = new Obj, obj2 = new Obj, ... objN = new Obj; тут при n-м вызове new Obj у каждого объекта будет ссылка на один и тоже метод foo, точнее так, метод будет доступен каждому объекту через Obj.prototype. |
Сообщ.
#33
,
|
|
|
Цитата Cfon @ помоему нет, не создаёшь...и вызываю ее n-е число раз то создается соответсвено n объектов, в каждом из которых есть свой метод foo. ща попробую покороче изложить мысль. Вчера, когда ты послал меня Дугласа курить, я пошёл не к нему, а пошёл посмотреть, что это такое "функциональное наследование", что ты там мутишь и как его на самом деле применять надо... Так вот, среди прочего попалось и это свойство объекта.prototype Насколько помню, в этом свойстве должна нажодиться ссылка на объект, который является прототипом для твоего createObj "класса". Когда ты будешь вызывать из obj1.foo( ) javascript сперва будет искать метод foo у самого obj1, но там его не будет. Тогда javascript проверит есть ли у твоего объекта свойство prototype и указывает ли оно на объект ( если свойство prototype не объект, то ничего дальше происходить не будет и может выдаст ошибку ). Так вот, если prototype это объект, то javascript переходит к поиску запрошенного метода foo в этом объекте. И так далее от объекта к объекту по ссылкам указанных в свойствах prototype каждого объекта во всей цепочки, пока не будет найден метод foo( ). Так что когда ты пишешь Obj.prototype.foo = function(){}; ты создаёшь метод foo( ) не в "классе" createObj, а в объекте указанном в свойстве createObj.prototype, который был создан от javascript по умолчанию. |
Сообщ.
#34
,
|
|
|
Меня терзают смутные подозрения, что кое-кто путает такие разные вещи как функции и замыкания...
|
Сообщ.
#35
,
|
|
|
а? чёта не то несу?
|
Сообщ.
#36
,
|
|
|
Главное таких "оптимизаторов" до продакшена не допускать
|
Сообщ.
#37
,
|
|
|
ок вот еще пример:
var createObj = function (o) { var obj = {}; obj.foo = o.foo; return obj; }; var bar = { foo: function () { return 'aaa'; } }; var obj1 = createObj(bar); bar.foo = function () { return 'bbb'; }; //<-- изменяем foo var obj2 = createObj(bar); console.log(obj1.foo()); // aaa console.log(obj2.foo()); // bbb надеюсь теперь понятно что при вызове createObj возвращается объект с новым набором методов? в JavaScript функции тоже являются объектами. |
Сообщ.
#38
,
|
|
|
|
Сообщ.
#39
,
|
|
|
художник функции то две
|
Сообщ.
#40
,
|
|
|
Цитата Cfon @ по крайней мере, язык разукрашек ты понимаешь лучше, чем языки программирования художник Цитата Cfon @ да хоть десять, там ещё много для чего память выделять надо, не буду же я ВСЁ тебе разрисовывать. Так что не отклоняйся от темы, а покажи мне по существу, как ты экономишь память перенеся метод .toString в отдельный блок { }. функции то две |
Сообщ.
#41
,
|
|
|
Цитата K313 @ ок умник вернемся назад к моему примеру: var createPerson = function (obj) { var person = {}; person.getName = function () { return obj.name; }; person.getAge = function () { return obj.age; }; person.addFriend = function (friend) { obj.friends.push(friend); }; person.toString = function () { var s = ''; var len = obj.friends.length; if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } return obj.name + ' is a ' + obj.age + ' years old. ' + s; }; return person; }; var gregory = createPerson({ name: 'Gregory', age: 42, friends: [] }); var shelby = createPerson({ name: 'Shelby', age: 27, friends: [] }); console.log( gregory.toString == shelby.toString); // false Выхлоп: false что скажешь? |
Сообщ.
#42
,
|
|
|
Цитата Cfon @ даже не знаю... ничего про это не нашёл. Может быть просто поведение такое у javascript... что скажешь? Но мне же это вроде бы никак не мешает в каждом новом объекте для person.toString = присваивать ссылку на блок в памяти с телом функции, а не копировать весь её исполняемый код снова и снова... Это было бы глупо... Так что пока остаюсь при своём мнении |
Сообщ.
#43
,
|
|
|
Цитата K313 @ Потому что умные книжки надо читать! Лан позже найду где читал, пока оставайся при своем мнении, которое кстати нафиг никому не сдалось |
Сообщ.
#44
,
|
|
|
Цитата из книги многоуважаемого Николаса Закаса "JavaScript для профессиональных веб-разработчиков"!
ты знаешь кто он такой? чтобы не приводить весь учебник поясню вкраце, что речь идет о функции-конструкторе Person: function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = function() { alert(this.name) }; } var person1 = new Person("Nicholas", 29, "Software Eпgineer"); var person2 = new Person("Greg", 27, "Doctor"); Цитата Хотя концепция конструктора полезна, она не лишена недостатков. Главный из них заключается в том, что методы создаются для каждого экземпляра. Так, в предыдущем примере и у person1, и у person2 есть метод с именем sayName(), но эти методы - не один и тот же экземпляр Function. Функции в ECMAScript являются объектами, так что при каждом определении функции создается объект. Логически конструктор на самом деле выглядит так: function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = new Function("alert(this.name)"); //логический эквивалент } При таком взгляде на конструктор очевидно, что каждый экземпляр Person получает свой экземпляр функции, выводящей на экран свойство name. Строго говоря, такое создание функции уникально в плане цепочек областей видимости и разрешения идентификаторов, но технически новый экземпляр Function создается обычным образом. В общем, одноименные функции в разных экземплярах не эквивалентны, что подтверждает следующий код: alert(personl.sayName == person2.sayName); // false Не имеет смысла создавать два экземпляра Function, делающих одно и то же, особенно если учесть, что благодаря объекту this можно отложить привязку функций к конкретным объектам до выполнения кода. Чтобы обойти это ограничение, можно вынести определение функции за пределы конструктора. |
Сообщ.
#45
,
|
|
|
Цитата K313 @ даже не знаю... ничего про это не нашёл. Может быть просто поведение такое у javascript... А какое поведение? Он каждый раз при вызове функции "createPerson" создаёт тучу новых функций, вместо использования существующих с другим контекстом. т.е. эта функция - обыкновенный фектори. 100 объектов (образно, конечно) так создаст и вкладка в хроме удивительно начинает жрать так, что Windows Vista нервно курит в сторонке. Добавлено Цитата Cfon @ чтобы не приводить весь учебник поясню вкраце, что речь идет о функции-конструкторе Person: Это плохая функция конструктор, т.к. ты забыл проверку контекста. Пишешь "Person(...)" без new и твоё приложение будет работать, но при втором вызове оной - обретаешь дзен. Повторяюсь, используй классы, для защиты. class Person { constructor(...args) { [this.name, this.age, this.job] = args; } } new Person("Nicholas", 29, "Software Eпgineer"); /** OK Person {name: "Nicholas", age: 29, job: "Software Eпgineer"} > age: 29 > job: "Software Eпgineer" > name: "Nicholas" > __proto__:Object */ Person("Nicholas", 29, "Software Eпgineer"); // Uncaught TypeError: Class constructor Person cannot be invoked without 'new' В ином случае всегда и всюду, либо принудительно привязывай контекст, либо делай его проверку. Добавлено Цитата Cfon @ Лан позже найду где читал, пока оставайся при своем мнении, которое кстати нафиг никому не сдалось Зачем ты задаёшь вопрос на форуме, если тебе пофигу на мнения участников? Иди и учи себе в одиночестве. |
Сообщ.
#46
,
|
|
|
ок, скажем так "ранил", но не убил! потом посмотрю ещё...
|
Сообщ.
#47
,
|
|
|
Цитата Serafim @ Цитата Cfon @ Лан позже найду где читал, пока оставайся при своем мнении, которое кстати нафиг никому не сдалось Зачем ты задаёшь вопрос на форуме, если тебе пофигу на мнения участников? Иди и учи себе в одиночестве. уважаемый а какой вопрос? вопрос о том что метод один на все объекты ? так это же не верно! и я это знал! и даже не спрашивал! а вот этот крендель мне обратное пихает, ну я и ему старался в вежливой форме доказать обратное а вопрос собственно то был про функциональное наследование и он уже решен, там была ошибка в коде см выше, найти ее помог AVA Добавлено Цитата K313 @ ок, скажем так "ранил", но не убил! потом посмотрю ещё... ну ты нехороший человек иди отсюда со своим мнением! |
Сообщ.
#48
,
|
|
|
Цитата K313 @ ок, скажем так "ранил", но не убил! потом посмотрю ещё... в книжке Девида Хермана "Сила JavaScript" также читал об этом, см совет 34 " Храните методы в прототипах". пацан знаешь кто такой Херман? цитировать лень, там кстати в картинках как ты любишь ска надеюсь теперь то убил оленя! |
Сообщ.
#49
,
|
|
|
Цитата Cfon @ ща нет у меня времени почитать про фабричные функции, написать тест и проверить, действительно ли " ... удивительно начинает жрать так, что Windows Vista нервно курит в сторонке" и если оно так, то полазить по сайтам разработчиков javascript и посмотреть, почему оно так. Так же хочу посмотреть на твоих кентов - Дуглассов и Херманов, вдруг они какакодеры какие нибудь, а ты за ними просто повторяешь... ска надеюсь теперь то убил оленя! Пока стреляй дальше, может ещё чё интересного выстрелишь |
Сообщ.
#50
,
|
|
|
|
Сообщ.
#51
,
|
|
|
Цитата K313 @ Так же хочу посмотреть на твоих кентов чо? Ты не попутал меня с кем-то, часом? Добавлено Цитата K313 @ и если оно так, то полазить по сайтам разработчиков javascript и посмотреть, почему оно так. Повторяюсь, потому что так никто не пишет - это плохой код. Добавлено Хотя иногда такие подходы имеют место быть... |
Сообщ.
#52
,
|
|
|
Цитата Serafim @ это всё Сифону, твоя просто цитата была. чо? Ты не попутал меня с кем-то, часом? Исправил, а то и в прваду, можно было подумать, что это ответ на твою цитату. Немножко некрасиво получилось. |
Сообщ.
#53
,
|
|
|
завязывай херню пороть! умей проигрывать! и читай больше умные книжки! я все сказал! пс. многоуважаемые Д.Крокфорд, Н.Закас, Д.Херман не мои кенты! мне до них далеко еще! я изучаю их опыт вот и все! и тебе советую! |
Сообщ.
#54
,
|
|
|
/* // это общий объект в котором реализованы методы var Person = { getName: function () { return this.name; }, getAge: function () { return this.age; }, addFriend: function (friend) { this.friends.push(friend); }, toString: function () { var s = ''; var len = this.friends.length; if (len > 0) { for (var i = 0; i < len; ++i) { s += this.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } return this.name + ' is a ' + this.age + ' years old. ' + s; } }; // тут мы дергаем методы из объекта Person var createPerson = function (obj) { var person = {}; person.getName = function () { return Person.getName.call(obj); //<-- тут можно было не заморачиваться и юзать obj.name }; person.getAge = function () { return Person.getAge.call(obj); }; person.addFriend = function (friend) { Person.addFriend.call(obj, friend); }; person.toString = function () { return Person.toString.call(obj); //<-- вместо большого кода мы просто дергаем метод toString из Person }; return person; }; // 912 Mb // 323 Mb */ /* var createPerson = function (obj) { var person = {}; person.getName = function () { return obj.name; //<-- тут можно было не заморачиваться и юзать obj.name }; person.getAge = function () { return obj.age; }; person.addFriend = function (friend) { obj.friends.push(friend); }; person.toString = function () { var s = ''; var len = obj.friends.length; if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } return obj.name + ' is a ' + obj.age + ' years old. ' + s; }; return person; }; // 912 Mb // 338 Mb */ /* var createPerson = function (obj) { var person = {}; person.getName = function () { return obj.name; //<-- тут можно было не заморачиваться и юзать obj.name }; person.getAge = function () { return obj.age; }; person.addFriend = function (friend) { obj.friends.push(friend); }; person.toString = function () { var s = ''; var len = obj.friends.length; // увеличу-ка я тело функции... if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } if (len > 0) { for (var i = 0; i < len; ++i) { s += obj.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } return obj.name + ' is a ' + obj.age + ' years old. ' + s; }; return person; }; // 912 Mb // 332 Mb */ var gregory = createPerson({ name: 'Gregory', age: 42, friends: [] }); var shelby = createPerson({ name: 'Shelby', age: 27, friends: [] }); console.log(gregory); console.log(shelby); var all_obj = []; for ( var j = 0; j < 1000000; j++ ) { all_obj.push( createPerson( { name: 'ooo_'+j, age: j, friends: [] } ) ); } alert('Created '+j+' objects!\n\n'+all_obj[ 999999 ].toString ); Windows XP Home Edition, Version 2002, Service Pack 3, Opera 10.61, движок javascript похоже Carakan будет время, посмотрю в других браузерах |
Сообщ.
#55
,
|
|
|
Цитата K313 @ ну не смеши ты народ братишка чтобы проверить это тебе надо немного больше потрудиться с кодом чем простой копипаст про оптимизацию кода никогда не слышал? например удаление не используемого кода, нет смысла оптимизировать тело функции, которая ни разу не используется, ее можно просто удалить. про оптимизацию Прошлое и будущее компиляции JavaScript по поводу производительности в JS Три принципа производительности в JavaScript, делающие Bluebird быстрым мало? тогда сам исчи! не отвлекай меня от работы |
Сообщ.
#56
,
|
|
|
Цитата K313 @ Windows XP Home Edition, Version 2002, Service Pack 3, Opera 10.61, движок javascript похоже Carakan Это ты где такое откопал? |
Сообщ.
#57
,
|
|
|
Цитата Cfon @ весь файл - внизу прикрепил.братишка чтобы проверить это тебе надо немного больше потрудиться с кодом чем простой копипаст var all_obj = []; var Cfon = createPerson( { name: 'Cfon', age: 10, friends: [ /* Д.Крокфорд, Н.Закас, Д.Херман, и др. */ ] } ); var all_ret = []; for ( var j = 0; j < 1000000; j++ ) { all_obj.push( createPerson( { name: 'ooo_'+j, age: j, friends: [] } ) ); all_obj[ j ].addFriend( Cfon ); all_ret.push( all_obj[ j ].toString() );//alert('for_j = '+j+'\n\n'+all_ret[j]); } alert('Created '+j+' objects!\n\n'+all_obj[ j-1 ].toString() ); Два первых теста заняли в диспетчере задач у Opera 10.61 по 1.205 Mb, у Opera 31.0 по 382-371 Mb памяти на 1.000.000 циклов. После увеличения тела функции .toString(), потребление памяти увеличилось почти в 20 раз ( 811 Мб. на 50.000 циклов ), но вынос её большого тела в отдельный класс Person результата НЕ изменил ( 773 Мб. на 50.000 циклов ). у Opera 31.0 два первых теста заняли по 520-540 Mb памяти на 1.000.000 циклов. После увеличения тела функции .toString(), потребление памяти увеличилось почти в 8 раз ( 162 Мб. на 50.000 циклов //// 477 Мб. на 200.000 циклов, там у Оперы память сразу на 60 Мб. потребляет, так что если по отнимать 162 - 60 и 477 - 60, то всё сходится, 100 Мб на 50 тыщ и 400 на 200 тыщ. ) но вынос её большого тела в отдельный класс Person тоже результата практически НЕ изменил ( 168 Мб. на 50.000 циклов //// 477 Мб. на 200.000 циклов ). Так что пока экономии памяти по твоему методу я не вижу... Windows XP Home Edition, Version 2002, Service Pack 3, Opera 10.61, движок javascript похоже Carakan Цитата Serafim @ + IE6 Это ты где такое откопал? Прикреплённый файлjs_Cfon_test.rar (2,06 Кбайт, скачиваний: 95) |
Сообщ.
#58
,
|
|
|
А в ci было слабо прогнать? Ну там тревис или циркл, не?
|
Сообщ.
#59
,
|
|
|
Цитата Serafim @ слабо мне так нагляднее, как мы память экономим. А в ci было слабо прогнать? |
Сообщ.
#60
,
|
|
|
Цитата K313 @ Так что пока экономии памяти по твоему методу я не вижу... естественно не будет экономии, потому что код оптимизируется компилятор js удаляет повторяющиеся участки кода! ты читал про оптимизацию? и что ты мне тут эту лажу пихаешь?! если хочешь доказать то приведи скришоты, что было до чтобы после, а не эти голые цифры в которых я даже ничего не понял! Цитата K313 @ После увеличения тела функции .toString(), потребление памяти увеличилось почти в 20 раз ( 811 Мб. на 50.000 циклов ), но вынос её большого тела в отдельный класс Person результата НЕ изменил ( 773 Мб. на 50.000 циклов ). т.е. ты признаешь что методы дублируются в каждом объекте? остается разобраться почему моя схема не работает, так? |
Сообщ.
#61
,
|
|
|
Цитата Cfon @ компилятор js 1) У JS нет компилятора (кроме диалекта под mono) 2) Какого компилятора? Варианты ответов: - V8 - Edge - Chakra - SpiderMonkey - Rhino - Tamarin - KJS (KHTML) - Narcissus - Carakan - Juce - Jerry - Futhark +встроенные: - Adobe Acrobat - OpenLaszio - Max/MSP - ANT Galio ? Добавлено 3) С чего ты решил что удаляет и про какую реализацию ты говорил? Добавлено Цитата K313 @ мне так нагляднее, как мы память экономим Нагляднее, нежели написать список тестов и стартануть их на разных версиях с разным окружением и увидеть в конце циферки (при желании даже с коверейджем, что выполнилось, а что заскипалось, примерно как тут: https://travis-ci.org/SerafimArts/Railgun/jobs/238566389)? Да ладно? |
Сообщ.
#62
,
|
|
|
Цитата Serafim @ Цитата Cfon @ компилятор js 1) У JS нет компилятора (кроме диалекта под mono) 2) Какого компилятора? Варианты ответов: Скрытый текст - V8 - Edge - Chakra - SpiderMonkey - Rhino - Tamarin - KJS (KHTML) - Narcissus - Carakan - Juce - Jerry - Futhark +встроенные: - Adobe Acrobat - OpenLaszio - Max/MSP - ANT Galio ? я не знакомился в движками броузеров, думаю у него это Carakan раз он на опере тестил? Цитата Serafim @ 3) С чего ты решил что удаляет и про какую реализацию ты говорил? тут я предположил, так как читал что компиляторы JS оптимизируют код разными способами, в том числе удаляют не нужный код. Serafim а не мог б ты протестить и мой код? если не лень а то я не юзал Travic CI. |
Сообщ.
#63
,
|
|
|
Цитата Cfon @ надо подумать... т.е. ты признаешь что методы дублируются в каждом объекте? Цитата Cfon @ остается разобраться почему моя схема не работает, так? Цитата Serafim @ да мне в лом, если чесно, разбираться что это и с чем его едят... Да ладно? |
Сообщ.
#64
,
|
|
|
Цитата K313 @ попробуй через прототип, тут всего один метод на все копии объектов: // функция-конструктор var Person = function (obj) { // условное приватные данные this._name = obj.name; this._age = obj.age; this._friends = obj.friends; }; // функции-методы Person.prototype.getName = function () { return this._name; }; Person.prototype.getAge = function () { return this._age; }; Person.prototype.addFriend = function (friend) { this._friends.push(friend); }; Person.prototype.toString = function () { var s = ''; var len = this._friends.length; if (len > 0) { for (var i = 0; i < len; ++i) { s += this._friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } return this._name + ' is a ' + this._age + ' years old. ' + s; }; var gregory = new Person({ name: 'Gregory', age: 42, friends: [] }); var shelby = new Person({ name: 'Shelby', age: 27, friends: [] }); console.log(gregory.toString == shelby.toString); // true |
Сообщ.
#65
,
|
|
|
Цитата Cfon @ Serafim а не мог б ты протестить и мой код? если не лень а то я не юзал Travic CI. Я тревис для js тоже не юзал, так что хз как там +) Если посмотреть по проектам - люди зачастую вот эту шнягю юзают: https://saucelabs.com/ А на выходе можно получить тестирвоание кода вообще на разных ОС и браузерах, например Win7 + IE10: https://saucelabs.com/beta/tests/74b837a08b...4dd/commands#84 Добавлено Цитата Cfon @ я не знакомился в движками броузеров, думаю у него это Carakan раз он на опере тестил? в опере 10 - да, каркакакакакан +) |
Сообщ.
#66
,
|
|
|
Цитата Cfon @ мы же не прототипы ковыряем, а "функциональное наследование" и как там, "фабричные функции"... так что не отвлекаемся от темы попробуй через прототип, тут всего один метод на все копии объектов: Цитата Cfon @ т.е. ты признаешь что методы дублируются в каждом объекте? сначало избавился от замыкания на параметр obj var createPerson = function (objjj) { var person = {}; person.getName = function () { return '-OOO-';//obj.name; //<-- тут можно было не заморачиваться и юзать obj.name }; person.getAge = function () { return 333;//obj.age; }; person.addFriend = function (friend, obj) { obj.friends.push(friend); }; person.toString = function (obj) { var s = ''; var len = obj.friends.length; // увеличу-ка я тело функции... Решил покопать с самого начала var all_obj = []; var all_res = []; var obj = null; var mtime = Date.now(); for ( var j = 0; j < 1000000; j++ ) { // TEST 1 //all_obj.push( 0 ); // массив размером в -> 10 Mln = 35 Mb., mtime = 900 msec // TEST 2 //all_obj.push( { } ); // пустые объекты -> 10 Mln = 310 Mb., mtime = 7.500 ... 9.000 msec // TEST 3 //all_obj.push( { name: 'ooo_'+j, age: j, friends: [] } ); // объекты со свойствами -> 4 Mln = 350 Mb., mtime = 7.000 msec //all_res.push( 123 * Math.random( ) ); // с добавкой массива для результатов -> 4 Mln = 405 Mb., mtime = 9.000 ... 10.000 msec /* // TEST 4 all_obj.push( { name: 'ooo_'+j, age: j, friends: [], foo : function( param ){return param * Math.random();} } ); all_res.push( all_obj[ j ].foo( 123 ) ); // с встроенным методом и его выполнением -> 1 Mln = 260 Mb., mtime = 30.000 msec */ /* по разнице между тестами 3 и 4 можно предположить, что встроенная функция объодится нам где-то в ( 260 - 405/4 ) Мб / 1 Млн. = 160 байт на функцию. */ /* // TEST 5 all_obj.push( { name: 'ooo_'+j, age: j, friends: [] } ); // с пристроенным (не знаю, как называется) методом и его выполнением -> 1 Mln = 145 Mb., mtime = 5.000 msec all_obj[ j ].foo = function( param ){return param * Math.random();}; all_res.push( all_obj[ j ].foo( 123 ) ); */ /* После 5-го теста видно, что потребление памяти (на удивление для меня) уменьшилось таким образом, что пристроенная функция объодится нам где-то в ( 145 - 405/4 ) Мб / 1 Млн. = 45 байт на функцию. Кроме того и скорость выполнения вызова такой функции увеличилась аж в 6 раз!!! */ // повторение 4-го теста БЕЗ выполнения встроенного метода -> 1 Mln = 235 Mb., mtime = 22.000 msec //all_obj.push( { name: 'ooo_'+j, age: j, friends: [], foo : function( param ){return param * Math.random();} } ); // в общем-то видно, что затяжка из-за объявления встроенного метода....... } alert('Created '+j+' objects!\n\nall_obj[ '+(--j)+' ] = "'+all_obj[ j ]+'"\n\nall_result[ '+j+' ] = "'+all_res[ j ]+'"\n\nmtime = '+(Date.now()-mtime) ); // для теста 4 и 5 //alert( 'obj[ '+j+' ].foo == obj[ '+(j-1)+' ].foo\n\n is '+(all_obj[ j ].foo == all_obj[ j-1 ].foo) ); сижу теперь, думаю, что бы это могло значить?... |
Сообщ.
#67
,
|
|
|
Цитата K313 @ Цитата Cfon @ мы же не прототипы ковыряем, а "функциональное наследование" и как там, "фабричные функции"... так что не отвлекаемся от темы попробуй через прототип, тут всего один метод на все копии объектов: на самом деле мы уже давно отвлеклись от темы напомню что тема была функциональное наследование, и даже не в названии темы дело, а дело было в ошибке, которую я исправил см пост вначале я уже не помню где это было наш же спор возник из-за твоего предположения (сразу скажу ошибочного), что каждый метод в экземплярах объектов, как в моем примере (см пост #1) существует ввиде ссылки на один и тот же общий метод, но это не так! и об этом пишут в любой книжке по JS. я не понимаю почему у тебя это вызывает сомнения?! нет конечно же ссылки на методы можно определять не суть, тут даже дело не в моем решении, в котором я вынес реализацию методов в другой объект Person, чтобы избежать такого дублирования по логике, ну да лана... далее, твои тесты для меня не ялвяются объективными, поскольку в JS много всего задействовано, и то что там у тебя показывает, я если чесно не очень понимаю поэтому предложил проверить твои тесты на прототипе, вот тут то как раз и будет один и тот же метод (к примеру toString) на все экземпляры объектов (как ты предполагал), таким образом если результаты твоих тестов будут без изменений, т.е. размер занимаемой память будет одинаковый плюс-минус, то можно сделать вывод, что твои тесты не корректны логично? Цитата K313 @ сижу теперь, думаю, что бы это могло значить?... я хз что это значит твои тесты для меня не очень понятны например что такое 10 Mln = 35 Mb? // TEST 1 //all_obj.push( 0 ); // массив размером в -> 10 Mln = 35 Mb., mtime = 900 msec Добавлено Цитата Serafim @ Цитата Cfon @ Serafim а не мог б ты протестить и мой код? если не лень а то я не юзал Travic CI. Я тревис для js тоже не юзал, так что хз как там +) очень жаль, а то я бессилен что либо объяснять K313 Цитата Serafim @ Если посмотреть по проектам - люди зачастую вот эту шнягю юзают: https://saucelabs.com/ А на выходе можно получить тестирвоание кода вообще на разных ОС и браузерах, например Win7 + IE10: https://saucelabs.com/beta/tests/74b837a08b...4dd/commands#84 ок потом по чекаю кстати все эти тесты, что ты предлагаешь, в его случае не будет полезным, т.к. они не показывают расход памяти, а тока производительность кода (время исполнения), так? мы же тут не можем решить, как на самом деле в случае моего примера из поста #1 создаются методы дублируются или ссылки, нет я то знаю как, а вот уважаемый коллега нет |
Сообщ.
#68
,
|
|
|
Цитата Cfon @ кстати все эти тесты, что ты предлагаешь, в его случае не будет полезным, т.к. они не показывают расход памяти, а тока производительность кода (время исполнения), так? вдруг там какие-то опции будут с коверейджем, скоростью и памятью, кто его знает |
Сообщ.
#69
,
|
|
|
Цитата Serafim @ т.е. смотреть на разницу производительности в зависимости от опций? ну не знаю докажет ли ему это то что методы дублируются в каждом объекте, не уверен нет мне то ничего не надо доказывать я итак знаю дублируются Добавлено я тестил оба варианта на jsPerf.com, собственно по скорости мой вариант (там где я вынес реализацию в отдельный объект) немного проигрывал, и это понятно, так в моем случае идет лишний вызов функции, но вот сколько памяти это занимает хз 2K313 возвращаясь к примеру из поста #9, там где я вынес реализацию в объект Person: var Person = { getName: function () { return this.name; }, getAge: function () { return this.age; }, addFriend: function (friend) { this.friends.push(friend); }, toString: function () { var s = ''; var len = this.friends.length; if (len > 0) { for (var i = 0; i < len; ++i) { s += this.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } return this.name + ' is a ' + this.age + ' years old. ' + s; } }; // функция фабрика с использованием методов из объекта Person var createPerson = function (obj) { var person = {}; person.getName = function () { return Person.getName.call(obj); //<-- вызов Person.getName в контексте obj }; person.getAge = function () { return Person.getAge.call(obj); }; person.addFriend = function (friend) { Person.addFriend.call(obj, friend); }; person.toString = function () { return Person.toString.call(obj); }; return person; } если изменить вызовы на ссылки, то получим след: // не работает, пояснения ниже var createPerson = function (obj) { var person = {}; person.getName = Person.getName; //<-- ссылка на функцию Person.getName person.getAge = Person.getAge; person.addFriend = Person.addFriend; person.toString = Person.toString; return person; }; var gregory = createPerson({ name: 'Gregory', age: 42, friends: [] }); console.log(gregory.toString()); если запустить этот код, то вылезет ошибка undefened length, потому что функцию Person.toString надо привязывать к контексту вызова obj, т.е. надо добавить в моем случае след: person.getName = Person.getName.bind(obj); но это уже не будет таже самая ссылка на функцию Person.getName, это будет ее копия, но не копия ссылки естествено, а копия самой функции (см https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind). |
Сообщ.
#70
,
|
|
|
Цитата Cfon @ всё верно НО это с точки зрения javascript, как ты мне уже и показывал наш же спор возник из-за твоего предположения (сразу скажу ошибочного), что методы в объектах JS созданных, как в моем примере (см пост #1) существуют ввиде ссылок (нет конечно же ссылки на методы можно определять не суть) на один и тот же общий метод, но это не так! и об этом пишут в любой книжке по JS. я не понимаю почему у тебя это вызывает сомнения?! function FF( ) { return { foo : function( ) { /* мноооооooooooooooooooooooooого кода */ } }; } alert( FF( ).foo == FF( ).foo ); // false Когда же ты "сэкономил" память, я те написал, что функции не копируются - это с точки зрения компилятора или С#. Этим я имел ввиду, что компилятору не надо для каждого вновь созданного объекта с методом foo, ни заного компилировать тело функции, ни копировать весь байт-код в каждом новом объекте у функции foo. Функция foo в тексте кода js объявляется один раз - её тело компилируется в байт-код и ВСЁ! во всех объектах при вызове метода foo, C# будет выполнять один и тот же байт-код! исполняемый код НЕ меняется, поэтому по моему мнению, C# не нужно делать в памяти копии этого исполняемого кода. Каждая такая копия всё равно будет делать одно и тоже и выдавать один и то же результат. Поэтому я тут и втираю, что функции не копируются, а передаются по ссылке ( с точки зрения C# ), то есть вынос функции toString в отдельный класс не должен был влиять на расход памяти. И так и так быйт-код тела функции в памяти должен быть в единственном экземпляре. А для каждого метода foo, каждого вновь созданного объекта, C# задаёт ему ссылку на блок в памяти, где лежит этот байт-код. НО это не ссылка javascript ( как ты думаешь ) и даже не ссылка C# ( голый DWORD или QWORD ). Там задаётся какая нибудь C#-структура в 20 - 30 байт, которая и описывает значение этой foo. Например что-то типа того: obj_xxx.foo = <STRUCTUR> { DWORD - по нему C# определяет например тип значения ( null, boolean, .... объект, функция, и т.д. ) BYTE - ... DWORD - а здесь например лежит ссылка - действительный адрес в памяти, где находится исполняемый код тела функции foo, куда C# потом будет передавать управления для её высполнения DWORD - ... BYTE - тут например, можно ли это значение менять или нет ( к примеру ) DWORD - а тут например id данной структуры, который у каждой свой. Таким образом потом при сравнении в javascript -> obj_xxx.foo == obj_xxx.foo выдаст false ... WORD - и так далее ... } общим размером в 20 - 30 байт И даже если мы в javascript создаём функцию через new Function function FF( ) { return { foo : new Function( ' var a = "New_Function_is_created";// \n\n/* мноооооого кода */ \n\n ' ) }; } alert( 'FF( ).foo = ' + FF( ).foo + '\n\nfoo == foo -> ' + ( FF( ).foo == FF( ).foo ) );// Далее, когда мы вызываем метод obj_xxx.foo( ... ), C# создаёт ещё одну структуру ( например call_foo<STRUCTUR> ), которая содержит адреса в памяти: - для переданных в функцию параметров, - для всех внутренних переменных функции, - ссылка на [[scope]], - если было замыкание при присвоении функции для данного obj_xxx.foo, то тоже ссылка на значения всех замкнутых переменных, - ссылка на this, - ну и так далее, что там ещё нужно внутри функции для её работы... C# бросает эту вновь созданную структуру в регистр EAX и после этого передаёт управление по адресу ( который я называл ссылкой, а ты возмущался по этому поводу ), указанному в структуре для данного объекта из которого идёт сейчас вызов функции obj_xxx.foo = <STRUCTUR>. Всё. После этого исполняемый код функции работает с этой call_foo<STRUCTUR>, знает что и где там указанно и как с этим работать. Для каждого вызова foo( ), C# создаёт новую call_foo<STRUCTUR> и поэтому каждый вызов foo( ) работает со своими персональными данными. НО тело ( исполняемый код ) функции foo в памяти одно на все вызовы! По аналогии с javascript: Ты пишешь код, затем видишь, что в некоторых местах кода строки повторяются. Что ты делаешь? Ты берёшь эти повторяющиеся строчки и выносишь их в отдельную функцию, а там где строки повторялись, заменяешь на вызов этой функции с передачей ей каких-то своих для данного вызова параметров. Всё. После этого функция делает одно и тоже, но работает каждый раз с переданными ей параметрами и возвращает нужный тебе в данном месте результат. Так же и в C#, я не вижу смысла делать копии одного и того же исполняемого кода. ------------------------------------------------------ Но после тестов, я если честно, теперь в замешательстве.... Это всё конечно только мои предположения на счёт реализации в C#, а что они там творят на самом деле, я не знаю. Может оптимизаторы так предпочитают создавать копии, и ради скорости плюют на расход памяти..... Хотя я не понимаю, что там можно копировать. Цитата Cfon @ ты путаешь моё предположение с совсем другой вещью. При прототипах, когда ты вызываешь метод foo из какого-то экземпляра объекта, то там внутри этого экземляра метода foo нет, javascript там его не найдёт. Поэтому он проверит у этого экземпляра свойство __proto__, увидит, что там указана ссылка на какой-то объект, а значит ему ( javascript ) нужно перейти по этой ссылке и продолжить поиск метода foo уже в том объекте. И вот там он его уже находит и возвращает. То есть когда ты вызываешь метод foo, его поиск всегда ( если в каком-то экземпляре объекта ты конечно метод foo не переопределил ) всегда приводит в оду и туже точку в одном и том же объекте. Поэтому смысла в таком тетсте я не вижу. поэтому предложил проверить твои тесты на прототипе, вот тут то как раз и будет один и тот же метод toString на все экземпляры объектов (как ты предполагал), Цитата Cfon @ например что такое 10 Mln = 35 Mb? это значит 10 миллионов итераций съели 35 мегабайт памяти и потратилось при этом времени 900 милисекунд. |
Сообщ.
#71
,
|
|
|
лана за сим закончим этот безполезный спор, ты не слышишь меня, я не понимаю тебя, останемся каждый при своем. |
Сообщ.
#72
,
|
|
|
кому интересно вот что говорят знающие люди на ru.stackoverflow.com
https://ru.stackoverflow.com/questions/681462/расход памяти объектов на Javascript позже запостю ту же тему на en.stackoverflow.com |
Сообщ.
#73
,
|
|
|
ну пока они ничего умного не сказали тоже на оптимизптор грешат. А на счёт предпочтения удобства (если разницы в памяти нет), у тебя же каждый раз лишний вызов будет Person.foo.aply(...); - а это лишнии действия... (надо тест сделать, посмотреть сколько отнимает вызов функции и метода), а так, чем тебе НЕ удобно то прописывать весь код в функции-конструкторе?
|
Сообщ.
#74
,
|
|
|
шо опять все заново?!
как я частично выяснил через профайлер Google Chrome, в случае варианта с методами внутри объекта и моим вариантом разницы по расходу памяти не было ~25 Mb на 100,000 объектов в каждом случае. Возможно отсутствие разницы связана с оптимизацией кода и оптимизатор делает подстановку кода вместо вызова по причине того что объем он не контролирует, а улучшает скорость выполнения кода, на то он и оптимизатор. Или же возможно оптимизатор уменьшает код toString так, что его размеры становятся предпочтительными для подстановки. Это всего лишь мои предположения, впрочем не лишеные смысла не так ли? . Надо написать реально большой метод на строк этак 100, а лучше 200 или 300 (копипаст думаю не канает), который невозможно будет сильно оптимизировать В реальности конечно же такие большие методы лучше не писать, уже по другой понятной причине, но в целях выяснения работы кухни JS можно. Также проверил через прототип, вот тут то, как раз память значительно меньше расходуется, у меня ~6 Mb на 100,000 объектов. Вывод? делай сам пс. когда напишу реальный, большой метод, протестю его и тогда уже будет ясен окончательный вердикт по целесообразности выноса в отдельный объект |
Сообщ.
#75
,
|
|
|
Цитата Cfon @ Также проверил через прототип, вот тут то, как раз память значительно меньше расходуется, у меня ~6 Mb на 100,000 объектов. Ну наконец-то дошло! Осталось заюзать классы, увидеть что там потребление ещё раза в два ниже и успокоиться. |
Сообщ.
#76
,
|
|
|
Цитата Serafim @ дошло что? что прототипы меньше расходуют памяти? дык я это знал, просто привожу результаты для уважаемого коллеги а то что мой вариант потребляет равное количество памяти по предварительным тестам, то это, как я писал выше, еще не точные данные ну а классы я не юзаю из принципа... название класс меня бесит! кстати надо протестить и классы и успокоить коего кого |
Сообщ.
#77
,
|
|
|
протестил классы результат тот же что и с прототипом ~6 Mb на 100,000 объектов, собствено это и не удивительно, ибо класс это синтаксический сахар, который в итоге преобразуется в прототипы
и к тому же еще не во всех броузерах поддерживается обосновал нормуль? |
Сообщ.
#78
,
|
|
|
Цитата Cfon @ и к тому же еще не во всех броузерах поддерживается Классы-то? Ну, как сказать http://kangax.github.io/compat-table/es6/ |
Сообщ.
#79
,
|
|
|
Цитата Астарот @ https://developer.mozilla.org/en-US/docs/We...tatements/class полная поддержка тока Google Chrome 42, Edge и FF 45, остальное под вопросом, и всеравно это не отменяет того факта что класс в JS синтаксический сахар, не? у меня в VS2013 ваще слово class выделяется как синтаксическая ошибка |
Сообщ.
#80
,
|
|
|
Цитата Cfon @ ну теперь есть, на кого всё валить! Не удивлюсь, если потом окажется, что он ( оптимизатор ) в конце концов будет твой ?-код реализации функционального наследования САМ переписывать на прототипное, спасая тем самым твою честь и гордость! Слава оптимизаторам!!! Ураааааааа!!! Возможно отсутствие разницы связана с оптимизацией кода и оптимизатор делает подстановку кода вместо вызова по причине того что объем он не контролирует, а улучшает скорость выполнения кода, на то он и оптимизатор. Или же возможно оптимизатор уменьшает код toString так, что его размеры становятся предпочтительными для подстановки. Это всего лишь мои предположения, впрочем не лишеные смысла не так ли? |
Сообщ.
#81
,
|
|
|
Цитата K313 @ ты не увиливай! что на счет один метод на все экземпляры объектов? |
Сообщ.
#82
,
|
|
|
Цитата Cfon @ полная поддержка тока Google Chrome 42, Edge и FF 45, остальное под вопросом, и всеравно это не отменяет того факта что класс в JS синтаксический сахар, не? Крайняя версия FF 54, хрома - 59. По-моему уже можно выдыхать. Цитата Cfon @ у меня в VS2013 ваще слово class выделяется как синтаксическая ошибка Это потому что вменяемые люде в 2017 году не пользуются для веб-разработки вижуал студией 2013... |
Сообщ.
#83
,
|
|
|
Цитата Cfon @ а ты уже разобрался, ЧТО оптимизатор в каждый метод в каждом экземпляре копирует? что на счет один метод на все экземпляры объектов? |
Сообщ.
#84
,
|
|
|
Цитата K313 @ я мля кого выше результаты тестов привел?! 25 Мб в случае объекта литерала и 6 Мб в случае прототипа! Добавлено Цитата Астарот @ вменяемые люди юзают то что дают по месту работы, а не гоняются за модными штучками! ясно? |
Сообщ.
#85
,
|
|
|
Цитата Cfon @ вменяемые люди юзают то что дают по месту работы, а не гоняются за модными штучками! ясно? А если дают что-то невменяемое? Ну, типа VS2013? зы пора бы тебе уже научиться пользоваться цитированием, не находишь? |
Сообщ.
#86
,
|
|
|
Цитата Астарот @ да у меня есть две версии студии 2013 и 2015 я юзаю 2013, почему? да потому что она у меня меньше зависает а что не так с цитированием? и даже если бы на слово class студия 2013 не ругалась, то я бы всеравно не юзал его! ИМХО оно вводит в заблуждение, т.к. в JavaScript нет классов по определению, там тока объекты! или не? |
Сообщ.
#87
,
|
|
|
Цитата Cfon @ я тебя спрашивал, ЧТО именно оптимизатор туда копирует? Голый текст функции javascript-кода? Байт-код тела функции? Или что ещё это может быть?я мля кого выше результаты тестов привел?! 25 Мб в случае объекта литерала и 6 Мб в случае прототипа! И коды тестов тоже мог бы и выложить, а не просто цифры нам называть |
Сообщ.
#88
,
|
|
|
Цитата Cfon @ а что не так с цитированием? Ну... его нет Прикреплённый файлUntitled.png (10,9 Кбайт, скачиваний: 309) |
Сообщ.
#89
,
|
|
|
Цитата K313 @ я тебя спрашивал, ЧТО именно оптимизатор туда копирует? Голый текст функции javascript-кода? Байт-код тела функции? Или что ещё это может быть? я откуда знаю что там и как в оптимизаторе? есть данные результата теста в профайлере Google Chrome все. Добавлено Цитата Астарот @ Ну... его нет а ну я просто чтобы уменьшить объем текста цитаты жал на кнопку "быстрая цитата". |
Сообщ.
#90
,
|
|
|
Цитата Cfon @ ИМХО оно вводит в заблуждение, т.к. в JavaScript нет классов по определению, там тока объекты! или не? Ты лет на 5 отстал от жизни. Подсказываю, открываешь консоль в хроме и пишешь `class VJSNetClassovYaTochnoUveren {}` |
Сообщ.
#91
,
|
|
|
Цитата Cfon @ а ну я просто чтобы уменьшить объем текста цитаты жал на кнопку "быстрая цитата". Ага, только не понятно на что ты отвечаешь, всего-то. |
Сообщ.
#92
,
|
|
|
Цитата Serafim @ Ты лет на 5 отстал от жизни. Подсказываю, открываешь консоль в хроме и пишешь `class VJSNetClassovYaTochnoUveren {}` возможно но не в программировании |
Сообщ.
#93
,
|
|
|
Serafim, оставь его в покое, не видишь что ли, человек прется с прототипной системы, ему кажется, что он познал дзен и ИСТИНУ Наиграется, пару раз споткнется о цепочку наследования, о потерянный контекст и прочие прелести - и тут же полюбит весь сахар
|
Сообщ.
#94
,
|
|
|
Цитата K313 @ И коды тестов тоже мог бы и выложить, а не просто цифры нам называть т.е. ты мне не веришь? да и пох! |
Сообщ.
#95
,
|
|
|
Cfon, а ты знаешь, что помимо protype ещё есть __proto__?
Скрытый текст fatality :troll: |
Сообщ.
#96
,
|
|
|
Цитата Serafim @ Cfon, а ты знаешь, что помимо protype ещё есть __proto__? да знаю, оно позволяет получить доступ к прототипу объекта, как правило его не следует юзать, лучше функцию Object.getPrototypeOf() Добавлено Цитата Астарот @ Наиграется, пару раз споткнется о цепочку наследования, о потерянный контекст и прочие прелести - и тут же полюбит весь сахар врядли я не собираюсь юзать наследование на практике, его в JS я изучаю просто для полноты картины языка и проверки его средств если есть примерчик того где я могу заблудиться в контекстах велком, буду рад размять кости |
Сообщ.
#97
,
|
|
|
let Some = {}; Some.protoype.alert = function(message) { console.log(message); } Some.prototype.todo = function() { this.alert('This is a message every 1 second'); } setInterval(new Some.todo, 1000); Развлекайся |
Сообщ.
#98
,
|
|
|
Цитата Serafim @ Скрытый текст let Some = {}; Some.protoype.alert = function(message) { console.log(message); } Some.prototype.todo = function() { this.alert('This is a message every 1 second'); } setInterval(new Some.todo, 1000); легко во-первых, так нельзя писать на JS в случае записи литералом, прототип объекта не доступен! разве что __proto__, но это свойство не везде реализовано, можно через Object.getPrototypeOf(), но тогда незабываем что методы будут добавлятся к Object.prototype. правильно надо так: // фукнция-конструктор var Some = function () {}; Some.prototype.alert = function (message) { console.log(message); } Some.prototype.todo = function () { this.alert('This is a message every 1 second'); } или так // объект-литерал var some = { alert: function (message) { console.log(message); }, todo: function () { this.alert('This is a message every 1 second'); } }; во-вторых, в setInterval ты передаешь функцию без контекстом вызова, точнее с глобальным контектом, в случае броузера это объект window, как быть? все просто надо его привязать след образом: var some = new Some(); setInterval(some.todo.bind(some), 1000); или setInterval(some.todo.bind(some), 1000); еще примеры |
Сообщ.
#99
,
|
|
|
ну да, там функция должна быть, очепятался
|
Сообщ.
#100
,
|
|
|
шо все больше нет примеров?
лана не суть так протестировал я тут еще один вариант, с привязкой методов // case 2 // объект Person с реализацией методов var Person = { getName: function () { return this.name; }, getAge: function () { return this.age; }, addFriend: function (friend) { this.friends.push(friend); }, toString: function () { var s = ''; var len = this.friends.length; if (len > 0) { for (var i = 0; i < len; ++i) { s += this.friends[i].getName() + ', '; } s = s.slice(0, s.length - 2); s += (len > 1) ? ' are friends.' : ' is a friend.'; } return this.name + ' is a ' + this.age + ' years old. ' + s; } }; // фабрика объектов с привязкой методов из объекта Person var createPerson = function (obj) { var person = {}; person.getName = Person.getName.bind(obj); person.getAge = Person.getAge.bind(obj); person.addFriend = Person.addFriend.bind(obj); person.toString = Person.toString.bind(obj); return person; }; и вот что получил: 1. 5 Мб (расходуемой памяти) 2. 4.3 Мб тесты проводил для 10,000 объектов, для 100,000 - ~20 Mb и 16Mb и это тока при такой малой реализации объекта. первый результат это исходный пример см файл case1.html, ну а второй - c привязкой case2.html, видно что на втором тесте памяти расходуется меньше, чем в первом, т.е можно сделать вывод, что объем памяти занимаемой объектом в случае привязки методов будет меньше, чем если определять методы в самом объекте. Чтобы протестировать, запускаете Chrome => Developer Tools => Memory ставите переключатель на Take Heap Snapshot и жмете кнопку Take Snapshot и зерите скока памяти жрут объекты в хипе. ВСЕ! Прикреплённый файлtests.rar (1,72 Кбайт, скачиваний: 143) да еще анализируя результаты в Хроме, заметил что в первом случае раздел system/Context занимает ~10,000 объектов при тесте 10,000 объектов, а вот во втором с привязкой всего 125 объектов, видимо в этом есть ответ на вопрос. |
Сообщ.
#101
,
|
|
|
продолжаю забивать в крышку гроба гвозди
на этот раз еще одна цитата из другой хорошей книжки Raffaele Cecco "Supercharged JavaScript Graphics" Цитата Глава 1. Многократное использование кода и его оптимизация Одно из достоинств использования наследования через прототипы заключается в эффективном применении памяти; свойства и методы прототипа объекта сохраняются лишь однажды, независимо от того, сколько раз от них происходит наследование. У функционального наследования такого полезного свойства нет; в каждом новом экземпляре свойства и методы будут создаваться заново, то есть дублироваться. Это обстоятельство может представлять проблему, если вы создаете многочисленные экземпляры крупных объектов (возможно, тысячи) и для вас критичен объем потребляемой памяти. Одно из решений такой проблемы — сохранять любые крупные свойства или методы в объекте, а потом передавать этот объект функциям конструктора в качестве аргумента. После этого все экземпляры смогут использовать один и тот же объектный ресурс, не создавая при этом собственных версий объекта. ну как я и предлагал вначале! мля я мля оракл! |
Сообщ.
#102
,
|
|
|
Цитата Cfon @ продолжаю забивать в крышку гроба гвозди Своего гроба? Или чьего, я не понимаю?.. |
Сообщ.
#103
,
|
|
|
Цитата Астарот @ Своего гроба? Или чьего, я не понимаю?.. нет всех тех кто не согласен со мной! |
Сообщ.
#104
,
|
|
|
Цитата Cfon @ продолжаю забивать в крышку гроба гвозди на этот раз еще одна цитата из другой хорошей книжки Raffaele Cecco "Supercharged JavaScript Graphics" Можешь открыть функциональное наследование (сообщение #3726885) где я предлагал воспользоваться прототипами (а заодно выкинуть в помойку книгу, где приводились в пример явный фектори, в качестве примера наследования, что, естественно является откровенным бредом), т.к. твоё решение было довольно плохим как раз с точки зрения тобою же приведённой цитаты от другого автора. Очень рад, что ты наконец её выинул и начал читать более адекватные книжки. Осталось совсем чуть-чуть А теперь ещё раз напоминаю, что на дворе 2017ый год, и хоть приведённая тобою цитата и верна, но эти подходы были актуальны в то время, когда я ещё в школе учился. |
Сообщ.
#105
,
|
|
|
Цитата Cfon @ Одно из решений такой проблемы — сохранять любые крупные свойства или методы в объекте, а потом передавать этот объект функциям конструктора в качестве аргумента. После этого все экземпляры смогут использовать один и тот же объектный ресурс, не создавая при этом собственных версий объекта. Мы не будем использовать прототипы, вместо этого мы создадим фабрику с непонятно каким поведением, наступим на все грабли, пару раз стрельнем себе в ногу, и получим ровно тоже самое Грамотный подход! |
Сообщ.
#106
,
|
|
|
вместо того чтобы писать мне выкинуть книжку или не использовать что-то, вы бы мне реальный пример привели, ну чтобы раскрыть мне глаза
а пока ваши слова не о чем, аргумент один, либо на дворе 2017 и так не пишут, либо это грабли! а что не пишут, как не пишут, где грабли, какие грабли хз ПРИМЕРЫ ГДЕ?! БАЛАБОЛЫ СКА! ЩА Я ВАМ ЗАБЬЮ БОЛЬШОЙ БОЛТ В КРЫШКУ ГРОБА |
Сообщ.
#107
,
|
|
|
Цитата Cfon @ забивай, забивай.... продолжаю забивать в крышку гроба гвозди Я пока всё равно не представляю, зачем мне создавать в памяти копии тела функции, если эти копии ДЕЛАЮТ ОДНО И ТОЖЕ. Даже если это прибомбассы оптимизатора, я так же не понимаю, что там можно копировать. Например, когда вызывается функция-конструктор (создаём очередной экземпляр объекта), и внутри этой функции идёт присвоение фабричного метода. А так как этот фабричный метод ещё не вызывается, то что? Оптимизатор может код этой функии не парсить, а просто скопировать голый текст тела этой фабричной функции в переменную объекта? А потом, когда этот фабричный метод ИМЕНО ЭТОГО объекта будет вызываться, уже тогда проводить все разборы СВОЕЙ КОПИИ голого текста тела фабричной функции? НО, тогда во первых придётся у каждого экземпляра проводить парсинг заного. Во вторых, что мне мешает так же вместо копирования голого текста тела функции в каждый объект, просто оставлять там ССЫЛКУ на адрес в памяти, где у меня этот текст может лежать в одном экземляре? Вобщем мне пока в голову ничё не приходит, для чего бы понадобилось создавать копии одного и того же. Цитата Cfon @ Одно из решений такой проблемы — сохранять любые крупные свойства или методы в объекте, а потом передавать этот объект функциям конструктора в качестве аргумента. После этого все экземпляры смогут использовать один и тот же объектный ресурс, не создавая при этом собственных версий объекта. Цитата Cfon @ ну как я и предлагал вначале! мля я мля оракл! Эй, оракл, тесты же показали, что разницы в расходе памяти НЕТ?! |
Сообщ.
#108
,
|
|
|
Цитата Cfon @ ПРИМЕРЫ ГДЕ?! Ну вот, например, давеча набросал простенький DI контейнер, изучай: https://github.com/SerafimArts/dioma Достаточно будет? Добавлено Или какие тебе примеры нужны? Реального кода, а не всяких либ? |
Сообщ.
#109
,
|
|
|
Я слегка отвлекся и многое пропустил. Скажите, пожалуйста, стюардессу уже сколько раз закапывали?
|
Сообщ.
#110
,
|
|
|
Цитата AVA12 @ Я слегка отвлекся и многое пропустил. Скажите, пожалуйста, стюардессу уже сколько раз закапывали? Пока только руку и левую пятку. |
Сообщ.
#111
,
|
|
|
Вот ведь развратники!
Восемь страниц мусолить вопрос, закрываемый чтением пары абзацев документации - это просто уму нерастяжимо! |
Сообщ.
#112
,
|
|
|
Цитата K313 @ Я пока всё равно не представляю, зачем мне создавать в памяти копии тела функции, если эти копии ДЕЛАЮТ ОДНО И ТОЖЕ. Даже если это прибомбассы оптимизатора, я так же не понимаю, что там можно копировать. тебе ничего не надо создавать, за тебя это делает интрепретатор JS. Цитата K313 @ Например, когда вызывается функция-конструктор (создаём очередной экземпляр объекта), и внутри этой функции идёт присвоение фабричного метода. что за фабричный метод присваивается? вот форма функции-конструстора тут нет никакого присваения фабричного метода: var Person = function(name, age){ this.name = name; this.age= age; }; var gregory = new Person('Gregory', 42); а вот фабрика можно написать так: var createPerson = function(name, age){ var o ={ name: name, age: age }; return o; }; var gregory = createPerson ('Gregory', 42); или так: var createPerson = function(name, age){ var o = {}; o.name = name; o.age = age; return o; }; или даже так: var createPerson = function(name, age){ return { name: name, age: age }; }; разница между конструктором и фабрикой в том, что конструктор имеет прототип, в который можно добавить общее методы или свойства, но свойства тут все открыты для доступа public, а в случае фабрики мы имеем дублирование кода методов, но свойства их такие как name, age можно закрыть от прямого доступа например так: var createPerson = function(name, age){ var o ={ getName: function() { return name}, getAge: function() { return age}, }; return o; }; var gregory = createPerson ('Gregory', 42); gregory.getName(); // Gregory gregory.name // undefined чего не сделаешь с конструктором. Цитата K313 @ Эй, оракл, тесты же показали, что разницы в расходе памяти НЕТ?! тесты показали, что разницы не было в случае вызова методов общего объекта, в случае же связывания методов разница была: на 10,000 объектов в первом случае ~5 Mb, во втором ~4.3 Mb. Добавлено Цитата Serafim @ Ну вот, например, давеча набросал простенький DI контейнер, изучай: https://github.com/SerafimArts/dioma Достаточно будет? Добавлено Или какие тебе примеры нужны? Реального кода, а не всяких либ? да желательно реальный код без либ. либу смотрел, но ничего не понял, сорри я не разработчик DI, я прикладной программер ну вот примерчик из книжки перепиши на свой стиль классов и покажи чем он лучше Прикреплённый файлsprites.rar (106,96 Кбайт, скачиваний: 84) Добавлено Цитата AVA12 @ Вот ведь развратники! Восемь страниц мусолить вопрос, закрываемый чтением пары абзацев документации - это просто уму нерастяжимо! балабол сам то читал эти пару абзацев дока? |
Сообщ.
#113
,
|
|
|
Цитата Cfon @ ну вот примерчик из книжки перепиши на свой стиль классов и покажи чем он лучше Смотри насколько сократился JS! Прикреплённый файлsprites.zip (35,46 Кбайт, скачиваний: 85) Добавлено Цитата Cfon @ да желательно реальный код без либ. А, ну вот, по вечерам пилю сервис аутентификации: https://github.com/SerafimArts/Laravel-Id/t...er/resources/js Демку можешь посмотреть подняв докер (docker-compose up в корне). Ну или если я комп не выключу (он не уйдёт спать) тут https://home.serafimarts.ru - это мой домашний комп, так что за работоспособность не отвечаю. |
Сообщ.
#114
,
|
|
|
Цитата Serafim @ Смотри насколько сократился JS! ок спс чуть позже посмотрю, а то ща немного занят |
Сообщ.
#115
,
|
|
|
Цитата Serafim @ Смотри насколько сократился JS! А ты трололо |
Сообщ.
#116
,
|
|
|
Цитата Астарот @ А ты трололо Ты хочешь сказать, что он не сократился? Или что результат отличается от результата Cfon? Мне кажется что нет, и код действительно на несколько порядков уменьшился. Я даже отвязался от JQuery, а это великое достижение |
Сообщ.
#117
,
|
|
|
Цитата Serafim @ Ты хочешь сказать, что он не сократился? Но не настолько же! |
Сообщ.
#118
,
|
|
|
Цитата Cfon @ Да, я имел ввиду функцию-фабрику, внутри которой идёт присваивание фабричного метода, такого как напримерчто за фабричный метод присваивается? getName: function() { return name}, но мысль о копирования одного и того же в каждый вновь созданный экземпляр объекта здесь не меняется... Цитата Cfon @ ну это помоему не серьёзно... мы же тестируем копирование тела фабричного метода, то есть было бы разумней применять в тестах большое тело метода? чтоб явно уже было видно разницутесты проводил для 10,000 объектов, для 100,000 - ~20 Mb и 16Mb и это тока при такой малой реализации объекта. Прикреплённый файл: js_Cfon_test.rar Цитата Cfon @ чёта я не понял, а куда по твоему во втором случае делись 10'000 объектов которые ты создал и они лежат сейчас у тебя в массиве var person = []; ? да еще анализируя результаты в Хроме, заметил что в первом случае раздел system/Context занимает ~10,000 объектов при тесте 10,000 объектов, а вот во втором с привязкой всего 125 объектов, видимо в этом есть ответ на вопрос. |
Сообщ.
#119
,
|
|
|
Это называется не фабричный метод, а геттер. Сабж просто не знает про свойства в JS, по-этому умеет только так писать.
|
Сообщ.
#120
,
|
|
|
Цитата K313 @ ну это помоему не серьёзно... мы же тестируем копирование тела фабричного метода, то есть было бы разумней применять в тестах большое тело метода? чтоб явно уже было видно разницу Прикреплённый файл: js_Cfon_test.rar да там же у тебя копипаст или ты проверял его и оптимизатор пропускает как есть? если так то позже тестану его Цитата K313 @ Цитата Cfon @ чёта я не понял, а куда по твоему во втором случае делись 10'000 объектов которые ты создал и они лежат сейчас у тебя в массиве var person = []; ?да еще анализируя результаты в Хроме, заметил что в первом случае раздел system/Context занимает ~10,000 объектов при тесте 10,000 объектов, а вот во втором с привязкой всего 125 объектов, видимо в этом есть ответ на вопрос. они никуда не делись, там еще раздел есть Array, думаю это и есть массив persons, вот там тоже ~10,000 объектов, а в разделе system/Context они повторно я так понимаю дублируются для первого случая, а во втором их уже нет, отсюда экономия памяти. Ну а что на самом деле там происходит я хз мне на самом деле еще много не ясно с JS, я просто читаю книжки и верю что там написано, написано что метод дублируются хорошо ок и бог и ним, пока не важно почему, зачем засорять мозг? то что ты мне пытаешься донести про экономию памяти (один метод на все экземплятры объектов) я знаю, если не в курсе я на С++ тоже лабаю, в частности на MFC (всеми не любимом ). Добавлено Цитата Serafim @ Это называется не фабричный метод, а геттер. Сабж просто не знает про свойства в JS, по-этому умеет только так писать. знаю, но по мне так яснее через геттер/сеттер! понимаешь в чем дело, я стараюсь перенять только самое нужное мне в данный момент времени, стараюсь не засорять мозг мусором Добавлено Цитата Serafim @ Цитата Cfon @ ну вот примерчик из книжки перепиши на свой стиль классов и покажи чем он лучше Смотри насколько сократился JS! Прикреплённый файлsprites.zip (35,46 Кбайт, скачиваний: 85) там у тебя это css-sprite техника? тогда еще пример Прикреплённый файлsprites2.rar (107,37 Кбайт, скачиваний: 83) перепиши как будет с классами и поясни в чем профит |
Сообщ.
#121
,
|
|
|
Цитата Cfon @ перепиши как будет с классами и поясни в чем профит А тут JS почти и не нужен. class Vec2 { constructor(x = 0, y = 0) { [this.x, this.y] = [x, y]; } } class Gear { size = new Vec2(32, 32); position = new Vec2(); velocity = new Vec2(); angle = 0; } class Layer { size = new Vec2(480, 320); nodes = []; tick() { for (let i of this.nodes) { i.position.x += i.velocity.x; i.position.y += i.velocity.y; angle += .1; angle = angle % 360; if (i.position.x + i.size.x > this.size.x || i.position.x < 0) { i.velocity.x *= -1; } if (i.position.y + i.size.y > this.size.y || i.position.y < 0) { i.velocity.y *= -1; } } } } export function bootstrap() { let layer = new Layer(); for (let i = 0; i < 10; ++i) { layer.nodes.push(new Gear()); } requestAnimationFrame(() => layer.tick()) } Дальше сам давай. Мне влом. Добавлено А ещё даже вращать ничего не надо, это делается через @keyframe + transform: rotate(x). Ну и размеры не нужны тоже. Т.е. код можно сократить ещё на 1/5 |
Сообщ.
#122
,
|
|
|
Цитата Serafim @ А тут JS почти и не нужен. class Vec2 { constructor(x = 0, y = 0) { [this.x, this.y] = [x, y]; } } class Gear { size = new Vec2(32, 32); position = new Vec2(); velocity = new Vec2(); angle = 0; } class Layer { size = new Vec2(480, 320); nodes = []; tick() { for (let i of this.nodes) { i.position.x += i.velocity.x; i.position.y += i.velocity.y; angle += .1; angle = angle % 360; if (i.position.x + i.size.x > this.size.x || i.position.x < 0) { i.velocity.x *= -1; } if (i.position.y + i.size.y > this.size.y || i.position.y < 0) { i.velocity.y *= -1; } } } } export function bootstrap() { let layer = new Layer(); for (let i = 0; i < 10; ++i) { layer.nodes.push(new Gear()); } requestAnimationFrame(() => layer.tick()) } Дальше сам давай. Мне влом. Добавлено А ещё даже вращать ничего не надо, это делается через @keyframe + transform: rotate(x). Ну и размеры не нужны тоже. Т.е. код можно сократить ещё на 1/5 не ну меня и тот вариант устроил без классов ты же мне про классы поешь понятное дело что все щас пишут на классах так? просто я изучаю JS без классов, почему? потому что они меня бесят! и пока это не надо что тут не ясно? к тому же ты же не думаешь, что потом я не смогу перейти к программированию в классовом стиле? как бэ на плюсах программил до этого когда надо просмотрю синтаксис классов в JS и вперед с песней не? |
Сообщ.
#123
,
|
|
|
Цитата Cfon @ понятное дело что все щас пишут на классах так? Нет Добавлено Цитата Cfon @ просто я изучаю JS без классов, почему? потому что они меня бесят! и пока это не надо что тут не ясно? Дело не в классах, а в подходах начала 2000х Добавлено Цитата Cfon @ к тому же ты же не думаешь, что потом я не смогу перейти к программированию в классовом стиле? В классовый сможешь, в нормальный ООП - нет. Человек, который не знает таких основ, как DI (ты сам выше признался) - ещё очень много учиться. И не только про понимание плюшек всяких, но и про предметную область. |
Сообщ.
#124
,
|
|
|
Цитата Cfon @ просто я изучаю JS без классов, почему? потому что они меня бесят! Вон из профессии |
Сообщ.
#125
,
|
|
|
Цитата Cfon @ как бэ на плюсах программил до этого По моему опыту средним плюсовикам лучше не лезть в языки высокого уровня. Особенно с большим опытам. Они будут применять свой опыт и соревноваться в микросекундах, вместо написания поддерживаемого и качественного кода. Средний плюсовик так же далёк от красивых абстракций, как битриксоид от понимания смысла залоченных 64х килобайт областей оперативки под линуком. Добавлено Цитата Cfon @ когда надо просмотрю синтаксис классов в JS и вперед с песней не? Нет. Далеко нет. Понимание семантики и предметной области из которой вытекают штуки, вроде DDD - это отдельная история, на которую ты можешь потратить пару лет. К примеру, EAV и ECS тоже используют ОО-модель, но они противоположны ОО подходу, как раз из за нарушений семантики. |
Сообщ.
#126
,
|
|
|
Цитата Serafim @ Цитата Cfon @ просто я изучаю JS без классов, почему? потому что они меня бесят! и пока это не надо что тут не ясно? Дело не в классах, а в подходах начала 2000х ну понятно, у меня другой подход к изучению предмета, я начинаю с основ языка в даном случае JS, а его база это не классы, а объекты, прототипы, функции. Цитата Serafim @ Цитата Cfon @ к тому же ты же не думаешь, что потом я не смогу перейти к программированию в классовом стиле? В классовый сможешь, в нормальный ООП - нет. Человек, который не знает таких основ, как DI (ты сам выше признался) - ещё очень много учиться. И не только про понимание плюшек всяких, но и про предметную область. на самом деле я знаю что такое DI, сталкивался с ним когда программил на Java + Spring. да-да не удивляйтесь раньше до С++ я был жавистом Добавлено Цитата Астарот @ Вон из профессии да гнать паганой метлой меня оттуда, но кто ж поднимет руку на гуру? на самом деле я фрилансер Добавлено Цитата Serafim @ По моему опыту средним плюсовикам лучше не лезть в языки высокого уровня. Особенно с большим опытам. Они будут применять свой опыт и соревноваться в микросекундах, вместо написания поддерживаемого и качественного кода. Средний плюсовик так же далёк от красивых абстракций, как битриксоид от понимания смысла залоченных 64х килобайт областей оперативки под линуком. тут не согласен, я как средний плюсовик , как раз очень хорошо понял JS, и собираюсь дальше его изучать и писать на нем Цитата Serafim @ Цитата Cfon @ когда надо просмотрю синтаксис классов в JS и вперед с песней не? Нет. Далеко нет. Понимание семантики и предметной области из которой вытекают штуки, вроде DDD - это отдельная история, на которую ты можешь потратить пару лет. К примеру, EAV и ECS тоже используют ОО-модель, но они противоположны ОО подходу, как раз из за нарушений семантики. ну не все сразу как гриться |
Сообщ.
#127
,
|
|
|
Цитата Cfon @ тут не согласен, я как средний плюсовик , как раз очень хорошо понял JS, и собираюсь дальше его изучать и писать на нем Ну тогда один простой вопрос: Angular, React или Vue? |
Сообщ.
#128
,
|
|
|
Цитата Serafim @ Цитата Cfon @ тут не согласен, я как средний плюсовик , как раз очень хорошо понял JS, и собираюсь дальше его изучать и писать на нем Ну тогда один простой вопрос: Angular, React или Vue? Дай угадаю - ты по вью тащишься? |
Сообщ.
#129
,
|
|
|
Цитата Астарот @ Дай угадаю - ты по вью тащишься? По всему потихоньку =) То что у меня есть более-менее продакшн-реди проектик на вуэ ещё ничего не значит И вообще knockout рулез |
Сообщ.
#130
,
|
|
|
Но правда в том, что ты органически тащишься от всяких новомодных фенек, к коим ву и относится
|
Сообщ.
#131
,
|
|
|
я бы тогда по реакту упарывался не?
Добавлено да и называть knockout новомодной штукой... ну... |
Сообщ.
#132
,
|
|
|
Цитата Serafim @ Ну тогда один простой вопрос: Angular, React или Vue? хз я не думал, есть книжки по все фреймворкам, кроме Vue, ща немного читаю книжку по Backbone.js, также графика интересует читаю книжку Раффаэло Чекко. какое это имеет отношение к изучению JS? ты напоминаешь мне чувака, который пытается усидеть сразу на двух стульях (без обид ) я же изучаю все последовательно неторопясь использую то что мне требуется в данный момент да возможно что-то устарело, что-то возможно не используется, но понимешь в чем дело, если использовать твой подход, то можно построить карточный домик, который упадет при первом же касании поэтому чтобы все стояло и не падал надо начинать с базы, потом можно дальше переходить к фреймворкам, библам, не надо искать самое новое! это самое новое может не подойти к твоей задаче. Вот такой мой подход! Добавлено Цитата Астарот @ Цитата Serafim @ Ну тогда один простой вопрос: Angular, React или Vue? Дай угадаю - ты по вью тащишься? что тут гадать то?! это тебе что загадка! мдя используй то что требуется в данный момент, главное решить задачку или что ты там решаешь кроссворд? |
Сообщ.
#133
,
|
|
|
Цитата Serafim @ я бы тогда по реакту упарывался не? Реакт старше вуя |
Сообщ.
#134
,
|
|
|
Backbone.js рулит!
зачем мне ReactJS? Добавлено Цитата Cfon @ Цитата K313 @ ну это помоему не серьёзно... мы же тестируем копирование тела фабричного метода, то есть было бы разумней применять в тестах большое тело метода? чтоб явно уже было видно разницу Прикреплённый файл: js_Cfon_test.rar да там же у тебя копипаст или ты проверял его и оптимизатор пропускает как есть? если так то позже тестану его тупо скопипастил метод toString как у тебя, но размер расхода памяти не изменился в первом случае (case1.html) ~5 Mb, во втором (case2.html) с привязкой - 4,4 Mb. т.е. я так понимаю оптимизатор просто удалил то что я скопипастил. |
Сообщ.
#135
,
|
|
|
Цитата Астарот @ Реакт старше вуя но как же виртуальный дом и всякие другие хипстерские шняги? Во вью они нативные компоненты тоже нативные Добавлено Цитата Cfon @ зачем мне ReactJS? писать нативные приложеньки под телефоны Добавлено Цитата Cfon @ хз я не думал, есть книжки по все фреймворкам в указанном списке только один фрейм - это Angular, остальное либы. |
Сообщ.
#136
,
|
|
|
Цитата Serafim @ но как же виртуальный дом и всякие другие хипстерские шняги? Я вот для себя еще не решил хорош этот виртуальный дом, или нет. Куски разметки в js пока выглядят диковато, но, судя по популярности, не так страшен ч0рт, как его малюют. Надо будет как-нить попробовать что-нибудь наструячисть на реакте. Добавлено ЗЫ в ангуляре лично я разочаровался, по крайней мере в первом. Как там во втором не знаю. |
Сообщ.
#137
,
|
|
|
Цитата Астарот @ Я вот для себя еще не решил хорош этот виртуальный дом, или нет. Куски разметки в js пока выглядят диковато, но, судя по популярности, не так страшен ч0рт, как его малюют. Надо будет как-нить попробовать что-нибудь наструячисть на реакте. Назови 10 отличий между реактом и FXML Цитата Астарот @ ЗЫ в ангуляре лично я разочаровался, по крайней мере в первом. Как там во втором не знаю. Эт чойто? Вроде всё по феншую делали, и сервисы красивенькие, и di, и легковесные обвязки над нодами через ng-X атрибуты |
Сообщ.
#138
,
|
|
|
Цитата Serafim @ Назови 10 отличий между реактом и FXML Я не знаю что такое fxml Цитата Serafim @ Эт чойто? Вроде всё по феншую делали, и сервисы красивенькие, и di, и легковесные обвязки над нодами через ng-X атрибуты У него бойлерплейта много. Вот я знал ангуляр, потом пару лет его не использовал, посмотрел в готовый проект - темный лес Портянки кода, который нужен только самому ангуляру что б жить, пока до бизнеслогики ради которой все затевалось докопаешься - рехнешься... В остальном-то все довольно хорошо, и di, и деление на сервисы, но вот эта тяжеловесность убила. |
Сообщ.
#139
,
|
|
|
Цитата Астарот @ Я не знаю что такое fxml Ты же джавист, Карл! Почему я знаю шаблонизатор JavaFX, а ты нет? |
Сообщ.
#140
,
|
|
|
Цитата Serafim @ Ты же джавист, Карл! Почему я знаю шаблонизатор JavaFX, а ты нет? Потому что я джавист, который пишет сервера, а не клепает мордочки Морда у нас как раз на ангуляре, и именно в нее я заглянул, когда ей исполнилось полтора года отроду |
Сообщ.
#141
,
|
|
|
Я тоже сервер-сайд разраб, но на симфони. И как бы, я о чём...
Ах, да... Тебе не стыдно не знать вообще всё о жабе? У тебя байткод от зубов должен отскакивать! А ещё должен свободно владеть котлином и скалой, а мысли излагать на греилс. |
Сообщ.
#142
,
|
|
|
Как много всего я оказывается должен
|
Сообщ.
#143
,
|
|
|
продолжаю закручивать саморезы!
вот еще 4 теста, в которых выполняется проверка на объем памяти с разной реализацией гипотетического объекта Person Прикреплённый файлTestCases.zip (3,07 Кбайт, скачиваний: 99) результаты приобрели более контретный вид, а именно: 1 тест (возврат объекта литерала с методами): ~11 Mb; 2 тест (возврат объекта литерала, но с выносом реализации методов и последующим их вызовом (мой предложеный изначально вариант )): ~6 Mb; 3 тест (возврат объекта литерала, но с выносом реализации методов и последующей их привязкой): ~5.3 Mb; 4 тест (возврат объекта литерала, но с указанием ссылок на локальные функции): ~6 Mb. тесты проверял в Developer Tools Google Chrome 59.0 вопросы? |
Сообщ.
#144
,
|
|
|
Цитата Cfon @ ты лентяй а оптимизптор вряд ли. person.toString = function () { return 'todo todo todo todo todo todo todo todo todo todo todo todo '+ 'todo todo todo todo todo todo todo todo todo todo todo todo '+ 'todo todo todo todo todo todo todo todo todo todo todo todo '+ 'todo todo todo todo todo todo todo todo todo todo todo todo '+ 'todo todo todo todo todo todo todo todo todo todo todo todo '+ |
Сообщ.
#145
,
|
|
|
Cfon, кто тебя так код писать учил?
- Табы + пробелы - Форматирования никакого - Концы строк не обрезаны - Переводы строк в crlf - BOM? Srsly? У меня JSLint сходит с ума, а если это дело ещё в VCS засунуть, то там вообще начнётся дичь... Я к тому, что обычно за такое сразу на костёр и не важно на каком языке пишешь, и какой код в конце получается, никто даже смотреть не будет - отправят вычищать. |
Сообщ.
#146
,
|
|
|
Цитата Serafim @ Cfon, кто тебя так код писать учил? Не мешай ему - он изучает js позавчерашнего дня, и кодит так, как кодили наши предки Прикреплённый файлfirst_script_html.gif (10,38 Кбайт, скачиваний: 336) |
Сообщ.
#147
,
|
|
|
Цитата Астарот @ Цитата Serafim @ Cfon, кто тебя так код писать учил? Не мешай ему - он изучает js позавчерашнего дня, и кодит так, как кодили наши предки Прикреплённый файлfirst_script_html.gif (10,38 Кбайт, скачиваний: 336) Да пофигу на это всё. Может и правильно делает, что с основ начинает (которые в некоторых случаях уже задепрекейчены). Человек говорил, что сишки шарит, а значит хоть какое-то представление о конвенциях должно быть (все упомянутые мною выше относятся вообще любому языку программирования, ну разве только кроме эзотерических). А тут смотришь на код и офигиваешь |
Сообщ.
#148
,
|
|
|
Цитата K313 @ ты лентяй а оптимизптор вряд ли. смотри мы рассматриваем случай 1, который приводит к большему расходу памяти так? у меня как раз TestCase1.html показывает 11 Мб, остальные 3, включая и мой вариант ~6 Mb, что меньше на 5Мб, если оптимизатор опмизировал 3 последних случая, тогда почему 1 вариант расходует больше памяти? пс. возможно у тебя какие другие цифры? тогда приведи сюда. Добавлено Цитата Serafim @ Cfon, кто тебя так код писать учил? - Табы + пробелы - Форматирования никакого - Концы строк не обрезаны - Переводы строк в crlf - BOM? Srsly? У меня JSLint сходит с ума, а если это дело ещё в VCS засунуть, то там вообще начнётся дичь... Я к тому, что обычно за такое сразу на костёр и не важно на каком языке пишешь, и какой код в конце получается, никто даже смотреть не будет - отправят вычищать. ну ну ну спокойно уважаемый! меня учил так писать Керниган и Ричи, знаешь их? так вот при кодировании на JS я юзаю их стиль, щас не будем развивать тему оформления кода ок? а данный код я набирал в Notepad++ там у меня все отображает нормуль, я хз где ты смотрел и куда Прикреплённый файлpic.png (32,43 Кбайт, скачиваний: 295) по теме есть что сказать? нет? я так и думал Добавлено Цитата Астарот @ Не мешай ему - он изучает js позавчерашнего дня, и кодит так, как кодили наши предки именно изучаю! пока другие не будем указывать пальцем, только балтают языком чувачок ты наверное кроме халоворлд не знаешь как написать, а туда же учишь, сначала покажи, что умеешь потом учи ясно? |
Сообщ.
#149
,
|
|
|
Цитата Cfon @ а данный код я набирал в Notepad++ |
Сообщ.
#150
,
|
|
|
Цитата Cfon @ пс. возможно у тебя какие другие цифры? тогда приведи сюда. вообще, когда провожу какие нибудь тесты, то стараюсь их проводить в условиях обычного пользователя. Мне же главное знать, как будут выполняться мои скрипты на компьютере у клиента?! Пойдёт его машина топором на дно или будет летать как бабочка?! Поэтому у меня даже настройки во всех браузерах обычно по умолчанию стоят. Конечно у узеров разные комьютеры, но для сравнения нагрузки от одного кода с другим - это не главное... А вот в разных браузерах, один и тот же код, может вести себя по разному. В одном всё летает, а в другом создаётся заметная нагрузка (слежу в основном в обычном TaskManager) Для нашего же случая, чтоб конкретно по потреблению памяти судить, я отключал у компа виртуальную память и потом опять же в TaskManager смотрел, как память тратится. Конечно, думаю интерпретатору javascript ни кто не помешает, что-то временно скинуть на диск, если память уже впритык, НО во время тестов, я такого не заметил. То есть если память доходила до предела, то скрипт молча вешался Кроме того, в разных браузерах сборщики мусора работают по разному. Например у меня в Опере память быстро освобождалась, при каждой перегрузке страницы. И потребление показывало практически одинакого при всех повторах одного и того же теста. То есть видно, что память освобождается каждый раз и всё начинается с нуля. А вот в другом (или в FF или в IE, не помню уже), там при перегрузке страницы было только увеличение потребления памяти, и так можно было 3 - 4 раза перегрузить страницу, пока не увидишь, что было произведено освобождение памяти... У Оперы сам голый процесс занимает у меня где-то 60 Мб памяти, её я от каждого результата сразу вычитаю... Далее тестю var all_obj = []; var all_res = []; var obj = null; var mtime = Date.now(); for ( var j = 0; j < 1000000; j++ ) { // TEST x } alert('Created '+j+' objects!\n\nall_obj[ '+(--j)+' ] = "'+all_obj[ j ]+'"\n\nall_result[ '+j+' ] = "'+all_res[ j ]+'"\n\nmtime = '+(Date.now()-mtime) ); TEST 1 all_obj.push( 0 ); // массив размером в -> 10 Mln = 35 Mb., mtime = 900 msec TEST 2 all_obj.push( { } ); // пустые объекты -> 10 Mln = 310 Mb., mtime = 7.500 ... 9.000 msec TEST 3 all_obj.push( { name: 'ooo_'+j, age: j, friends: [] } ); // объекты со свойствами -> 4 Mln = 350 Mb., mtime = 7.000 msec all_res.push( 123 * Math.random( ) ); // с добавкой массива для результатов -> 4 Mln = 405 Mb., mtime = 9.000 ... 10.000 msec Потом значит, использовал прогу HxD, делал снимок памяти и находил там все созданные объекты от "ooo_0" до "ooo_3999999". Все были там, ни кто ни куда не пропал. TEST 4 all_obj.push( { name: 'ooo_'+j, age: j, friends: [], foo : function( param ){return param * Math.random();} } ); all_res.push( all_obj[ j ].foo( 123 ) ); // с встроенным методом и его выполнением -> 1 Mln = 260 Mb., mtime = 30.000 msec TEST 5 all_obj.push( { name: 'ooo_'+j, age: j, friends: [] } );// с пристроенным (не знаю, как называется) методом и его выполнением -> 1 Mln = 145 Mb., mtime = 5.000 msec all_obj[ j ].foo = function( param ){return param * Math.random();}; all_res.push( all_obj[ j ].foo( 123 ) ); То есть первое подозрение было, что при объявлении функции прямо в объекте, в памяти создаётся новый блок с телом функции для каждого нового объекта. Хотя по моему мнению, тело функции должно было быть одно на все объекты, а у каждого объекта в структуре foo : <STRUCTUR> должна была бы лежать ссылка на память, где это тело. В тесте 5 похоже так и есть, функция одна, а в foo : <STRUCTUR> каждого объекта лежит ссылка на неё... Потом повторил тест 4 но без выполнения метода foo, думал может выполнение столько тратит. Но результат не сильно изменился. // повторение 4-го теста БЕЗ выполнения встроенного метода foo -> 1 Mln = 235 Mb., mtime = 22.000 msec Сейчас сижу вот и думаю (тесты месяц назад же писал), может это <STRUCTUR type="function"> такая большая (160 байт, вернее 160 - 45 = 115 байт). Тогда при встроенном методе, у каждого foo : <STRUCTUR> лежит ссылка на свой <STRUCTUR type="function">, то есть эта структура <STRUCTUR type="function"> у каждого объекта своя. А вот у каждой этой структуры <STRUCTUR type="function"> уже лежит ссылка на память, где находится само тело функции, и эта память одна на все эти структуры, то есть тело функции уже в одном экземпляре. А когда функция прикручена, то структура <STRUCTUR type="function"> одна на всех, а у каждого объекта в foo : <STRUCTUR> лежит ссылка на эту единственную для всех <STRUCTUR type="function">. Таким образом и сохраняется правильное поведение javascript при проверке для встроенных методов all_obj[ x.foo ] == all_obj[ y.foo ] // false all_obj[ x.foo ] == all_obj[ y.foo ] // true Чтоб проверить это надо повторить тест 4, но уже с бооольшим телом функции. Только мне сейчас и влом и времени нету на это. |
Сообщ.
#151
,
|
|
|
я не пропал, работаю
подойдем делу с другой стороны: function createPerson(name, age){ var person = {}; person.getName = function(){ return name; }; // замыкание name person.setName = function(value){ name = value; } // тоже person.getAge = function(){ return age; }; // замыкание age person.setAge = function(value){ age = value; } // тоже return person; } var gregory = createPerson('Gregory', 42), miller = createPerson('Miller', 30); gregory.getName(); // Gregory miller.getName(); // Miller gregory.getAge(); // 42 miller.getAge(); // 30 как думаешь (2K313), если бы функция имела одно определение для всех экземпляров объектов в данном случае, то как бы можно реализовать такое поведение? ну вот возмем к примеру функцию getName, как она возвращает разные значения имени? пробую сымитировать одно определение на все объекты, выношу определение функции и присваюваю ссылку на нее, в результате пустая строка: function getName(){ return name; }; function createPerson(name, age){ var person = {}; person.getName = getName; // ссылка на внешнюю функци person.setName = function(value){ name = value; } person.getAge = function(){ return age; }; // замыкание age person.setAge = function(value){ age = value; } return person; } var gregory = createPerson('Gregory', 42), miller = createPerson('Miller', 30); gregory.getName(); // '' miller.getName(); // '' gregory.getAge(); // 42 miller.getAge(); // 30 если не понятно, то объясню вызов getName во втором случае возвращает значение name глобального объекта, в случае броузера это window, т.е. window.name, а в первом случае getName и другие создают замыкания на локальные переменные, и каждый возвращаемый объект создает свою копию функции getName, которая замкнута на свою name, значение которого и возращает. жду комментарий можно с картинками пс. я работаю в бюро ритуальных услуг, делаю гробы, ну там саморезы завернуть или гвоздь забить спросите зачем там программирование? ну как же и там тоже нужен учет |
Сообщ.
#152
,
|
|
|
Цитата Cfon @ да думал я об этом уже тоже. не хочу опять на пол страницы тут расписывать, поэтому буду краток. ты же в С# шаришь...как думаешь (2K313), если бы функция Когда функция-конструктор вызывается, у неё составляется свой [[scope]] (так вроде называется) и там хранятся все текушие переменные (включая и переданные функции параметры и может ещё чего). Так вот, после того как функция своё отработала, все эти значения больше никому не нужны и занимаемая ими память освобождается. Когда же на какую-то из этих переменных (главное что она не глобальная, всмысле не window.aaa) есть замыкание (скажем внутри функции getName ), то текущий [[scope]] не уничтожается, а закидывается в <STRUCTUR type="function"> которая была только что создана (когда выполнялась строка getName = function( )... ) Возможно что в этом [[scope]] будет всё лишнее удалено и остануться только те переменные, на которые есть замыкание. Таким образом, когда позже вызывается getName( ), у неё есть все замкнутые переменные, значения которых были заданы ещё во время создания этой функции. Но это лишь мои предположения, так что если что не так - я не виноват. Получается что тело функции getName должно быть полюбому расспарсено сразу ещё при выполнении функции-конструктора, чтоб знать какие в ней переменные используются и на какие из них есть замыкание. Я вот только пока щас ещё не знаю, если внутри функции getName тоже делать присвоение функции (напр. getSupName = function ... и тоже с замыканием на какой нибудь переданный аргумент функции-конструктору (только не name, чтоб было видно что замыкание работает и через голову родителя), то будет ли эта переменная в ней видна??? Добавлено А код тела функции один на всех, который работает с текущей стуктурой <STRUCTUR type="function"> ссылку на которую, перед передачей управления исполняемому коду, закидывается скажем например в регистр eax и таким образом код работает с данными по этому адресу. но код один на всех! |
Сообщ.
#153
,
|
|
|
Цитата K313 @ Я вот только пока щас ещё не знаю, если внутри функции getName тоже делать присвоение функции (напр. getSupName = function ... и тоже с замыканием на какой нибудь переданный аргумент функции-конструктору (только не name, чтоб было видно что замыкание работает и через голову родителя), то будет ли эта переменная в ней видна??? да будет видна, например: function createPerson(name, age){ var person = {}; person.getName = function(){ return name; }; person.setName = function(value){ name = value; } person.getAge = function(){ return age; }; person.setAge = function(value){ age = value; } person.toString = (function(){ var s = name + ' is a '; return function(){ return s + age + ' years old.'; }; }()); return person; } var gregory = createPerson('Gregory', 42), miller = createPerson('Miller', 30); gregory.toString(); // Gregory is a 42 years old. miller.toString(); // Miller is a 30 years old. Добавлено Цитата K313 @ А код тела функции один на всех, который работает с текущей стуктурой <STRUCTUR type="function"> ссылку на которую, перед передачей управления исполняемому коду, закидывается скажем например в регистр eax и таким образом код работает с данными по этому адресу. но код один на всех! остается понять почему gregory.getName === miller.getName; // false известно, что функции в JS тоже являются объектами и выражение person.getName = function(){ return name; }; является присваиванием ссылки на объект-функцию, которая хранится как и все объекты в куче. заметь что в данном случае функция не имеет имени, т.е. является анонимной, следовательно у интерпретатора нет возможности заранее выделить ее в отдельное место в куче и потом присваивать ссылки на нее, он это делает непосредственно при вызове createPerson |
Сообщ.
#154
,
|
|
|
Цитата Cfon @ ну яне много другое вроде бы имел ввиду. потом напишу, ща влом...да будет видна, например: Цитата Cfon @ посмотри от сэда, сообщение #150остается понять почему Цитата K313 @ Тогда при встроенном методе, у каждого foo : <STRUCTUR> лежит ссылка на свой <STRUCTUR type="function">, то есть эта структура <STRUCTUR type="function"> у каждого объекта своя. |
Сообщ.
#155
,
|
|
|
Цитата K313 @ Цитата Cfon @ посмотри от сэда, сообщение #150остается понять почему Цитата K313 @ Тогда при встроенном методе, у каждого foo : <STRUCTUR> лежит ссылка на свой <STRUCTUR type="function">, то есть эта структура <STRUCTUR type="function"> у каждого объекта своя. нет я думаю ты ошибаешься под структурой что ты имеешь ввиду в JS носит название контекст выполнения функции, в котором сохраняются все локальные переменные функции. |
Сообщ.
#156
,
|
|
|
хотя возможно, что ты прав
вот что я увидел в Chrome Developer Tools на примере кода из поста №153 видно что методы каждого объекта имееют скрытое свойство [[FunctionLocation]], которое указывает на общее расположение кода. я так понял в книжках имелось ввиду, что сами методы (объекты-функции) у каждого объекта разные, которые имеют набор свойств, в том числе и указатель на сам код. также они имеют скрытое свойство [[Scopes]], где определены два объекта: Global и Closure. |
Сообщ.
#157
,
|
|
|
foo : <STRUCTUR> - это описатель самой foo, что это за зверь такой, переменная, объект, функция, undefined или число и так далее. И в этой структуре так же должен лежать адрес на память, где находится <STRUCTUR type="function">, которая уже является описателем самой функции, там уже побольше разных данных нужно держать...
Цитата Cfon @ я не понял, чего ты там хотел сделать...да будет видна, например: я же хотел попробовать наколоть функцию createPerson, чтоб она решила, что никаких замыканий на её текущий [[scope]] и он был бы уничтожен после завершения функции function createPerson(name, age){ var person = {}; person.getName = function(){ return 1; }; person.setName = function(value){ return 2; } person.getAge = function(){ return 3; }; person.setAge = function(value){ return 4; } person.toString = function(){ var s = {}; s.foo = function(){ var u = {}; u.foo = function(){ return name; } return u; }; return s; }; return person; } createPerson(name, age).toString().foo().foo(); |
Сообщ.
#158
,
|
|
|
Цитата K313 @ я не знаю какое у javascript при этом поведение должно быть, вернётся потом при вызове createPerson(name, age).toString().foo().foo(); вернется namе, потому что для замыкания не имеет значения глубина вложения функции,все к чему выше (по коду) идет обращение образует замыкание. Прикреплённый файлpic1.png (49,13 Кбайт, скачиваний: 309) Цитата K313 @ я же хотел попробовать наколоть функцию createPerson, чтоб она решила, что никаких замыканий на её текущий [[scope]] и он был бы уничтожен после завершения функции Скрытый текст function createPerson(name, age){ var person = {}; person.getName = function(){ return 1; }; person.setName = function(value){ return 2; } person.getAge = function(){ return 3; }; person.setAge = function(value){ return 4; } person.toString = function(){ var s = {}; s.foo = function(){ var u = {}; u.foo = function(){ return name; } return u; }; return s; }; return person; } наколоть не получится |
Сообщ.
#159
,
|
|
|
Цитата Cfon @ а если тело внучки в eval упаковать? наколоть не получится |
Сообщ.
#160
,
|
|
|
Цитата K313 @ Цитата Cfon @ а если тело внучки в eval упаковать? наколоть не получится хз предпочитаю не юзать ее вообще, также как new Function('код') имхо исполнять код переданный через строку это моветон, поэтому даже не буду предполагать что там дак Добавлено меня вот заинтересовало другое function foo() { return function(){ // some code }; } var bar1 = foo(); var bar2 = foo(); ... var barN = foo(); будет ли в этом случае ссылки на функции bar1...barN указывать на одно тело или таки каждая имеет свое тело? если сравнивать ссылки, то они указывают на разные функции, как и в случае с указателями на разные объекты bar1 === bar2; // false если в консоли Chrome напечатать bar1, то выводит просто определение функции function(){ // some code }; |
Сообщ.
#161
,
|
|
|
Цитата Cfon @ ты же знаешь моё мнение тело одно, структуры <STRUCTUR type="function"> разные.указывать на одно тело или таки каждая имеет свое тело Структура <STRUCTUR type="function"> для foo создаётся ещё во время парсинга, а для return function() каждый раз новая при каждом вызове foo( ); |
Сообщ.
#162
,
|
|
|
Цитата K313 @ Цитата Cfon @ ты же знаешь моё мнение тело одно, структуры <STRUCTUR type="function"> разные.указывать на одно тело или таки каждая имеет свое тело Структура <STRUCTUR type="function"> для foo создаётся ещё во время парсинга, а для return function() каждый раз новая при каждом вызове foo( ); да пожалуй что так Добавлено рассмотрим на примере function compare(a, b){ if (a < b){ return -1; } else if (a > b){ return 1; } else { return 0; } } когда определяется функция, интерпретатор парсит ее проверяет на синтаксис и если все в порядке создает объект в который заносит свойства { arguments: null caller: null length: 2 name: "compare" prototype: Object __proto__: function () [[FunctionLocation]]: VM227:1 [[Scopes]]: Scopes[1] -> 0: Global } тело, код или порядок выполнения инструкций, лежит по ссылке [[FunctionLocation]] VM227:1 это некий адрес в памяти когда происходит вызов var result = compare(10, 5); создается контекст выполнения, в котором формируется цепочка областей видимости [[Scores]] этой функции. далее в [[Scores]] запишется указатель на глобальную область видимость Global, тот что уже создан при определении функции, а также будет создан так называемый объект активизиции, в который будут хранится значения аргументов a=10, b=5, а также arguments. данный объект активизации (точнее его адрес) будет также добавлен в [[Scores]]. ну и собственно далее испольнение кода, результат которого будет записан в result. вроде все верно пс. позже обрисую происходящее в случае замыкания. |
Сообщ.
#163
,
|
|
|
рассмотрим замыкание на примере упрощенной версии функции createPerson:
var createPerson = function(name){ return { getName: function(){return name;}, setName: function(value){name = value;} }; }; var greg = createPerson('Greg', 42); интерпретатор создает определение функции createPerson, затем идет вызов createPerson('Greg', 42), создается контекст выполнения вида { getName: function () arguments: null caller: null length: 0 name: "getName" prototype: Object __proto__: function () [[FunctionLocation]]: VM241:3 [[Scopes]]: Scopes[2] 0: Closure (createPerson) name: "Greg" 1: Global setName: function () arguments: null caller: null length: 0 name: "setName" prototype: Object __proto__: function () [[FunctionLocation]]: VM241:4 [[Scopes]]: Scopes[2] 0: Closure (createPerson) name: "Greg" 1: Global __proto__: Object } видно, что отличие от примера без замыкания, в наличие дополнительного объекта Closure в котором хранится наше замыкание. ВСЕ РАЗОБРАЛСЯ! да понял я тело всегда одно, спасибо курящая обезьяна! |
Сообщ.
#164
,
|
|
|
Цитата Cfon @ это ведь не от нас с тобой зависит, а от того C#-шника, который этот очередной интерпретатор для javascript писал. Захочет он чтоб было много тел, так и будет их много. да понял я тело всегда одно Цитата Cfon @ да на здоровье, гробовщик, забивающий шурупы в крышку гроба спасибо курящая обезьяна! |
Сообщ.
#165
,
|
|
|
Цитата K313 @ это ведь не от нас с тобой зависит, а от того C#-шника, который этот очередной интерпретатор для javascript писал. Google Chrome V8 на С++ написан |