представлять
В этой главе мы объясним стратегию передачи параметров функциям функций в Ecmascript.
В информатике эта стратегия обычно называется «стратегией оценки» (примечание дяди: некоторые люди говорят, что она переводится в стратегию оценки, в то время как другие переводят ее в стратегию назначения. Посмотреть на следующее содержание, я думаю, что более уместно называть ее стратегией назначения. В любом случае, название должно быть написано как стратегия оценки, которая легко понять). Например, в языках программирования настраивание правил для оценки или выражений расчетов. Стратегия передачи параметров функции - это особый случай.
http://dmitrysoshnikov.com/ecmascript/chapter-8-valuation strategy/
Причина написания этой статьи заключается в том, что кто -то на форуме попросил точно объяснить некоторые стратегии для передачи параметров. Мы дали соответствующее определение здесь, надеясь, что оно будет полезно для всех.
Многие программисты убеждены, что в JavaScript (даже на некоторых других языках) объекты передаются ссылкой, а исходный тип значения передается значениями. Кроме того, многие статьи говорят об этом «факте», но многие люди действительно понимают этот термин, а сколько правильные? Мы объясним это один за другим в этой статье.
Общая теория
Следует отметить, что в теории назначения, как правило, есть две стратегии назначения: строгие - означает, что параметры рассчитываются перед входом в программу; Не -строгих - означает, что расчет параметров рассчитывается на основе требований расчета (то есть он эквивалентен расчету задержки).
Затем здесь мы рассмотрим стратегию передачи параметров основной функции, которая очень важна от начальной точки Ecmascript. Первое, что следует отметить, это то, что в ECMASCRIPT используются строгие стратегии передачи параметров (даже на других языках, таких как C, Java, Python и Ruby).
Кроме того, порядок расчета прошедших параметров также очень важен - в Ecmascript он остается вправо, и вводной порядок (справа от справа), реализованный на других языках, также может использоваться.
Строгая стратегия передачи также разделена на несколько семян -стратегий, и мы обсудим наиболее важные стратегии в этой главе.
Не все стратегии, обсуждаемые ниже, используются в Ecmascript, поэтому при обсуждении конкретного поведения этих стратегий мы использовали псевдокод, чтобы показать его.
Пройти по значению
Проходя по значению, многие разработчики хорошо знают, что значение параметра является копией значения объекта, передаваемого вызывающим абонент. Изменение значения параметра внутри функции не повлияет на внешний объект (значение внешнего параметра). Вообще говоря, новая память пересматривается (мы не обращаем внимания на то, как реализована выделенная память - это также стек или динамическое распределение памяти). Значение нового блока памяти является копией внешнего объекта, и его значение используется внутри функции.
Кода -копия выглядит следующим образом:
бар = 10
Процедура Foo (Bararg):
bararg = 20;
конец
foo (бар)
// Изменение значения внутри Foo не повлияет на значение внутренней полосы
Печать (бар) // 10
Однако, если параметры функции не являются исходным значением, а сложным структурным объектом, это принесет большие проблемы с производительностью. C ++ имеет эту проблему. При передаче структуры в качестве значения в функцию это полная копия.
Давайте приведем общий пример, используйте следующую стратегию назначения для ее проверки. Подумайте о функции, которая принимает 2 параметра. Первый параметр - это значение объекта, а второй - логический знак, чтобы отметить, полностью ли изменен объект (переназначение объекта на объект), или только некоторые свойства объекта изменяются.
Кода -копия выглядит следующим образом:
// ПРИМЕЧАНИЕ. Ниже приведены все псевдокод, а не реализация JS
bar = {
x: 10,
Y: 20
}
Процедура foo (bararg, isfullchange):
Если isfullChange:
bararg = {z: 1, Q: 2}
Выход
конец
Bararg.x = 100
Bararg.Y = 200
конец
foo (бар)
// пройти по значению, внешние объекты не будут изменены
print (bar) // {x: 10, y: 20}
// Полностью изменить объект (назначьте новое значение)
foo (бар, правда)
// тоже нет изменений
print (bar) // {x: 10, y: 20}, вместо {z: 1, q: 2}
Пройти через ссылку
Другая известная проходная ссылка-это не копия значения, а неявная ссылка на объект, такой как прямой справочный адрес объекта снаружи. Любые изменения в параметрах внутри функции влияют на значение объекта вне функции, поскольку оба ссылаются на один и тот же объект, то есть параметр эквивалентен псевдониме внешнего объекта.
псевдокод:
Кода -копия выглядит следующим образом:
Процедура foo (bararg, isfullchange):
Если isfullChange:
bararg = {z: 1, Q: 2}
Выход
конец
Bararg.x = 100
Bararg.Y = 200
конец
// Использовать тот же объект, что и выше
bar = {
x: 10,
Y: 20
}
// Результат вызова по ссылке заключается в следующем:
foo (бар)
// значение свойства объекта было изменено
print (bar) // {x: 100, y: 200}
// Перераспределение новых значений также влияет на объект
foo (бар, правда)
// Этот объект уже новым объектом
print (bar) // {z: 1, Q: 2}
Эта стратегия может более эффективно проходить сложные объекты, такие как крупные структурные объекты с большими партиями атрибутов.
Позвонить, поделившись
Все знают две вышеупомянутые стратегии, но вы можете не знать стратегию, о которой вы хотите поговорить здесь (на самом деле, это академическая стратегия). Тем не менее, мы скоро увидим, что это именно та стратегия, которая играет ключевую роль в стратегии доставки параметров в Ecmascript.
Эта стратегия также имеет некоторые синонимы: «пройти мимо объекта» или «пройти мимо объекта».
Эта стратегия была предложена в 1974 году Барбарой Лисков для языка программирования CLU.
Ключевой момент этой стратегии состоит в том, что функция получает копию (копию) объекта, а эталонная копия связана с формальными параметрами и его значениями.
Мы не можем назвать ссылки, которые появляются здесь «пройтись по ссылке», потому что параметры, полученные функцией, не являются прямым псевдонимом объекта, а копией справочного адреса.
Наиболее важное отличие состоит в том, что функция переназначает новые значения в параметр внутри, не повлияет на внешний объект (в случае с этим справочником в приведенном выше примере), но поскольку параметр является копией адреса, тот же объект, доступ к которому и внутри (например, внешний объект не является полной копией, как вы хотите пройти по значению). Изменение значения атрибута объекта параметра повлияет на внешний объект.
Кода -копия выглядит следующим образом:
Процедура foo (bararg, isfullchange):
Если isfullChange:
bararg = {z: 1, Q: 2}
Выход
конец
Bararg.x = 100
Bararg.Y = 200
конец
// все еще используют эту структуру объекта
bar = {
x: 10,
Y: 20
}
// Прохождение по вкладу повлияет на объект
foo (бар)
// свойства объекта были изменены
print (bar) // {x: 100, y: 200}
// Перезагрузка не работает
foo (бар, правда)
// все еще вышеуказанное значение
print (bar) // {x: 100, y: 200}
Предположение этой обработки состоит в том, что объекты, используемые на большинстве языков, не являются исходными значениями.
Пропустить Share - это особый случай прохождения по стоимости
Стратегия доставки путем обмена используется на многих языках: Java, Ecmascript, Python, Ruby, Visual Basic и т. Д. Кроме того, сообщество Python использовало этот термин, и его можно использовать на других языках, поскольку другие имена, как правило, заставляют людей чувствовать себя запутанными. В большинстве случаев, например, в Java, Ecmascript или Visual Basic, эта стратегия также называется Pass -By -Value - Значение: Специальное значение - Справочная копия (копия).
С одной стороны, это похоже на это - параметры, передаваемые функции, являются просто именем связанного значения (ссылочный адрес) и не будут влиять на внешний объект.
С другой стороны, эти термины действительно считаются неправильными, не углубляясь в них, так как многие форумы говорят о том, как передавать объекты в функции JavaScript).
В общей теории действительно существует высказывание, которое проходит по цене: но в настоящее время это значение - то, что мы называем копией адреса (копия), поэтому оно не нарушает правила.
В Ruby эта стратегия называется Pass By Retower. Позвольте мне еще раз сказать: он не передается с точки зрения копии большой структуры (например, не по значению), а с другой стороны, мы не обрабатываем ссылки на исходный объект и не можем его изменить; Следовательно, эта концепция перекрестных терминов может быть более запутанной.
В теории нет особого случая, подобного особому случаю, передаваемому по цене.
Но все еще необходимо понять эти стратегии в технологиях, упомянутых выше (Java, Ecmascript, Python, Ruby, другие). На самом деле, стратегия, которую они используют, состоит в том, чтобы пройти, поделившись.
Пресс -общая и указатель
Для С/С ++ эта стратегия такая же, как и проход по значению указателя, но существует важное различие - эта стратегия может определить указатели и полностью изменять объекты. Однако, в целом, распределение значения (адрес) указателя на новый блок памяти (то есть блок памяти, на который ссылаются ранее, остается неизменным); Изменение свойств объекта через указатель повлияет на внешний объект Adong.
Итак, и категории указателей мы четко видим, что это передается по значению адреса. В этом случае прохождение по обмену - это просто «синтетический сахар», например, поведение назначения указателя (но не выразительное) или изменение свойств, таких как ссылки (не требуется операция по определению), иногда его можно назвать «безопасным указателем».
Однако С/С + + также имеет специальный синтаксический сахар при обращении к свойствам объектов без неопределенности очевидных указателей:
Кода -копия выглядит следующим образом:
obj-> x вместо (*obj) .x
Эта идеология, которая наиболее тесно связана с C ++, можно увидеть из реализации «умных указателей». Например, в Boost :: shared_ptr оператор назначения и конструктор копирования перегружены, и контрольный счетчик объекта также используется для удаления объекта через GC. Этот тип данных даже имеет аналогичное имя - share_ptr.
Реализация ECMASCRPE
Теперь мы знаем политику передачи объектов как параметры в Ecmascript - пройти через Share: изменение свойств параметра будет влиять на внешнюю часть, в то время как переназначение значения не повлияет на внешний объект. Однако, как мы упоминали выше, разработчики Ecmascript обычно называют его: пройти по значению, за исключением того, что значение является копией справочного адреса.
ИНДЕНТОР JAVASCRPT Брендан Эш также написал: «Что передается, - это копия ссылки (копия адреса). Итак, то, что все упомянули на форуме, также верно под этим объяснением.
Точнее, это поведение можно понимать как простое задание. Мы видим, что внутренние объекты являются совершенно разными объектами, но упоминается одно и то же значение - то есть копия адреса.
Код ECMASCRIPT:
Кода -копия выглядит следующим образом:
var foo = {x: 10, y: 20};
var bar = foo;
оповещение (бар === foo); // истинный
bar.x = 100;
bar.y = 200;
оповещение ([foo.x, foo.y]); // [100, 200]
То есть два идентификатора (привязка имени) связаны с одним и тем же объектом в памяти и делятся этим объектом:
Значение Foo: addr (0xff) => {x: 100, y: 200} (адрес 0xff) <= значение панели: addr (0xff)
Для переназначения связывание представляет собой новый идентификатор объекта (новый адрес), не влияя на объект, который был ранее связан:
Кода -копия выглядит следующим образом:
bar = {z: 1, Q: 2};
оповещение ([foo.x, foo.y]); // [100, 200] Нет изменений
оповещение ([bar.z, bar.q]); // [1, 2] Но теперь ссылка является новым объектом
То есть у Foo и Bar теперь есть разные значения и разные адреса:
Кода -копия выглядит следующим образом:
Значение Foo: addr (0xff) => {x: 100, y: 200} (адрес 0xff)
Значение стержня: addr (0xfa) => {z: 1, q: 2} (адрес 0xfa)
Позвольте мне еще раз подчеркнуть, что значение упомянутого здесь объекта - это адрес, а не сама структура объекта и назначение переменной другой переменной - ссылка на назначенное значение. Следовательно, две переменные относятся к одному и тому же адресу памяти. Следующим назначением является новый адрес, который должен разрешить привязку к адресу старого объекта, а затем связываться с адресом нового объекта. Это наиболее важное различие между прохождением по ссылке.
Кроме того, если мы рассмотрим только уровень абстракции, предоставленный стандартом ECMA-262, мы видим только концепцию «значения» в алгоритме, которая реализует переданное «значение» (может быть исходным значением или объектом), но в соответствии с нашим вышеупомянутым определением его также можно полностью назвать «передаваемым значением», потому что ссылочный адрес также является значением.
Однако, чтобы избежать недоразумения (почему свойства внешних объектов могут быть изменены внутри функции), здесь необходимо учитывать детали уровня реализации - то, что мы видим, передается путем совместного использования, или, другими словами - передаваемые с помощью безопасного указателя, который не может быть представлен и изменен, но значение свойства объекта может быть изменена.
Термическая версия
Давайте определим терминную версию этой политики в Ecmascript.
Его можно назвать «пройти по значению» - значение, упомянутое здесь, является особым случаем, то есть значение - это копия адреса. На этом уровне мы можем сказать: Объекты в ECMASCRIPT, за исключением того, что исключения передаются по значению, что на самом деле является уровнем абстракции ECMASCRIPT.
Или в этом случае это специально называется «пройденным путем обмена». Благодаря этому вы можете увидеть разницу между традиционным прохождением по значению и прохождением по ссылке. Эта ситуация можно разделить на две ситуации: 1: исходное значение передается по значению; 2: объект передается путем совместного использования.
Фраза «функционировать путем ссылки на типы» не имеет ничего общего с Ecmascript, и это неправильно.
в заключение
Я надеюсь, что этот пост поможет узнать больше о макроуровне и реализации в Ecmascript. Как всегда, если есть какие -либо вопросы, пожалуйста, не стесняйтесь обсуждать это.