Урок 0, Стойности и типове в JavaScript
Допълнителни линкове към този урок:
- Кода от този урок
- Документация: typeof, MDN
- "Страхотен текст: Втора част", Khan Academy
- "Data types", javascript.info
- "Function expressions", javascript.info
Основни точки от този урок
В JavaScript, стойности ("values") са нещата, с които може да "оперираме", нещата, които нашия код може да използва. Всяка стойност може да бъде записана в променлива.
Пример за стойност би било числото 100. Знаем, че 100 е стойност, тъй като можем да запишем 100 в някоя променлива и след това да го прочетем. Например:
let x = 100 // Записваме стойност в променлива
rect(x, 0, 50, 50) // Прочитаме същата стойност от променливата
Не всичко е стойност. Някои неща са изрази ("expressions"); един израз обяснява какво правим с някоя стойност и резултата от израза е стойност, но сам по себе си, израза не е стойност. Онагледено с пример, може да видим как x + 10
е израз а не стойност, тъй като, самия израз не е това, което записваме в променливата:
let x = 100 // Записваме стойност в променлива
let x10 = x + 10 // Отново записваме стойност в променлива
= 0 // Променяме стойност в `x`
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
= 250 // Без значение дали променяме променливата от израза (x < 200), стойността на c не се променя
x 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) {
= ellipse // Променяме стойността на променливата
f
}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 имаме право да запишем стойност от тип низ в променлива, в която до сега е имало стойност от тип число — но в много други програмни езици, самия език ни ограничава да не можем да правим това. Дали това е от полза за нас като програмисти, или е само уловка, която да ни изненада, е дискусия за друг път, но е добре да го имаме предвид когато пишем код използващ стойности от различни типове.
Задача (по желание)
Мисленето за различните типове стойности е често-срещана тема, когато се говори за измислянето на нови програмни езици. Връщайки се на примера за правене на палачинки от по-рано, помислете за това какви типове стойности би имал един измислен (наш си) програмен език за описване на рецепти.
За по-лесно измисляне, може да използвате този списък от въпроси:
- С какво би се занимавал програмен език за готвене? Какви са предметите, с които той би боравел?
- Например, ако говорим за палачинки, може би един важен за нас предмет е "брашно".
- Какви са операциите в такъв език за програмиране? Какви действия трябва да може да опише?
- Например, пак говорейки за палачинки, може би една важна операция е "разбъркай". Но дали примерно има различни начини за разбъркване, които трябва да можем да опишем—да речем, месене на тесто, разбиване на белтъци до пяна, внимателно бъркане на сметана/кисело мляко, ...?
- Как може да обясним видовете неща които някои от тези операции взимат или пък произвеждат като резултат?
- Продължавайки със примера, операцията "разбъркай" може да приложим само ако имаме нещо за разбъркване, може би някой съд или някоя смес—а резултата е същия съд или смес, само че вече разбъркани.
Обикновено, типовете в един програмен език образуват някакъв вид "дърво" или йерархична структура. Например, в някои езици има отделни типове за "цяло число" и "число с десетична/плаваща запетая", но и двата типа са част от по-големия тип "число". Така че, не е проблем, ако някои от операциите, които сте измислили, приемат неща от няколко различи типа.
Упражнения
Следните упражнения може да помогнат да затвърдите разбирането си за различни типове стойности. Вижте дали може да отговорите правилно – но ако да объркате, няма проблем; някои от упражненията са леко подвеждащи, с цел да ви помогнат да намирате подобни грешки, когато вие самите пишете код.
Какви са типовете на тези стойности/изрази?
25
Отговор:
Число,
"number"
.34 * 10 - 15 * 3
Отговор:
Число,
"number"
.34 * 5 < 10 * 13
Отговор:
Булева стойност (true/false),
"boolean"
.x < 10 && y > 10
Отговор:
Булева стойност (true/false),
"boolean"
."Здрасти"
Отговор:
Низ/текст,
"string"
."102"
Отговор:
Низ/текст,
"string"
."Здрасти" + "!"
Отговор:
Низ/текст,
"string"
."102" + 50
Отговор:
Низ/текст,
"string"
.
В случая, стойността на израза е"10250"
, тъй като50
бива преобразувано до низ преди да се слее с първия низ."102" * 2
Отговор:
Число,
"number"
! (Това не беше част от урока 😉)
В случая, стойността на израза е204
, тъй като операцията*
винаги преобразува стойностите, които ѝ подаваме, до числови стойности.rect
Отговор:
Функция,
"function"
. (Ако използваме p5.js; иначе може и да е променлива със стойност от друг тип.)rect(0, 0, 10, 10)
Отговор:
Недефинирана,
"undefined"
. (Ако използваме p5.js.)
Не всички функции произвеждат резултатundefined
. Ако функцията завърши съсreturn (стойност)
, то тази стойност става резултат от изпълнението на функцията—нещо, за което ще се говори в следващ урок. Ако погледнем документацията заrect
, може да видим, че никъде не се споменава функцията да връща ("returns") нещо. Следователно, резултата еundefined
.random(0, 100)
Отговор:
Число,
"number"
. (Ако използваме p5.js.) Ако погледнем документацията заrandom
, може да видим, че най-отдолу пише "Returns: Number" – така знаем, че функцията произвежда число. (Виж също бележката за горното упражнение.)function name() { return "Име" } name
Отговор:
Функция,
"function"
. Ако на последния ред, следname
имаше скоби,name()
, то резултата би бил от тип низ,"string"
. Но тъй като не изпълняваме функцията, резултата е от тип"function"
.let x if (2 > 100) { = 3 x } x
Отговор:
Недефинирана,
"undefined"
.
Ако условието беше написано "на обратно" като2 < 100
, то стойността наx
би била от тип число,"number"
.typeof 13
Отговор:
Низ,
"string"
.
стойността на изразаtypeof 13
е"number"
— но типа на тази стойност (на"number"
) е низ,"string
.
Какви типове бихте могли да използвате за да опишете...
С какъв тип данни може да опишем мястото на играча на екрана, ако играча може да се движи само наляво/надясно?
Отговор:
Число,
"number"
.С какъв тип данни може да опишем името на играча, което той е въвел преди да започне играта?
Отговор:
Низ (текст),
"string"
.С какъв тип данни може да опишем дали противника се движи в момента нагоре или надолу?
Отговор:
Имаме няколко опции:
- Булева стойност,
"boolean"
— определяме едната посока (например надолу) катоtrue
а другата оставаfalse
. - Число,
"number"
— използваме подобно на "скорост" или "посока", така че +1 да е в посока увеличаване на Y (надолу), а -1 да е в посока намаляване на Y (нагоре). Така може да напишем нещо подобно напозиция += скорост
. - Низ (текст),
"string"
— използваме например стойностите"up"
и"down"
за двете посоки. - (Вероятно обекти или дори функции биха били опция също, но тези трите са по-стандартни.)
- Булева стойност,
С какъв тип данни може да опишем дали бутона е бил натиснат в предишния кадър?
Отговор:
Булева стойност (true/false),
"boolean"
.С какъв тип данни може да опишем кой екран би трябвало да се покаже, измежду няколко опции, например "главно меню", "в игра", "настройки"?
Отговор:
Отново имаме няколко опции:
- Низ (текст),
"string"
— използваме например стойностите"menu"
,"game"
,"settings"
за всеки от екраните, и после проверяваме коя е текущата стойност. - Функция,
"function"
— използваме например няколко функции, напримерfunction menu()
,function game()
иfunction settings()
, а след това в променлива записваме коя функция трябва да използваме за текущия екран. - Обект,
"object"
— подобно на функция, но използвайки класове (които ще разгледаме малко по-късно). - (Число също е опция, но използването на някой от другите варианти е по-често срещано.)
- Низ (текст),