Страницы

Поиск по вопросам

вторник, 9 июля 2019 г.

JavaScritpt: разница в методах задания строчных переменных

Имеют ли какие-нибудь технические различия следующие два метода задания строчных переменных в JavaScrpit?
// 1 var s1= "JavaScript"; // 2 var s2 = new String("JavaScript");


Ответ

Начать можно с MDN
Различие между примитивами строк и объектами строк Важно: в Javascript присутствуют различия между объектами строк и примитивами (Это верно и для Boolean, и Number) Литералы строк (обозначаяются двойными или одинарными кавычками) и строки возвращенный вызвом String в не-конструкторском контексте (т.е. без ключевого слова new) - примитивы строк. Javascript автоматически конвертирует примитивы в объекты String, поэтому возможно использовать методы объекта String для примитивов строк. В ситуациях, когда для примитива строки нужно вызвать метод или найти свойство, Javascript автоматически обернет примитив в объект и вызовет нужный метод или свойство.
var s_prim = 'foo'; var s_obj = new String(s_prim); console.log(typeof s_prim); // Logs "string" console.log(typeof s_obj); // Logs "object"
Примитивы строк и объекты строк, имеют различие при использовании eval(). Примитивы переданные в eval будут обработаны как исходный код; Объекты строк будут обработаны как и все другие объекты, возвращением самого себя, например:
var s1 = '2 + 2'; // creates a string primitive var s2 = new String('2 + 2'); // creates a String object console.log(eval(s1)); // returns the number 4 console.log(eval(s2), s2 === eval(s2)); // returns the string "2 + 2"
Поэтому код может сломаться, если получит на вход объект String, вместо ожидаемого примитива строка, однако, обычно не нужно беспокоиться о различиях.
у строки-объекта всегда можно получить соответствующий ей примитив, с помощью вызова метода valueOf
Кроме того: литералы неизменяемы, поэтому, в отличие от объектов им нельзя добавить новых свойств, а так же их сравнение происходит как сравнение объектов
var primitive_s = '123'; var primitive_s2 = '123' var s1 = new String('123'); var s2 = new String('123'); primitive_s.prop = 10; console.log('primitive_s.prop', primitive_s.prop); s1.prop = 10; console.log('s1.prop', s1.prop); console.log(primitive_s == primitive_s2, primitive_s === primitive_s2); console.log(s1 == s2, s1 === s2); // но! console.log(primitive_s == s1, primitive_s === s2);
примеры на основе ответов: первый, второй

С точки зрения спецификации
При получении значения свойства, в случае примитивного объекта вызывается абстрактная функция ToObject. У результата вызывается нужное свойство с нужным this.

С точки зрения реализации.
Спецификация никак не ограничивает как должны быть реализованы примитивы и объекты. А так же не регламентирует наличие/отсутствие свойств у примитивов.
Например, для V8
Строковые примитивы разбираются в объект класса v8::String. Следовательно методы могут быть вызваны напрямую у этого объекта.
Строки-объекты, в свою очередь, разбираются в объекты класса v8::StringObject, который расширяет класс Object и будучи полноценным объектом служит оболочкой для v8::String
этот пункт частичный перевод ответа на английский вопрос

Комментариев нет:

Отправить комментарий