Как сделать критическую массу в прототип

Добавил пользователь Евгений Кузнецов
Обновлено: 04.10.2024

У меня свой кружок "Ответственное потребление". Учу подростков наносить меньший урон окружающей среде. Фото: личный архив

У меня свой кружок "Ответственное потребление". Учу подростков наносить меньший урон окружающей среде. Фото: личный архив

Если применить на нашу жизнь, то для запуска необратимого процесса в обществе достаточно 3,5-5% критической массы людей. Это я у политологов прочитала.

Например, чтобы прекратить быть самой глупой нацией в мире, надо чтобы 3,5-5% населения было продвинутым и пропагандировало ценность образования.

Короче, приятно быть членом критической массы)) Так я на вас влияю, а вы и не подозреваете.

Нашла интересный пример по поводу критической массы на примере физики. Возьмем в каждую руку по килограмму Урана. Если свести руки вместе-произойдет ядерный взрыв. Уран обладает критической массой в два килограмма, при которой ядра сами начинают лавинообразно делиться. Он взрывается. Если будет 1 кг 900 граммов, то ничего не произойдёт, чтобы вы не делали.

Может быть вы и есть тот человек с многоразовой сумкой, который "добьет" критическую массу до нужного количества?


Я так писал. Да так и надо. Должно быть чёткое понятие о том, во что ты будешь играть или даже покупать. Если что-то читателю не нужно, то он сам выберет то, что надо, а "писатель" должен рассказать обо всём (кроме сюжета)


Вот вот, согласен. Нужно подробнее описывать, чтобы человек понял, стоит ли играть в эту игру или нет

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

Оказалось, что есть много неочевидных вещей из старых времён ES5 и даже ES6, о которых я не слышал. А еще оказалось, что вывод консоли браузера может не соответствовать действительности.

Что такое прототип

Объект в JS имеет собственные и унаследованные свойства, например, в этом коде:

у объекта foo имеется собственное свойство bar со значением 1 , но также имеются и другие свойства, такие как toString . Чтобы понять, как объект foo получает новое свойство toString , посмотрим на то, из чего состоит объект:




Дело в том, что у объекта есть ссылка на другой объект-прототип. При доступе к полю foo.toString сначала выполняется поиск такого свойства у самого объекта, а потом у его прототипа, прототипа его прототипа, и так пока цепочка прототипов не закончится. Это похоже на односвязный список объектов, где поочередно проверяется объект и его объекты-прототипы. Так реализовано наследование свойств, например, у (почти, но об этом позже) любого объекта есть методы valueOf и toString .

Как выглядит прототип

У всех прототипов имеются два общих свойства, constructor и __proto__ . Свойство constructor указывает на функцию-конструктор, с помощью которой создавался объект, а свойство __proto__ указывает на следующий прототип в цепочке (либо null, если это последний прототип). Остальные свойства доступны через . , как в примере выше.

Да кто такой этот ваш constructor

constructor – это ссылка на функцию, с помощью которой был создан объект:

Не совсем понятна идея зачем он был нужен, возможно, как способ клонирования объекта:

Но я не нашел подходящий пример его использования, если у Вас есть примеры проектов, где это использовалось, то напишите об этом. В остальном же использовать constructor лучше не стоит, так как это writable свойство, которое можно случайно перезаписать, работая с прототипом, и сломать часть логики.

Где живёт прототип

На самом деле, объекты представляют собой не только поля, доступные для JS кода. Интерпретатор также сохраняет некоторые приватные данные объекта для работы с ним, для этого в стандарте определено понятие внутренних слотов, которые обозначены как имя в квадратных скобках [[SlotName]] . Для прототипов отведен приватный слот [[Prototype]] содержащий ссылку на объект-прототип (либо null , если прототипа нет).

Из-за того, что [[Prototype]] предназначался исключительно для самого JS движка, получить доступ к прототипу объекта было невозможно. Для случаев когда это было нужно, ввели нестандартное свойство __proto__ , которое поддержали многие браузеры и которое по итогу попало в сам стандарт, но как опциональное и стандартизированное только для обратной совместимости с существующим JS кодом.

О чем вам недоговаривает дебаггер, или он вам не прототип

Свойство __proto__ является геттером и сеттером для внутреннего слота [[Prototype]] и находится в Object.prototype :




Из-за этого я избегал записи __proto__ для обозначения прототипа. __proto__ находится не в самом объекте, что приводит к неожиданным результатам. Для демонстрации попробуем через __proto__ удалить прототип объекта и затем восстановить его:

Как так получилось? Дело в том, что __proto__ – это унаследованное свойство Object.prototype , а не самого объекта foo . Из-за этого в момент когда в цепочке прототипов пропадает ссылка на Object.prototype , __proto__ превращается в тыкву и перестает работать с прототипом.
А теперь отработаем кликбейт из введения. Представим следующую цепочку прототипов:



В консоли Chrome foo будет выглядеть следующим образом:




А теперь уберем связь между baz и Object.prototype :

И теперь в консоли Chrome видим следующий результат:




Связь с Object.prototype разорвана у baz и __proto__ возвращает undefined даже у дочернего объекта foo , однако Chrome все равно показывает что __proto__ есть. Скорее всего тут имеется в виду внутренний слот [[Prototype]] , но для простоты это было изменено на __proto__ , ведь если не извращаться с цепочкой прототипов, это будет верно.

Как работать с прототипом объекта

Рассмотрим основные способы работы с прототипом: изменение прототипа и создание нового объекта с указанным прототипом.

Для изменения прототипа у существующего объекта есть всего два метода: использование сеттера __proto__ и метод Object.setPrototypeOf .

Если браузер не поддерживает ни один из этих методов, то изменить прототип объекта невозможно, можно только создать его копию с новым прототипом.
Но есть один нюанс с внутренним слотом [[Extensible]] который указывает на то, возможно ли добавлять к нему новые поля и менять его прототип. Есть несколько функций, которые выставляют этот флаг в false и предотвращают смену прототипа: Object.freeze , Object.seal , Object.preventExtensions . Пример:

А теперь менее категоричный вопрос создания нового объекта с прототипом. Для этого есть следующие способы.
Стандартный способ:

Если нет поддержки Object.create , но есть __proto__ :

И в случае если отсутствует поддержка всего вышеперечисленного:

Способ основан на логике работы оператора new , о которой поговорим чуть ниже. Но сам способ основан на том, что оператор new берет свойство prototype функции и использует его в качестве прототипа, т.е. устанавливает объект в [[Prototype]] , что нам и нужно.

Функции и конструкторы

А теперь поговорим про функции и как они работают в качестве конструкторов.

Функция Person тут является конструктором и создает два поля в новом объекте, а цепочка прототипов выглядит так:




Откуда взялся Person.prototype ? При объявлении функции, у нее автоматически создается свойство prototype для того чтобы ее можно было использовать как конструктор (note 3), таким образом свойство prototype функции не имеет отношения к прототипу самой функции, а задает прототипы для дочерних объектов. Это позволит реализовывать наследование и добавлять новые методы, например так:



И теперь вызов user.fullName() вернет строку "John Doe".

Что такое new

На самом деле оператор new не таит в себе никакой магии. При вызове new выполняет несколько действий:

  1. Создает новый объект self
  2. Записывает свойство prototype функции конструктора в прототип объекта self
  3. Вызывает функцию конструктор с объектом self в качестве аргумента this
  4. Возвращает self если конструктор вернул примитивное значение, иначе возвращает значение из конструктора

Все эти действия можно сделать силами самого языка, поэтому можно написать свой собственный оператор new в виде функции:

Но начиная с ES6 волшебство пришло и к new в виде свойства new.target, которое позволяет определить, была ли вызвана функция как конструктор с new, или как обычная функция:

new.target будет undefined для обычного вызова функции, и ссылкой на саму функцию в случае вызова через new ;

Наследование

Зная все вышеперечисленное, можно сделать классическое наследование дочернего класса Student от класса Person . Для этого нужно

  1. Создать конструктор Student с вызовом логики конструктора Person
  2. Задать объекту `Student.prototype` прототип от `Person`
  3. Добавить новые методы к `Student.prototype`



Фиолетовым цветом обозначены поля объекта (они все находятся в самом объекте, т.к. this у всей цепочки прототипов один), а методы желтым (находятся в прототипах соответствующих функций)
Вариант 1 предпочтительнее, т.к. Object.setPrototypeOf может привести к проблемам с производительностью.

Сколько вам сахара к классу

Для того чтобы облегчить классическую схему наследование и предоставить более привычный синтаксис, были представлены классы, просто сравним код с примерами Person и Student:

Уменьшился не только бойлерплейт, но и поддерживаемость:

  • В отличие от функции конструктора, при вызове конструктора без new выпадет ошибка
  • Родительский класс указывается ровно один раз при объявлении

При этом цепочка прототипов получается идентичной примеру с явным указанием prototype у функций конструкторов.

Наивно было бы ожидать, что одна статья ответит на все вопросы. Если у Вас есть интересные вопросы, экскурсы в историю, аргументированные или беспочвенные заявления о том, что я сделал все не так, либо правки по ошибкам, пишите в комментарии.

P. P. S.

К сожалению главный кликбейт статьи перестал быть актуальным. В данный момент Chrome (версия 93, на момент обновления статьи) перестал использовать __proto__ для обозначения прототипа, и теперь отображает его как слот [[Prototype]] :

image

Справедливости ради хочу отметить что в Firefox (92) также не используется обозначение __proto__ :


С момента окончания самой страшной в истории человечества войны прошло чуть более двух месяцев. И вот 16 июля 1945 года американскими военными была испытана первая ядерная бомба, а спустя еще месяц в атомном пекле гибнут тысячи жителей японских городов. С тех пор ядерное оружие, так же как и средства доставки его к целям, непрерывно совершенствовалось на протяжении более полувека.

Военным хотелось получить в свое распоряжение как сверхмощные боеприпасы, одним ударом сметающие с карты целые города и страны, так и сверхмалые, умещающиеся в портфель. Такое устройство вывело бы диверсионную войну на небывалый доселе уровень. Как с первым, так и со вторым возникли непреодолимые трудности. Виной всему, так называемая, критическая масса. Однако, обо всем по порядку.

Такое взрывоопасное ядро

Чтобы разобраться в порядке работы ядерных устройств и понять, что называется критической массой, вернемся ненадолго за парту. Из школьного курса физики мы помним простое правило: одноименные заряды отталкиваются. Там же, в средней школе ученикам рассказывают о строении атомного ядра, состоящего из нейтронов, нейтральных частиц и протонов, заряженных положительно. Но как такое возможно? Положительно заряженные частицы расположены так близко друг к другу, силы отталкивания должны быть колоссальными.

Ядро урана

Науке до конца не известна природа внутриядерных сил, удерживающих вместе протоны, хотя свойства этих сил изучены достаточно хорошо. Силы действуют только на очень близком расстоянии. Но стоит хотя бы чуть-чуть разделить протоны в пространстве, как силы отталкивания начинают превалировать, и ядро разлетается на куски. А мощность такого разлета воистину колоссальна. Известно, что силы взрослого мужчины не хватило бы для удержания протонов всего лишь одного единственного ядра атома свинца.

Чего испугался Резерфорд

Ядра большинства элементов таблицы Менделеева стабильны. Однако с ростом атомного числа эта стабильность все уменьшается. Дело в размере ядер. Представим себе ядро атома урана, состоящее из 238 нуклидов, из которых 92 – протоны. Да, протоны находятся в тесном контакте друг с другом, и внутриядерные силы надежно цементируют всю конструкцию. Но сила отталкивания протонов, находящихся на противоположных концах ядра становится заметной.

Эрнест Резерфорд

Что проделывал Резерфорд? Он производил бомбардировку атомов нейтронами (электрон не пройдет через электронную оболочку атома, а положительно заряженный протон не сможет приблизиться к ядру из-за сил отталкивания). Нейтрон, попадая в ядро атома, вызывал его деление. В стороны разлетались две отдельные половинки и два-три свободных нейтрона.

Деление ядра урана

Этот распад, в силу громадных скоростей разлетающихся частиц, сопровождался выбросом громадной энергии. Ходил слух, что Резерфорд даже хотел скрыть свое открытие, испугавшись его возможных последствий для человечества, но это, скорее всего, не более чем сказки.

Так при чем тут масса и почему она критическая

Уточним масштаб. Если за ядро атома принять яблоко на нашем столе, то для того, чтобы представить себе ядро соседнего атома, такое же яблоко придется отнести и положить на стол даже не в соседней комнате, а… в соседнем доме. Нейтрон же будет размером с вишневую косточку.

Для того, чтобы выделившиеся нейтроны не улетали впустую за пределы слитка урана, а более 50 % из них находили бы себе цель в виде атомных ядер, этот слиток должен иметь соответствующие размеры. Вот что называется критической массой урана – масса, при которой более половины выделяющихся нейтронов сталкиваются с другими ядрами.

На деле это происходит в одно мгновение. Количество расщепленных ядер нарастает как лавина, их осколки устремляются во все стороны со скоростями сопоставимыми со скоростью света, вспарывая воздух, воду, любую другую среду. От их столкновений с молекулами окружающей среды область взрыва мгновенно нагревается до миллионов градусов, излучая жар, испепеляющий все в округе нескольких километров.

Ядерный взрыв

Резко нагретый воздух мгновенно увеличивается в размерах, создавая мощную ударную волну, которая сносит с фундаментов здания, переворачивает и крушит все на своем пути… такова картина атомного взрыва.

Как это выглядит на практике

Устройство атомной бомбы на удивление просто. Имеются два слитка урана (или другого радиоактивного металла), масса каждого из которых немного меньше критической. Один из слитков изготовлен в виде конуса, другой – шара с конусообразным отверстием. Как нетрудно догадаться, при совмещении обеих половинок получается шар, у которого достигается критическая масса. Это стандартная простейшая ядерная бомба. Соединяются две половинки при помощи обычного тротилового заряда (конус выстреливается в шар).

Атомная бомба

Почему не бывает атомной бомбы размером с пачку сигарет

Все по той же причине. Критическая масса самого распространенного изотопа урана 235 составляет около 45 кг. Взрыв такого количества ядерного топлива – это уже катастрофа. А изготовить взрывное устройство с меньшим количеством вещества невозможно – оно просто не сработает.

По той же причине не получилось и создать сверхмощные атомные заряды из урана или других радиоактивных металлов. Для того, чтобы бомба была очень мощной, ее делали из десятка слитков, которые при подрыве детонирующих зарядов устремлялись к центру, соединяясь как дольки апельсина.

А как же работает мирный атом

атомная станция

ТВЭЛы изготавливаются в виде стержней, между которыми находятся регулирующие стержни, выполненные из материала, хорошо поглощающего нейтроны. Принцип работы прост:

  • регулирующие (поглощающие) стержни вводятся в пространство между стержнями урана – реакция замедляется или останавливается вовсе;
  • регулирующие стержни выводятся из зоны – радиоактивные элементы активно обмениваются нейтронами, ядерная реакция протекает интенсивнее.

Действительно, получается та же атомная бомба, в которой критическая масса достигается настолько плавно и регулируется так четко, что это не приводит к взрыву, а лишь к нагреву теплоносителя.

Хотя, к сожалению, как показывает практика, не всегда человеческий гений способен обуздать эту огромную и разрушительную энергию – энергию распада атомного ядра.

Читайте также: