Skip to content
От: Божидар Маринов Дата: Последна промяна:

Урок 0, Стойности и типове в JavaScript

Допълнителни линкове към този урок:

Основни точки от този урок

В JavaScript, стойности ("values") са нещата, с които може да "оперираме", нещата, които нашия код може да използва. Всяка стойност може да бъде записана в променлива.

Пример за стойност би било числото 100. Знаем, че 100 е стойност, тъй като можем да запишем 100 в някоя променлива и след това да го прочетем. Например:

let x = 100        // Записваме стойност в променлива
rect(x, 0, 50, 50) // Прочитаме същата стойност от променливата

Не всичко е стойност. Някои неща са изрази ("expressions"); един израз обяснява какво правим с някоя стойност и резултата от израза е стойност, но сам по себе си, израза не е стойност. Онагледено с пример, може да видим как x + 10 е израз а не стойност, тъй като, самия израз не е това, което записваме в променливата:

let x = 100          // Записваме стойност в променлива
let x10 = x + 10     // Отново записваме стойност в променлива
x = 0                // Променяме стойност в `x`
rect(x10, 0, 50, 50) // Прочитаме записаната стойност от `x10`
                     // Тъй като в `b` е записана стойността 110,
                     //  а не израза (a+10), правоъгълника се изрисува
                     //  на координати (115, 0) а не (10, 0)

Типове стойности

Стойностите се делят на типове

Типа стойности, с който сме най-запознати до сега, е типа число ("number"). В уроците да сега, почти всички стойности които съхранявахме в променливи бяха от този тип. С една числова стойност, операциите, които може да извършваме включват събиране, изваждане, умножение, деление, и прочие.

let x = 100
let x10 = x + 10  // число + число == число

Друг тип стойности, които сме използвали, са стойностите от булев тип ("boolean"). Има само две стойности от този тип: true (истина) и false (неистина). Тези стойности получаваме когато сравним две стойности или когато комбинираме две булеви стойности с логическите операции И (&&), ИЛИ (||) и НЕ (!).

let b = true      // Стойност от булев тип
let c = (x < 200) // Резултата от сравнението се съхранява в променливата като true или false
x = 250           // Без значение дали променяме променливата от израза (x < 200), стойността на c не се променя
if (c) {          // Накрая, може да използваме булевата променлива директно в някой `if`
}

Трети вид стойности са текстовите стойности, или стойностите от тип низ ("string"). Тези стойности се записват в кавички (например "Hi!") и представляват някакъв текст или дума, която може да изпишем на екрана. Има много операции, които може да се правят с текст и които ще разгледаме в следващите уроци, но засега, най-простата операция, която може да правим с текст е това да слеем или залепим два текста—което в JavaScript се извърша със събиране. Така например, ако изпълним израза "a" + "b", ще видим че това произвежда стойността "ab" като резултат.

text("Hi!", 50, 50)        // Изрисуване на текст на екрана
let s = "Hi!"              // Стойност от тип низ
text(s + "There!", 50, 50) // Сливане на два текста ("Hi!There!")
text(s + x, 50, 50)        // Сливане на текст и число ("Hi!100")

Четвърти вид стойности, с които сме работили до сега са стойностите от тип функция ("function"). Това може да е леко учудващо, но е изключително полезно, както ще видим в следващите уроци. Една операция която може да правим с функции е да ги извикаме. В следващия пример, може да видите как една функция бива съхранена в променлива.

let f = rect        // Тъй като няма скоби (`(` и `)`) след rect, то само взимаме стойността на функцията, а не я извикваме
f(100, 100, 50, 50) // А тук, вече извикваме функцията записана в f, която в случая е rect
if (c) {
  f = ellipse       // Променяме стойността на променливата
}
f(100, 200, 50, 50) // А тук, ако `c` е вярно, ще нарисуваме елипса, а иначе ще нарисуваме правоъгълник; зависи от стойността на f

Пети тип стойности, е типа на недефинирана стойност ("undefined"). Тази стойност е специална, тъй като е стойността по подразбиране на всяка променлива на която не сме дали стойност. От този тип има само една стойност, undefined, и единствената операция, която може да правим с нея е да я сравняваме:

let u                 // Променливата u няма начална стойност, така че стойността ѝ е undefined
if (u == undefined) { // Тази стойност, може да проверим със сравняване*
  rect(200, 100, 50, 50)
}
// (* забележка: обикновено се използва едно по-специално сравнение за тази проверка, с ===; за това ще стане въпрос малко по-късно)
function example(a) {
}
example() // тъй като не задаваме стойност за параметъра `a`, то той взема стойността undefined

Проверка на типа на стойност

Може да проверим типа на една стойност като използваме специалната дума typeof. Тя ни връща стойност от тип низ, която описва типа на стойността която сме подали. Така например:

let x = 100    // 100 e стойност от тип число
typeof x       // -> "number" - число
typeof 100     // -> "number" - число
typeof x + 10  // -> "number" - число
typeof x < 100 // -> "boolean" - булева стойност

if (typeof x == "number") {
  // изпълнява се само ако x е число
}

Стойности от тип обект

В следващите уроци, ще разгледаме повече за стойностите от тип "обект" ("object"), като например:

typeof {} // "object"
typeof [] // "object"

Таблица на типовете стойности

В следната таблица ще намерите различните типове стойности и операциите, които можем да правим с тях:

Тип Резултат от typeof Примерни стойности Операции, които може да използваме
(всички) Сравнения: ==, !=, >, <, >=, <=
Число "number" 1, 20, 3.14, NaN, ... Аритметични операции: +, -, *, /, ...
Булев "boolean" true, false -=
Низ/текст "string" 'а', "Hello World!",
"Кавичка: \" " , "Две \n линии.", ...
Сливане: +, ...
Функция "function" function x(a,b,c) { ... }, ... Извикване на функцията: x(1,2,3)
Без стойност "undefined" undefined -=
Обект "object" {}, [], ... x.y и x[y], ще ги разгледаме в следващите уроци

Забележка: В JavaScript, за разлика от някои други програмни езици, стойностите имат тип, но променливите нямат. По тази причина, в JavaScript имаме право да запишем стойност от тип низ в променлива, в която до сега е имало стойност от тип число — но в много други програмни езици, самия език ни ограничава да не можем да правим това. Дали това е от полза за нас като програмисти, или е само уловка, която да ни изненада, е дискусия за друг път, но е добре да го имаме предвид когато пишем код използващ стойности от различни типове.

Задача (по желание)

Мисленето за различните типове стойности е често-срещана тема, когато се говори за измислянето на нови програмни езици. Връщайки се на примера за правене на палачинки от по-рано, помислете за това какви типове стойности би имал един измислен (наш си) програмен език за описване на рецепти.

За по-лесно измисляне, може да използвате този списък от въпроси:

Обикновено, типовете в един програмен език образуват някакъв вид "дърво" или йерархична структура. Например, в някои езици има отделни типове за "цяло число" и "число с десетична/плаваща запетая", но и двата типа са част от по-големия тип "число". Така че, не е проблем, ако някои от операциите, които сте измислили, приемат неща от няколко различи типа.

Упражнения

Следните упражнения може да помогнат да затвърдите разбирането си за различни типове стойности. Вижте дали може да отговорите правилно – но ако да объркате, няма проблем; някои от упражненията са леко подвеждащи, с цел да ви помогнат да намирате подобни грешки, когато вие самите пишете код.

Какви са типовете на тези стойности/изрази?

  1. 25

    Отговор:

    Число, "number".

  2. 34 * 10 - 15 * 3

    Отговор:

    Число, "number".

  3. 34 * 5 < 10 * 13

    Отговор:

    Булева стойност (true/false), "boolean".

  4. x < 10 && y > 10

    Отговор:

    Булева стойност (true/false), "boolean".

  5. "Здрасти"

    Отговор:

    Низ/текст, "string".

  6. "102"

    Отговор:

    Низ/текст, "string".

  7. "Здрасти" + "!"

    Отговор:

    Низ/текст, "string".

  8. "102" + 50

    Отговор:

    Низ/текст, "string".
    В случая, стойността на израза е "10250", тъй като 50 бива преобразувано до низ преди да се слее с първия низ.

  9. "102" * 2

    Отговор:

    Число, "number"! (Това не беше част от урока 😉)
    В случая, стойността на израза е 204, тъй като операцията * винаги преобразува стойностите, които ѝ подаваме, до числови стойности.

  10. rect

    Отговор:

    Функция, "function". (Ако използваме p5.js; иначе може и да е променлива със стойност от друг тип.)

  11. rect(0, 0, 10, 10)

    Отговор:

    Недефинирана, "undefined". (Ако използваме p5.js.)
    Не всички функции произвеждат резултат undefined. Ако функцията завърши със return (стойност), то тази стойност става резултат от изпълнението на функцията—нещо, за което ще се говори в следващ урок. Ако погледнем документацията за rect, може да видим, че никъде не се споменава функцията да връща ("returns") нещо. Следователно, резултата е undefined.

  12. random(0, 100)

    Отговор:

    Число, "number". (Ако използваме p5.js.) Ако погледнем документацията за random, може да видим, че най-отдолу пише "Returns: Number" – така знаем, че функцията произвежда число. (Виж също бележката за горното упражнение.)

  13. function name() { return "Име" }
    
    name
    Отговор:

    Функция, "function". Ако на последния ред, след name имаше скоби, name(), то резултата би бил от тип низ, "string". Но тъй като не изпълняваме функцията, резултата е от тип "function".

  14. let x
    if (2 > 100) {
      x = 3
    }
    
    x
    Отговор:

    Недефинирана, "undefined".
    Ако условието беше написано "на обратно" като 2 < 100, то стойността на x би била от тип число, "number".

  15. typeof 13
    Отговор:

    Низ, "string".
    стойността на израза typeof 13 е "number" — но типа на тази стойност (на "number") е низ, "string.

Какви типове бихте могли да използвате за да опишете...

  1. С какъв тип данни може да опишем мястото на играча на екрана, ако играча може да се движи само наляво/надясно?

    Отговор:

    Число, "number".

  2. С какъв тип данни може да опишем името на играча, което той е въвел преди да започне играта?

    Отговор:

    Низ (текст), "string".

  3. С какъв тип данни може да опишем дали противника се движи в момента нагоре или надолу?

    Отговор:

    Имаме няколко опции:

    • Булева стойност, "boolean" — определяме едната посока (например надолу) като true а другата остава false.
    • Число, "number" — използваме подобно на "скорост" или "посока", така че +1 да е в посока увеличаване на Y (надолу), а -1 да е в посока намаляване на Y (нагоре). Така може да напишем нещо подобно на позиция += скорост.
    • Низ (текст), "string" — използваме например стойностите "up" и "down" за двете посоки.
    • (Вероятно обекти или дори функции биха били опция също, но тези трите са по-стандартни.)
  4. С какъв тип данни може да опишем дали бутона е бил натиснат в предишния кадър?

    Отговор:

    Булева стойност (true/false), "boolean".

  5. С какъв тип данни може да опишем кой екран би трябвало да се покаже, измежду няколко опции, например "главно меню", "в игра", "настройки"?

    Отговор:

    Отново имаме няколко опции:

    • Низ (текст), "string" — използваме например стойностите "menu", "game", "settings" за всеки от екраните, и после проверяваме коя е текущата стойност.
    • Функция, "function" — използваме например няколко функции, например function menu(), function game() и function settings(), а след това в променлива записваме коя функция трябва да използваме за текущия екран.
    • Обект, "object" — подобно на функция, но използвайки класове (които ще разгледаме малко по-късно).
    • (Число също е опция, но използването на някой от другите варианти е по-често срещано.)