Имеют ли какие-нибудь технические различия следующие два метода задания строчных переменных в 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
этот пункт частичный перевод ответа на английский вопрос
Комментариев нет:
Отправить комментарий