Wynik wyrażenia 1 + "1"

0

Wynikiem wyrażenia 1 + "1" jest "11" w stringu. Chciałbym spytać czy dzieję się tak dlatego, że aplikacja chce tu wykonać dodawanie stringów i dlatego typ number konwertuje na typ string?

8

tak

2

Warto dodać, że taki wynik jest jedynie przy dodawaniu, ponieważ istnieje możliwość łączenia stringów

console.log("lorem" + " " + "ipsum"); // lorem ipsum
console.log(1 + "1"); // "11"

ale nie ma mnożenia lub odejmowania i tutaj JavaScript prawidłowo zamienia typ string na number :P

console.log("5" * 2); // 10
console.log("8" / "4"); // 2
4
Xarviel napisał(a):

ale nie ma mnożenia lub odejmowania i tutaj JavaScript prawidłowo zamienia typ string na number :P

console.log("5" * 2); // 10
console.log("8" / "4"); // 2

"Prawidłowo" to duże nadużycie w tym przypadku. Prawidłowo to powinno się wywalić.

1

Tak narzekacie na php, a w nim "2" + 2 = 4 xD

0

To się nazywa "type coercion" i jest opisane np tu https://www.freecodecamp.org/news/js-type-coercion-explained-27ba3d9a2839/
Dlaczego liczba się skonwertowała na stringa a nie string na liczbę? Bo ta zamiana się zawsze uda, a zamiana stringa na liczbę niekoniecznie. Kompilator (/parser) nie robi dodatkowych analiz wartości przed konwersją tylko kieruje się prostą listą priorytetów. Gdyby zamieniał w tym przypadku stringa na liczbę to kod typu 'Mam ' + wiek + ' lat' lub ile + ' lat temu' produkowałby NaN.

Trzeba pamiętać że javascript zaczynał jako prosty język wspomagający działanie z formularzami na stronie. Wartości z formularza zawsze były stringami a javascript miał być prostym językiem pozwalającym na przykład na pomnożenie wartości z dwóch inputów i wyświetlenie w trzecim. Gdyby były tu wymagane ciągłe konwersje string -> number -> string to język już nie byłby taki prosty.

Jeśli chcesz zamienić stringa na liczbę daj plusa przed stringiem 1 + (+"1") lub 1 + Number('1').

Najlepiej używaj typescript zamiast javascript, zainstaluj eslint, włącz wszystkie strict checki i będziesz miał błędy kompilacji (transpilacji) przy tego rodzaju zagrywkach.

0
sajek587 napisał(a):

Wynikiem wyrażenia 1 + "1" jest "11" w stringu. Chciałbym spytać czy dzieję się tak dlatego, że aplikacja chce tu wykonać dodawanie stringów i dlatego typ number konwertuje na typ string?

JavaScript jest językiem słabo-typowanym i dynamicznie typowanym. Opisane jest to lepiej tutaj:

W mojej opinii, w rozwoju języków programowania istnieje pewne wahanie. Co pewien okres czasu "moda" w językach programowania podchodzi blisko statycznych typów, ludzie się nimi męczą (ciężej się w nich programuje), i potem wahadło leci w stronę słabych typów, ale te aplikacje z reguły są mniej bezpieczne, więc potem wahadło znów jedzie w stronę silniejszych typów, i tak w kółko. Są oczywiście kompromisy i podziały, ale ogólna tendencja jest raczej "wahadłowa".

Ja osobiście lubię silnie typowane (ale nie koniecznie statycznie typowane) języki, bo podobnie jak @Saalin uważam że w każdym sensownym języku, wyrażenie 1 + "1" powinno się wywalić. Niestety JavaScript powstawał w latach ~1995, i wtedy może to uchodziło za "usprawnienie"/"przyspieszenie". Przyspiesza pracę, owszem - ale przyspiesza powstawanie bugów, also owszem.

0

Wbij sobie do głowy @sajek587, że JS wykonuje wyrażenia analogicznie jak poniżej:

screenshot-20230127151854.png

🤣

0
Riddle napisał(a):

W mojej opinii, w rozwoju języków programowania istnieje pewne wahanie. Co pewien okres czasu "moda" w językach programowania podchodzi blisko statycznych typów, ludzie się nimi męczą (ciężej się w nich programuje), i potem wahadło leci w stronę słabych typów, ale te aplikacje z reguły są mniej bezpieczne, więc potem wahadło znów jedzie w stronę silniejszych typów, i tak w kółko. Są oczywiście kompromisy i podziały, ale ogólna tendencja jest raczej "wahadłowa".

Niby tak, ale jednak w nowoczesnych językach statycznie typowanych standardem jest inferencja typów, co sprawia, że statyczne typowanie nie jest aż tak męczące, bo większość zmiennych sama się wypełnia typem. Kiedyś zdaje się inferencja typów nie była aż tak powszechna.

Jednak ze statycznym typowaniem problem (rozumiany jako problem z "developer experience") pojawia się myślę nie wtedy, kiedy trzeba podać samą nazwę typu np. foo: Foo, tylko wtedy, kiedy deklaracja typu staje się strasznie złożona, zagnieżdżona, najeżona generykami, rozmaitymi adnotacjami itp.

Języki dynamiczne nie muszą się tym przejmować. Np. w JS każdy element tablicy może zawierać inny typ danych:

const arr = [10, "kotek", {name: "John"}]

w Rust już potrzebowałbym jakiegoś enuma.

Jednak zaletą języków silnych i statycznie typowanych jest to, że edytory są sprytne i dobrze podpowiadają. No i że nie trzeba robić tyle asercji typów w runtime (bo w słabo typowanych dynamicznych językach funkcja może dostać wszystko jako argument i trzeba sprawdzać często, co tak naprawdę funkcja dostała, robić dynamiczne sprawdzanie typu)

Niestety JavaScript powstawał w latach ~1995, i wtedy może to uchodziło za "usprawnienie"/"przyspieszenie".

Bo nikt się nie spodziewał, że będzie się pisać poważne programy w JS.

1
LukeJL napisał(a):
Riddle napisał(a):

W mojej opinii, w rozwoju języków programowania istnieje pewne wahanie. Co pewien okres czasu "moda" w językach programowania podchodzi blisko statycznych typów, ludzie się nimi męczą (ciężej się w nich programuje), i potem wahadło leci w stronę słabych typów, ale te aplikacje z reguły są mniej bezpieczne, więc potem wahadło znów jedzie w stronę silniejszych typów, i tak w kółko. Są oczywiście kompromisy i podziały, ale ogólna tendencja jest raczej "wahadłowa".

Niby tak, ale jednak w nowoczesnych językach statycznie typowanych standardem jest inferencja typów, co sprawia, że statyczne typowanie nie jest aż tak męczące, bo większość zmiennych sama się wypełnia typem. Kiedyś zdaje się inferencja typów nie była aż tak powszechna.

Jednak ze statycznym typowaniem problem (rozumiany jako problem z "developer experience") pojawia się myślę nie wtedy, kiedy trzeba podać samą nazwę typu np. foo: Foo, tylko wtedy, kiedy deklaracja typu staje się strasznie złożona, zagnieżdżona, najeżona generykami, rozmaitymi adnotacjami itp.

Języki dynamiczne nie muszą się tym przejmować. Np. w JS każdy element tablicy może zawierać inny typ danych:

const arr = [10, "kotek", {name: "John"}]

w Rust już potrzebowałbym jakiegoś enuma.

Jednak zaletą języków silnych i statycznie typowanych jest to, że edytory są sprytne i dobrze podpowiadają. No i że nie trzeba robić tyle asercji typów w runtime (bo w słabo typowanych dynamicznych językach funkcja może dostać wszystko jako argument i trzeba sprawdzać często, co tak naprawdę funkcja dostała, robić dynamiczne sprawdzanie typu)

No tak, opisałeś w zasadzie wady i zalety statycznego i dynamicznego typowania. Jeśli znasz strukturę map i obiektów, to jeszcze można sobie z tym radzić, ale jak dostajesz JSON'a z nie wiadomo kąd, i masz go sparsować, to dynamicznie typowane języki są do tego dużo lepsze ("lepsze", mam na myśli żę szybciej można zakodzić pierwszą wersję). I właśnie z tego wnioskuję że jest taki moment wahania. To są takie targi, czy bardziej wolimy szybkość developowania, czy stabilność aplikacji, to z kolei przekłada się na trendy, a trendy dyktują kolejne projekty; do momentu kiedy wchodzi jakaś rewolucja, ludzie są zmęczeni jednym z podejśc, więc tworzą rewolucyjną biblioteke/framework który jest bardziej/mniej statyczny/dynamiczny, i on teraz wytacza nowe trendy, i mamy wahadło.

Końcem wahadała byłby język który ma "just the right amount" of static and dynamic typing. Nie wiem czy to jest w ogóle osiągalne, możliwe że nie.

0
LukeJL napisał(a):

Jednak zaletą języków silnych i statycznie typowanych jest to, że edytory są sprytne i dobrze podpowiadają.

Może jeszcze uzupełnię swoją wypowiedź, że nie chodzi tylko o edytory, ale też o weryfikację, czy dany kod się w ogóle skompiluje. I że dobry silny system typów może uchronić przed pewnymi błędami zanim w ogóle odpalimy program. Np. Rust potrafi zapobiec temu, żeby dana zmienna/obiekt była modyfikowana w różnych miejscach naraz (a jak wiadomo mutowalny współdzielony stan to źródło wszelkiego zła), bo żeby zmutować zmienną, to trzeba ją jawnie oznaczyć jako mut i jak przekazujesz referencje do takiej zmiennej, to kompilator pilnuje, żeby nie istniała więcej niż jedna mutowalna referencja naraz. I tak powinno być, jak chce się pisać przewidywalne programy, które działają i nie robią kuku (chociaż to utrudnia prototypowanie i ogólnie sprawia, że jest wyższy poziom wejścia).

0
LukeJL napisał(a):
LukeJL napisał(a):

Jednak zaletą języków silnych i statycznie typowanych jest to, że edytory są sprytne i dobrze podpowiadają.

Może jeszcze uzupełnię swoją wypowiedź, że nie chodzi tylko o edytory, ale też o weryfikację, czy dany kod się w ogóle skompiluje. I że dobry silny system typów może uchronić przed pewnymi błędami zanim w ogóle odpalimy program.

Dlatego po chwili pisania w typescript nie wyobrażam sobie pisania w surowym javascript. Typescript setki razy już mnie uchronił przed pomyłką dzięki pilnowaniu typów i umożliwia bezpieczny refaktoring, zmianę nazw itp. Tworzenie większej aplikacji w javascript to jak bieganie z nożyczkami.
Typescript to świetny kompromis między światem silnie i słabo typowanym, w każdej chwili można pominąć typowanie lub siłą uznać jeden typ za inny i aż mnie zszokował jak bardzo jest rozwinięty. Do tego stopnia że typy generyczne mogą w typescript mieć instrukcje warunkowe, a nawet dzielić stringa i wyłuskać typ z zagnieżdżonego obiektu. Można na przykład napisać funkcję która przyjmuje stringa ze ścieżką do property np "a.objects.first.name" i zwróci poprawny typ zależny od przekazanego stringa a wszystko będzie sprawdzone na etapie kompilacji (transpilacji) a edytor będzie jeszcze podpowiadał podczas pisania tego stringa jakie są dostępne wartości.

1 użytkowników online, w tym zalogowanych: 0, gości: 1