Как работает равенство строк в JavaScript?
Есть много учебных пособий для ==
и ===
, поэтому, пожалуйста, не направляйте меня в основной учебник, мой вопрос немного конкретнее:
Например http://www.w3schools.com/jsref/jsref_obj_string.asp заявляет, что:
Синтаксис:
var txt = new String("string");
// or more simply:
var txt = "string";
Хорошо, но как насчет этого?
alert(new String("a") == new String("a")); // false
alert("a" == "a"); // true
var a = new String("a");
var b = new String("a");
alert(a == b); // false
var c = "a";
var d = "a";
alert(c == d); // true
alert(c === d); // true
alert (a === c); // false
Конечно, в любом случае никто не звонит new String()
, но разве это что-то значит о неудаче равенства, потому что new String()
обрабатывается как объект не как строка?
И, конечно же, W3Schools - не самый надежный источник, но я бы ожидал, что все вышеупомянутые предупреждения скажут правду.
Пожалуйста, объясните.
Ответы
Ответ 1
"Удивительные результаты" исходят из того, как Javascript обрабатывает равенство для объектов, а также путаницу, возникающую между строковыми литералами и объектами String. В справочном руководстве Mozilla для оператора ==
:
Если два операнда не одного типа, JavaScript преобразует операнды затем применяют строгое сравнение. Если либо операнд - это число или логическое значение, операнды, если возможно, преобразуются в числа; еще если любой операнд является строкой, другой операнд преобразуется в если возможно. Если оба операнда являются объектами, то JavaScript сравнивает внутренние ссылки, которые равны, когда операнды ссылаются на тот же объект в памяти.
Вы можете испытать такое же поведение с числами:
new Number(5) == new Number(5) // false
И проясните свой ум:
typeof "string" // string
typeof new String("string") // object
Ответ 2
Строковые литералы, которые являются примитивными типами значений, отличаются от новых объектов String
, которые представляют собой сущности с различными ссылками, обертывающие эти значения. Подробнее см. Предопределенные основные объекты в документах JavaScript Mozilla.
Итак, вы правы в том, что сравнение обрабатывается по-разному для литералов и для объектов, просто потому, что они сравнивают их значения, а другие сравнивают ссылки.
Ответ 3
Вы правы, что в вашем примере вы сравниваете две разные ссылки на объекты. В пределах спецификации языка вы найдете этот алгоритм. Часть, которую вы ищете, - это раздел 1 f.
11.9.3 Алгоритм сравнения абстрактного равенства
11.9.3 The Abstract Equality Comparison Algorithm
The comparison x == y, where x and y are values, produces true or false. Such a comparison is performed as
follows:
1. If Type(x) is the same as Type(y), then
a. If Type(x) is Undefined, return true.
b. If Type(x) is Null, return true.
c. If Type(x) is Number, then
i. If x is NaN, return false.
ii. If y is NaN, return false.
iii. If x is the same Number value as y, return true.
iv. If x is +0 and y is -0, return true.
v. If x is -0 and y is +0, return true.
vi. Return false.
d. If Type(x) is String, then return true if x and y are exactly the same sequence of characters (same
length and same characters in corresponding positions). Otherwise, return false.
e. If Type(x) is Boolean, return true if x and y are both true or both false. Otherwise, return false.
f. Return true if x and y refer to the same object. Otherwise, return false.
2. If x is null and y is undefined, return true.
3. If x is undefined and y is null, return true.
4. If Type(x) is Number and Type(y) is String,
return the result of the comparison x == ToNumber(y).
5. If Type(x) is String and Type(y) is Number,
return the result of the comparison ToNumber(x) == y.
6. If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.
7. If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
8. If Type(x) is either String or Number and Type(y) is Object,
return the result of the comparison x == ToPrimitive(y).
9. If Type(x) is Object and Type(y) is either String or Number,
return the result of the comparison ToPrimitive(x) == y.
10. Return false.
Также обратите внимание, что шаги 8 и 9, которые упрощают работу с объектами String.
alert(new String("a") == "a"); // true
alert("a" == new String("a")); // true