Подтвердить что ты не робот

Примитивное значение vs Базовое значение

Я прочитал книгу под названием "Профессиональный Javascript для веб-разработчика", и он говорит: "Переменная назначается ссылочным значением или примитивным значением. Опорные значения - это объекты, хранящиеся в памяти". И тогда он ничего не говорит о том, как хранится Primitive значение. Поэтому я предполагаю, что он не хранится в памяти. Исходя из этого, когда у меня есть script, как это:

var foo = 123;

Как Javascript помнит переменную foo для дальнейшего использования?

4b9b3361

Ответ 1

A variable может содержать один из двух типов значений: primitive values или reference values.

  • primitive values - это данные, которые хранятся в стеке.
  • Primitive value хранится непосредственно в месте доступа к переменной.
  • reference values объекты, которые хранятся в куче.
  • Reference value, хранящийся в местоположении переменной, является указателем на местоположение в памяти, где хранится объект.
  • Примитивные типы включают Undefined, Null, Boolean, Number или String.

Основы:

Объекты - это совокупности свойств. Свойство может ссылаться на object или primitive. Primitives are values, они не имеют свойств.

Обновлено:

JavaScript имеет 6 примитивных типов данных: строка, число, boolean, null, undefined, символ (новый в ES6). За исключением нулей и undefined, все значения примитивов имеют эквиваленты объектов, которые обертывают примитивные значения, например. объект String обходит вокруг примитива строки. Все примитивы неизменны.

Ответ 2

Хорошо, представьте, что ваша переменная - лист бумаги - заметка.

Примечание 1: Переменная - это заметка.

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

Примечание 2: У вас бесконечное количество липких заметок, в которых хранятся небольшие объемы информации.

Отлично, что вы можете написать на своей заметке? Я могу написать:

  • Да или нет (a boolean).
  • Мой возраст (номер).
  • Мое имя (строка ).
  • Ничего (undefined).
  • Дудл или что-то еще, что мне ничего не значит (null).

Таким образом, мы можем писать простые вещи (пусть снисходительны и называть их примитивными вещами) на наших липких заметках.

Примечание 3: Вы можете писать примитивные вещи на своих липких заметках.

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

Когда я иду, чтобы поместить свою липкую записку на холодильник, я вижу, что моя жена положила еще одну записку на холодильник, которая также говорит 30 (чтобы напомнить мне, что ее день рождения - 30 числа этого месяца).

Q: Разве обе липкие заметки передают одну и ту же информацию?

A: Да, они оба говорят 30. Мы не знаем, если это 30 ломтиков сыра или 30-й день месяца, и, честно говоря, нам все равно. Для человека, который не знал ничего лучшего, все равно.

var slicesOfCheese = 30;
var wifesBirthdate = 30;

alert(slicesOfCheese === wifesBirthdate); // true

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

Я очень рад сегодня вечером - болтаюсь со старыми друзьями, прекрасно проводя время. Затем некоторые из моих друзей зовут меня и говорят, что они не смогут сделать это на вечеринке.

Итак, я иду к своему холодильнику и стираю 30 на моей липкой ноте (не моя липкая заметка), которая заставит ее рассердиться) и сделайте ее 20.

Примечание 5: Вы можете удалить то, что написано на заметке, и написать что-то еще.

Q: Что все хорошо и хорошо, но что, если моя жена хотела написать список продуктов для меня, чтобы забрать, пока я был, чтобы получить сыр. Должна ли она писать записку для каждого предмета?

A: Нет, она возьмет более длинный список бумаги и напишет список продуктов на этой бумаге. Затем она напишет записку, в которой расскажут мне, где найти список продуктов.

Итак, что здесь происходит?

  • Список продуктов - это, очевидно, не простые (erm... примитивные) данные.
  • Моя жена написала это на более длинном листе бумаги.
  • Она написала, где найти это в липкой заметке.

Дорогая, список продуктов находится под вашей клавиатурой.

Повторить:

  • Фактический объект (список продуктов) находится под моей клавиатурой.
  • Липкая нота говорит мне, где ее найти (адрес объекта).

Примечание 6: Контрольные значения - это ссылки на объекты (адреса, где они будут найдены).

Q: Как мы узнаем, что две липкие заметки говорят одно и то же? Скажите, что моя жена сделала еще один список продуктов на случай, если я упустил первое место, и написал для него еще одну заметку. Оба списка говорят одно и то же, но ли заметки говорят то же самое?

A: №. Первая заметка говорит нам, где найти первый список. Второй рассказывает нам, где найти второй список. Не имеет значения, говорят ли в двух списках одно и то же. Это два разных списка.

var groceryList1 = ["1 dozen apples", "2 loaves of bread", "3 bottles of milk"];
var groceryList2 = ["1 dozen apples", "2 loaves of bread", "3 bottles of milk"];

alert(groceryList1 === groceryList2); // false

Примечание 7: Две липкие заметки передают одну и ту же информацию только в том случае, если они относятся к одному и тому же объекту.

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

Дорогая, список продуктов находится под вашей клавиатурой.

Содержит ту же информацию, что и:

Не забывайте, что список продуктов находится под вашей клавиатурой.

В терминах программирования:

var groceryList1 = ["1 dozen apples", "2 loaves of bread", "3 bottles of milk"];
var groceryList2 = groceryList1;

alert(groceryList1 === groceryList2); // true

Итак, все, что вам нужно знать о примитивах и ссылках в JavaScript. Не нужно вдаваться в такие вещи, как куча и динамическое распределение памяти. Это важно, если вы программируете на C/С++.

Изменить 1: О, и важно то, что когда вы передаете переменные вокруг, вы по существу передаете примитивные значения по значению и ссылочные значения по ссылке.

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

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

Изменить 2: В ответ на комментарий, отправленный @LacViet:

Ну для начала мы говорим о JavaScript, а JavaScript не имеет стека или кучи. Это динамический язык, и все переменные в JavaScript являются динамическими. Чтобы объяснить разницу, я сравню ее с C.

Рассмотрим следующую программу C:

#include <stdio.h>

int main() {
    int a = 10;
    int b = 20;
    int c = a + b;
    printf("%d", c);
    return 0;
}

При компиляции этой программы мы получаем исполняемый файл. Исполняемый файл разделяется на несколько сегментов (или разделов). Эти сегменты включают сегмент стека, сегмент кода, сегмент данных, дополнительный сегмент и т.д.

  • Сегмент стека используется для хранения состояния программы при вызове функции или обработчика прерываний. Например, когда функция f вызывает функцию g, тогда состояние функции f (все значения в регистрах того времени) сохраняются в стеке. Когда g возвращает управление в f, то эти значения восстанавливаются.
  • Сегмент кода содержит фактический код, который будет выполняться процессором. Он содержит кучу инструкций, которые процессор должен выполнять как add eax, ebx (где add - код операции, а eax и ebx - аргументы). Эта инструкция добавляет содержимое регистров eax и ebx и сохраняет результат в регистре eax.
  • Сегмент данных используется для резервирования пространства для переменных. Например, в приведенной выше программе нам нужно зарезервировать место для целых чисел a, b и c. Кроме того, нам также необходимо зарезервировать пространство для строковой константы "%d". Таким образом, зарезервированные переменные имеют фиксированный адрес в памяти (после компоновки и загрузки).
  • В дополнение ко всем этим вы также предоставляете немного дополнительного места для операционной системы. Это называется кучей. Из этого места выделяется любая дополнительная память. Память, выделенная таким образом, называется динамической памятью.

Посмотрите программу с динамической памятью:

#include <stdio.h>
#include <malloc.h>

int main() {
    int * a = malloc(3 * sizeof(int));

    a[0] = 3;
    a[1] = 5;
    a[2] = 7;

    printf("a: %d\nb: %d\nc: %d\n", a[0], a[1], a[2]);

    return 0;
}

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

Итак, мы создаем указатель int (int *), называемый a. Пространство для a выделяется из сегмента данных (т.е. Не динамического). Затем мы вызываем malloc, чтобы выделить смежное пространство для 3 целых чисел из кучи. Адрес памяти первого int возвращается и сохраняется в указателе a.

Q: Что мы узнали?

A: Фиксированное количество пространства выделяется для всех переменных. Каждая переменная имеет фиксированный адрес. Мы также можем выделить дополнительную память из кучи и сохранить адрес этой дополнительной памяти в указателе. Это называется схемой динамической памяти.

Концептуально это похоже на то, что я объяснил, что переменные являются заметками. Все переменные (включая указатели - это липкие заметки). Однако указатели являются особыми, потому что они ссылаются на ячейку памяти (которая похожа на ссылку на объект в JavaScript).

Однако здесь и заканчивается сходство. Вот отличия:

  • В C все передано значением (включая адреса в указателях). Чтобы передать ссылку, вам нужно использовать косвенную привязку с помощью указателей. JavaScript передает только примитивы по значению. Передача ссылок обрабатывается прозрачно движком и подобно передаче любой другой переменной.
  • В C вы можете создать указатель на примитивный тип данных, например int. В JavaScript вы не можете создать ссылку на примитивное значение, например number. Все примитивы всегда сохраняются по значению.
  • В C вы можете выполнять различные операции с указателями. Это называется арифметикой указателя. JavaScript не имеет указателей. У него есть только ссылки. Таким образом, вы не можете выполнить любую арифметику указателя.

Помимо этих трех самых больших различий между C и JavaScript, все переменные в JavaScript фактически указывают. Поскольку JavaScript является динамическим языком, для сохранения number и string в разные моменты времени можно использовать одну и ту же переменную.

JavaScript - интерпретируемый язык, а интерпретатор обычно написан на С++. Таким образом, все переменные в JavaScript отображаются на объекты в языке хоста (даже примитивы).

Когда мы объявляем переменную в JavaScript, интерпретатор создает для нее новую общую переменную. Затем, когда мы присваиваем ему значение (будь то примитивным или ссылочным), интерпретатор просто присваивает ему новый объект. Внутри он знает, какие объекты являются примитивными и которые на самом деле являются объектами.

Концептуально это похоже на следующее:

JSGenericObject ten = new JSNumber(10); // var ten = 10;

Q: Что это значит?

A: Это означает, что все значения (примитивы и объекты) в JavaScript выделены из кучи. Даже сами переменные выделяются из кучи. Неправильно указывать, что примитивы выделяются из стека, и из кучи выделяются только объекты. Это самая большая разница между C и JavaScript.

Ответ 3

В javascript Primitive values находятся данные, которые хранятся в stack.

Primitive value хранится непосредственно в месте доступа к переменной.

И Reference values являются объектами, которые хранятся в heap.

Справочное значение, хранящееся в местоположении переменной, является указателем на местоположение в памяти, где хранится объект.

JavaScript поддерживает пять примитивных типов данных: number, string, Boolean, undefined, and null.

Эти типы называются примитивными типами, поскольку они являются основными строительными блоками, из которых могут быть построены более сложные типы.

Из пяти только number, string, and Boolean являются реальными типами данных в смысле фактического хранения данных.

Undefined and null являются типами, которые возникают при особых обстоятельствах. primitive type имеет фиксированный размер в памяти. Например, число занимает восемь байтов памяти, а логическое значение может быть представлено только одним битом.

И типы ссылок могут быть любой длины - они не имеют фиксированного размера.

Ответ 4

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

Это упрощение и не предназначено для описания фактической реализации JavaScript.

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

Различие между примитивными и ссылочными типами является важным, поскольку они ведут себя по-разному. Рассмотрим следующий код, который использует числа (примитивный тип):

var a = 3.14;  // Declare and initialize a variable
var b = a;     // Copy the variable value to a new variable
a = 4;         // Modify the value of the original variable
alert(b)       // Displays 3.14; the copy has not changed

Нет ничего удивительного в этом коде. Теперь рассмотрим, что произойдет, если мы немного изменим код, чтобы вместо массивов использовать массивы (ссылочный тип):

var a = [1,2,3];  // Initialize a variable to refer to an array
var b = a;        // Copy that reference into a new variable
a[0] = 99;        // Modify the array using the original reference
alert(b);         // Display the changed array [99,2,3] using the new reference

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

Ответ 5

Примитивное значение - это базовая единица, которая представлена ​​на самом низком уровне реализации языка, а в JavaScript - один из следующих типов: number, string, Boolean, undefined и null.