This content originally appeared on DEV Community and was authored by ipelovski
Когато сте въвеждали текст на български език ползвайки кирилска клавиатурна подредба като БДС или фонетична, то навярно сте забелязали, че с тези подредби не може да се въвеждат някои символи като квадратни и къдрави скоби ([]
и {}
). Разбира се това не е пречка да се ползват кирилските клавиатурни подредби. Неудобство е обаче, ако искате да програмирате на ДжаваСкрипт ползвайки подобна подредба. Някои биха отбелязали, че не само липсата на квадратни и къдрави скоби би представлявала трудност да се програмира на ДжаваСкрипт ползвайки Кирилица. Всички ключови думи в ДжаваСкрипт като function
и var
са на английски и изискват латински букви за въвеждането им. В този блог пост ще се опитам да разгледам възможно ли е да се програмира на ДжаваСкрипт без да се превключва на английска клавиатурна подредба, т.е. възможно ли е да се пишат програми ползвайки само кирилски букви и символи, които могат да се въведат с кирилска подредба. Ще разгледам някои от основните контролни структури в ДжаваСкрипт и ще потърся техни заместители.
Нужно е да отбележа, че някои среди за разработка позволяват да се въведат английски ключови думи ползвайки кирилски букви, както и задаване на клавишни комбинации за въвеждане на определени символи. Въпреки, че такива среди биха позволили лесно да се програмира с кирилска клавиатурна подредба, аз няма да ги разглеждам в този пост. Вместо това ще се съсредоточа върху конзолата за въвеждане на команди достъпна във всеки широко използван браузър, която най-често е достъпна след натискане на бутона F12, когато прозореца е фокусиран. Ще оставя настрана и предимствата и недостатъците от програмирането на език различен от английски. Когато става за професионално писане на код, споделям мнението, че английският език е най-подходящия за тази цел. За любителски цели обаче смятам, че българският език е напълно достатъчен за програмиране.
Както стана дума, в ДжаваСкрипт ключовите думи и имената на свойствата, с които вградените обекти са достъпни, са на английски език и за изписването им ни е потребна Латиницата. Често използваните конструкции като let
и while
могат обаче да се заменят с функции, чиито имена са на български, както и да се добавят нови български имена на някои свойства на вградените обекти. Например създавенето на нов обект с new Object()
или {}
, може да бъде заменено с извикването на функция. Или пък итерирането на масив [1, 2, 3].map(a => a * 2)
, да бъде заменено с функция, която създава масив, и вграден метод, който да е достъпен под ново име, например: масив(1, 2, 3).изведи(а => а * 2)
. По-надолу ще разгледам как може да стане това.
Особеност на браузърните конзоли е, че когато се задава стойност на недекларирана променлива в конзолата, то браузъра по подразбиране добавя ново свойство на глобалния обект globalThis
, и по-точно на window
. Например ако изпълним а = 1
в конзолата, то верни ще бъдат следните сравнения: globalThis.а === 1
и window.а === 1
. Ще използвам тази особеност за по-сбито и ясно деклариране на функциите, които ще дефинирам.
Команди и изрази
Програмите на ДжаваСкрипт се състоят от декларации, команди и изрази. Декларациите включват добавянето на нова променлива с let
, на нов клас с class
, добавянето на съществуващи обекти с import
и т.н. Команди са if else
, for
, while
. Изразите са всичко останало – събиране с оператора +
, извикване на функции, присвояване на стойност на променлива. Всеки израз има крайна стойност, която може да се ползва в друг израз или да се върне като резултат от функция например.
Тъй като декларациите и повечето команди изискват ключови думи на Латиница, както и квадратни и къдрави скоби, то ще обърна внимание на изразите. Повечето изрази не изискват ключова дума. Вместо това те се състоят от оператори като +
, -
и =
, кръгли скоби ()
, както и имена на променливи и свойства, които ако са дефинирани на български, не би било проблем да се изписват с кирилските клавиатурни подредби. Като краен резултат ще имаме програмен код на български, който се състои изцяло от изрази.
Функции
Основно място в ДжаваСкрипт заемат функциите. Функциите обикновено се декларират с ключовата дума function
и се състоят от списък от аргументи и тяло под формата на блок. Освен с ключовата дума function
, ДжаваСкрипт позволява функции да се декларират и с така наречените arrow функции: () => ...
Тъй като arrow функциите не изискват ключова дума ще използваме предимно тях, когато програмираме на Кирилица. Тялото на функциите, дефинирани с function
, се намира между къдрави скоби – { ... тяло ... }
. За arrow functions това не е изискване. С тях можем да зададем функция под формата () => израз
. Например (а, б) => а + б
е напълно валидна дефиниция на функция в ДжаваСкрипт.
Дотук добре, но какво да правим, когато желаем да имаме последователност от команди в тялото на функция? Тук на помощ идва операторът ,
. С негова помощ може да се зададе последователност от повече от един израз, като стойността на тази последователност е стойността на последния израз в нея. Тъй като приоритета на оператора ,
е много нисък, то в повечето случаи ще е необходимо да се ползва оператора за групиране ()
. С помощта на тези два оператора може да изписва поредица от изрази, като присвояване и извикване на функция:
(а, б) => (console.log(а, б), а = а + б, а)
За да се въведе нова променлива, обикновено се ползвa някоя от ключовите думи var
, let
и const
. Това изисква използването на Латиница и не би вършило работа. В ДжаваСкрипт променливи са също и аргументите на една функция. Те не изискват ключова дума и имат сходно поведение на променливите декларирани с var
– могат да се ползват от самото начало на една функция.
Например ако във функцията (а, б) => а + б
искам да въведа междинна променлива в
, на която да присвоя резултата от събирането и след това да върна този резултат, мога да го направя по следния начин:
(а, б, в) => (в = а + б, в)
Така дефинирана обаче функцията може да предизвика объркване. Ако някой друг програмист види, че функцията има 3 параметъра, то е много вероятно този програмист да си помисли че трябва да подаде 3 аргумента, когато извиква функцията.
Това може да се избегне чрез използването на допълнителна вътрешна функция
(а, б) => (в => (в = а + б, в))()
Използвайки възможността да се зададе начална стойност на параметрите в една ДжаваСкрипт функция, горния ред може да се промени по следния начин:
(а, б) => ((в = а + б) => в)()
Задаването на начална стойност изисква списъка от параметри задължително да се постави между скоби, за да не се интерпретира като обикновено присвояване. Това са доста скоби, но те са необходими, за да може ДжаваСкрипт да разпознае правилно вътрешната функция и да я извика на правилното място.
За да си спестя писането на малко скоби, когато искам да въведа нова променлива, ще добавя помощна функция, която да ме улесни:
нека = блок => блок()
Ето как би изглеждала горната фунцията сега:
(а, б) => нека((в = а + б) => в)
Нека я извикаме със следния код въведен в конзолата:
((а, б) => нека((в = а + б) => в))(1, 2) // -> 3
Условен оператор
Една от най-често използваните конструкции в ДжаваСкрипт е if else
. За щастие ДжаваСкрипт като език предлага и условния оператор ?:
, който може да замени if else
, при условие, че всички операнди на оператора са изрази. Например следната функция ще върне по-голямато число между а
и б
:
(а, б) => а > б ? а : б
Цикли
Други често използвани конструкции са циклите като for
и while
. Ще се спра на while
, като по-обща конструкция, и ще се опитам да я превърна във функция под името докато
. while
се състои от условие и тяло: while(условие) тяло
. Условието може да се оцени повече от веднъж, т.е. подобно на блоковете, може да се изпълни на по-късен момент от програмата. Затова в новата функция условието ще е блок, както и тялото.
докато = (условие, тяло) => { while(условие()) тяло() }
Ще дефинирам функция, която при вход цяло положително число, връща като резултат числото умножено по две. Следната дефиниця определено не най-оптималната и служи само за пример:
по2 = (а) =>
нека((б = 0) => (
докато(
() => (а-- > 0),
() => б += 2
),
б
))
по2(2) // -> 4
Данни
Когато пишем програми, не можем да минем без данни. Числата и низовете лесно се изписват с клавиатурна подредба на Кирилица: 1.23
, '456'
, 'едно'
, 'две'
. Булевите стойности също може да се изпишат на кирилица като добавим нови свойства към глобалния обект:
истина = true, да = true
неистина = false, не = false
(1 === 1) === истина // -> true
По подобен начин можем да въведем null
и undefined
:
нищо = null
неопределено = undefined
Масиви
Ше разгледам и съставните типове данни. Първо ще се спра на масивите. ДжаваСкрипт предлага кратък начин за изписване на масиви с помощта на квадратни скоби [1, 2, 3]
. Този вид скоби не са налични при кирилските клавиатурни подредби, затова ще добавя функция, която да създава масив от аргументите, които ѝ са подадени:
масив = (...елементи) => елементи
Добавянето на нова функционалност към масивите става лесно като се зададат нови свойства на вградения обект Array.prototype
:
Array.prototype.на = Array.prototype.at
Array.prototype.задай = function(индекс, стойност) {
return this[индекс] = стойност;
}
м1 = масив(1, 2, 3)
м1.на(1) // -> 2
м1.задай(1, 2.5) // -> 2.5
м1.на(1) // -> 2.5
По същия начин ще добавя нови свойства с български имена на по-често използваните методи на масивите:
Array.prototype.обиколи = Array.prototype.forEach
Array.prototype.изведи = Array.prototype.map
Array.prototype.сведи = Array.prototype.reduce
масив(1, 2, 3).изведи(по2) // -> [2, 4, 6]
Обекти
ДжаваСкрипт позволява да се създават и обекти с помощта на конструктори, вградени функции или чрез краткото изписване ползвайки къдравите скоби { свойство: стойност }
. Този вид скоби също не може да бъде въведен с кирилска клавиатурна подредба, затова ще добавя функция, която да връща нов обект от подадени имена на свойства и стойности. Преди това за удобство ше пренеса един от методите от масивите, който много често ще се ползва и при обектите, и с чиято помощ ще добавям или сменям стойността на някое от свойствата на един обект, когато това свойство не ми е известно предварително:
Object.prototype.задай = function(свойство, стойност) {
return this[свойство] = стойност;
}
обект = (...свойства) => свойства.сведи(
(обект, елемент, индекс) => (
индекс % 2 === 0
? (
обект.задай(елемент, свойства.на(индекс + 1)),
обект
)
: обект
),
new Object()
)
обект(
'дължина', 4,
'ширина', 3
) // -> {дължина: 4, ширина: 3}
Ще добавя и друг начин за създаване на обект и задаване на неговите свойства. При този начин функцията създаваща обекти приема анонимна функция, чиято цел е да добави нужните свойства към обекта. Ще я наречем обектБ
съкратено от “обект чрез блок”
обектБ = (блок) =>
нека((о = обект()) => (
блок(о),
о
))
обектБ(о => (
о.дължина = 4,
о.ширина = 3
)) -> {дължина: 4, ширина: 3}
Този начин позволява и добавяне на методи към обекта, без да се ползва this
или конструкцията class
изискваща къдрави скоби. Ако е потребна референция към текущия обект, то може да се използва аргумента на arrow функцията:
правоъгълник = обектБ(о => (
о.дължина = 4,
о.ширина = 3,
о.лице = () => о.дължина * о.ширина
))
правоъгълник.лице() // -> 12
Когато методите на обект са дефинирани в неговия прототип, е нужна ключовата дума this
, за да се достъпят свойствата на обекта, за когото се извикват методите. Възможно е обаче this
да се преименува, като се подаде стойността на this
като първи аргумент на функцията, която служи за дефиниция на метода. Ето как може да се осъществи това:
метод = (метод) => function(...аргументи) {
return метод(this, ...аргументи)
}
създайОбект = Object.create
прототипНаПравоъгълници = обект(
'лице', метод(о => о.дължина * о.ширина)
)
правоъгълник2 = създайОбект(прототипНаПравоъгълници)
правоъгълник2.дължина = 4
правоъгълник2.ширина = 3
правоъгълник2.лице() // -> 12
Заключение
Показаните функции и начините за тяхното ползване не са достатъчни за написването на цяла програма. В ДжаваСкрипт има още много конструкции и вградени обекти, които се използват в ежедневието на един програмист. Но са достатъчни да се създават кратки функции за забавление и да се получи бегла представа как би изглеждала една програма на български език. Като край ще дефинирам функция, която връща н-тия елемент на редицата на Фибоначи.
нека((фибоначи = (н) =>
н === 0
? 0
: н <= 2
? 1
: фибоначи(н - 1) + фибоначи(н - 2)
) =>
фибоначи(10)
) // -> 55
В тази дефиниция липсва проверка дали н
е цяло неотрицателно число. Ако ви е харесала мисълта да програмирате на български, може да опитате да добавите сами такава проверка.
This content originally appeared on DEV Community and was authored by ipelovski