Why [‘1’, ‘7’, ’11’].map(parseint) returns [1, nan, 3] in javascript

map()

Мы почти у цели!

Map — это метод в прототипе массива, который возвращает новый массив из результатов вызова функции для каждого элемента исходного массива. Например, следующий код умножает каждый элемент массива на 3:

Теперь предположим, что я хочу вывести каждый элемент используя map() (и не используя return). Можно просто передать console.log в качестве аргумента в map() … правильно?

Происходит что-то странное. Вместо того чтобы выводить только значение, каждый вызов console.log выводит индекс и массив полностью.

При передаче функции в map() на каждой итерации она будет получать три аргумента: currentValue, currentIndex и полный array. Вот почему при каждой итерации выводятся три записи.

Теперь у нас есть всё что нужно для раскрытия тайны.

Исключаем и преобразуем: replacer

Полный синтаксис :

value
Значение для кодирования.
replacer
Массив свойств для кодирования или функция соответствия .
space
Дополнительное пространство (отступы), используемое для форматирования.

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

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

Например:

Здесь мы, наверное, слишком строги. Список свойств применяется ко всей структуре объекта. Так что внутри – пустые объекты, потому что нет в списке.

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

Теперь всё, кроме , сериализовано. Но список свойств довольно длинный.

К счастью, в качестве мы можем использовать функцию, а не массив.

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

В нашем случае мы можем вернуть «как есть» для всего, кроме . Чтобы игнорировать , код ниже возвращает :

Обратите внимание, что функция получает каждую пару ключ/значение, включая вложенные объекты и элементы массива. И она применяется рекурсивно

Значение внутри – это объект, который содержит текущее свойство.

Первый вызов – особенный. Ему передаётся специальный «объект-обёртка»: . Другими словами, первая пара имеет пустой ключ, а значением является целевой объект в общем. Вот почему первая строка из примера выше будет .

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

JavaScript

JS Array
concat()
constructor
copyWithin()
entries()
every()
fill()
filter()
find()
findIndex()
forEach()
from()
includes()
indexOf()
isArray()
join()
keys()
length
lastIndexOf()
map()
pop()
prototype
push()
reduce()
reduceRight()
reverse()
shift()
slice()
some()
sort()
splice()
toString()
unshift()
valueOf()

JS Boolean
constructor
prototype
toString()
valueOf()

JS Classes
constructor()
extends
static
super

JS Date
constructor
getDate()
getDay()
getFullYear()
getHours()
getMilliseconds()
getMinutes()
getMonth()
getSeconds()
getTime()
getTimezoneOffset()
getUTCDate()
getUTCDay()
getUTCFullYear()
getUTCHours()
getUTCMilliseconds()
getUTCMinutes()
getUTCMonth()
getUTCSeconds()
now()
parse()
prototype
setDate()
setFullYear()
setHours()
setMilliseconds()
setMinutes()
setMonth()
setSeconds()
setTime()
setUTCDate()
setUTCFullYear()
setUTCHours()
setUTCMilliseconds()
setUTCMinutes()
setUTCMonth()
setUTCSeconds()
toDateString()
toISOString()
toJSON()
toLocaleDateString()
toLocaleTimeString()
toLocaleString()
toString()
toTimeString()
toUTCString()
UTC()
valueOf()

JS Error
name
message

JS Global
decodeURI()
decodeURIComponent()
encodeURI()
encodeURIComponent()
escape()
eval()
Infinity
isFinite()
isNaN()
NaN
Number()
parseFloat()
parseInt()
String()
undefined
unescape()

JS JSON
parse()
stringify()

JS Math
abs()
acos()
acosh()
asin()
asinh()
atan()
atan2()
atanh()
cbrt()
ceil()
cos()
cosh()
E
exp()
floor()
LN2
LN10
log()
LOG2E
LOG10E
max()
min()
PI
pow()
random()
round()
sin()
sqrt()
SQRT1_2
SQRT2
tan()
tanh()
trunc()

JS Number
constructor
isFinite()
isInteger()
isNaN()
isSafeInteger()
MAX_VALUE
MIN_VALUE
NEGATIVE_INFINITY
NaN
POSITIVE_INFINITY
prototype
toExponential()
toFixed()
toLocaleString()
toPrecision()
toString()
valueOf()

JS OperatorsJS RegExp
constructor
compile()
exec()
g
global
i
ignoreCase
lastIndex
m
multiline
n+
n*
n?
n{X}
n{X,Y}
n{X,}
n$
^n
?=n
?!n
source
test()
toString()

(x|y)
.
\w
\W
\d
\D
\s
\S
\b
\B
\0
\n
\f
\r
\t
\v
\xxx
\xdd
\uxxxx

JS Statements
break
class
continue
debugger
do…while
for
for…in
for…of
function
if…else
return
switch
throw
try…catch
var
while

JS String
charAt()
charCodeAt()
concat()
constructor
endsWith()
fromCharCode()
includes()
indexOf()
lastIndexOf()
length
localeCompare()
match()
prototype
repeat()
replace()
search()
slice()
split()
startsWith()
substr()
substring()
toLocaleLowerCase()
toLocaleUpperCase()
toLowerCase()
toString()
toUpperCase()
trim()
valueOf()

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

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

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

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

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

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

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

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

Исключение:

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

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

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

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

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

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

Как испугать Java-разработчика

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

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

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

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

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

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

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

Аренда офисных площадей в Республиканском Бизнес-инкубаторе

Республиканский бизнес-инкубатор – это здание, площадью 1 582,4 кв.м., профессиональные консультанты для развития бизнеса компаний, ежегодное сопровождение до 30 предприятий, на которых создается около 170 рабочих мест. Автономное учреждение Удмуртской республики «Республиканский бизнес-инкубатор» образовано в октябре 2006 года Правительством Удмуртской Республики при поддержке Министерства экономического развития Российской Федерации. Его целью стало создание условий для развития начинающего бизнеса путем оказания льготных услуг на первоначальном этапе развития.

Арендуйте офис на льготных условиях

Предоставление помещений начинающим предпринимателям на территории бизнес-инкубаторов (г. Глазов, г. Ижевск, г. Воткинск, с. Якшур-Бодья)

Стать резидентами РБИ могут субъекты малого предпринимательства, зарегистрированные на территории Удмуртской Республики. Для попадания в РБИ им необходимо пройти конкурсный отбор

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

Стоимость аренды в бизнес-инкубаторе составляет: 

  • 1 год размещения — 257,21 руб./кв.м./ месяц; 
  • 2 год размещения – 323,67 руб./кв.м./ месяц; 
  • 3 год размещения – 456,60 руб. руб./кв.м./ месяц.

В стоимость входит: аренда помещения, оснащенного техникой, мебелью и доступом к информационным системам, индивидуальная образовательная программа (коучинг), коммунальные услуги, охрана, уборка, электричество и т.д. Дополнительно оплачиваются только интернет и телефония. 

Резидент РБИ получает:

  • доступ к материально-техническим ресурсам бизнес-инкубатора для работы над проектом: компьютеры, оргтехнику, телефонную связь, интернет.
  • бесплатный доступ к справочно-правовой системе Консультант Плюс, 1С Предприятие
  • бесплатные консультации по правовым, налоговым, финансовым и другим вопросам в построении своего бизнеса.
  • информационную поддержку по грантам, конкурсам, программам поддержки малого бизнеса на региональном и федеральном уровне.
  • в пользование переговорные комнаты для работы над проектом;
  • доступ ко всем мероприятиям (образовательные программы, тренинги, семинары, преакселератор и т.д.), проводимых на территории и при участии бизнес-инкубатора.

Метод stringify()

Метод stringify() преобразует значение JavaScript в строку JSON.

Особенности преобразования:

  • Значение , функция или значение типа , встреченные во время преобразования, будут либо опущены (если они найдены в объекте), либо превращены в (если они найдены в массиве).
  • Члены прототипа и неперечислимые свойства игнорируются.

Параметры

value
Значение, которое будет преобразовано в строку JSON.
replacer (необязательный)
Значением параметра может быть функция, массив или .

  • Массив определяет набор свойств объекта, которые будут включены в JSON-строку. В качестве значений массива указываются строки, соответствующие именам свойств преобразуемого объекта.
  • Функция позволяет заменить значения свойств объекта в JSON-строке. Функция должна содержать два параметра: имя свойства и значение свойства. Имя свойства является строкой. Функция должна возвращать новое значение свойства.
  • Если значением параметра является , то JSON-строка будет включать все свойства объекта.
space (необязательный)
Делает JSON-строку более удобочитаемой, добавляя отступы для каждого уровня вложенности. Значением параметра может быть строка или число.

  • Число указывает количество пробелов, используемых в качестве отступа для каждого уровня вложенности. Каждый последующий уровень вложенности дополняется новыми отступами. Например, если в качестве значения параметра используется число 2, то на первом уровне вложенности отступ будет составлять два пробела, на последующем уровне вложенности отступ будет составлять 4 пробела и т. д. Максимальное количество пробелов, которое можно указать – 10. Если указать большее число, оно автоматически уменьшится до 10.
  • Строка определяет символ, используемый в качестве отступа для каждого уровня вложенности. Длина строки ограничена 10 символами, если указать строку длиннее, она обрезается до 10 символов. Использование строки также позволяет использовать табуляцию («\t») в качестве отступа. Каждый последующий уровень вложенности дополняется новыми символами отступа. Например, если в качестве значения параметра указан символ (дефис), то на первом уровне вложенности в качестве отступа будет использоваться один дефис, на последующем уровне вложенности будет использоваться 2 дефиса и т. д.

Пример

let person = {
  name: "Гомэр",
  age: 40,
  work: {
    place: "Атомная станция",
    location: "Спрингфилд"
  }
}

// Пример с одним параметром
console.log(JSON.stringify(person));   // '{"name":"Гомэр","age":40,"work":{"place":"Атомная станция","location":"Спрингфилд"}}'

// Пример с двумя параметрами (массив)
console.log(JSON.stringify(person, ));   // '{"name":"Гомэр","age":40}'

// Пример с двумя параметрами (функция)
console.log(JSON.stringify(person, function (key, value) {
  switch (key) {
    case "name":
      return "Барт";
    case "age":
      return 10;
    case "work":
      return undefined;
    default:
      return value;
  }
}));   // '{"name":"Барт","age":10}'

// Пример с тремя параметрами
console.log(JSON.stringify(person, null, 2));   /* {
                                                *    "name": "Гомэр",
                                                *    "age": 40,
                                                *    "work": {
                                                *      "place": "Атомная станция",
                                                *      "location": "Спрингфилд"
                                                *    }
                                                *  } 
                                                */

Настроить: open

Синтаксис:

Этот метод – как правило, вызывается первым после создания объекта .

Задаёт основные параметры запроса:

  • – HTTP-метод. Как правило, используется GET либо POST, хотя доступны и более экзотические, вроде TRACE/DELETE/PUT и т.п.

  • – адрес запроса. Можно использовать не только http/https, но и другие протоколы, например и .

    При этом есть ограничения безопасности, называемые «Same Origin Policy»: запрос со страницы можно отправлять только на тот же , с которого она пришла. В следующих главах мы рассмотрим, как их можно обойти.

  • – если установлено в , то запрос производится синхронно, если – асинхронно.

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

«Асинхронный запрос» означает, что браузер отправит запрос, а далее результат нужно будет получить через обработчики событий, которые мы рассмотрим далее.

user, password – логин и пароль для HTTP-авторизации, если нужны.

Вызов не открывает соединение

Заметим, что вызов , в противоположность своему названию ( – англ. «открыть») не открывает соединение. Он лишь настраивает запрос, а коммуникация инициируется методом .

Пример использования

Базовый анализ строк в виде JSON

В следующем примере мы с Вами рассмотрим как с помощью глобальной функции JSON.parse() объекта JSON произвести анализ строк в формате JSON и вернуть значения, полученные в ходе анализа.

// инициализируем три переменные, содержащие строки в формате JSON
const jsonString = '{"a":true, "b":10, "c": , "d":{"d1": 1, "d2": 2, "d3": 3}}',
      jsonString2 = '',
      jsonString3 = '"test"';

// анализируем переданные строки и инициализируем переменные, полученным значением
const obj = JSON.parse(jsonString),
      obj2 = JSON.parse(jsonString2),
      obj3 = JSON.parse(jsonString3);

// выводим в консоль значения переменных
console.log(obj);
{a: true, b: 10, c: , d: {d1: 1, d2: 2, d3: 3}}

console.log(obj2);


console.log(obj3);
"test"

В этом примере мы инициализируем три переменные, которые содержат строки в формате JSON. С помощью метода JSON.parse() мы анализируем переданные строки и инициализируем переменные, полученным значением. Для демонстрации работы метода JSON.parse() выводим полученные значения в консоль.

Использование функции для преобразования JSON

В этом примере мы рассмотрим использование второго аргумента метода JSON.parse() — функции, которая позволяет преобразовать значение, полученное в ходе анализа перед его возвращением из метода:

// инициализируем переменную, содержащую строку в формате JSON
const jsonString = '{"a": 1,"b": false,"c": "3"}';

// преобразуем значение, полученное в ходе анализа таким образом, что оставляем только те свойства значения которых не являются числами
const obj = JSON.parse( jsonString, (key, val) => typeof val !== "number" ? val  undefined );
console.log(obj);
{b: false, c: "3"}

// преобразуем значение, полученное в ходе анализа таким образом, что оставляем только те свойства значения которых являются числами
const obj2 = JSON.parse( jsonString, (key, val) => typeof val === "number" || key === "" ? val  undefined );
console.log(obj2);
{a: 1}

// преобразуем значение, полученное в ходе анализа таким образом, что изменяем все числовые значения на 777
const obj3 = JSON.parse( jsonString, (key, val) => typeof val === "number" ? val = 777  val );
console.log(obj3);
{a: 777, b: false, c: "3"}

// преобразуем значение, полученное в ходе анализа таким образом, что изменяем значение свойства "b" на "deleted"
const obj4 = JSON.parse( jsonString, (key, val) => key === "b" ? val = "deleted"  val );
console.log(obj4);
{a: 1, b: "deleted", c: "3"}

В этом примере с использованием функции метода JSON.parse() (второй аргумент), предназначенной для преобразования значения, полученного в ходе анализа перед его возвращением из метода мы:

В первом случае оставляем только те свойства значения которых не являются числами.
Во втором случае оставляем только те свойства значения которых являются числами

Обратите внимание, что последний вызов функции осуществляется с пустым ключом, по этой причине мы добавляем дополнительную проверку. В описании аргумента есть пояснение этому.
В третьем случае изменяем все числовые значения на 777.
В четвертом случае изменяем значение свойства «b» на «deleted».

Глубокое копирование объекта

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

Давайте рассмотрим как с помощью методов JSON.parse() и JSON.stringify() сделать глубокую копию нашего объекта:

// инициализируем переменную, содержащую объект
let obj = {
    a: 1,
    b: {
      c: 2
    }
};

// осуществляем глубокое копирование объекта и инициализируем переменную
let newObj = JSON.parse( JSON.stringify( obj ) );
console.log( newObj );  // переменная содержит значение { a: 1, b: { c: 2} }

obj.b.c = 200;          // изменяем значение свойства объекта obj
console.log( obj );     // переменная содержит значение { a: 1, b: { c: 200} }
console.log( newObj );  // переменная содержит значение { a: 1, b: { c: 2} } 

В этом примере с использованием метода JSON.stringify() мы преобразовали значение переменной obj в строку JSON, а с помощью метода JSON.parse() анализируем эту строку и возвращаем новый объект, соответствующий переданной строке. В результате чего, свойства, значением которых является объект имеют собственные значения, а не ссылаются на первоначальный объект. Благодаря этим преобразованиям мы получаем новый объект, который является действительно полноценной копией оригинала.

JavaScript JSON

Аренда производственных площадей и производственно-офисных помещений в индустриальном парке «Развитие»

Индустриальный парк «Развитие» – это готовые площадки для промышленных предприятий и складские помещения. Резиденты получают:

  • площадь любого размера в удобном, современном и экономичном комплексе класса «А»;
  • газовое отопление, электроэнергию, водоснабжение и водоотведение;
  • охраняемую и освещённую территорию;
  • удобные подъезды для транспорта;
  • согласованные юридические условия для предпринимательской деятельности;
  • лёгкий выезд на федеральную трассу.

Льготные арендные ставки предоставляются для резидентов:

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

Объекты находятся по адресам:

  • Дерябина, 3/36 (Бизнес-центр «Развитие»);
  • Дерябина, 4 (производственные площади);
  • Дерябина, 2/65 (1 и 5-ти этажные корпуса производственно-офисных помещений);
  • Новоажимова, 27 (производственные, складские и торговые площади);
  • Воткинское шоссе, 298 (производственные и складские площади);
  • К. Маркса, 23а (офисные площади).

Oktalzahlen mit führender Null[Bearbeiten]

Besonders im Bereich der Datumsberechnung werden häufig Zahlen mit führender Null benutzt. Einfache Aufgaben wie liefern dann scheinbar falsche Ergebnisse oder gar Fehlermeldungen.

Des Rätsels Lösung dafür ist, dass JavaScript Zahlen mit führender 0 als Oktalzahlen interpretiert, nicht als Dezimalzahlen. Die Notation von Oktalzahlen mit einer führenden Null ist eine in vielen Programmiersprachen verbreitete Konvention, die ursprünglich von C kommt.

Mit einer Anweisung wie können Sie das Problem vermeiden und erzwingen, dass der Wert dezimal interpretiert wird.

Empfehlung: Verwenden Sie den strict mode, um die Interpretation als Oktalzahlen auszuschließen.

Пример использования

Number.parseInt( "1" );          // Метод возвращает 1
Number.parseInt( "    1" );      // Метод возвращает 1
Number.parseInt( "    1    " );  // Метод возвращает 1
Number.parseInt( "1.23abc" );    // Метод возвращает 1
Number.parseInt( "1.23" );       // Метод возвращает 1
Number.parseInt( "123e-3" );     // Метод возвращает 123
Number.parseInt( "0.0123E+3" );  // Метод возвращает 0
Number.parseInt( "0xAA" );       // Метод возвращает 170
Number.parseInt( "N", 32 );      // Метод возвращает 23
Number.parseInt( "A", 16 );      // Метод возвращает 10
Number.parseInt( "F", 16 );      // Метод возвращает 15

Number.parseInt( "123FA", 10 );  // Метод возвращает 123
Number.parseInt( "123FA", 16 );  // Метод возвращает 74746

Number.parseInt( "A" );          // Метод возвращает NaN
Number.parseInt( Infinity );     // Метод возвращает NaN
Number.parseInt( -Infinity );    // Метод возвращает NaN
Number.parseInt( "abc1.23abc" ); // Метод возвращает NaN
Number.parseInt( "abc1.23" );    // Метод возвращает NaN
Number.parseInt( undefined );    // Метод возвращает NaN
Number.parseInt( true );         // Метод возвращает NaN
Number.parseInt( null );         // Метод возвращает NaN
Number.parseInt( [] );           // Метод возвращает NaN
Number.parseInt( {} );           // Метод возвращает NaN
Number.parseInt( "" );           // Метод возвращает NaN
Number.parseInt( " " );          // Метод возвращает NaN

JavaScript Number

Основание системы счисления

Когда мы считаем от нуля до девяти, мы используем разные символы для каждого из чисел (0-9). Однако, как только мы достигаем десяти, нам нужны два разных символа (1 и 0) для представления числа. Это связано с тем, что мы используем десятичную систему счисления.

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

Например, цифры 11 обозначают разные числа в этих трёх системах счисления. Для двоичной — это число 3. Для шестнадцатеричной — это число 17.

Внимательный читатель вероятно заметил что код с parseInt возвращает 3, когда вход равен 11, что соответствует двоичному столбцу из таблицы выше.

Итого

Существует 3 наиболее широко используемых преобразований: строковое, численное и логическое.

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

– Происходит в математических операциях. Может быть вызвано с помощью .

Преобразование подчиняется правилам:

Значение Становится…
Пробельные символы по краям обрезаются. Далее, если остаётся пустая строка, то , иначе из непустой строки «считывается» число. При ошибке результат .

– Происходит в логических операторах. Может быть вызвано с помощью .

Подчиняется правилам:

Значение Становится…
, , , ,
любое другое значение

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

  • при численном преобразовании становится , не .
  • и строки из одних пробелов типа при логическом преобразовании всегда .

В этой главе мы не говорили об объектах. Мы вернёмся к ним позже, в главе Преобразование объектов в примитивы, посвящённой только объектам, сразу после того, как узнаем больше про основы JavaScript.

Итого

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

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

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

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

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

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

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

Ссылка на основную публикацию