| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > JavaScript: Общие вопросы > Объекты, примитивы... |
| Автор: Sardar 13.2.2006, 18:18 | ||||||
Не совсем, привести обьект String к обьекту HTMLDocumentElement или к любому другому не возможно. Мало того в JS нет операторов приведения к типу вообще, впрочем как и типов В скриптовом мире почти всегда используеться http://en.wikipedia.org/wiki/Duck_typing, т.е. не важно что за обьект перед нами, важен его интерфейс. Можем написать свой String, прадва обломаемся на перегрузке операторов, её просто нет (ещё один - к JS). Примитивы оборачиваються в обьекты когда это необходимо (обращение с ними как с обьектами), называем autoboxing. Примитивы конвертируються другие примитивы (какие?), тут говорим о приведении к типу. Примитивы не изменяемые, любое приведение, например числа к строке порождает новый примитив, что естественно.
Не совсем, любой примитив имеет свой конструктор порождающий обьект, для чисел это Number, для строк это String, булевы Boolean. Когда требуеться работать с примитивом как с обьектом его "примитивный" тип сопостовляеться с конструктором, прототипом (интерфейсом) которого и пользуемся. Сам примитив не имеет локального хранилища для своих полей, потому создать их не можем, имеем только интерфейс из прототипа. Обьекты имеют не только локальное хранилище но и ссылку на конструктор и его прототип. Если конструкто заменяет свой прототип на полностью другой обьект (следовательно содержащий другой конструктор), то мы порождаем совершенно новый конструктор, все обьекты порождённые ранее от него будут продолжать указывать на старый конструктор. Мозгодробильно? Тогда пройдёмся по шагам и вдумчиво:
Отсюда понимаем различия между типами и интерфейсами Типы в JS не нужны, все обьекты выполнены по одному принципу, наличие своих полей и прототипы отделяют один обьект от другого. Добавлено @ 18:22 А зачем это нужно если .constructor выдаст функцию порождающую обьект? Т.к. все обьекты прототипами уходят в Object, то и у всех toString() существует, что выдаёт строковое значение обьекта (не приводит к строке!). Можешь написать своё поле toString, куда положи функцию возвращающую строку. Отсюда делаем точное различие между приведением к типу и простым вызовом API О прототипах и "оборачивании" обьяснил выше. |
| Автор: Zeroglif 13.2.2006, 20:23 | ||||||||||||
Сложно что-то сказать, потому как просто не понимаю, какой смысл кроется в утверждении про отсутствующие типы. Честно, не понимаю. Ecma - There are nine types (Undefined, Null, Boolean, String, Number, Object, Reference, List, and Completion). Values of type Reference, List, and Completion are used only as intermediate results of expression evaluation and cannot be stored as properties of objects.. Преобразования типов в определённых случаях сплошь и рядом, от конкатенации, точечной нотации, функциями Number(), String()...
В Javascript нет autoboxing как такового, не используется этот термин даже и в качестве жаргона, это я специально подчёркиваю ещё раз для тех любознательных, кто вдруг решит погуглить на сей предмет и ничего не найдёт, в крайнем случае можно говорить о "wrapper"-е для примитива, как о временно создаваемом объекте, в который он временно "упаковывается".
Я бы сказал так. Число само по себе изначально не связано с конструктором, интерпретатор знает сам в какие моменты и с каким именно конструктором его связать, отталкиваясь только от его типа. Соотвественно сначала происходит выбор конструктора интерпретатором, а потом обыкновенная процедура создания нового объекта со всеми из этого вытекающими связями (new Number()).
Почему мозгодробильно? Всё понятно, только не совсем правильно. Объект сам по себе не имеет ссылку на свой конструктор (ни явную, ни неявную), он имеет только неявную ссылку на свой прототип. Смысл вашего примера заключается в том, что если мы перепределяем объект-прототип, то все вновь порождённые от функции-конструктора объекты будут неявно ссылаться именно на этот новый объект. Ранее созданные этой же функцией объекты по-прежнему будут ссылаться на переданный им при рождении объект-прототип, т.к. эту связь уже не разорвать, она не явная. Иначе говоря, конструктор остаётся тот же самый, но свойство constructor указывает на другой объект, т.к это свойство летает вместе с прототипом, куда он, туда и свойство.
Типы нужны, т.к. откуда же взяться конструктору и прототипу, как не от анализа типа и его конвертации в объект.
Речь не об этом. Интерпретатор приводит число 7 к объекту по причине обнаруженной нотации (точку обнаружил), соответственно он проводит ряд действий, прежде чем решит, что именно искать, левую часть приведёт к объекту, правую часть к строке, только потом ищет свойство объекта: new Number(7).constructor |
| Автор: Sardar 13.2.2006, 22:27 | ||||||
Вероятно формальное определение наличия типов варьируеться от языка к языку, я понимаю тип как это принято в Java, C++ и других языках с физическими различиями между типами обьектов (разные структуры). В скриптовом окружении, в частности JS (хотя зависит от реализации), разница между String, Object и MyType по сути в наполнении "локального интерфейса"* и из прототипов (вру, String всё таки нативный тип *термин возможно нигде не встречаеться, употребляю его для описания прямых (собственных) полей обьекта. В то же время типом можно назвать "нечто" отличающееся своим интерфейсом, хотя как тогда с отношениями "это есть"? В любом случае звиняюсь что навязываю своё представление о типах Autoboxing это как раз создание такого wrapper'а автоматически. Тут верно, храниться не явно только прототип, потому конструктор меняеться у обьекта если заменить прототип его конструктора другим обьектом.
Это внутреннее представление, большая разница между примитивами и полноценными обьектами. Разницы между обьектами фактически нет. О типах говорил выше, всё зависит от угла зрения, человек программирующий на Ruby вообще не поймёт какие типы в скриптовом языке
Не совсем, разбор полностью выполняеться до того как будет выполнен скрипт, транслируеться в примитивные команды (байт код). Оперделить тип на момент транляции не всегда возможно, потому и применяються "динамические типы". .constructor - заставляет интерпретатора искать поле в значении по левую сторону, если это не обьект, он приводиться к обьекту. Если поле не найдено, возвращаеться undefined - это и ещё null единственные значения не приводимые к обьекту, потому на них выскочит исключение если обратиться к ним как к обьекту. Как заключение: много говорим |
| Автор: 12345c 13.2.2006, 22:48 | ||||
Разговор был начат в предыдущей теме с неисправимости модели языка JS - так это присуще всем интерпретаторам. Самое большее, что можно сделать - такая система неявных типов, как описал Zeroglif, и ещё важен Р-сод, и следующий шаг высшего пилотажа - динамическая компиляция (мы тут совсем не про JS). Самая затратная часть, как показывает эксперимент - обращение к объектам документа, особенно, когда перерисовывается графика. Тут скорость катастрофически падает, поэтому типичный способ оптимизации - брать не obj.style.left, а obj.left=obj.style.left; . Это замечание по истокам темы, чтобы знать, откуда ноги растут. (Однако, и медленность операций с примитивами, думаю, - следствие общей неозабоченности быстродействием, с которым сразу смирились, что мало. В частности, интерпретатор, видимо, ходит сразу по тексту функций, и в этом следует искать истоки его медленнодействия.) Далее, Sardar, зачем так сложно о том, что можно описать простой схемой? И на экспериментах выясняем, как на самом деле реализовано (так проще ,чем читать документацию примерно в таких же выражениях Конечно, анализ показывает, что объекты-имена хранятся в виде Тип_объекта; значение (Объект-имя - это, то, что Sardar назвал "объектом, выполненным по одному принципу", то, на что ссылается таблица имён операционной среды - окна браузера.) Значение, скорее всего, это 8 байт на примитив числа или ссылку. Имеем фромат объекта-имени: 1) Число; значение (примитив числа) 2) Строка; ссылка (ссылка: ) примитив строки. 3) Массив; ссылка (...) 4) Функция; ссылка (ссылка: ) примитив строки. 5) Объект; ссылка (ссылка: ) объект (вот это ключевой момент, объясняющий фокусы с a=new Number(0); - единственный тип, который ссылается на другие типы, создавая цепочку ссылок) ... Далее, исследуем работу схемы - что происходит, если определим объект так или иначе. Разбор в этом ключе будет нагляден и не требует переопределений понятия типа, например. (Ладно, математики запутывают модель, тщась достичь новизны, или юристы, чтобы оставить лазейки формулировок К примеру, этот случай с объектом-числом:
Видим, что создана схема 5) Объект; ссылка (ссылка: ) примитив числа , и результат - "объект существует". Теперь раскомментируем 2-ю стр., и видим, что любое действие с оператором приводит наш объект к примитиву числа: 1) Число; значение (примитив числа) , результат - "число =0". Добавлено @ 23:02 массив тогда тоже нативный тип вот это есть в моей схеме поле типа, Тип_объекта. Хранится только признак. Если признак==Объект, то в нём есть ссылка на функцию-прототип. Да, не нарисовал в прежнем посте: 5) 'Объект'; ссылка на проототип или встроенный тип; ссылка (ссылка: ) объект (ссылка на прототип: ) прототип - примитив строки - описание функции. |
| Автор: Zeroglif 14.2.2006, 00:44 | ||
Что бы это значило, что значит ссылается на другие типы? |
| Автор: 12345c 14.2.2006, 01:44 | ||
| Zeroglif, мы говорим о представлении об объекте. Предполагаем, что он хранится в виде 2 областей как минимум: Когда пишем a=new Object(); , вызов a даёт
"ссылка" недоступна, но присваивая другой объект объекту а, мы её меняем. Это значит, что ссылается на другой тип объекта (на объект2). объект2 может быть функцией, числом. Не знаю, может ли быть другим объектом. |
| Автор: Sardar 14.2.2006, 02:03 | ||||
| 12345c, это уже про связывание значения с идентификатором, лучше не называть это ссылкой когда говорим о значениях что являються ссылочными, т.е. не содержат "на прямую" значение и передаються по ссылке Примитивы не мутируемы, следовательно следующий код:
Создаст значение 90 и свяжет с a в текущем "пространстве имён", затем 100, при этом 90 "выбросит". Во первых это не так накладно как кажеться, во вторых ни что не мешает транслятору выполнить оптимизацию в таком случае", хотя это и не всегда "ошибко устойчиво"
Нет, всё транслируеться в байт-код (P-код), просто API браузерное тормознутое, т.к. DOM ноды, стили и прочее это не простые фишки |
| Автор: 12345c 14.2.2006, 02:49 |
| Что есть мутируемость и как она проявляется, в каких языках? |
| Автор: regis 14.2.2006, 13:15 | ||
| Чувствуется, что дискуссия пошла слишком хардкорная для меня -- в такие тонкости объектной модели JS я вникнуть и не пытался. ;) К тому же, все это явно реализационно-зависимые вещи. Но, рассматривая пример Sardar'а:
видим, что если каждая такая операция требует выделения/освобождения памяти, то a -- это уже объект, или нечто подобное. Сошлюсь еще на мнение знатного куровода Дм. Котерова (http://www.dklab.ru/chicken/nablas/38.html): Возможно, вы слышали, что любая переменная в JavaScript — это на самом деле объект. Не важно, число это или строка. (и так далее, там есть примеры...) хотя, что именно он имеет в виду под "объектом", в контексте этой дискуссии опять-таки можно спорить... |
| Автор: Zeroglif 14.2.2006, 16:33 | ||
Дм. Котеров очень познавательно и популярно пишет свои наблы, но это не значит, что в них нет ошибок, они есть. Но дело не в этом, а в том, что мы действительно спорим о терминах, каждый имеет в виду что-то своё. В таком контексте можно говорить вообще что угодно, например, что всё в JavaScript-e - это грибы, и попробуй разберись потом, что под этим скрывается... Один скажет, что число 7 - это объект, т.к. ему можно подсунуть метод и он его скушает, другой (типа меня) ответит, что скушает-то он скушает, но исключительно по причине транспарентной временной конвертации в объектный тип, и вообще о какой объектной уникальности можно говорить, если (7 == 7) даст true, тогда как (new Number(7) == new Number(7)) справедливо даст false, третий скажет про read-only объект... и так далее... Имхо самый правильный путь - это стараться удерживать себя в рамках терминологии стандарта, потому как сейчас сплошь и рядом применяются различные кальки на Javascript из других языков, которые может и помогают ассоциативно мыслить, но человеку неискушённому могут также и навредить. А стандарте, как известно, живут не только одни лишь объекты... |
| Автор: Sardar 15.2.2006, 01:14 | ||||||
| <Значение> - говорим не о переменной и связях с идентификаторами, а о значении - результат любого выражения Значение может изменяться, например массив; может не изменяться, т.е. физически не изменяться, любая операция приводит к копии. Например а++ , по идее, для числа должно породить новое значение, затем записать его в а. На практике такие ситуации легко отслеживаються и можно эффективно "просто изменить значение" уже существующего <значения> (обьект в памяти) Другой пример:
При этом обычно интерпретатор не делает разницы между значениями что передаються "по значению" и с теми что "по ссылке", просто они физически так устроены, все кто передаються по ссылке на самом деле ссылочные обьекты и при копировании <значение> содержащее ссылку копируеться, получаеться две ссылки на один и тот же обьект. Все кто передаються "по значению" на прямую храняться в <значении>, потому при их копировании происходит реальное копирование значение, отсюда и получаем "по значению". Строка ссылочное значение, но не мутируемая (не изменяемая за всю короткую жизнь), это в целях быстроты выполнения и экономии на памяти:
В более продвинутых реализациях символы строк могут храниться в блоках, на подстроки из блоков указывают "звенья" собранные в одну цепочку. Таким образом можно построить массу строк, при этом затратив память только на звенья, не на символы и без каких либо копирований целых массивов. JS скорее всего сие не поддерживает, на питоне пример:
на самом деле не должно быть кпопирований символов, всего 2 константы "test" и " some text" в памяти, строки же построены из цепочек звеньев указывающих на части констант. Не знаю так ли в питоне, до исходников ещё не дошёл, но в моём Trilobite Scripting Language (разработал специально для проекта) строки реализованны именно так (про остальное умолчу, лажа Xорошее замечание. P.S. стал замечать за собой, много пишу... народ не провоцируйте млин |
| Автор: 12345c 15.2.2006, 23:03 | ||
Ну да, можно сказать кратко - мутируемость - свойство семантики выражений, когда вычисление происходит с копией, что полезно для чистоты языка при использовании операций, изменяющих значение аргументов.
Но мы отвлеклись на частности. Значит, о чём мы тут начинали? Всё ли считать объектом? А если не всё, то во что это выливается. Имеем понятие о том, что есть примитивы - значения выражений, в частности, и объекты, порождаемые оп. new , присваиваниями и обработкой документа. И их механика присваиваний идёт по странноватым законам, целиком понимаемыми при понимании их ссылочной природы. Далее, Sardar, ты говоришь, что присутствие ссылок не всегда объект, в частности, строки, они ведут себя как примитивы. Похоже, в этом суть разговора, и пока я не вижу ни разногласий, ( и ни цели : ) ). |
| Автор: Sardar 15.2.2006, 23:38 | ||
| Да, мы вообще наофтопили серьёзно ИМXО лучше пользоваться определениями от ECMA, разногласий и недопониманий не будет. Другое дело что когда от концепций языка начинаешь переходить на детали реализации, тогда и грешишь явным делением (не)мутируемых, (не)ссылочных и прочие вещи. В любом случае на использование это особо не влияет, если только себя самому не ограничивать. Вопрос зарождался от идеи не будет ли сильно тормозить выполнение если всё станет обьектами, как ответ - нет тормозить не будет, времяёмкие операции это всё вызовы API браузера. Остальное детали, не важно, лишь бы к целому не так приводили:
|
| Автор: 12345c 16.2.2006, 04:42 |
| В любом случае, самую причудливую организацию языка можно оптимизировать в фазе трансляции. Считаем всё объектами (Ruby, что ли) - но простые переменные, пока они не превратились в функции, прекрасно алгоритмизируются на уровне работы с короткими примитивами. Для этого должен иметься хороший транслятор, что трудно требовать от компактного кода, встроенного в браузер, поэтому сама конструкция и идеология языка - компромисс. |
| Автор: regis 17.2.2006, 16:34 |
| @12345c: в общем, верно. Но тут как раз и проявляется один из главных недостатков JS: отсутствие языковой типизации. Невозможно сильно оптимизировать при трансляции даже выражение A+B, если при выполнении операция + может оказаться и сложением, и конкатенацией, в зависимости от типов операндов. |
| Автор: Sardar 17.2.2006, 17:11 |
| Это как раз одно из достоинств скриптов в целом. Отсутствие типов позволяет работать с любым выражением как угодно, лишь бы не выходило за рамки логики С жёсткими типами код получался бы громоздким, не красивым и "весьма ограниченным", любители могут попробовать VBS. |
| Автор: Zeroglif 17.2.2006, 17:19 | ||
Вот именно, поэтому и удручает то, куда сейчас движется язык - в сторону бегемотизации. |
| Автор: Sardar 17.2.2006, 17:38 | ||
По моему сам язык никуда не движеться, пока, развиваеться API хоста где JS используеться. Примеры? В "недостатки" отошлю сейчас ещё одну проблему с тредами, столкнулся буквально вчера. |