Почему Kotlin / JS возвращает разные результаты для === чем Kotlin / JVM? - PullRequest
3 голосов
/ 01 июля 2019

С учетом этого кода:

val value = "something"

println(value.toUpperCase().toLowerCase() == value)   // prints true
println(value.toUpperCase().toLowerCase() === value)  // prints false

На Kotlin / JVM 1.3.40 я получаю:

true
false

На Kotlin / JS 1.3.40 я получаю:

true
true

Я ожидал бы одинаковых результатов на обоих, и я ожидал бы результатов Kotlin / JVM в целом (так как у меня должны быть разные String объекты).

Почему я получаю разные результаты на основев среде выполнения?

Ответы [ 2 ]

3 голосов
/ 01 июля 2019

Это из-за того, как среда выполнения это обрабатывает.

В JVM == отображается на equals, а === отображается на == (проверка личности), как указано здесь . Между тем, операторы JavaScript равные страннее . Если вы декомпилируете свой код, вы получите это с помощью JS:

kotlin.kotlin.io.output.flush();
if (typeof kotlin === 'undefined') { 
    throw new Error("Error loading module 'moduleId'. Its dependency 'kotlin' was not found. Please, check whether 'kotlin' is loaded prior to 'moduleId'."); 
}
var moduleId = function (_, Kotlin) { 
    'use strict'; 
    var equals = Kotlin.equals; 
    var println = Kotlin.kotlin.io.println_s8jyv4$; 
    function main(args) { 
        var value = 'something';
        println(equals(value.toUpperCase().toLowerCase(), value)); // NOTE: equals
        println(value.toUpperCase().toLowerCase() === value);      // NOTE: ===
    } 
    _.main_kand9s$ = main; 
    main([]); 
    Kotlin.defineModule('moduleId', _); 
    return _; 
}(typeof moduleId === 'undefined' ? {} : moduleId, kotlin); 
kotlin.kotlin.io.output.buffer;

Теперь, если вы рассматриваете эквивалентный Java-код (слегка укороченный и без Kotlin):

public static void main(String []args){
    String value = "something";

    System.out.println(value.toUpperCase().toLowerCase().equals(value));
    System.out.println(value.toUpperCase().toLowerCase() == value);
}

toUpperCase().toLowerCase() создает новый объект, который нарушает сравнение ==, которое является проверкой личности .

Хотя === также обозначается как проверка идентичности, a === b имеет значение true, если a и b - строки, содержащие одинаковые символы . Как видно из декомпилированного кода Kotlin, Kotlin.JS компилируется в примитивные строки, а не в объекты String. Из-за этого === в JS вернет true, когда вы имеете дело с примитивными строками.

1 голос
/ 01 июля 2019

В JavaScript есть как примитивные строки, так и строковые объекты (см., Например, «Различие между строковыми примитивами и строковыми объектами» в https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String).

value.toUpperCase().toLowerCase() === value в Kotlin / JS компилируется в value.toUpperCase().toLowerCase() === value в JavaScript (как вы можете убедиться, посмотрев вкладку «Сгенерированный код JavaScript» на https://try.kotlinlang.org/). value.toUpperCase().toLowerCase(), возвращает примитивную строку. === на примитивных строках есть нормальное равенство.

...