Bazaprogram.ru

Новости из мира ПК
0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Must be lvalue javascript

JavaScript Primitive vs. Reference Values

Summary: in this tutorial, you will learn the differences between primitive and reference values.

Accessing by value or by reference

In JavaScript, a variable may store two types of data: primitive and reference. JavaScript provides six primitive types as undefined , null , boolean , number , string , and symbol , and a reference type object .

The size of a primitive value is fixed, therefore, JavaScript stores primitive values on the stack. On the other hand, the size a reference value is dynamic therefore JavaScript stores the reference values on the heap.

When you assign a value to a variable, the JavaScript engine must determine whether the value is a primitive or reference value.

If the value is primitive, when you access the variable, you are manipulating the actual value stored in the variable. In other words, the variable that stores a primitive value is accessed by value.

Unlike the primitive value, when you manipulate an object, you are working on the reference to that object, rather than the actual object. In short, a variable that stores an object is accessed by reference.

To determine the type of a primitive value you use the typeof operator. For example:

To find the type of a reference value, you use the instanceof operator:

For example, the following rgb variable is an instance of the Array object:

Copying primitive values

When you assign a variable that stores a primitive value to another, the value stored in the variable is created and copied into the new variable.

Let’s take a look at the following example.

First, declare a variable a and initialize its value to 10.

Second, declare another variable b and assign it a value of the variable a . Internally, JavaScript engine copies the value stored in a into the location of b .

Third, assign the variable b new value 20.

Because a and b have no relationship, therefore when you change the value stored in the b variable, the value of the a variable remains intact.

Copying reference values

When you assign a reference value from one variable to another, the value stored in the variable is also copied into the location of the new variable. The difference is that the values stored in both variables now are the address of the actual object stored in the heap. As a result, both variables are pointing to the same object.

Consider the following example.

First, declare a variable x that holds an object whose name property is ‘John’ .

Second, declare another variable y and assign the x variable to y . Both x and y are now pointing to the same object on the heap.

Third, modify the value stored in the name property of the object using the y variable.

Because both x and y are pointing to the same object, therefore, the change is also reflected if you access the object using the x variable.

In this tutorial, you have learned about accessing by value and by reference, and also the differences between them.

Преобразование объектов: toString и valueOf

Материал на этой странице устарел, поэтому скрыт из оглавления сайта.

Более новая информация по этой теме находится на странице https://learn.javascript.ru/object-toprimitive.

Ранее, в главе Преобразование типов для примитивов мы рассматривали преобразование типов для примитивов. Теперь добавим в нашу картину мира объекты.

Бывают операции, при которых объект должен быть преобразован в примитив.

  • Строковое преобразование – если объект выводится через alert(obj) .
  • Численное преобразование – при арифметических операциях, сравнении с примитивом.
  • Логическое преобразование – при if(obj) и других логических операциях.

Рассмотрим эти преобразования по очереди.

Логическое преобразование

Проще всего – с логическим преобразованием.

Любой объект в логическом контексте – true , даже если это пустой массив [] или объект <> .

Строковое преобразование

Строковое преобразование проще всего увидеть, если вывести объект при помощи alert :

Как видно, содержимое объекта не вывелось. Это потому, что стандартным строковым представлением пользовательского объекта является строка «[object Object]» .

Такой вывод объекта не содержит интересной информации. Поэтому имеет смысл его поменять на что-то более полезное.

Читать еще:  Как восстановить давно удаленную переписку в вк

Если в объекте присутствует метод toString , который возвращает примитив, то он используется для преобразования.

Метод toString не обязан возвращать именно строку.

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

Поэтому мы и называем его здесь «строковое преобразование», а не «преобразование к строке».

Все объекты, включая встроенные, имеют свои реализации метода toString , например:

Численное преобразование

Для численного преобразования объекта используется метод valueOf , а если его нет – то toString :

Метод valueOf обязан возвращать примитивное значение, иначе его результат будет проигнорирован. При этом – не обязательно числовое.

У большинства встроенных объектов такого valueOf нет, поэтому численное и строковое преобразования для них работают одинаково.

Исключением является объект Date , который поддерживает оба типа преобразований:

Если посмотреть в стандарт, то в пункте 15.2.4.4 говорится о том, что valueOf есть у любых объектов. Но он ничего не делает, просто возвращает сам объект (непримитивное значение!), а потому игнорируется.

Две стадии преобразования

Итак, объект преобразован в примитив при помощи toString или valueOf .

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

Например, рассмотрим применение к объекту операции == :

Объект obj был сначала преобразован в примитив, используя численное преобразование, получилось 1 == true .

Далее, так как значения всё ещё разных типов, применяются правила преобразования примитивов, результат: true .

То же самое – при сложении с объектом при помощи + :

Или вот, для разности объектов:

Объект Date по историческим причинам является исключением.

Бинарный оператор плюс + обычно использует численное преобразование и метод valueOf . Как мы уже знаем, если подходящего valueOf нет (а его нет у большинства объектов), то используется toString , так что в итоге преобразование происходит к строке. Но если есть valueOf , то используется valueOf . Выше в примере как раз a + b это демонстрируют.

У объектов Date есть и valueOf – возвращает количество миллисекунд, и toString – возвращает строку с датой.

…Но оператор + для Date использует именно toString (хотя должен бы valueOf ).

Это и есть исключение:

Других подобных исключений нет.

В языке Java (это не JavaScript, другой язык, здесь приведён для примера) логические значения можно создавать, используя синтаксис new Boolean(true/false) , например new Boolean(true) .

В JavaScript тоже есть подобная возможность, которая возвращает «объектную обёртку» для логического значения.

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

Почему запустился alert ? Ведь в if находится false … Проверим:

Дело в том, что new Boolean – это не примитивное значение, а объект. Поэтому в логическом контексте он преобразуется к true , в результате работает первый пример.

А второй пример вызывает alert , который преобразует объект к строке, и он становится «false» .

В JavaScript вызовы new Boolean/String/Number не используются, а используются простые вызовы соответствующих функций, они преобразуют значение в примитив нужного типа, например Boolean(val) === !!val .

Итого

  • В логическом контексте объект – всегда true .
  • При строковом преобразовании объекта используется его метод toString . Он должен возвращать примитивное значение, причём не обязательно именно строку.
  • Для численного преобразования используется метод valueOf , который также может возвратить любое примитивное значение. У большинства объектов valueOf не работает (возвращает сам объект и потому игнорируется), при этом для численного преобразования используется toString .

Полный алгоритм преобразований есть в спецификации ECMAScript, смотрите пункты 11.8.5, 11.9.3, а также 9.1 и 9.3.

Заметим, для полноты картины, что некоторые тесты знаний в интернет предлагают вопросы типа:

Если вы запустите эти выражения в консоли, то результат может показаться странным. Подвох здесь в том, что если фигурные скобки <. >идут не в выражении, а в основном потоке кода, то JavaScript считает, что это не объект, а «блок кода» (как if , for , но без оператора просто группировка команд вместе используется редко).

Читать еще:  Скачать прогу для восстановления флешки микро сд

Вот блок кода с командой:

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

То есть, такие вопросы – не на преобразование типов, а на понимание, что если < . >находится вне выражений, то это не объект, а блок.

Задачи

Почему результат true ?

Если с одной стороны – объект, а с другой – нет, то сначала приводится объект.

В данном случае сравнение означает численное приведение. У массивов нет valueOf , поэтому вызывается toString , который возвращает список элементов через запятую.

В данном случае, элемент только один – он и возвращается. Так что [‘x’] становится ‘x’ . Получилось ‘x’ == ‘x’ , верно.

P.S. По той же причине верны равенства:

Преобразование

Объявлен объект с toString и valueOf .

Какими будут результаты alert ?

Подумайте, прежде чем ответить.

Первый alert(foo)

Возвращает строковое представление объекта, используя toString , т.е. «foo» .

Второй alert(foo + 1)

Оператор ‘+’ преобразует объект к примитиву, используя valueOf , так что результат: 3 .

Третий alert(foo + „3“)

То же самое, что и предыдущий случай, объект превращается в примитив 2 . Затем происходит сложение 2 + ‘3’ . Оператор ‘+’ при сложении чего-либо со строкой приводит и второй операнд к строке, а затем применяет конкатенацию, так что результат – строка «23» .

Почему [] == [] неверно, а [ ] == ![ ] верно?

Почему первое равенство – неверно, а второе – верно?

Какие преобразования происходят при вычислении?

Ответ по первому равенству

Два объекта равны только тогда, когда это один и тот же объект.

В первом равенстве создаются два массива, это разные объекты, так что они неравны.

Ответ по второму равенству

Первым делом, обе части сравнения вычисляются. Справа находится ![] . Логическое НЕ ‘!’ преобразует аргумент к логическому типу. Массив является объектом, так что это true . Значит, правая часть становится ![] = !true = false . Так что получили:

Проверка равенства между объектом и примитивом вызывает численное преобразование объекта.

У массива нет valueOf , сработает toString и преобразует массив в список элементов, то есть – в пустую строку:

Сравнение различных типов вызывает численное преобразование слева и справа:

Теперь результат очевиден.

Вопросник по преобразованиям, для объектов

Подумайте, какой результат будет у выражений ниже. Когда закончите – сверьтесь с решением.

new Date(0) – дата, созданная по миллисекундам и соответствующая 0 мс от 1 января 1970 года 00:00:00 UTC. Оператор минус — преобразует дату обратно в число миллисекунд, то есть в 0 .

new Array(num) при вызове с единственным аргументом-числом создаёт массив данной длины, без элементов. Поэтому его нулевой элемент равен undefined , при сложении со строкой получается строка «undefined» .

Фигурные скобки – это создание пустого объекта, у него нет свойства ‘0’ . Так что значением будет undefined . Обратите внимание на внешние, круглые скобки. Если их убрать и запустить <>[0] в отладочной консоли браузера – будет 0 , т.к. скобки <> будут восприняты как пустой блок кода, после которого идёт массив.

Массив преобразуется в строку «1» . Оператор «+» при сложении со строкой приводит второй аргумент к строке – значит будет «1» + «1» = «11» .

Массивы приводятся к строке и складываются.

Массив преобразуется в пустую строку «» + null + 1 , оператор «+» видит, что слева строка и преобразует null к строке, получается «null» + 1 , и в итоге «null1» .

[[0]] – это вложенный массив [0] внутри внешнего [ ] . Затем мы берём от него нулевой элемент, и потом ещё раз.

Если это непонятно, то посмотрите на такой пример:

Квадратные скобки после массива/объекта обозначают не другой массив, а взятие элемента.

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

What is an lvalue?

vinaysena

can u guys plz provide me an example?

Was this answer useful? Yes

Syam Prasad N

    Jul 13th, 2006

example to demonstrate lvalue

#define CONSTANT_VAR 10

The variable var is an integer, which is a storable location in memory. Therefore, the statement var = 1 qualifies var to be an lvalue . Notice the second assignment statement, * pntr_int = 5 . By using the * modifier to reference the area of memory that pntr_int points to, * pntr_int is qualified as an lvalue .

Читать еще:  Java в visual studio

In contrast, observe the CONSTANT variable:

In this statements, the left side of the statement evaluates to a constant value that cannot be changed because constants do not represent storable locations in memory. Therefore, this assignment statements do not contain lvalues and will be flagged by your compiler as errors.

Was this answer useful? Yes

khalil Ahmad

    Apr 13th, 2007

lvalue is variable or you can say a memory location which can store (predefined type) rvalue while rvalue is constant

Was this answer useful? Yes

eyehz

    May 14th, 2007

lvalue is an expression that referes to a memory location or object. However, it is not necessary to appear on the left side of equation. For example:

Notice the assignment in line 3, since we declared y as a pointer to integer, the right side value must be a lvalue, ie. &x is a lvalue that points to a memory location and match the requirements of the y declaration. But the following statement would be wrong:

because x is not a lvalue.

Was this answer useful? Yes

    May 17th, 2007

however, that is not entirely correct, because both of these statements are valid:
y = NULL
y = 0;

Was this answer useful? Yes

anand

    Jul 5th, 2007

A lvalue is simply the address value, where, the value assigned to a variable is to be stored.

Was this answer useful? Yes

Bharath B.G.

    Jul 24th, 2007

lvalue is the starting address of a data object(any variable). rvalue is the value stored in that location.

Was this answer useful? Yes

vinayak

    Jul 25th, 2007

lvalue of a assignement statement is always a variable it cant be expr. Assignement is storing of rvalue into it. lvalue of cond statement can be expr

Was this answer useful? Yes

Nabhi

    Sep 17th, 2007

Example for the lvalue:

first it will increament the value of i as it is preincreamnet as 6.
now the expression looks like 6++;

can u imigine how its possible to increament a one number in this case 6++;

the compiler trying to find out where is the variable . here it is a number that is why it will ask for the lvalue required.
>

i think i have cleared ur dpubt. with suitable example. if not means just drop a mail to nabhi_jkd @ yahoo . co . in

Was this answer useful? Yes

sadhus_01

Profile Answers by sadhus_01

    Oct 20th, 2007

Expressions that refer to memory locations are called “l-value” expressions. An l-value represents a storage region’s “locator” value, or a “left” value, implying that it can appear on the left of the equal sign (=). L-values are often identifiers.

Expressions referring to modifiable locations are called “modifiable l-values.” A modifiable l-value cannot have an array type, an incomplete type, or a type with the const attribute. For structures and unions to be modifiable l-values, they must not have any members with the const attribute. The name of the identifier denotes a storage location, while the value of the variable is the value stored at that location.

An identifier is a modifiable l-value if it refers to a memory location and if its type is arithmetic, structure, union, or pointer. For example, if ptr is a pointer to a storage region, then *ptr is a modifiable l-value that designates the storage region to which ptr points.

Any of the following C expressions can be l-value expressions:

    An identifier of integral, floating, pointer, structure, or union type

A subscript ([ ]) expression that does not evaluate to an array

A member-selection expression (–> or .)

A unary-indirection (*) expression that does not refer to an array

An l-value expression in parentheses

  • A const object (a nonmodifiable l-value)
  • Ссылка на основную публикацию
    Adblock
    detector