![]() |
|
Модераторы: Sardar, Aliance |
![]()
|
|
| Zeroglif |
|
||||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 644 Регистрация: 22.9.2005 Репутация: 28 Всего: 66 |
Если не возражаете, продолжение разговора, начатого здесь - http://forum.vingrad.ru/index.php?showtopic=83216&st=15
Всё так, динамически, но справедливости ради autoboxing-а в оригинале в JavaScript нет, есть приведение типов/преобразование к типу/type conversion вне зависимости от того, примитив ли надо преобразовывать или нет.
Примитив (допустим, число) - не объект, пока он не станет объектом в результате преобразования к объектному типу никакой внутренней связи (ссылки) со своим прототипом у него не будет.
Мой вариант (второстепенные шаги пропущены): - вычисляем левую часть (3+4), результат 7, тип number; - приводим примитив 7 к объектному типу, функция-конструктор создаёт новый объект (new Number(7)), привязывает его внутреннюю ссылку [[Prototype]] к Number.prototype; - приводим правую часть (constructor) к строковому типу; - ищем свойство constructor у нового объекта (не находим, потому как его нет); - ищем свойство constructor у прототипа нового объекта (находим, это ссылка на функцию-конструктор); Дальше те же действия, но уже с toString(): - ищем свойство toString у функции-конструктора (не находим); - ищем свойство toString у прототипа функции-конструктора (находим); - вызываем - получаем конструктор в строковом типе в стиле FunctionDeclaration; |
||||||||
|
|||||||||
| Sardar |
|
||||||
![]() Бегун ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 78 Всего: 317 |
Не совсем, привести обьект String к обьекту HTMLDocumentElement или к любому другому не возможно. Мало того в JS нет операторов приведения к типу вообще, впрочем как и типов В скриптовом мире почти всегда используеться duck-typing, т.е. не важно что за обьект перед нами, важен его интерфейс. Можем написать свой String, прадва обломаемся на перегрузке операторов, её просто нет (ещё один - к JS). Примитивы оборачиваються в обьекты когда это необходимо (обращение с ними как с обьектами), называем autoboxing. Примитивы конвертируються другие примитивы (какие?), тут говорим о приведении к типу. Примитивы не изменяемые, любое приведение, например числа к строке порождает новый примитив, что естественно.
Не совсем, любой примитив имеет свой конструктор порождающий обьект, для чисел это Number, для строк это String, булевы Boolean. Когда требуеться работать с примитивом как с обьектом его "примитивный" тип сопостовляеться с конструктором, прототипом (интерфейсом) которого и пользуемся. Сам примитив не имеет локального хранилища для своих полей, потому создать их не можем, имеем только интерфейс из прототипа. Обьекты имеют не только локальное хранилище но и ссылку на конструктор и его прототип. Если конструкто заменяет свой прототип на полностью другой обьект (следовательно содержащий другой конструктор), то мы порождаем совершенно новый конструктор, все обьекты порождённые ранее от него будут продолжать указывать на старый конструктор. Мозгодробильно? Тогда пройдёмся по шагам и вдумчиво:
Отсюда понимаем различия между типами и интерфейсами Типы в JS не нужны, все обьекты выполнены по одному принципу, наличие своих полей и прототипы отделяют один обьект от другого. Добавлено @ 18:22 А зачем это нужно если .constructor выдаст функцию порождающую обьект? Т.к. все обьекты прототипами уходят в Object, то и у всех toString() существует, что выдаёт строковое значение обьекта (не приводит к строке!). Можешь написать своё поле toString, куда положи функцию возвращающую строку. Отсюда делаем точное различие между приведением к типу и простым вызовом API О прототипах и "оборачивании" обьяснил выше. -------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
||||||
|
|||||||
| Zeroglif |
|
||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 644 Регистрация: 22.9.2005 Репутация: 28 Всего: 66 |
Сложно что-то сказать, потому как просто не понимаю, какой смысл кроется в утверждении про отсутствующие типы. Честно, не понимаю. 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 |
|
||||||
![]() Бегун ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 78 Всего: 317 |
Вероятно формальное определение наличия типов варьируеться от языка к языку, я понимаю тип как это принято в Java, C++ и других языках с физическими различиями между типами обьектов (разные структуры). В скриптовом окружении, в частности JS (хотя зависит от реализации), разница между String, Object и MyType по сути в наполнении "локального интерфейса"* и из прототипов (вру, String всё таки нативный тип *термин возможно нигде не встречаеться, употребляю его для описания прямых (собственных) полей обьекта. В то же время типом можно назвать "нечто" отличающееся своим интерфейсом, хотя как тогда с отношениями "это есть"? В любом случае звиняюсь что навязываю своё представление о типах Autoboxing это как раз создание такого wrapper'а автоматически. Тут верно, храниться не явно только прототип, потому конструктор меняеться у обьекта если заменить прототип его конструктора другим обьектом.
Это внутреннее представление, большая разница между примитивами и полноценными обьектами. Разницы между обьектами фактически нет. О типах говорил выше, всё зависит от угла зрения, человек программирующий на Ruby вообще не поймёт какие типы в скриптовом языке
Не совсем, разбор полностью выполняеться до того как будет выполнен скрипт, транслируеться в примитивные команды (байт код). Оперделить тип на момент транляции не всегда возможно, потому и применяються "динамические типы". .constructor - заставляет интерпретатора искать поле в значении по левую сторону, если это не обьект, он приводиться к обьекту. Если поле не найдено, возвращаеться undefined - это и ещё null единственные значения не приводимые к обьекту, потому на них выскочит исключение если обратиться к ним как к обьекту. Как заключение: много говорим -------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
||||||
|
|||||||
| 12345c |
|
||||
![]() Круглый ![]() ![]() ![]() ![]() Профиль Группа: Vingrad developer Сообщений: 2018 Регистрация: 26.12.2005 Где: наша не пропадала ? Репутация: 57 Всего: 101 |
Разговор был начат в предыдущей теме с неисправимости модели языка 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) 'Объект'; ссылка на проототип или встроенный тип; ссылка (ссылка: ) объект (ссылка на прототип: ) прототип - примитив строки - описание функции. Это сообщение отредактировал(а) 12345c - 13.2.2006, 23:07 -------------------- Google Code Playground - онлайн-отладка своих примеров HTML+JS без регистрации, с сохранением по URL, без кириллицы. Go |
||||
|
|||||
| Zeroglif |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 644 Регистрация: 22.9.2005 Репутация: 28 Всего: 66 |
||||
|
||||
| 12345c |
|
|||
![]() Круглый ![]() ![]() ![]() ![]() Профиль Группа: Vingrad developer Сообщений: 2018 Регистрация: 26.12.2005 Где: наша не пропадала ? Репутация: 57 Всего: 101 |
Zeroglif, мы говорим о представлении об объекте. Предполагаем, что он хранится в виде 2 областей как минимум:
Когда пишем a=new Object(); , вызов a даёт
"ссылка" недоступна, но присваивая другой объект объекту а, мы её меняем. Это значит, что ссылается на другой тип объекта (на объект2). объект2 может быть функцией, числом. Не знаю, может ли быть другим объектом. -------------------- Google Code Playground - онлайн-отладка своих примеров HTML+JS без регистрации, с сохранением по URL, без кириллицы. Go |
|||
|
||||
| Sardar |
|
||||
![]() Бегун ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 78 Всего: 317 |
12345c, это уже про связывание значения с идентификатором, лучше не называть это ссылкой когда говорим о значениях что являються ссылочными, т.е. не содержат "на прямую" значение и передаються по ссылке
Примитивы не мутируемы, следовательно следующий код:
Создаст значение 90 и свяжет с a в текущем "пространстве имён", затем 100, при этом 90 "выбросит". Во первых это не так накладно как кажеться, во вторых ни что не мешает транслятору выполнить оптимизацию в таком случае", хотя это и не всегда "ошибко устойчиво"
Нет, всё транслируеться в байт-код (P-код), просто API браузерное тормознутое, т.к. DOM ноды, стили и прочее это не простые фишки -------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
||||
|
|||||
| 12345c |
|
|||
![]() Круглый ![]() ![]() ![]() ![]() Профиль Группа: Vingrad developer Сообщений: 2018 Регистрация: 26.12.2005 Где: наша не пропадала ? Репутация: 57 Всего: 101 |
Что есть мутируемость и как она проявляется, в каких языках?
-------------------- Google Code Playground - онлайн-отладка своих примеров HTML+JS без регистрации, с сохранением по URL, без кириллицы. Go |
|||
|
||||
| regis |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 232 Регистрация: 12.12.2005 Где: Москва, Россия Репутация: нет Всего: 7 |
Чувствуется, что дискуссия пошла слишком хардкорная для меня -- в такие тонкости объектной модели JS я вникнуть и не пытался.
;) К тому же, все это явно реализационно-зависимые вещи. Но, рассматривая пример Sardar'а:
видим, что если каждая такая операция требует выделения/освобождения памяти, то a -- это уже объект, или нечто подобное. Сошлюсь еще на мнение знатного куровода Дм. Котерова (http://www.dklab.ru/chicken/nablas/38.html): Возможно, вы слышали, что любая переменная в JavaScript — это на самом деле объект. Не важно, число это или строка. (и так далее, там есть примеры...) хотя, что именно он имеет в виду под "объектом", в контексте этой дискуссии опять-таки можно спорить... --------------------
В. В чем разница между hardware и software?О. В отличие от второго, по первому можно двинуть кулаком или пнуть ногой. |
|||
|
||||
| Zeroglif |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 644 Регистрация: 22.9.2005 Репутация: 28 Всего: 66 |
Дм. Котеров очень познавательно и популярно пишет свои наблы, но это не значит, что в них нет ошибок, они есть. Но дело не в этом, а в том, что мы действительно спорим о терминах, каждый имеет в виду что-то своё. В таком контексте можно говорить вообще что угодно, например, что всё в JavaScript-e - это грибы, и попробуй разберись потом, что под этим скрывается... Один скажет, что число 7 - это объект, т.к. ему можно подсунуть метод и он его скушает, другой (типа меня) ответит, что скушает-то он скушает, но исключительно по причине транспарентной временной конвертации в объектный тип, и вообще о какой объектной уникальности можно говорить, если (7 == 7) даст true, тогда как (new Number(7) == new Number(7)) справедливо даст false, третий скажет про read-only объект... и так далее... Имхо самый правильный путь - это стараться удерживать себя в рамках терминологии стандарта, потому как сейчас сплошь и рядом применяются различные кальки на Javascript из других языков, которые может и помогают ассоциативно мыслить, но человеку неискушённому могут также и навредить. А стандарте, как известно, живут не только одни лишь объекты... |
|||
|
||||
| Sardar |
|
||||||
![]() Бегун ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 78 Всего: 317 |
<Значение> - говорим не о переменной и связях с идентификаторами, а о значении - результат любого выражения Значение может изменяться, например массив; может не изменяться, т.е. физически не изменяться, любая операция приводит к копии. Например а++ , по идее, для числа должно породить новое значение, затем записать его в а. На практике такие ситуации легко отслеживаються и можно эффективно "просто изменить значение" уже существующего <значения> (обьект в памяти) Другой пример:
При этом обычно интерпретатор не делает разницы между значениями что передаються "по значению" и с теми что "по ссылке", просто они физически так устроены, все кто передаються по ссылке на самом деле ссылочные обьекты и при копировании <значение> содержащее ссылку копируеться, получаеться две ссылки на один и тот же обьект. Все кто передаються "по значению" на прямую храняться в <значении>, потому при их копировании происходит реальное копирование значение, отсюда и получаем "по значению". Строка ссылочное значение, но не мутируемая (не изменяемая за всю короткую жизнь), это в целях быстроты выполнения и экономии на памяти:
В более продвинутых реализациях символы строк могут храниться в блоках, на подстроки из блоков указывают "звенья" собранные в одну цепочку. Таким образом можно построить массу строк, при этом затратив память только на звенья, не на символы и без каких либо копирований целых массивов. JS скорее всего сие не поддерживает, на питоне пример:
на самом деле не должно быть кпопирований символов, всего 2 константы "test" и " some text" в памяти, строки же построены из цепочек звеньев указывающих на части констант. Не знаю так ли в питоне, до исходников ещё не дошёл, но в моём Trilobite Scripting Language (разработал специально для проекта) строки реализованны именно так (про остальное умолчу, лажа Xорошее замечание. P.S. стал замечать за собой, много пишу... народ не провоцируйте млин -------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
||||||
|
|||||||
| 12345c |
|
|||
![]() Круглый ![]() ![]() ![]() ![]() Профиль Группа: Vingrad developer Сообщений: 2018 Регистрация: 26.12.2005 Где: наша не пропадала ? Репутация: 57 Всего: 101 |
Ну да, можно сказать кратко - мутируемость - свойство семантики выражений, когда вычисление происходит с копией, что полезно для чистоты языка при использовании операций, изменяющих значение аргументов.
Но мы отвлеклись на частности. Значит, о чём мы тут начинали? Всё ли считать объектом? А если не всё, то во что это выливается. Имеем понятие о том, что есть примитивы - значения выражений, в частности, и объекты, порождаемые оп. new , присваиваниями и обработкой документа. И их механика присваиваний идёт по странноватым законам, целиком понимаемыми при понимании их ссылочной природы. Далее, Sardar, ты говоришь, что присутствие ссылок не всегда объект, в частности, строки, они ведут себя как примитивы. Похоже, в этом суть разговора, и пока я не вижу ни разногласий, ( и ни цели : ) ). -------------------- Google Code Playground - онлайн-отладка своих примеров HTML+JS без регистрации, с сохранением по URL, без кириллицы. Go |
|||
|
||||
| Sardar |
|
|||
![]() Бегун ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 78 Всего: 317 |
Да, мы вообще наофтопили серьёзно
ИМXО лучше пользоваться определениями от ECMA, разногласий и недопониманий не будет. Другое дело что когда от концепций языка начинаешь переходить на детали реализации, тогда и грешишь явным делением (не)мутируемых, (не)ссылочных и прочие вещи. В любом случае на использование это особо не влияет, если только себя самому не ограничивать. Вопрос зарождался от идеи не будет ли сильно тормозить выполнение если всё станет обьектами, как ответ - нет тормозить не будет, времяёмкие операции это всё вызовы API браузера. Остальное детали, не важно, лишь бы к целому не так приводили:
-------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
|||
|
||||
| 12345c |
|
|||
![]() Круглый ![]() ![]() ![]() ![]() Профиль Группа: Vingrad developer Сообщений: 2018 Регистрация: 26.12.2005 Где: наша не пропадала ? Репутация: 57 Всего: 101 |
В любом случае, самую причудливую организацию языка можно оптимизировать в фазе трансляции. Считаем всё объектами (Ruby, что ли) - но простые переменные, пока они не превратились в функции, прекрасно алгоритмизируются на уровне работы с короткими примитивами. Для этого должен иметься хороший транслятор, что трудно требовать от компактного кода, встроенного в браузер, поэтому сама конструкция и идеология языка - компромисс.
-------------------- Google Code Playground - онлайн-отладка своих примеров HTML+JS без регистрации, с сохранением по URL, без кириллицы. Go |
|||
|
||||
![]()
|
| Форум для вопросов, которые имеются в справочниках, но их поиск вызвал затруднения, или для разработчика требуется совет или просьба отыскать ошибку. Напоминаем: 1) чётко формулируйте вопрос, 2) приведите пример того, что уже сделано, 3) укажите явно, нужен работающий пример или подсказка о том, где найти информацию. |
| 1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | JavaScript: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |