diff --git a/00_intro.md b/00_intro.md index 35055bc4..e57a693e 100644 --- a/00_intro.md +++ b/00_intro.md @@ -1,78 +1,79 @@ {{meta {load_files: ["code/intro.js"]}}} -# Introduction +# Giriş -{{quote {author: "Ellen Ullman", title: "Close to the Machine: Technophilia and its Discontents", chapter: true} +{{quote {author: "Ellen Ullman", title: "Close to the Machine: Technophilia and Its Discontents", chapter: true} -We think we are creating the system for our own purposes. We believe we are making it in our own image... But the computer is not really like us. It is a projection of a very slim part of ourselves: that portion devoted to logic, order, rule, and clarity. +Sistemleri kendi amaçlarımız için oluşturduğumuzu düşünüyoruz. Onu kendi görüntümüzde yapıyor olduğumuza inanıyoruz... Ancak bilgisayar gerçekten bizim gibi değil. Aslında, çok ince bir kısmımızın yansımasıdır: mantık, düzen, kural ve netliğe adanmış kısmın bir yansımasıdır. quote}} {{figure {url: "img/chapter_picture_00.jpg", alt: "Illustration of a screwdriver next to a circuit board of about the same size", chapter: "framed"}}} -This is a book about instructing ((computer))s. Computers are about as common as screwdrivers today, but they are quite a bit more complex, and making them do what you want them to do isn't always easy. +Bu bir bilgisayarlara talimat verme kitabıdır. Bilgisayarlar bugün tornavida kadar yaygın olsa da, oldukça karmaşıklar ve onları istediğiniz şekilde hareket ettirmek her zaman kolay değildir. -If the task you have for your computer is a common, well-understood one, such as showing you your email or acting like a calculator, you can open the appropriate ((application)) and get to work. But for unique or open-ended tasks, there often is no appropriate application. +Bilgisayarınız için göreviniz yaygın, iyi anlaşılmış bir görevse, örneğin e-postanızı göstermek veya bir hesap makinesi gibi davranmak gibi, uygun uygulamayı açabilir ve işe koyulabilirsiniz. Ancak benzersiz veya açık uçlu görevler için muhtemelen bir uygulama yoktur. -That is where ((programming)) may come in. _Programming_ is the act of constructing a _program_—a set of precise instructions telling a computer what to do. Because computers are dumb, pedantic beasts, programming is fundamentally tedious and frustrating. +İşte programlamaya girilen yer burası olabilir. _Programlama_, bir programı oluşturma eylemidir - bir bilgisayara ne yapması gerektiğini söyleyen kesin talimatlar kümesi. Çünkü bilgisayarlar aptal, pedantik yaratıklardır, programlama temelde sıkıcı ve sinir bozucudur. {{index [programming, "joy of"], speed}} -Fortunately, if you can get over that fact—and maybe even enjoy the rigor of thinking in terms that dumb machines can deal with—programming can be rewarding. It allows you to do things in seconds that would take _forever_ by hand. It is a way to make your computer tool do things that it couldn't do before. On top of that, it makes for a wonderful game of puzzle solving and abstract thinking. +Neyse ki, eğer bu gerçeği aşabilir ve hatta aptal makinelerin anlayabileceği terimlerle düşünmenin titizliğinden zevk alırsanız, programlama ödüllendirici olabilir. Size _saatler_ sürecek şeyleri anında yapma olanağı sağlar. Bilgisayar aracınızın önce yapamadığı şeyleri yapmasını sağlar. Ve soyut düşünme için harika bir egzersiz sunar. -Most programming is done with ((programming language))s. A _programming language_ is an artificially constructed language used to instruct computers. It is interesting that the most effective way we've found to communicate with a computer borrows so heavily from the way we communicate with each other. Like human languages, computer languages allow words and phrases to be combined in new ways, making it possible to express ever new concepts. +Çoğu programlama, programlama dilleri ile yapılır. Bir _programlama dili_, bilgisayarlara talimat vermek için kullanılan yapay bir dil. Bir bilgisayarla iletişim kurmanın en etkili yolunun, birbirimizle iletişim kurma şeklimizden ağır şekilde ödünç alınması ilginçtir. İnsan dilleri gibi, bilgisayar dilleri de kelimelerin ve ifadelerin yeni yollarla birleştirilmesine izin verir, böylece her zaman yeni kavramları ifade etmek mümkün olur. {{index [JavaScript, "availability of"], "casual computing"}} -At one point, language-based interfaces, such as the BASIC and DOS prompts of the 1980s and 1990s, were the main method of interacting with computers. For routine computer use, these have largely been replaced with visual interfaces, which are easier to learn but offer less freedom. But if you know where to look, the languages are still there. One of them, _JavaScript_, is built into every modern web ((browser))—and is thus available on almost every device. +Bir zamanlar BASIC ve DOS gibi dil tabanlı arayüzler, 1980'lerin ve 1990'ların ana bilgisayarlarla etkileşim yöntemiydi. Daha rutin bilgisayar kullanımı için bunlar genel olarak kullanımı öğrenmesi kolay olan ancak özgürlüğünüzü sınırlandıran görsel arayüzlerle değiştirildi. Ancak bilgisayar dilleri hala orada, tabii nereye bakacağınızı bilirseniz. O dillerden bir tanesi olan JavaScript, her modern web tarayıcısına yerleştirilmiştir ve böylece neredeyse her cihazda bulunur. {{indexsee "web browser", browser}} -This book will try to make you familiar enough with this language to do useful and amusing things with it. +Bu kitap, bu dili yararlı ve eğlenceli şeyler yapmak için yeterince tanımanıza yardımcı olmaya çalışacaktır. -## On programming +## Programlama hakkında {{index [programming, "difficulty of"]}} -Besides explaining JavaScript, I will introduce the basic principles of programming. Programming, it turns out, is hard. The fundamental rules are simple and clear, but programs built on top of these rules tend to become complex enough to introduce their own rules and complexity. You're building your own maze, in a way, and you can easily get lost in it. +JavaScript'i açıklamanın yanı sıra, programlamanın temel prensiplerini de tanıtacağım. Programlama, anlaşıldığı kadarıyla zor bir iştir. Temel kurallar basit ve net olsa da, bu kuralların üzerine inşa edilen programlar kendi kurallarını ve karmaşıklıklarını tanıtmaya yeterince karmaşık hale gelir. Bir bakıma kendi labirentinizi oluşturuyorsunuz ve bundan ötürü içinde kolayca kaybolabilirsiniz. {{index learning}} -There will be times when reading this book feels terribly frustrating. If you are new to programming, there will be a lot of new material to digest. Much of this material will then be _combined_ in ways that require you to make additional connections. +Bu kitabı okurken bazen son derece sinir bozucu hissedeceğiniz zamanlar olacak. Eğer programlamaya yeni başlayan biriyseniz, sindirmeniz gereken çok yeni malzeme olacak. Bu materyalin büyük bir kısmı daha sonra ek bağlantılar kurmanızı gerektiren şekillerde _birleştirilecek_. -It is up to you to make the necessary effort. When you are struggling to follow the book, do not jump to any conclusions about your own capabilities. You are fine—you just need to keep at it. Take a break, reread some material, and make sure you read and understand the example programs and ((exercises)). Learning is hard work, but everything you learn is yours and will make further learning easier. +Gereken çabayı göstermek size bağlıdır. Kitabı takip etmekte zorlandığınızda, kendi yeteneklerinizle ilgili herhangi bir sonuca varmayın. Sorun yok, sadece devam etmeniz gerekiyor. Ara verin, bazı materyalleri tekrar okuyun, örnek programları ve ((alıştırmaları)) okuyup anladığınızdan emin olun. Öğrenmek zor bir iş olabilir, ancak öğrendiğiniz her şey sizindir ve daha sonraki öğrenmeyi kolaylaştıracaktır. {{quote {author: "Ursula K. Le Guin", title: "The Left Hand of Darkness"} {{index "Le Guin, Ursula K."}} -When action grows unprofitable, gather information; when information grows unprofitable, sleep. +Eylem faydasız hale geldiğinde, bilgi toplayın; bilgi faydasız hale geldiğinde, uyuyun. quote}} {{index [program, "nature of"], data}} -A program is many things. It is a piece of text typed by a programmer, it is the directing force that makes the computer do what it does, it is data in the computer's memory, and at the same time it controls the actions performed on this memory. Analogies that try to compare programs to familiar objects tend to fall short. A superficially fitting one is to compare a program to a machine—lots of separate parts tend to be involved, and to make the whole thing tick, we have to consider the ways in which these parts interconnect and contribute to the operation of the whole. +Bir program birçok şeydir. Bir programcı tarafından yazılan bir metindir, bilgisayarın yaptığı işi yapan yönlendirici güçtür, bilgisayarın belleğindeki veridir ve aynı zamanda bu bellekte gerçekleştirilen eylemleri kontrol eder. Programları tanıdık nesnelerle karşılaştırmaya çalışan benzetmeler genellikle eksik kalır. Yüzeysel olarak uygun olanlardan biri, bir programı bir makineye benzetmektir - genellikle birçok ayrı parça içerir ve tümünün çalışmasını sağlamak için bu parçaların nasıl birbirine bağlandığını ve tümünün işleyişine nasıl katkıda bulunduğunu düşünmemiz gerekir. -A ((computer)) is a physical machine that acts as a host for these immaterial machines. Computers themselves can do only stupidly straightforward things. The reason they are so useful is that they do these things at an incredibly high ((speed)). A program can ingeniously combine an enormous number of these simple actions to do very complicated things. +Bir bilgisayar, bu soyut makinelerin barındırıcısı olarak işlev gören fiziksel bir makinadır. Bilgisayarlar kendileri sadece aptalca basit şeyler yapabilir. Onların bu kadar faydalı olmasının nedeni, bu işleri inanılmaz derecede yüksek bir hızda yapmalarıdır. Bir program, çok karmaşık şeyler yapmak için birçok bu tür basit eylemi ustaca birleştirebilir. {{index [programming, "joy of"]}} -A program is a building of thought. It is costless to build, it is weightless, and it grows easily under our typing hands. But as a program grows, so does its ((complexity)). The skill of programming is the skill of building programs that don't confuse yourself. The best programs are those that manage to do something interesting while still being easy to understand. +Bir program bir düşünce binasıdır. İnşa etmek bedelsizdir, ağırlıksızdır ve yazarak ellerimizin altında kolayca büyür. Ancak bir program büyüdükçe, karmaşıklığı da artar. Programlamanın becerisi, kendinizi kafanızı karıştırmayan programlar oluşturma becerisidir. En iyi programlar, anlaşılması kolay olmasına rağmen ilginç bir şey yapmayı başaranlardır. {{index "programming style", "best practices"}} Some programmers believe that this complexity is best managed by using only a small set of well-understood techniques in their programs. They have composed strict rules ("best practices") prescribing the form programs should have and carefully stay within their safe little zone. +Bazı programcılar, bu karmaşıklığın programlarında yalnızca iyi anlaşılan birkaç teknik kullanılarak en iyi şekilde yönetildiğine inanırlar. Programların hangi formda olması ve küçük güvenli alanlarında dikkatlice kalmaları gerektiğini düşündükleri katı kurallar ("en iyi pratikler") oluşturdular. {{index experiment}} -This is not only boring, it is ineffective. New problems often require new solutions. The field of programming is young and still developing rapidly, and it is varied enough to have room for wildly different approaches. There are many terrible mistakes to make in program design, and you should go ahead and make them at least once so that you understand them. A sense of what a good program looks like is developed with practice, not learned from a list of rules. +Bu sadece sıkıcı değil, etkisizdir de. Yeni sorunlar genellikle yeni çözümler gerektirir. Programlama alanı genç ve hala hızla gelişmekte olup, oldukça farklı yaklaşımlar için yer bulacak kadar çeşitlidir. Program tasarımında yapılacak pek çok korkunç hata vardır ve onları anlamanız için en azından bir kez yapmalısınız. İyi bir programın nasıl göründüğüne dair bir anlayış, pratikle geliştirilir, kurallar listesinden öğrenilmez. -## Why language matters +## Dil neden önemlidir {{index "programming language", "machine code", "binary data"}} -In the beginning, at the birth of computing, there were no programming languages. Programs looked something like this: +Başta, bilgisayarların doğuşunda herhangi bir programlama dili yoktu. Programlar şu şekilde gözüküyordu: ```{lang: null} 00110001 00000000 00000000 @@ -88,49 +89,49 @@ In the beginning, at the birth of computing, there were no programming languages {{index [programming, "history of"], "punch card", complexity}} -This is a program to add the numbers from 1 to 10 together and print the result: `1 + 2 + ... + 10 = 55`. It could run on a simple hypothetical machine. To program early computers, it was necessary to set large arrays of switches in the right position or punch holes in strips of cardboard and feed them to the computer. You can imagine how tedious and error-prone this procedure was. Even writing simple programs required much cleverness and discipline. Complex ones were nearly inconceivable. +Bu, sayıları 1'den 10'a kadar toplayıp sonucu yazdıran bir programdır: 1 + 2 + ... + 10 = 55. Basit bir varsayımsal makinede çalışabilirdi. Erken bilgisayarları programlamak için, büyük anahtar dizilerini doğru konuma ayarlamak veya karton şeritlere delikler açmak ve bunları bilgisayara beslemek gerekiyordu. Bu prosedürün ne kadar sıkıcı ve hata yapmaya açık olduğunu hayal edebilirsiniz. Basit programları yazmak bile çok zeka ve disiplin gerektirirdi. Karmaşık olanlar neredeyse hayal edilemezdi. {{index bit, "wizard (mighty)"}} -Of course, manually entering these arcane patterns of bits (the ones and zeros) did give the programmer a profound sense of being a mighty wizard. And that has to be worth something in terms of job satisfaction. +Tabii ki, bu gizemli desenlerin (birler ve sıfırlar) el ile girilmesi, programcıya güçlü bir büyücü hissi veriyordu. Ve bu, iş tatmini açısından bir şeylere değer olmalı. {{index memory, instruction}} -Each line of the previous program contains a single instruction. It could be written in English like this: +Önceki programın her satırı yalnızca bir talimat içerir. Bu İngilizce olarak şöyle yazılabilir: - 1. Store the number 0 in memory location 0. - 2. Store the number 1 in memory location 1. - 3. Store the value of memory location 1 in memory location 2. - 4. Subtract the number 11 from the value in memory location 2. - 5. If the value in memory location 2 is the number 0, continue with instruction 9. - 6. Add the value of memory location 1 to memory location 0. - 7. Add the number 1 to the value of memory location 1. - 8. Continue with instruction 3. - 9. Output the value of memory location 0. +1. Bellek konumu 0'da 0 sayısını saklayın. +2. Bellek konumu 1'de 1 sayısını saklayın. +3. Bellek konumu 1'in değerini bellek konumu 2'ye saklayın. +4. Bellek konumu 2'deki değerden 11'i çıkarın. +5. Bellek konumu 2'deki değer 0 ise, talimat 9 ile devam edin. +6. Bellek konumu 0'ın değerine bellek konumu 1'in değerini ekleyin. +7. Bellek konumu 1'in değerine 1 sayısını ekleyin. +8. Talimat 3 ile devam edin. +9. Bellek konumu 0'ın değerini sonuç olarak çıkarın. {{index readability, naming, binding}} -Although that is already more readable than the soup of bits, it is still rather obscure. Using names instead of numbers for the instructions and memory locations helps: +Bu, artık bitlerin karışımından daha okunabilir olsa da, hala oldukça belirsizdir. Talimatlar ve bellek konumları için sayılar yerine isimler kullanmak çok daha yardımcı olur. ```{lang: "null"} - Set “total” to 0. - Set “count” to 1. -[loop] - Set “compare” to “count”. - Subtract 11 from “compare”. - If “compare” is zero, continue at [end]. - Add “count” to “total”. - Add 1 to “count”. - Continue at [loop]. + “total” değerini 0 yap. + “count” değerini 1 yap. +[while] + “compare” değerini “count” değerine ata. + “compare” değerinden 11 çıkar. + Eğer “compare” sıfırsa şuradan devam et: [end]. + “count” değerini “total” değerine ekle. + “count” değerine 1 ekle. + Şuradan devam et: [loop]. [end] - Output “total”. + Sonuç “total”. ``` {{index loop, jump, "summing example"}} -Can you see how the program works at this point? The first two lines give two memory locations their starting values: `total` will be used to build up the result of the computation, and `count` will keep track of the number that we are currently looking at. The lines using `compare` are probably the most confusing ones. The program wants to see whether `count` is equal to 11 to decide whether it can stop running. Because our hypothetical machine is rather primitive, it can only test whether a number is zero and make a decision based on that. It therefore uses the memory location labeled `compare` to compute the value of `count - 11` and makes a decision based on that value. The next two lines add the value of `count` to the result and increment `count` by 1 every time the program decides that `count` is not 11 yet. +Artık programın nasıl çalıştığını görebiliyor musunuz? İlk iki satır, iki bellek konumuna başlangıç değerlerini verir: `total`, hesaplamanın sonucunu oluşturmak için kullanılacak ve `count`, şu anda baktığımız sayıyı takip edecek. `compare` değerini kullanan satırlar muhtemelen en karışık olanlardır. Program, çalışmayı durdurup durduramayacağını belirlemek için `count` değerinin 11'e eşit olup olmadığını görmek istiyor. Varsayımsal makinemiz oldukça ilkel olduğundan, yalnızca bir sayının sıfır olup olmadığını test edebip buna dayanarak bir karar verebiliyor. Bu nedenle, `compare` olarak etiketlenmiş bellek konumunu kullanarak `count - 11` değerini hesaplar ve bu değere dayanarak bir karar verir. Bir sonraki iki satır, `count` değerini `total` değerine ekler ve `count` değerninin 11 olmadığına karar verdiğinde `count` değerini bir artırır. -Here is the same program in JavaScript: +Aynı programın JavaScript'teki hali: ``` let total = 0, count = 1; @@ -144,15 +145,16 @@ console.log(total); {{index "while loop", loop, [braces, block]}} -This version gives us a few more improvements. Most importantly, there is no need to specify the way we want the program to jump back and forth anymore—the `while` construct takes care of that. It continues executing the block (wrapped in braces) below it as long as the condition it was given holds. That condition is `count <= 10`, which means “the count is less than or equal to 10”. We no longer have to create a temporary value and compare that to zero, which was just an uninteresting detail. Part of the power of programming languages is that they can take care of uninteresting details for us. +Bu versiyon bize birkaç iyileştirme sağlar. En önemlisi, artık programa ileri geri nasıl atlamak istediğimizi belirtmemize gerek yoktur - `while` yapısı bununla ilgilenir. Verilen koşul geçerli olduğu sürece, onun altında (süslü parantezlerle sarılı) bloğu devam ettirir. Bu koşul `sayac <= 10`dur, yani "sayım 10'a eşit veya daha azdır" anlamına gelir. Artık geçici bir değer oluşturup bunu sıfır ile karşılaştırmamıza gerek yoktur, bu sadece ilgisiz bir ayrıntıydı. Programlama dillerinin gücünün bir kısmıysa bizim için o tür ilgisiz ayrıntıları ele alabilmeleridir. {{index "console.log"}} -At the end of the program, after the `while` construct has finished, the `console.log` operation is used to write out the result. +Programın sonunda, `while` yapısı bitirdikten sonra, sonucu yazmak için `console.log` işlemi kullanılır. {{index "sum function", "range function", abstraction, function}} Finally, here is what the program could look like if we happened to have the convenient operations `range` and `sum` available, which respectively create a ((collection)) of numbers within a range and compute the sum of a collection of numbers: +Son olarak, `range` ve `sum` adlı belirli değerler arasında sayılar koleksiyonu oluşturup onların toplamını bulan kullanışlı fonksiyonlarımızın mevcut olduğu bir durumda programımızın nasıl görünebileceğine dair: ```{startCode: true} console.log(sum(range(1, 10))); @@ -161,13 +163,13 @@ console.log(sum(range(1, 10))); {{index readability}} -The moral of this story is that the same program can be expressed in both long and short, unreadable and readable ways. The first version of the program was extremely obscure, whereas this last one is almost English: `log` the `sum` of the `range` of numbers from 1 to 10. (We will see in [later chapters](data) how to define operations like `sum` and `range`.) +Bu hikayenin özü, aynı programın uzun ve kısa, okunaksız ve okunabilir yollarla ifade edilebileceğidir. Programın ilk versiyonu son derece belirsizken, bu son versiyon neredeyse İngilizce gibidir: 1'den 10'a kadar olan sayıların aralığının(`range(10)`) toplamını(`sum`) konsolda görüntüleyin(`console.log`). (Sonraki bölümlerde toplam ve aralık gibi işlemleri nasıl tanımlayacağımızı göreceğiz.) {{index ["programming language", "power of"], composability}} -A good programming language helps the programmer by allowing them to talk about the actions that the computer has to perform on a higher level. It helps omit details, provides convenient building blocks (such as `while` and `console.log`), allows you to define your own building blocks (such as `sum` and `range`), and makes those blocks easy to compose. +İyi bir programlama dili, programcının daha yüksek bir seviyede bilgisayarın gerçekleştirmesi gereken eylemler hakkında konuşmasına izin vererek ona yardımcı olur. Detayları atlamasına yardımcı olur, uygun yapı taşları sağlar (`while` ve `console.log` gibi), kendi yapı taşlarınızı tanımlamanıza izin verir (`sum` ve `range` gibi) ve bu blokları kolayca birleştirmenizi sağlar. -## What is JavaScript? +## JavaScript nedir? {{index history, Netscape, browser, "web application", JavaScript, [JavaScript, "history of"], "World Wide Web"}} @@ -175,47 +177,48 @@ A good programming language helps the programmer by allowing them to talk about {{indexsee Web, "World Wide Web"}} -JavaScript was introduced in 1995 as a way to add programs to web pages in the Netscape Navigator browser. The language has since been adopted by all other major graphical web browsers. It has made modern web applications possible—that is, applications with which you can interact directly without doing a page reload for every action. JavaScript is also used in more traditional websites to provide various forms of interactivity and cleverness. +JavaScript is also used in more traditional websites to provide various forms of interactivity and cleverness. +JavaScript, 1995 yılında Netscape Navigator tarayıcısına websitelere interaktif programlar oluşturmanın bir yolu olarak eklendi. O zamandan beri, dil diğer tüm önemli grafiksel web tarayıcıları tarafından benimsendi. JavaScript, bugünkü her eylem için sayfanın yeniden yüklenmesine gerek kalmadan doğrudan etkileşimde bulunabileceğiniz modern web uygulamalarını mümkün kıldı, ayrıca daha geleneksel web sitelerinde de çeşitli etkileşim sağlamak için kullanıldı. {{index Java, naming}} -It is important to note that JavaScript has almost nothing to do with the programming language named Java. The similar name was inspired by marketing considerations rather than good judgment. When JavaScript was being introduced, the Java language was being heavily marketed and was gaining popularity. Someone thought it was a good idea to try to ride along on this success. Now we are stuck with the name. +JavaScript'in Java adındaki programlama diliyle neredeyse hiçbir ilgisi olmadığını belirtmek önemlidir. Benzer ad, iyi bir değerlendirme yerine pazarlama düşüncelerinden esinlenmiştir. JavaScript tanıtıldığında, Java dili yoğun bir şekilde pazarlanıyor ve popülerlik kazanıyordu. Birisi bu başarıya eşlik etmeyi denemek için iyi bir fikir olduğunu düşündü. Şimdi ise isimle sıkışıp kaldık. {{index ECMAScript, compatibility}} -After its adoption outside of Netscape, a ((standard)) document was written to describe the way the JavaScript language should work so that the various pieces of software that claimed to support JavaScript could make sure they actually provided the same language. This is called the ECMAScript standard, after the Ecma International organization that conducted the standardization. In practice, the terms ECMAScript and JavaScript can be used interchangeably—they are two names for the same language. +Netscape dışında benimsenmesinin ardından, JavaScript dilini desteklendiğini iddia eden çeşitli yazılımların aslında aynı dili desteklediklerini garanti edebilemek adına bir standart belgesi yazıldı. Bu, standardizasyonu gerçekleştiren Ecma International organizasyonunun adından ECMAScript standardı olarak adlandırıldı. Uygulamada, ECMAScript ve JavaScript terimleri değiştirilebilir şekilde kullanılabilir— bu iki isim aynı programlama diline hitap etmektedir. {{index [JavaScript, "weaknesses of"], debugging}} -There are those who will say _terrible_ things about JavaScript. Many of these things are true. When I was required to write something in JavaScript for the first time, I quickly came to despise it. It would accept almost anything I typed but interpret it in a way that was completely different from what I meant. This had a lot to do with the fact that I did not have a clue what I was doing, of course, but there is a real issue here: JavaScript is ridiculously liberal in what it allows. The idea behind this design was that it would make programming in JavaScript easier for beginners. In actuality, it mostly makes finding problems in your programs harder because the system will not point them out to you. +JavaScript hakkında _korkunç_ şeyler söyleyenler vardır ve söylenen bu şeylerin pek çoğu doğrudur. İlk kez JavaScript'te bir şeyler yazmam gerektiğinde, ondan nefret etmeye hızlıca başladım çünkü JavaScript neredeyse yazdığım her şeyi kabul eder, ancak yazdıkalrımı hep istediğimden başka bir şekilde yorumlardı. Bu durum, tabii ki ne yaptığımı bilmediğim gerçeğiyle çok ilgiliydi, ancak burada gerçek bir sorun var: JavaScript, maalesef izin verdiği şeylerde son derece cömerttir. Bu tasarımın arkasındaki fikir, JavaScript'te programlamanın yeni başlayanlar için daha kolay olmasını sağlamaktı ama aslında bu, programlarınızdaki sorunları bulmayı çoğunlukla daha zor hale getirir çünkü sistem size bunları işaret etmez. {{index [JavaScript, "flexibility of"], flexibility}} -This flexibility also has its advantages, though. It leaves room for techniques that are impossible in more rigid languages and makes for a pleasant, informal style of programming. After ((learning)) the language properly and working with it for a while, I have come to actually _like_ JavaScript. +Ancak bu esnekliğin avantajları da vardır. Daha katı dillerde mümkün olmayan tekniklere olanak tanır ve hoş, gayri resmi bir programlama tarzı sunar. Dilin düzgün bir şekilde öğrendikten ve bir süre kendisiyle çalıştıktan sonra JavaScript'i aslında _sevmeye_ başladım. {{index future, [JavaScript, "versions of"], ECMAScript, "ECMAScript 6"}} -There have been several versions of JavaScript. ECMAScript version 3 was the widely supported version during JavaScript's ascent to dominance, roughly between 2000 and 2010. During this time, work was underway on an ambitious version 4, which planned a number of radical improvements and extensions to the language. Changing a living, widely used language in such a radical way turned out to be politically difficult, and work on the version 4 was abandoned in 2008. A much less ambitious version 5, which made only some uncontroversial improvements, came out in 2009. In 2015, version 6 came out, a major update that included some of the ideas planned for version 4. Since then we've had new, small updates every year. +JavaScript'in birkaç versiyonu olmuştur. ECMAScript sürüm 3, yaklaşık olarak 2000 ile 2010 arasında JavaScript'in hakimiyetinin arttığı dönemde yaygın olarak desteklenen sürümdü. Bu dönemde, dili radikal bir şekilde iyileştirmeyi ve genişletmeyi planlayan cesur bir sürüm 4 üzerinde çalışmalar devam ediyordu. Ancak, geniş kullanılan bir dilin bu kadar radikal bir şekilde değiştirilmesi politik olarak zorlu çıktı ve sürüm 4 üzerindeki çalışmalar 2008'de terkedildi. Yalnızca bazı tartışmasız iyileştirmeler getiren çok daha iddiasız bir sürüm olan 5. sürüm, 2009'da piyasaya çıktı. 2015'te, sürüm 6, sürüm 4 için planlanan bazı fikirleri içeren önemli bir güncelleme olarak yayınlandı. O zamandan beri her yıl yeni, küçük güncellemeler yapılmaktadır. -The fact that JavaScript is evolving means that browsers have to constantly keep up. If you're using an older browser, it may not support every feature. The language designers are careful to not make any changes that could break existing programs, so new browsers can still run old programs. In this book, I'm using the 2023 version of JavaScript. +JavaScript'in gelişmekte olması, tarayıcıların sürekli olarak ayak uydurması gerektiği anlamına gelir. Eski bir tarayıcı kullanıyorsanız, JavaScript'in her özelliğini desteklemeyebilir. Dil tasarımcıları, mevcut programları bozabilecek herhangi bir değişiklik yapmamaya dikkat eder, bu nedenle yeni tarayıcılar hala eski programları çalıştırabilir. Bu kitapta, 2023 sürümünü kullanıyorum. {{index [JavaScript, "uses of"]}} -Web browsers are not the only platforms on which JavaScript is used. Some databases, such as MongoDB and CouchDB, use JavaScript as their scripting and query language. Several platforms for desktop and server programming, most notably the ((Node.js)) project (the subject of [Chapter ?](node)), provide an environment for programming JavaScript outside of the browser. +Web tarayıcıları, JavaScript'in kullanıldığı tek platformlar değildir. MongoDB ve CouchDB gibi bazı veritabanları JavaScript'i scripting ve sorgu dili olarak kullanır. Masaüstü ve sunucu programlama için birçok platform, özellikle Node.js projesi tarayıcı dışında JavaScript kullanabilmek için bir ortam sağlar. -## Code, and what to do with it +## Kod ve onunla ne yapılacağı {{index "reading code", "writing code"}} -_Code_ is the text that makes up programs. Most chapters in this book contain quite a lot of code. I believe reading code and writing ((code)) are indispensable parts of ((learning)) to program. Try to not just glance over the examples—read them attentively and understand them. This may be slow and confusing at first, but I promise that you'll quickly get the hang of it. The same goes for the ((exercises)). Don't assume you understand them until you've actually written a working solution. +_Kod_, programları oluşturan metindir. Bu kitaptaki çoğu bölüm oldukça fazla kod içerir. Kod okumak ve kod yazmak, programlamayı öğrenmenin vazgeçilmez parçaları olduğuna inanıyorum. Örnekleri sadece gözden geçirmeyin ve onları dikkatlice okuyup anlamaya çalışın. Başlangıçta bu yavaş ve kafa karıştırıcı olabilir, ancak hızlıca alışacaksınıza söz veriyorum. Aynı şey ((alıştırmalar)) için de geçerlidir, lütfen bir çalışan çözüm yazmadan önce onları anladığınızı varsaymayın. {{index interpretation}} -I recommend you try your solutions to exercises in an actual JavaScript interpreter. That way, you'll get immediate feedback on whether what you are doing is working, and, I hope, you'll be tempted to ((experiment)) and go beyond the exercises. +Çözümlerinizi gerçek bir JavaScript yorumlayıcısında denemenizi öneririm. Böylece, yaptıklarınızın çalışıp çalışmadığı konusunda hemen geri bildirim alırsınız ve umarım, ((deney yapmaya)) ve alıştırmaların ötesine geçmeye teşvik edilirsiniz. {{if interactive -When reading this book in your browser, you can edit (and run) all example programs by clicking them. +Bu kitabı tarayıcınızda okurken, tüm örnek programları düzenleyip çalıştırabilir ve üzerlerine tıklayarak çalıştırabilirsiniz. if}} @@ -223,37 +226,37 @@ if}} {{index download, sandbox, "running code"}} -The easiest way to run the example code in the book—and to experiment with it—is to look it up in the online version of the book at [_https://eloquentjavascript.net_](https://eloquentjavascript.net/). There, you can click any code example to edit and run it and to see the output it produces. To work on the exercises, go to [_https://eloquentjavascript.net/code_](https://eloquentjavascript.net/code), which provides starting code for each coding exercise and allows you to look at the solutions. +Kitaptaki örnek kodları çalıştırmanın ve bunlarla deney yapmanın en kolay yolu, kitabın çevrimiçi sürümünü [_https://eloquentjavascript.net_](https://eloquentjavascript.net/) adresinden bulmaktır. Orada, herhangi bir kod örneğine tıklayarak onu düzenleyebilir, çalıştırabilir ve ürettiği çıktıyı görebilirsiniz. Alıştırmalar üzerinde çalışmak için, [_https://eloquentjavascript.net/code_](https://eloquentjavascript.net/code) adresine gidin, bu adres her programlama alıştırması için başlangıç kodu sağlar ve çözümleri görebilmenize olanak tanır. if}} {{index "developer tools", "JavaScript console"}} -Running the programs defined in this book outside of the book's website requires some care. Many examples stand on their own and should work in any JavaScript environment. But code in later chapters is often written for a specific environment (the browser or Node.js) and can run only there. In addition, many chapters define bigger programs, and the pieces of code that appear in them depend on each other or on external files. The [sandbox](https://eloquentjavascript.net/code) on the website provides links to ZIP files containing all the scripts and data files necessary to run the code for a given chapter. +Bu kitapta tanımlanan programları kitabın web sitesinin dışında çalıştırmak biraz dikkat gerektirir. Birçok örnek kendi başına durur ve herhangi bir JavaScript ortamında normal çalışabilmelidir. Ancak, daha sonraki bölümlerdeki kodlar genellikle belirli bir ortam için yazılmıştır (tarayıcı veya Node.js) ve yalnızca orada çalışabilir. Ayrıca, birçok bölüm daha büyük programlar tanımlar ve onlarda görünen kod parçaları birbirlerine veya dış dosyalara bağlıdır. Web sitesindeki [dijital kum havuzu](https://eloquentjavascript.net/code), belirli bir bölüm için kodu çalıştırmak için gerekli tüm betikleri ve veri dosyalarını içeren ZIP dosyalarına bağlantılar sağlar. -## Overview of this book +## Kitaba genel bakış -This book contains roughly three parts. The first 12 chapters discuss the JavaScript language. The next seven chapters are about web ((browsers)) and the way JavaScript is used to program them. Finally, two chapters are devoted to ((Node.js)), another environment to program JavaScript in. There are five _project chapters_ in the book that describe larger example programs to give you a taste of actual programming. +Bu kitap yaklaşık üç bölüm içerir. İlk 12 bölüm JavaScript dilini tartışır. Sonraki yedi bölüm web ((tarayıcıları)) ve JavaScript'in onları programlamak için kullanımı hakkındadır. Son olarak, iki bölüm, JavaScript programlamak için başka bir ortam olan ((Node.js))'e adanmıştır. Kitapta, gerçek programlamaya bir tat vermek için daha büyük örnek programları açıklayan beş _proje bölümü_ bulunmaktadır. -The language part of the book starts with four chapters that introduce the basic structure of the JavaScript language. They discuss [control structures](program_structure) (such as the `while` word you saw in this introduction), [functions](functions) (writing your own building blocks), and [data structures](data). After these, you will be able to write basic programs. Next, Chapters [?](higher_order) and [?](object) introduce techniques to use functions and objects to write more _abstract_ code and keep complexity under control. +Kitabın dil kısmı, JavaScript dilinin temel yapısını tanıtan dört bölümle başlar. Bunlar [kontrol yapıları](program_structure) (bu girişte gördüğünüz while kelimesi gibi), [fonksiyonlar](functions) (kendi yapı taşlarınızı yazma), ve veri [yapıları'nı](data) tartışır. Bunlardan sonra, temel programlar yazabilir duruma geleceksiniz. Ardından, [?](higher_order) ve [?](object) numaralı bölümler, daha _soyut_ kod yazmak ve karmaşıklığı kontrol altında tutmak için fonksiyonlar ve nesneleri kullanma tekniklerini tanıtır. -After a [first project chapter](robot) that builds a crude delivery robot, the language part of the book continues with chapters on [error handling and bug fixing](error), [regular expressions](regexp) (an important tool for working with text), [modularity](modules) (another defense against complexity), and [asynchronous programming](async) (dealing with events that take time). The [second project chapter](language), where we implement a programming language, concludes the first part of the book. +[İlk bir proje bölümü](robot) olan robot adlı bölümün ardından, kitabın dil kısmı, [hata işleme ve hata düzeltme](error), [düzenli ifadeler](regexp) (metinle çalışmak için önemli bir araç), [modülerlik](modules) (karmaşıklığa karşı bir diğer savunma) ve [asenkron programlama](async) (zaman alan olaylarla başa çıkma) üzerine bölümlerle devam eder. Bir programlama dilini uyguladığımız [ikinci proje bölümü](language), kitabın ilk bölümünü tamamlar. -The second part of the book, Chapters [?](browser) to [?](paint), describes the tools that browser JavaScript has access to. You'll learn to display things on the screen (Chapters [?](dom) and [?](canvas)), respond to user input ([Chapter ?](event)), and communicate over the network ([Chapter ?](http)). There are again two project chapters in this part, building a [platform game](game) and a [pixel paint program](paint). +Kitabın ikinci bölümü, [?](browser) ile [?](paint) arasındaki bölümler, tarayıcı içindeki JavaScript'in erişebileceği araçları tanımlar. Ekran üzerinde şeyler görüntülemeyi ([?](dom) ve [?](canvas) numaralı bölümler), kullanıcı girişlerine yanıt vermeyi ([?](event) numaralı bölüm), ve ağ üzerinden iletişim kurmayı ([?](http) numaralı bölüm) öğreneceksiniz. Bu bölümde yine iki proje bölümü bulunmaktadır, biri [platform oyunu](game) ve diğeri [piksel boya programı](paint) oluşturur. -[Chapter ?](node) describes Node.js, and [Chapter ?](skillsharing) builds a small website using that tool. +[?](node) numaralı bölüm Node.js'yi tanımlarken, [?](skillsharing) numaralı bölüm bu aracı kullanarak küçük bir web sitesi oluşturur. {{if commercial -Finally, [Chapter ?](fast) describes some of the considerations that come up when optimizing JavaScript programs for speed. +Son olarak, [?](fast) numaralı bölüm, JavaScript programlarını hız için optimize etmesi adına dikkate alınması gereken bazı hususlar hakkında bilgi verir. if}} -## Typographic conventions +## Tipografik kurallar {{index "factorial function"}} -In this book, text written in a `monospaced` font will represent elements of programs. Sometimes these are self-sufficient fragments, and sometimes they just refer to part of a nearby program. Programs (of which you have already seen a few) are written as follows: +Bu kitapta, `monospace` fontuyla yazılmış metinler program öğelerini temsil edecektir. Bazı durumlarda bunlar kendi başına yeterli parçalar olabilir, bazen ise yalnızca yanındaki bir programın bir parçasına atıfta bulunabilirler. Programlar (birkaçını zaten gördünüz) şu şekilde yazılır: ``` function factorial(n) { @@ -267,11 +270,11 @@ function factorial(n) { {{index "console.log"}} -Sometimes, to show the output that a program produces, the expected output is written after it, with two slashes and an arrow in front. +Bazen, bir programın ürettiği çıktıyı göstermek için, beklenen çıktı programın sonrasına, iki eğik çizgi ve bir ok ile yazılır. ``` console.log(factorial(8)); // → 40320 ``` -Good luck! +İyi şanslar! diff --git a/01_values.md b/01_values.md index 843a47e0..63b6acde 100644 --- a/01_values.md +++ b/01_values.md @@ -1,10 +1,10 @@ {{meta {docid: values}}} -# Values, Types, and Operators +# Değerler, Tipler ve Operatörler {{quote {author: "Master Yuan-Ma", title: "The Book of Programming", chapter: true} -Below the surface of the machine, the program moves. Without effort, it expands and contracts. In great harmony, electrons scatter and regroup. The forms on the monitor are but ripples on the water. The essence stays invisibly below. +Makinenin yüzeyinin altında, program hareket eder. Çaba sarf etmeden genişler ve daralır. Büyük bir uyum içinde, elektronlar dağılır ve yeniden gruplanır. Monitördeki formlar sadece suyun üstünde dalgalar gibiyken öz ise görünmez bir şekilde altta kalır. quote}} @@ -14,42 +14,42 @@ quote}} {{index "binary data", data, bit, memory}} -In the computer's world, there is only data. You can read data, modify data, create new data—but that which isn't data cannot be mentioned. All this data is stored as long sequences of bits and is thus fundamentally alike. +Bilgisayarın dünyasında, sadece veri vardır. Veriyi okuyabilir, değiştirebilir, yeni veri oluşturabilirsiniz - ancak veri olmayan şeylerden bahsedilemez. Tüm bu veriler, sıfır ve birlerden oluşan bitlerin bir araya geldiği uzun diziler olarak depolanır ve bu nedenle temel olarak birbirlerine benzerler. {{index CD, signal}} -_Bits_ are any kind of two-valued things, usually described as zeros and ones. Inside the computer, they take forms such as a high or low electrical charge, a strong or weak signal, or a shiny or dull spot on the surface of a CD. Any piece of discrete information can be reduced to a sequence of zeros and ones and thus represented in bits. +_Bitler_, genellikle sıfırlar ve birler olarak tanımlanan her türlü iki değerli şeydir. Bilgisayarın içinde, yüksek veya düşük bir elektrik yükü, güçlü veya zayıf bir sinyal veya bir CD'nin yüzeyinde parlak veya mat bir leke gibi şekiller alırlar. Herhangi bir soyut bilgi parçası, sıfırların ve birlerin bir dizisine indirgenebilir ve bu şekilde bitlerle temsil edilebilir. -{{index "binary number", radix, "decimal number"}} +{{index "binary number", "decimal number"}} -For example, we can express the number 13 in bits. This works the same way as a decimal number, but instead of 10 different ((digit))s, we have only 2, and the weight of each increases by a factor of 2 from right to left. Here are the bits that make up the number 13, with the weights of the digits shown below them: +Örneğin, sayı 13'ü bitlerle ifade edebiliriz. Bu, ondalık bir sayıyla aynı çalışır, ancak 10 farklı ((rakam)) yerine yalnızca 2 tane vardır ve her birinin ağırlığı sağdan sola doğru bir faktörle artar. İşte 13'ü oluşturan bitler ve rakamların ağırlıkları aşağıda gösterilmiştir: ```{lang: null} 0 0 0 0 1 1 0 1 128 64 32 16 8 4 2 1 ``` -That's the binary number 00001101. Its non-zero digits stand for 8, 4, and 1, and add up to 13. +Bu, ikili sayı 00001101. Sıfır olmayan rakamlar, 8, 4 ve 1'i temsil eder ve toplamda 13'e eşittir. -## Values +## Değerler {{index [memory, organization], "volatile data storage", "hard drive"}} -Imagine a sea of bits—an ocean of them. A typical modern computer has more than 100 billion bits in its volatile data storage (working memory). Nonvolatile storage (the hard disk or equivalent) tends to have yet a few orders of magnitude more. +Bitlerden oluşan bir denizi, bir okyanusu hayal edin. Tipik bir modern bilgisayarın, geçici veri depolama alanında (çalışma belleği) 100 milyarın üzerinde biti vardır. Kalıcı depolamaysa(sabit disk veya benzeri) genellikle birkaç kat daha fazla sayıda bit barındırır. -To be able to work with such quantities of bits without getting lost, we separate them into chunks that represent pieces of information. In a JavaScript environment, those chunks are called _((value))s_. Though all values are made of bits, they play different roles. Every value has a ((type)) that determines its role. Some values are numbers, some values are pieces of text, some values are functions, and so on. +Bu miktardaki bitlerle kaybolmadan çalışabilmek için, onları bilgi parçalarını temsil eden parçalara ayırırız. Bir JavaScript ortamında, bu parçalara ((_değer_))ler denir. Tüm değerler bitlerden oluşsa da, farklı roller üstlenirler. Her değerin rolünü belirleyen bir ((_tür_))ü vardır. Bazı değerler sayıdır, bazıları metin parçalarıdır, bazıları fonksiyonlardır ve benzeri. {{index "garbage collection"}} -To create a value, you must merely invoke its name. This is convenient. You don't have to gather building material for your values or pay for them. You just call for one, and _whoosh_, you have it. Of course, values are not really created from thin air. Each one has to be stored somewhere, and if you want to use a gigantic number of them at the same time, you might run out of computer memory. Fortunately, this is a problem only if you need them all simultaneously. As soon as you no longer use a value, it will dissipate, leaving behind its bits to be recycled as building material for the next generation of values. +Bir değer oluşturmak için, yalnızca adını çağırmanız gerekir. Bu kullanışlıdır. Değerleriniz için yapı malzemesini toplamanıza veya ödeme yapmanıza gerek yoktur. Sadece bir tane çağırırsınız ve _şup_, ona sahip olursunuz. Tabii ki, değerler gerçekten birdenbire hiçlikten yaratılmaz. Her biri bir yerde depolanmalıdır ve eğer hepsini aynı anda kullanmak isterseniz, bilgisayar belleği tükenebilir. Neyse ki, bu sadece hepsine aynı anda ihtiyacınız varsa bir problem olur. Bir değeri artık kullanmadığınızda, o dağılır ve arkasında bitlerini bırakır, böylece bir sonraki nesil değerler için yapı malzemesi olarak geri dönüştürülebilir. -The remainder of this chapter introduces the atomic elements of JavaScript programs, that is, the simple value types and the operators that can act on such values. +Bu bölümün geri kalanı, JavaScript programlarının atomik unsurlarını, yani basit değer tiplerini ve bu tür değerler üzerinde işlem yapabilen operatörleri tanıtır. -## Numbers +## Sayılar {{index [syntax, number], number, [number, notation]}} -Values of the _number_ type are, unsurprisingly, numeric values. In a JavaScript program, they are written as follows: +_Sayı_ türündeki değerler, beklenildiği gibi, sayısal değerlerdir. Bir JavaScript programında, şu şekilde yazılırlar: ``` 13 @@ -57,21 +57,22 @@ Values of the _number_ type are, unsurprisingly, numeric values. In a JavaScript {{index "binary number"}} -Using that in a program will cause the bit pattern for the number 13 to come into existence inside the computer's memory. +Bunu bir programda kullanmak, bilgisayar belleğinde sayı 13 için bit deseninin varlığını ortaya çıkarır. {{index [number, representation], bit}} -JavaScript uses a fixed number of bits, 64 of them, to store a single number value. There are only so many patterns you can make with 64 bits, which limits the number of different numbers that can be represented. With _N_ decimal ((digit))s, you can represent 10^N^ numbers. Similarly, given 64 binary digits, you can represent 2^64^ different numbers, which is about 18 quintillion (an 18 with 18 zeros after it). That's a lot. +JavaScript, bir adet sayı değeri saklamak için sabit olarak 64 bit kullanır. 64 bit ile yapabileceğiniz sadece belirli bir sayıda desen vardır, bu da temsil edilebilecek farklı sayıların sayısını sınırlar. _N_ ondalık ((basamak)) ile 10^N^ adet farklı sayıyı temsil edebilirsiniz. Benzer şekilde, 64 adet ikilik sayı basamakları ile 2^64^ farklı sayıyı temsil edebilirsiniz, bu da yaklaşık olarak 18 katrilyon (18'in arkasında 18 sıfır olan bir sayı), yani çok fazla. -Computer memory used to be much smaller, and people tended to use groups of 8 or 16 bits to represent their numbers. It was easy to accidentally _((overflow))_ such small numbers—to end up with a number that did not fit into the given number of bits. Today, even computers that fit in your pocket have plenty of memory, so you are free to use 64-bit chunks, and you need to worry about overflow only when dealing with truly astronomical numbers. +Bilgisayar belleği eskiden çok daha küçüktü ve insanlar sayılarını temsil etmek için 8 veya 16 bitlik gruplar kullanma eğilimindeydi. Bu tür küçük sayılarla işlemler yaparken kazara ((taşma)) durumuyla karşılaşmak, yani verilen bit sayısını aşan bir sayıya yanlışlıkla ulaşmak kolaydı. Bugün, cebinizdeki telefon adlı bilgisayarlar bile yeterince belleğe sahiptir, bu yüzden 64 bitlik parçaları özgürce kullanabilirsiniz ve gerçekten astronomik sayılarla uğraşmadığınız sürece taşma sorunuyla ilgilenmeniz gerekmez. {{index sign, "floating-point number", "sign bit"}} -Not all whole numbers less than 18 quintillion fit in a JavaScript number, though. Those bits also store negative numbers, so one bit indicates the sign of the number. A bigger issue is representing nonwhole numbers. To do this, some of the bits are used to store the position of the decimal point. The actual maximum whole number that can be stored is more in the range of 9 quadrillion (15 zeros)—which is still pleasantly huge. +The actual maximum whole number that can be stored is more in the range of 9 quadrillion (15 zeros)—which is still pleasantly huge. +Ancak, 18 katrilyonun altında kalan tüm tam sayılar bir JavaScript sayısına sığmaz. Bu bitler ayrıca negatif sayıları da saklar, bu nedenle bir bit sayının artı veya eksi olup olmadığını gösterir. Daha büyük bir sorunsa tam olmayan sayıları temsil etmektir. Bunun için, sayı bitlerinin bazıları ondalık noktanın konumunu saklamak için kullanılır. Depolanabilen asıl maksimum tam sayı, 9 katrilyon aralığındadır (15 sıfır). {{index [number, notation], "fractional number"}} -Fractional numbers are written using a dot: +Kesirli sayılar bir nokta kullanılarak yazılır: ``` 9.81 @@ -80,22 +81,23 @@ Fractional numbers are written using a dot: {{index exponent, "scientific notation", [number, notation]}} For very big or very small numbers, you may also use scientific notation by adding an _e_ (for _exponent_), followed by the exponent of the number: +Çok büyük veya çok küçük sayılar için, sayının üssünü belirten bir e (((_üs/exponent_)) için) ekleyerek bilimsel gösterim de kullanabilirsiniz: ``` 2.998e8 ``` -That's 2.998 × 10^8^ = 299,800,000. +Bu, 2.998 × 10^8^ = 299,800,000'dir. {{index pi, [number, "precision of"], "floating-point number"}} -Calculations with whole numbers (also called _((integer))s_) that are smaller than the aforementioned 9 quadrillion are guaranteed to always be precise. Unfortunately, calculations with fractional numbers are generally not. Just as π (pi) cannot be precisely expressed by a finite number of decimal digits, many numbers lose some precision when only 64 bits are available to store them. This is a shame, but it causes practical problems only in specific situations. The important thing is to be aware of it and treat fractional digital numbers as approximations, not as precise values. +Yukarıda bahsedilen 9 katrilyonun altındaki tüm tam sayılarla yapılan hesaplamalar her zaman kesindir. Ne yazık ki, tam olmayan sayılarla yapılan hesaplamalarsa genellikle kesin değildir. Pi (π) gibi birçok sayı, yalnızca 64 bit kullanılarak saklandığında bazı hassasiyetlerini kaybeder. Bu bir dezavantaj olsa da yalnızca belirli durumlarda yalnızca pratik problemlere neden olur. Önemli olan bunun farkında olmak ve tam olmayan sayıları kesin değerler olarak değil, yaklaşımlar olarak ele almaktır. -### Arithmetic +### Aritmetik {{index [syntax, operator], operator, "binary operator", arithmetic, addition, multiplication}} -The main thing to do with numbers is arithmetic. Arithmetic operations such as addition or multiplication take two number values and produce a new number from them. Here is what they look like in JavaScript: +Sayılarla yapılan temel işlem aritmetiktir. Toplama veya çarpma gibi aritmetik işlemler iki sayı değerini alır ve bunlardan yeni bir sayı üretir. JavaScript'te bunlar şu şekildedir: ```{meta: "expr"} 100 + 4 * 11 @@ -103,11 +105,11 @@ The main thing to do with numbers is arithmetic. Arithmetic operations such as a {{index [operator, application], asterisk, "plus character", "* operator", "+ operator"}} -The `+` and `*` symbols are called _operators_. The first stands for addition and the second stands for multiplication. Putting an operator between two values will apply it to those values and produce a new value. +`+` ve `*` sembolleri ((_operatör_)) olarak adlandırılır. İlk sembol toplamayı temsil eder ve ikincisi çarpma işlemini temsil eder. İki değer arasına bir operatör koymak işlemin bu değerlere uygulanmasına ve yeni bir değer üretmesine sebep olur. {{index grouping, parentheses, precedence}} -Does this example mean "Add 4 and 100, and multiply the result by 11", or is the multiplication done before the adding? As you might have guessed, the multiplication happens first. As in mathematics, you can change this by wrapping the addition in parentheses: +Bu örnek, "4'e 100'ü ekle ve sonucu 11 ile çarp" mı demektir, yoksa çarpma işlemi eklemeden önce mi yapılır? Tahmin ettiğiniz gibi, çarpma önce gerçekleşir. Matematikte olduğu gibi, bunu parantez içine alarak değiştirebilirsiniz: ```{meta: "expr"} (100 + 4) * 11 @@ -115,33 +117,32 @@ Does this example mean "Add 4 and 100, and multiply the result by 11", or is the {{index "hyphen character", "slash character", division, subtraction, minus, "- operator", "/ operator"}} -For subtraction, there is the `-` operator. Division can be done with the `/` operator. +Çıkarma için `-` operatörü bulunur. Bölme işlemi `/` operatörü ile yapılır. -When operators appear together without parentheses, the order in which they are applied is determined by the _((precedence))_ of the operators. The example shows that multiplication comes before addition. The `/` operator has the same precedence as `*`. Likewise, `+` and `-` have the same precedence. When multiple operators with the same precedence appear next to each other, as in `1 - 2 + 1`, they are applied left to right: `(1 - 2) + 1`. +Operatörler parantez olmadan bir araya geldiğinde, uygulanma sırası operatörlerin ((_önceliği_)) tarafından belirlenir. Örnek, çarpmanın toplamadan önce geldiğini gösterir. `/` operatörünün önceliği `*` ile aynıdır. Benzer şekilde, `+` ve `-` aynı önceliğe sahiptir. Aynı önceliğe sahip birden çok operatör yan yana geldiğinde, örneğin `1 - 2 + 1`, soldan sağa uygulanır: `(1 - 2) + 1`. -Don't worry too much about these precedence rules. When in doubt, just add parentheses. +Bu öncelik kuralları hakkında çok fazla endişelenmeyin. Şüphede kaldığınızda, sadece parantez ekleyin. {{index "modulo operator", division, "remainder operator", "% operator"}} -There is one more arithmetic operator, which you might not immediately recognize. The `%` symbol is used to represent the _remainder_ operation. `X % Y` is the remainder of dividing `X` by `Y`. For example, `314 % 100` produces `14`, and `144 % 12` gives `0`. The remainder operator's precedence is the same as that of multiplication and division. You'll also often see this operator referred to as _modulo_. +Hemen tanıyamayabileceğiniz biraz farklı olan bir aritmetik operatör daha var. `%` sembolü _kalan_ işlemi temsil etmek için kullanılır. `X % Y`, `X`'i `Y` ile böldüğünüzde kalanı verir. Örneğin, `314 % 100` `14` üretir ve `144 % 12` ise `0` verir. Kalan operatörünün önceliği, çarpma ve bölme işlemiyle aynıdır. Bu operatör aynı zamanda _modülo_ olarak da adlandırılır. -### Special numbers +### Özel sayılar {{index [number, "special values"], infinity}} -There are three special values in JavaScript that are considered numbers but don't behave like normal numbers. The first two are `Infinity` and `-Infinity`, which represent the positive and negative infinities. `Infinity - 1` is still `Infinity`, and so on. Don't put too much trust in infinity-based computation, though. It isn't mathematically sound, and it will quickly lead to the next special number: `NaN`. - +JavaScript'te normal sayılar gibi davranmayan ancak sayı olarak değerlendirilen üç adet özel değer vardır. İlk ikisi `Infinity` ve `-Infinity`, pozitif ve negatif sonsuzlukları temsil eder. `Infinity - 1` hala `Infinity`'dir ve benzeri. Ancak sonsuzluk tabanlı hesaplara fazla güvenmeyin. Matematiksel olarak sağlam değildir ve hızla bir sonraki özel sayıya yol açacaktır: `NaN`. {{index NaN, "not a number", "division by zero"}} -`NaN` stands for "not a number", even though it _is_ a value of the number type. You'll get this result when you, for example, try to calculate `0 / 0` (zero divided by zero), `Infinity - Infinity`, or any number of other numeric operations that don't yield a meaningful result. +`NaN`, "sayı değil" anlamına gelir, ancak _sayı türünden bir değerdir_. Örneğin `0 / 0` (sıfır bölü sıfır), `Infinity - Infinity` veya anlamlı bir sonuç vermeyen diğer sayısal işlemleri hesaplamaya çalıştığınızda da bu sonucu alırsınız. -## Strings +## Dizeler {{indexsee "grave accent", backtick}} {{index [syntax, string], text, character, [string, notation], "single-quote character", "double-quote character", "quotation mark", backtick}} -The next basic data type is the _((string))_. Strings are used to represent text. They are written by enclosing their content in quotes. +Sonraki temel veri türü _((dize))_ dir. Dizeler metni temsil etmek için kullanılır. İçeriklerini tırnak işaretleri içine alarak yazılırlar. ``` `Down on the sea` @@ -149,28 +150,29 @@ The next basic data type is the _((string))_. Strings are used to represent text 'Float on the ocean' ``` -You can use single quotes, double quotes, or backticks to mark strings, as long as the quotes at the start and the end of the string match. +Dizeleri işaretlemek için başlangıç ve sonundaki tırnaklar eşleştiği sürece tek tırnak, çift tırnak veya ters tırnaklar kullanabilirsiniz. {{index "line break", "newline character"}} -You can put almost anything between quotes to have JavaScript make a string value out of it. But a few characters are more difficult. You can imagine how putting quotes between quotes might be hard, since they will look like the end of the string. _Newlines_ (the characters you get when you press [enter]{keyname}) can be included only when the string is quoted with backticks (`` ` ``). +JavaScript'te neredeyse her şeyi tırnaklar arasına koyarak dize değeri yapmasını sağlayabilirsiniz. Ancak birkaç karakter daha zordur. Tırnakların arasına tırnak koymak zor olabilir, çünkü bunlar dizenin sonu gibi görünecektir. _Satır sonları_ (klavyede [enter]{keyname} tuşuna basarak elde edilen karakter) yalnızca ters tırnaklarla (`` ` ``) alıntılanmış dizelerde dahil edilebilir. {{index [escaping, "in strings"], ["backslash character", "in strings"]}} -To make it possible to include such characters in a string, the following notation is used: a backslash (`\`) inside quoted text indicates that the character after it has a special meaning. This is called _escaping_ the character. A quote that is preceded by a backslash will not end the string but be part of it. When an `n` character occurs after a backslash, it is interpreted as a newline. Similarly, a `t` after a backslash means a ((tab character)). Take the following string: +Bu tür karakterleri bir dizeye dahil etmeyi mümkün kılmak için ters bölü çubuğu (`\`) gösterimi kullanılır ve tırnak içindeki metin içinde onun sonrasındaki karakterin özel bir anlamı olduğunu belirtir. Bu, karakterin _kaçırılması_ olarak adlandırılır. Bir ters bölü çubuğundan sonra gelen bir tırnak dizeyi sonlandırmaz, ancak onun bir parçası olur. Bir ters bölü çubuğu (`\`) sonrasında bir `n` karakteri varsa, bu bir satır sonu olarak yorumlanır. Benzer şekilde, bir ters bölü çubuğu (`\`) sonrasında bir `t` karakteri, bir ((tab karakteri)) anlamına gelir. Aşağıdaki dizeyi düşünün: ``` "This is the first line\nAnd this is the second" ``` -This is the actual text is that string: +Bu, dizenin gerçek metni: ```{lang: null} This is the first line And this is the second ``` -There are, of course, situations where you want a backslash in a string to be just a backslash, not a special code. If two backslashes follow each other, they will collapse together, and only one will be left in the resulting string value. This is how the string "_A newline character is written like `"`\n`"`._" can be expressed: +This is how the string "_A newline character is written like `"`\n`"`._" can be expressed: +Elbette, bir dizeye bir ters bölü çubuğunun özel bir kod değil yalnızca bir ters bölü çubuğu olmasını istediğiniz durumlar da vardır. Ardışık olarak iki ters bölü çubuğu takip ederse, bunlar birleşir ve sonuçta değer dizesinde yalnızca bir tane kalır. Aşağıdaki dize "_A newline character is written like `"`\n`"`._" olarak ifade edilebilir: ``` "A newline character is written like \"\\n\"." @@ -180,37 +182,40 @@ There are, of course, situations where you want a backslash in a string to be ju {{index [string, representation], Unicode, character}} -Strings, too, have to be modeled as a series of bits to be able to exist inside the computer. The way JavaScript does this is based on the _((Unicode))_ standard. This standard assigns a number to virtually every character you would ever need, including characters from Greek, Arabic, Japanese, Armenian, and so on. If we have a number for every character, a string can be described by a sequence of numbers. And that's what JavaScript does. +Dizeler de bilgisayarın içinde var olabilmek için bir dizi bitler olarak modellenmelidir. JavaScript'in bunu yapmasının yolu _((Unicode))_ standardına dayanmaktadır. Bu standart, Yunanca, Arapça, Japonca, Ermenice ve diğer diller de dahil olmak üzere ihtiyacınız olan hemen hemen her karaktere bir spesifik bir numara atar. Her karakter için bir sayımız olduğuna göre, bir dize bir dizi numara ile açıklanabilir. Ve işte JavaScript bunu yapıyor. {{index "UTF-16", emoji}} -There's a complication though: JavaScript's representation uses 16 bits per string element, which can describe up to 2^16^ different characters. However, Unicode defines more characters than that—about twice as many, at this point. So some characters, such as many emoji, take up two "character positions" in JavaScript strings. We'll come back to this in [Chapter ?](higher_order#code_units). +Ancak bir karmaşıklık var: JavaScript dize temsilinde dizenin her karakterini temsil etmek için ancak 16 bit yani 2^16^ değerine kadar farklı karakteri açıklayabiliyor. Ancak Unicode, bu noktada, bunun yaklaşık iki katı kadar daha fazla karakteri tanımlar. Bu nedenle, birçok emoji gibi bazı karakterler, JavaScript dizelerinde iki "karakter konumu" kaplar. Buna [bölüm ?'da](higher_order#code_units)'da geri döneceğiz. {{index "+ operator", concatenation}} Strings cannot be divided, multiplied, or subtracted. The `+` operator _can_ be used on them, not to add, but to _concatenate_—to glue two strings together. The following line will produce the string `"concatenate"`: +Dizeler bölünemez, çarpılamaz veya çıkarılamaz. `+` operatörü onlar üzerinde _kullanılabilir_, ancak ekleme değil iki diziyi _birleştirmek_, yani yapıştırmak için. Aşağıdaki satır `"concatenate"` dizesini üretecektir: ```{meta: "expr"} "con" + "cat" + "e" + "nate" ``` -String values have a number of associated functions (_methods_) that can be used to perform other operations on them. I'll say more about these in [Chapter ?](data#methods). +String values have a number of associated functions (_methods_) that can be used to perform other operations on them. I'll say more about these in . +Dize değerleri üzerinde, onlarla diğer işlemleri gerçekleştirmek için kullanılabilecek bir dizi ilgili fonksiyonlar(_metodlar_) bulunur. Bunlar hakkında daha fazla bilgiyi [bölüm ?'da](data#methods) vereceğim. {{index interpolation, backtick}} -Strings written with single or double quotes behave very much the same—the only difference lies in which type of quote you need to escape inside of them. Backtick-quoted strings, usually called _((template literals))_, can do a few more tricks. Apart from being able to span lines, they can also embed other values. +Tek tırnak veya çift tırnakla yazılan dizeler çok benzer şekilde davranır—tek fark, içlerinde hangi tür tırnak karakterini kaçırmanız gerektiğindedir. Geri tırnakla oluşturulmuş dizeler, genellikle _((template literals))_ olarak adlandırılır ve birkaç daha iyi şeyler vardır. Satır soru karakterlerini içlerinde yazabilmenizin yanı sıra, dizenizin içerisine başka dinamik değerler de gömmenizi sağlarlar. ```{meta: "expr"} `half of 100 is ${100 / 2}` ``` When you write something inside `${}` in a template literal, its result will be computed, converted to a string, and included at that position. This example produces "_half of 100 is 50_". +Bir şablon literalde `${}` içine bir şey yazarsanız, sonucu hesaplanır, bir dizeye dönüştürülür ve dizenin içerisinde yazdığınız o konumda dahil edilir. Bu örnek "_half of 100 is 50_" dizesini üretir. -## Unary operators +## Tekil operatörler {{index operator, "typeof operator", type}} -Not all operators are symbols. Some are written as words. One example is the `typeof` operator, which produces a string value naming the type of the value you give it. +Tüm operatörler semboller olarak yazılmaz, bazıları kelimeler olarak yazılır. Bu operatörlere bir örnek `typeof` operatörüdür. Bu operatör verdiğiniz değerin türünün adını içeren bir dize değeri üretir. ``` console.log(typeof 4.5) @@ -223,28 +228,28 @@ console.log(typeof "x") {{id "console.log"}} -We will use `console.log` in example code to indicate that we want to see the result of evaluating something. More about that in the [next chapter](program_structure). +Örnek kodlarda değerlendirmek istediğimiz kodun sonucunu görebilmek için `console.log` kullanacağız. Bununla ilgili daha fazla bilgiye [sonraki bölümde](program_structure) ulaşabilirsiniz. {{index negation, "- operator", "binary operator", "unary operator"}} -The other operators shown so far in this chapter all operated on two values, but `typeof` takes only one. Operators that use two values are called _binary_ operators, while those that take one are called _unary_ operators. The minus operator can be used both as a binary operator and as a unary operator. +Bu bölümde şimdiye kadar gösterilen diğer operatörlerin hepsi iki değer üzerinde işlem yaparken, typeof sadece bir değer alır. İki değer kullanan operatörler _ikili operatörler_ olarak adlandırılırken, bir tane alanlar _tekil operatörler_ olarak adlandırılır. Eksi operatörü hem ikili operatör olarak hem de tekil operatör olarak kullanılabilir. ``` console.log(- (10 - 2)) // → -8 ``` -## Boolean values +## Boolean değerleri {{index Boolean, operator, true, false, bit}} -It is often useful to have a value that distinguishes between only two possibilities, like "yes" and "no" or "on" and "off". For this purpose, JavaScript has a _Boolean_ type, which has just two values, true and false, written as those words. +"Evet" ve "hayır" veya "açık" ve "kapalı" gibi yalnızca iki olasılığı birbirinden ayıran bir değere sahip olmak genellikle faydalıdır. Bu amaçla JavaScript'te, birebir bu kelimelerle `true` ve `false` olarak yazılan ve yalnızca iki değere sahip olan bir _Boolean_ türü vardır. -### Comparison +### Karşılaştırma {{index comparison}} -Here is one way to produce Boolean values: +İşte Boolean değerlerini üretmenin bir yolu: ``` console.log(3 > 2) @@ -255,9 +260,9 @@ console.log(3 < 2) {{index [comparison, "of numbers"], "> operator", "< operator", "greater than", "less than"}} -The `>` and `<` signs are the traditional symbols for "is greater than" and "is less than", respectively. They are binary operators. Applying them results in a Boolean value that indicates whether they hold true in this case. +`>` ve `<` işaretleri, sırasıyla "büyüktür" ve "küçüktür" için geleneksel sembollerdir. Bunlar ikili operatörlerdir. Bu operatörleri kullanmak, bu durumda doğru olup olmadığını gösteren bir Boolean değeri üretir. -Strings can be compared in the same way: +Dizeler de aynı şekilde karşılaştırılabilir: ``` console.log("Aardvark" < "Zoroaster") @@ -266,11 +271,11 @@ console.log("Aardvark" < "Zoroaster") {{index [comparison, "of strings"]}} -The way strings are ordered is roughly alphabetic but not really what you'd expect to see in a dictionary: uppercase letters are always "less" than lowercase ones, so `"Z" < "a"`, and nonalphabetic characters (!, -, and so on) are also included in the ordering. When comparing strings, JavaScript goes over the characters from left to right, comparing the ((Unicode)) codes one by one. +Dizelerin sıralanma şekli yaklaşık olarak alfabetiktir, ancak bir sözlükte görmeyi beklediğiniz gibi değildir: büyük harfler her zaman küçük harflerden "daha azdır", bu nedenle "Z" < "a" ifadesi doğrudur ve alfabetik olmayan karakterler (!, -, ve benzeri) de sıralamaya dahildir. Dizeler karşılaştırıldığında, JavaScript karakterleri soldan sağa doğru geçer ve onlara atanmış sayısal değerlerden oluşan Unicode kodlarını bir birine karşı karşılaştırır. {{index equality, ">= operator", "<= operator", "== operator", "!= operator"}} -Other similar operators are `>=` (greater than or equal to), `<=` (less than or equal to), `==` (equal to), and `!=` (not equal to). +Diğer benzer operatörler `>=` (büyük eşittir), `<=` (küçük eşittir), `==` (eşittir) ve `!=` (eşit değildir). ``` console.log("Garnet" != "Ruby") @@ -281,24 +286,24 @@ console.log("Pearl" == "Amethyst") {{index [comparison, "of NaN"], NaN}} -There is only one value in JavaScript that is not equal to itself, and that is `NaN` ("not a number"). +JavaScript'te kendine eşit olmayan yalnızca bir değer vardır, o da NaN ("not a number"). ``` console.log(NaN == NaN) // → false ``` -`NaN` is supposed to denote the result of a nonsensical computation, and as such, it isn't equal to the result of any _other_ nonsensical computations. +`NaN`, anlamsız bir hesaplamanın sonucunu belirtmek için kullanılır ve bu nedenle, başka anlamsız hesaplamaların sonucuyla da eşit değildir. -### Logical operators +### Mantıksal operatörler {{index reasoning, "logical operators"}} -There are also some operations that can be applied to Boolean values themselves. JavaScript supports three logical operators: _and_, _or_, and _not_. These can be used to "reason" about Booleans. +Boolean değerlere kendilerine uygulanabilen bazı işlemler de vardır. JavaScript, üç mantıksal operatörü destekler: _ve_, _veya_ ve _değil_. Bunlar, Boolean değerleri hakkında "akıl yürütmek" için kullanılabilir. {{index "&& operator", "logical and"}} -The `&&` operator represents logical _and_. It is a binary operator, and its result is true only if both the values given to it are true. +`&&` operatörü mantıksal _ve_'yi temsil eder. Bu, ikili bir operatördür ve verilen değerlerin her ikisi de doğruysa sonucu `true` değeri olur. ``` console.log(true && false) @@ -309,7 +314,7 @@ console.log(true && true) {{index "|| operator", "logical or"}} -The `||` operator denotes logical _or_. It produces true if either of the values given to it is true. +`||` operatörü, mantıksal _veya_'yı gösterir. Verilen değerlerden herhangi biri doğru ise `true` değerini üretir. ``` console.log(false || true) @@ -321,10 +326,11 @@ console.log(false || false) {{index negation, "! operator"}} _Not_ is written as an exclamation mark (`!`). It is a unary operator that flips the value given to it—`!true` produces `false` and `!false` gives `true`. +_Değil operatörü_, bir tekil operatör olarak ünlem işareti (`!`) ile yazılır. Verilen değeri ters çeviren bir operatördür — `!true`, `false` değerini üretir ve `!false` ise `true` değerini üretir. {{index precedence}} -When mixing these Boolean operators with arithmetic and other operators, it is not always obvious when parentheses are needed. In practice, you can usually get by with knowing that of the operators we have seen so far, `||` has the lowest precedence, then comes `&&`, then the comparison operators (`>`, `==`, and so on), and then the rest. This order has been chosen such that, in typical expressions like the following one, as few parentheses as possible are necessary: +Bu Boolean operatörlerini aritmetik ve diğer operatörlerle karıştırdığınızda, parantezlere ne zaman ihtiyaç duyacağımız her zaman çok da belli değildir. Uygulamada, şimdiye kadar gördüğümüz operatörlerden, `||` operatörünün en düşük önceliğe sahip olduğunu, sonra `&&` operatörünün daha öncelikli olduğunu, ardından karşılaştırma operatörlerinin (`>`, `==`, vb.) ve sonra geri kalanın daha öncelikli olduğunu bilerek işleri genellikle yürütebilirsiniz. Bu sıra, aşağıdaki gibi tipik ifadelerde mümkün olduğunca az parantez gerektirecek şekilde seçilmiştir: ```{meta: "expr"} 1 + 1 == 2 && 10 * 10 > 50 @@ -332,7 +338,7 @@ When mixing these Boolean operators with arithmetic and other operators, it is n {{index "conditional execution", "ternary operator", "?: operator", "conditional operator", "colon character", "question mark"}} -The last logical operator we will look at is not unary, not binary, but _ternary_, operating on three values. It is written with a question mark and a colon, like this: +Bakacağımız son mantıksal operatör, tekil değil, ikili değil, ancak üç değere işlem yapan üçlü operatördür. Soru işareti ve iki nokta üst üste ile şu şekilde yazılır: ``` console.log(true ? 1 : 2); @@ -341,23 +347,23 @@ console.log(false ? 1 : 2); // → 2 ``` -This one is called the _conditional_ operator (or sometimes just _the ternary operator_ since it is the only such operator in the language). The operator uses the value to the left of the question mark to decide which of the two other values to "pick". If you write `a ? b : c`, the result will be `b` when `a` is true and `c` otherwise. +Bu, _koşullu_ operatör olarak adlandırılır (veya bazen sadece _üçlü operatör_ olarak adlandırılır, çünkü dildeki bu türde var olan tek operatördür). Operatör, soru işaretinin solundaki değeri iki diğer değerden hangisini "seçeceğine" karar vermek için kullanır. `a ? b : c` yazarsanız, `a` değeri `true` olduğunda sonuç `b` veya `a` değeri `false`olduğu takdirde sonuç `c` olur. -## Empty values +## Boş değerler {{index undefined, null}} -There are two special values, written `null` and `undefined`, that are used to denote the absence of a _meaningful_ value. They are themselves values, but they carry no information. +_Anlamlı_ bir değerin yokluğunu belirtmek için kullanılan `null` ve `undefined` olarak yazılan iki özel değer vardır. Kendileri, kendi başlarına birer değerdirler ancak hiçbir bilgi taşımazlar. -Many operations in the language that don't produce a meaningful value yield `undefined` simply because they have to yield _some_ value. +Dil içinde herhangi bir değer üretmeyen bir işlem, _herhangi bir_ değeri üretmek zorunda olduğundan ötürü sadece `undefined` değerini üretir. -The difference in meaning between `undefined` and `null` is an accident of JavaScript's design, and it doesn't matter most of the time. In cases where you actually have to concern yourself with these values, I recommend treating them as mostly interchangeable. +`undefined` ve `null` arasındaki anlam farkı, JavaScript'in tasarımının bir kazasıdır ve çoğu zaman önemli değildir. Bu değerlerle gerçekten ilgilenmeniz gereken durumlarda, onları genellikle birbirinin yerine kullanılabilir olarak ele almanızı öneririm. -## Automatic type conversion +## Otomatik tür dönüşümü {{index NaN, "type coercion"}} -In the Introduction, I mentioned that JavaScript goes out of its way to accept almost any program you give it, even programs that do odd things. This is nicely demonstrated by the following expressions: +Giriş bölümünde, JavaScript'in hemen hemen her türde programı kabul etmeye çalıştığını, hatta garip şeyler yapan programları bile kabul ettiğini belirttim. Bunun güzel bir örneği aşağıdaki ifadelerle gösterilmiştir: ``` console.log(8 * null) @@ -374,15 +380,15 @@ console.log(false == 0) {{index "+ operator", arithmetic, "* operator", "- operator"}} -When an operator is applied to the "wrong" type of value, JavaScript will quietly convert that value to the type it needs, using a set of rules that often aren't what you want or expect. This is called _((type coercion))_. The `null` in the first expression becomes `0` and the `"5"` in the second expression becomes `5` (from string to number). Yet in the third expression, `+` tries string concatenation before numeric addition, so the `1` is converted to `"1"` (from number to string). +Bir operatörün "yanlış" türdeki bir değere uygulandığında, JavaScript o değeri sessizce ihtiyaç duyduğu türe dönüştürür, ancak bunu genellikle istemediğiniz veya beklemediğiniz kurallar kullanarak yapar. Buna _((tür dönüşümü))_ denir. İlk ifadedeki `null` `0` olur ve ikinci ifadedeki `"5"` değeri `5`'e dönüşür olur (dize türünden sayıya). Ancak üçüncü ifadede `+`, sayısal eklemeye geçmeden önce dize birleştirme denemesi yapar, bu nedenle `1` değeri "1" değerine dönüştürülür (sayıdan dizeye). {{index "type coercion", [number, "conversion to"]}} -When something that doesn't map to a number in an obvious way (such as `"five"` or `undefined`) is converted to a number, you get the value `NaN`. Further arithmetic operations on `NaN` keep producing `NaN`, so if you find yourself getting one of those in an unexpected place, look for accidental type conversions. +Açık bir şekilde bir sayıya eşlenmeyen bir şey (örneğin, `"five"` veya `undefined`) sayıya dönüştürüldüğünde, `NaN` değerini elde edersiniz. `NaN` üzerinde yapılan daha fazla aritmetik işlemler, sürekli olarak `NaN` üretir, bu nedenle beklenmedik bir yerde bunlardan birini bulursanız, kazara oluşma ihtimali olan tür dönüşümlerini arayın. {{index null, undefined, [comparison, "of undefined values"], "== operator"}} -When comparing values of the same type using the `==` operator, the outcome is easy to predict: you should get true when both values are the same, except in the case of `NaN`. But when the types differ, JavaScript uses a complicated and confusing set of rules to determine what to do. In most cases, it just tries to convert one of the values to the other value's type. However, when `null` or `undefined` occurs on either side of the operator, it produces true only if both sides are one of `null` or `undefined`. +`==` operatörünü kullanarak aynı türdeki değerleri karşılaştırdığınızda, sonucu tahmin etmek kolaydır: her iki değer de aynı olduğunda `true` değerini almalısınız, tabii `NaN` durumunda hariç. Ancak türler farklı olduğunda, JavaScript ne yapacağını belirlemek ve bir değeri diğer değerin türüne çevirip işlemi devam ettirebilmek için karmaşık ve kafa karıştırıcı bir kural seti kullanır. Çoğu durumda, sadece değerlerden birini diğer değerin türüne dönüştürmeye çalışır. Ancak, operatörün herhangi bir tarafında `null` veya `undefined` göründüğünde, yalnızca her iki tarafın da `null` veya `undefined` değerlerinden biri olduğunda `true` değerini üretir. ``` console.log(null == undefined); @@ -391,23 +397,24 @@ console.log(null == 0); // → false ``` -That behavior is often useful. When you want to test whether a value has a real value instead of `null` or `undefined`, you can compare it to `null` with the `==` or `!=` operator. +Bu davranış genellikle yararlıdır. Bir değerin `null` veya `undefined` yerine gerçek bir değer olup olmadığını test etmek istediğinizde, onu `==` veya `!=` operatörü ile null ile karşılaştırabilirsiniz. {{index "type coercion", [Boolean, "conversion to"], "=== operator", "!== operator", comparison}} -What if you want to test whether something refers to the precise value `false`? Expressions like `0 == false` and `"" == false` are also true because of automatic type conversion. When you do _not_ want any type conversions to happen, there are two additional operators: `===` and `!==`. The first tests whether a value is _precisely_ equal to the other, and the second tests whether it is not precisely equal. Thus `"" === false` is false as expected. +The first tests whether a value is _precisely_ equal to the other, and the second tests whether it is not precisely equal. Thus `"" === false` is false as expected. +Peki ya bir şeyin tam olarak `false` değeri olup olmadığını test etmek istiyorsanız ne olacak? `0 == false` ve `"" == false` gibi ifadeler, otomatik tür dönüşümünden ötürü aynı şekilde `true` değerine çözümlenirler. Herhangi bir tür dönüşümü olmasını _istemiyorsanız_, iki ek operatör vardır: `===` ve `!==`. İlk, bir değerin tam olarak diğerine eşit olup olmadığını test eder ve ikincisi, _tam olarak_ eşit olup olmadığını test eder. Bu nedenle, `"" === false`, ifadesi beklenildiği gibi `false` değerine çözümlenir. -I recommend using the three-character comparison operators defensively to prevent unexpected type conversions from tripping you up. But when you're certain the types on both sides will be the same, there is no problem with using the shorter operators. +Beklenmedik tür dönüşümlerinin sizi zorlamasını önlemek adına üç karakterli karşılaştırma operatörlerini kullanmanızı öneririm. Ancak eğer her iki taraftaki türlerin aynı olacağından eminseniz, kısa operatörleri kullanmakta da bir sorun yoktur. -### Short-circuiting of logical operators +### Mantıksal operatörlerin kısa devre davranışı {{index "type coercion", [Boolean, "conversion to"], operator}} -The logical operators `&&` and `||` handle values of different types in a peculiar way. They will convert the value on their left side to Boolean type in order to decide what to do, but depending on the operator and the result of that conversion, they will return either the _original_ left-hand value or the right-hand value. +`&&` ve `||` mantıksal operatörler, farklı türlerdeki değerleri ilginç bir şekilde işlemektedirler. Ne yapacaklarına karar vermek için sol taraftaki değeri Boolean türüne dönüştürürler, ancak operatöre ve bu dönüşümün sonucuna bağlı olarak, ya _orijinal_ sol taraf değerini ya da sağ taraf değerini döndürürler. {{index "|| operator"}} -The `||` operator, for example, will return the value to its left when that value can be converted to true and will return the value on its right otherwise. This has the expected effect when the values are Boolean and does something analogous for values of other types. +Örneğin, `||` operatörü, sol taraftaki değeri `true` değerine dönüştürebiliyorsa o değeri döndürür, aksi takdirde sağ taraftaki değeri döndürür. Bu, değerlerin Boolean olduğunda beklenen etkiyi yapar ve diğer türlerdeki değerler için de benzer bir şey yapar. ``` console.log(null || "user") @@ -418,11 +425,11 @@ console.log("Agnes" || "user") {{index "default value"}} -We can use this functionality as a way to fall back on a default value. If you have a value that might be empty, you can put `||` after it with a replacement value. If the initial value can be converted to false, you'll get the replacement instead. The rules for converting strings and numbers to Boolean values state that `0`, `NaN`, and the empty string (`""`) count as `false`, while all the other values count as `true`. That means `0 || -1` produces `-1`, and `"" || "!?"` yields `"!?"`. +Bu işlevselliği bir varsayılan değere yedek olarak düşmek adına kullanabiliriz. Boş olabilecek bir değeriniz varsa sonrasına `||` operatörünü yazıp yerine varsayılan bir değer olarak gelmesini istediğiniz diğer değeri yazabilirsiniz. Başlangıç ​​değeri eğer `false` değerine dönüştürülebiliyorsa, operatör sonrasına yazdığınız değeri varsayılan değer olarak alırsınız. Dizeleri ve sayıları Boolean değerlere dönüştürme kuralları, `0`, `NaN` ve boş dize (`""`) değerlerinin `false` değeri olarak sayıldığını, diğer tüm değerlerinse `true`değeri olarak sayıldığını belirtir. Bu, `0 || -1` ifadesinin `-1` değerini üreteceğini ve `"" || "!?"` ifadesinin `"!?"`değerini vereceği anlamına gelir. {{index "?? operator", null, undefined}} -The `??` operator resembles `||`, but returns the value on the right only if the one on the left is null or undefined, not if it is some other value that can be converted to `false`. Often, this is preferable to the behavior of `||`. +`??` operatörü, `||` operatörüne benzer şekilde çalışır ancak soldaki değer yalnızca `null` veya `undefined` değerlerinden biri olduğunda sağdaki değeri döndürür. Genel olarak `??` operatörün davranışı `||` operatörün davranışı yerine tercih edilir. ``` console.log(0 || 100); @@ -435,18 +442,18 @@ console.log(null ?? 100); {{index "&& operator"}} -The `&&` operator works similarly but the other way around. When the value to its left is something that converts to false, it returns that value, and otherwise it returns the value on its right. +`&&` operatörü de benzer şekilde çalışır ancak tam tersi şekildedir. Soldaki ifade `false` değerine dönüştürülebilecek bir şey ise, o değeri döndürür ve aksi takdirde sağdaki değeri döndürür. -Another important property of these two operators is that the part to their right is evaluated only when necessary. In the case of `true || X`, no matter what `X` is—even if it's a piece of program that does something _terrible_—the result will be true, and `X` is never evaluated. The same goes for `false && X`, which is false and will ignore `X`. This is called _((short-circuit evaluation))_. +Bu iki operatörün bir başka önemli özelliği de, operatörün sağ tarafında kalan ifadeleri yalnızca gerekli olduğunda değerlendirmeleridir. `true || X` durumunda, `X` ne olursa olsun - hatta o bir program parçasıysa ve korkunç bir şey yapsa bile - sonuç `true` değeri olacaktır ve `X` asla değerlendirilmeyecektir. Aynı şey, false && X için de geçerlidir, bu false'tur ve X göz ardı edilir. Buna _((kısa devre değerlendirme))_ denir. {{index "ternary operator", "?: operator", "conditional operator"}} -The conditional operator works in a similar way. Of the second and third values, only the one that is selected is evaluated. +Koşullu operatör de benzer bir şekilde çalışır. İkinci ve üçüncü değerlerden yalnızca seçilen değer değerlendirilecektir. -## Summary +## Özet -We looked at four types of JavaScript values in this chapter: numbers, strings, Booleans, and undefined values. Such values are created by typing in their name (`true`, `null`) or value (`13`, `"abc"`). +Bu bölümde dört tür JavaScript değerine baktık: sayılar, dizeler, Booleans ve tanımsız değerler. Bu tür değerler, adlarını (`true`, `null`) veya değerlerini (`13`, `"abc"`) yazarak oluşturulur. -You can combine and transform values with operators. We saw binary operators for arithmetic (`+`, `-`, `*`, `/`, and `%`), string concatenation (`+`), comparison (`==`, `!=`, `===`, `!==`, `<`, `>`, `<=`, `>=`), and logic (`&&`, `||`, `??`), as well as several unary operators (`-` to negate a number, `!` to negate logically, and `typeof` to find a value's type) and a ternary operator (`?:`) to pick one of two values based on a third value. +Operatörlerle değerleri birleştirebilir ve dönüştürebilirsiniz. Aritmetik (`+`, `-`, `*`, `/`, ve `%`), dize birleştirme (`+`), karşılaştırma (`==`, `!=`, `===`, `!==`, `<`, `>`, `<=`, `>=`) ve mantık (`&&`, `||`, `??`) için ikili operatörler, tekil operatörler (bir sayıyı negatif yapmak için `-`, mantıksal olarak olumsuzlamak için `!` ve bir değerin türünü bulmak için `typeof`) ve bir üçüncü bir değere göre diğer iki değerden birisini seçmek adına var olan tek üçlü operatörü (`?:`) gördük. -This gives you enough information to use JavaScript as a pocket calculator but not much more. The [next chapter](program_structure) will start tying these expressions together into basic programs. +Bu, JavaScript'i bir cep hesap makinesi olarak kullanmanız için yeterli bilgiyi verir, ancak çok daha fazlası değil. [Sonraki bölüm](program_structure), bu ifadeleri temel programlara bağlamamıza yardımcı olacak. diff --git a/02_program_structure.md b/02_program_structure.md index 9e729694..8b250096 100644 --- a/02_program_structure.md +++ b/02_program_structure.md @@ -1,8 +1,8 @@ -# Program Structure +# Program Yapısı -{{quote {author: "_why", title: "Why's (Poignant) Guide to Ruby", chapter: true} +{{quote {author: "\_why", title: "Why's (Poignant) Guide to Ruby", chapter: true} -And my heart glows bright red under my filmy, translucent skin and they have to administer 10cc of JavaScript to get me to come back. (I respond well to toxins in the blood.) Man, that stuff will kick the peaches right out your gills! +Ve kalbim, bulanık, saydam cildimin altında parlak kırmızı yanarken beni geri getirmek için 10cc JavaScript uygulamak zorunda kalırlar. (Kandaki toksinlere iyi tepki veririm.) Vay be, o madde doğrudan soluğu keser! quote}} @@ -10,47 +10,47 @@ quote}} {{figure {url: "img/chapter_picture_2.jpg", alt: "Illustration showing a number of tentacles holding chess pieces", chapter: framed}}} -In this chapter, we will start to do things that can actually be called _programming_. We will expand our command of the JavaScript language beyond the nouns and sentence fragments we've seen so far to the point where we can express meaningful prose. +Bu bölümde, gerçek anlamda _programlama_ olarak adlandırılabilecek şeyler yapmaya başlayacağız. Şimdiye kadar gördüğümüz isimler ve cümle parçaları ötesinde JavaScript dilini anlamamızı sağlayacağız, böylece anlamlı bir yazılar ifade edebileceğiz. -## Expressions and statements +## İfade ve beyanlar {{index grammar, [syntax, expression], [code, "structure of"], grammar, [JavaScript, syntax]}} -In [Chapter ?](values), we made values and applied operators to them to get new values. Creating values like this is the main substance of any JavaScript program. But that substance has to be framed in a larger structure to be useful. That's what we'll cover in this chapter. +[?](values) Bölümünde, değerler oluşturduk ve bunlara operatörler uygulayarak yeni değerler elde ettik. Bu şekilde değer oluşturmak, herhangi bir JavaScript programının ana maddesidir. Ancak bu maddenin faydalı olabilmesi için daha büyük bir yapı içerisinde çerçevelenmelidir. İşte bu bölümde ele alacağımız şey budur. {{index "literal expression", [parentheses, expression]}} -A fragment of code that produces a value is called an _((expression))_. Every value that is written literally (such as `22` or `"psychoanalysis"`) is an expression. An expression between parentheses is also an expression, as is a ((binary operator)) applied to two expressions or a ((unary operator)) applied to one. +Bir değer üreten kod parçasına _((ifade))_ denir. Yazılmış olan her değer (örneğin `22` veya `"psikanaliz"`) bir ifadedir. Parantezler arasındaki bir ifade de bir ifade olarak kabul edilir, iki ifadeye uygulanan ((ikili operatör)) veya bir ifadeye uygulanan ((tekli operatör)) de ifadedir. {{index [nesting, "of expressions"], "human language"}} -This shows part of the beauty of a language-based interface. Expressions can contain other expressions in a way similar to how subsentences in human languages are nested—a subsentence can contain its own subsentences, and so on. This allows us to build expressions that describe arbitrarily complex computations. +Bu, dil tabanlı bir arabirimin güzelliğinin bir kısmını gösterir. İfadeler, insan dillerindeki yan cümlelerin iç içe geçmiş olduğu şekilde diğer ifadeleri içerebilir - bir yan cümle kendi yan cümlelerini içerebilir ve böyle devam eder. Bu, istediğimiz şekilde karmaşık hesaplamaları tanımlayan ifadeler oluşturmamıza izin verir. {{index statement, semicolon, program}} -If an expression corresponds to a sentence fragment, a JavaScript _statement_ corresponds to a full sentence. A program is a list of statements. +Bir JavaScript ifadesi bir cümle parçasına karşılık geliyorsa, bir JavaScript beyanı tam bir cümleye karşılık gelir. Bir program, bir beyanlar listesidir. {{index [syntax, statement]}} -The simplest kind of statement is an expression with a semicolon after it. This is a program: +En basit türde bir beyan, ardından bir noktalı virgül bulunan bir ifadedir. Bu bir programdır: ``` 1; !false; ``` -It is a useless program, though. An ((expression)) can be content to just produce a value, which can then be used by the enclosing code. However, a ((statement)) stands on its own, so if it doesn't affect the world, it's useless. It may display something on the screen, as with `console.log`, or change the state of the machine in a way that will affect the statements that come after it. These changes are called _((side effect))s_. The statements in the previous example just produce the values `1` and `true` and then immediately throw them away. This leaves no impression on the world at all. When you run this program, nothing observable happens. +Ancak bu işe yaramaz bir programdır. Bir ((ifade)), sadece bir değer üretmekle yetinebilir, ardından bu değer çevreleyen kod tarafından kullanılabilir. Ancak, bir ((beyan)) kendi başına durur, bu nedenle dünyayı etkilemiyorsa, işe yaramazdır. `console.log` ile olduğu gibi ekranın bir şeyler görüntülemesi veya makinenin durumunu bunlar ardından gelen beyanları etkileyecek şekilde değiştirmesi de olabilir. Bu değişikliklere _((yan etki))_ denir. Önceki örnekteki deyimler sadece `1` ve `true` değerlerini üretir ve hemen sonra onları yok eder. Bu, dünyada hiçbir iz bırakmaz. Bu programı çalıştırdığınızda, gözlemlenebilir hiçbir şey olmaz. {{index "programming style", "automatic semicolon insertion", semicolon}} -In some cases, JavaScript allows you to omit the semicolon at the end of a statement. In other cases, it has to be there, or the next ((line)) will be treated as part of the same statement. The rules for when it can be safely omitted are somewhat complex and error-prone. So in this book, every statement that needs a semicolon will always get one. I recommend you do the same, at least until you've learned more about the subtleties of missing semicolons. +Bazı durumlarda, JavaScript bir beyanın sonundaki noktalı virgülü atlayabilmenize izin verir ancak bazı durumlarda, orada olmalıdır çünkü aksi takdirde bir sonraki ((satır)), aynı beyanın bir parçası olarak işlenebilir. Ne zaman güvenle atlanabileceğine dair kurallar biraz karmaşıktır ve hata yapmaya müsaittir. Bu yüzden bu kitapta, noktalı virgül gerektiren her beyan her zaman bir noktalı virgül ile bitecek. En azından noktalı virgüllerin eksikliği hakkındaki incelikleri daha fazla öğrenene kadar aynısını yapmanızı öneririm. -## Bindings +## Bağlantılar {{indexsee variable, binding}} {{index [syntax, statement], [binding, definition], "side effect", [memory, organization], [state, in binding]}} -How does a program keep an internal state? How does it remember things? We have seen how to produce new values from old values, but this does not change the old values, and the new value must be used immediately or it will dissipate again. To catch and hold values, JavaScript provides a thing called a _binding_, or _variable_: +Bir program nasıl içsel bir durum tutar? Nasıl şeyleri hatırlar? Eski değerlerden yeni değerler üretmeyi gördük, ancak bu eski değerleri değiştirmez ve yeni değer hemen kullanılmalıdır, aksi takdirde tekrar kaybolur. Değerleri yakalamak ve tutmak için JavaScript, bir _bağlantı_ veya _değişken_ adı verilen bir şey sağlar: ``` let caught = 5 * 5; @@ -58,11 +58,11 @@ let caught = 5 * 5; {{index "let keyword"}} -That gives us a second kind of ((statement)). The special word (_((keyword))_) `let` indicates that this sentence is going to define a binding. It is followed by the name of the binding and, if we want to immediately give it a value, by an `=` operator and an expression. +Bu bize bir ikinci tür ((beyan)) verir. Özel bir kelime (((anahtar kelime))) olan `let`, bu cümlenin bir bağlantıyı tanımlayacağını gösterir. Ondan hemen sonra bağlantının adı ve eğer hemen bağlantı tanımlama sırasınfa bir değer vermek istiyorsak, bir `=` operatörü ve bir ifade bulunur. -The example creates a binding called `caught` and uses it to grab hold of the number that is produced by multiplying 5 by 5. +Örnekte, `caught` adında bir bağlantı oluşturulur ve 5'in 5 ile çarpılmasıyla üretilen sayıyı tutmak için kullanılır. -After a binding has been defined, its name can be used as an ((expression)). The value of such an expression is the value the binding currently holds. Here's an example: +Bir bağlantı tanımlanıp oluşturulduktan sonra, adı bir ((ifade)) olarak kullanılabilir. Böyle bir ifadenin değeri, bağlantının o anda tuttuğu değerdir. İşte bir örnek: ``` let ten = 10; @@ -72,7 +72,7 @@ console.log(ten * ten); {{index "= operator", assignment, [binding, assignment]}} -When a binding points at a value, that does not mean it is tied to that value forever. The `=` operator can be used at any time on existing bindings to disconnect them from their current value and have them point to a new one: +Bir bağlantı bir değere işaret ettiğinde, bu onun sonsuza dek o değere bağlı olduğu anlamına gelmez. Mevcut bağlantılar üzerinde istendiğinde `=` operatörü kullanılarak bunları mevcut değerlerinden ayırabilir ve onları yeni bir değere işaret etmesini sağlayabilirsiniz: ``` let mood = "light"; @@ -85,9 +85,9 @@ console.log(mood); {{index [binding, "model of"], "tentacle (analogy)"}} -You should imagine bindings as tentacles rather than boxes. They do not _contain_ values; they _grasp_ them—two bindings can refer to the same value. A program can access only the values to which it still has a reference. When you need to remember something, you either grow a tentacle to hold on to it or reattach one of your existing tentacles to it. +Bağlantıları kutular yerine bir ahtapotun dokunaçları olarak hayal etmelisiniz. Değerleri _içermezler_; onları _kavrarlar_ - iki bağlantı aynı değere atıfta bulunabilir. Bir program sadece hala bir referansı olan değerlere erişebilir. Bir şeyi hatırlamanız gerektiğinde, onu tutmak için bir ahtapot dokunaçı büyütür veya mevcut ahtapot dokunaçlarınızdan birini ona takarsınız. -Let's look at another example. To remember the number of dollars that Luigi still owes you, you create a binding. When he pays back $35, you give this binding a new value: +Başka bir örneğe bakalım. Luigi'nin size hala borçlu olduğu dolar miktarını hatırlamak için bir bağlantı oluşturursunuz. 35 doları size geri ödediğinde, bu bağlantıya yeni bir değer verirsiniz: ``` let luigisDebt = 140; @@ -98,11 +98,11 @@ console.log(luigisDebt); {{index undefined}} -When you define a binding without giving it a value, the tentacle has nothing to grasp, so it ends in thin air. If you ask for the value of an empty binding, you'll get the value `undefined`. +Bir değer vermeden bir bağlantı tanımladığınızda, ahtapot dokungacının kavrayacağı hiçbir şey yoktur, bu yüzden boş havada biter. Boş bir bağlantının değerini isterseniz, `undefined` değerini alırsınız. {{index "let keyword"}} -A single `let` statement may define multiple bindings. The definitions must be separated by commas: +Tek bir `let` beyanı birden fazla bağlantı tanımlayabilir ancak her spesifik isime tanımlanan bağlantılar virgülle ayrılmalıdır: ``` let one = 1, two = 2; @@ -110,7 +110,7 @@ console.log(one + two); // → 3 ``` -The words `var` and `const` can also be used to create bindings, in a similar fashion to `let`: +`var` ve `const` kelimeleri de, `let` ile benzer bir şekilde belirli isimlere bağlantı oluşturmak için kullanılabilir: ``` var name = "Ayda"; @@ -122,20 +122,21 @@ console.log(greeting + name); {{index "var keyword"}} The first of these, `var` (short for "variable"), is the way bindings were declared in pre-2015 JavaScript, when `let` didn't exist yet. I'll get back to the precise way it differs from `let` in the [next chapter](functions). For now, remember that it mostly does the same thing, but we'll rarely use it in this book because it behaves oddly in some situations. +Bunlardan ilki, `var` (kısaltma olarak "variable" - değişken anlamına gelir), 2015 öncesi JavaScript'te bağlantıların nasıl bildirildiğidir, o zamanlarda `let` henüz mevcut değildi. [Sonraki bölümde](functions) `var` bağlantılarının `let` bağlantılarından nasıl farklılık gösterdiğine dair ayrıntılı bilgilere göstereceğim ancak şimdilik, çoğunlukla aynı işi yaptığını hatırlayın. Bu kitapta `var` bağlantılarını nadiren kullanacağız çünkü bazı durumlarda garip davranışları bulunmakta. {{index "const keyword", naming}} -The word `const` stands for _((constant))_. It defines a constant binding, which points at the same value for as long as it lives. This is useful for bindings that just give a name to a value so that you can easily refer to it later. +`const` kelimesi _((constant))_ için kullanılır. Bu, yaşadığı sürece aynı değere işaret eden sabit bir bağlantı tanımlar. Bu, bir değere ad veren ve daha sonra kolayca başvurabileceğiniz bağlantılar için kullanışlıdır. -## Binding names +## Bağlantı isimleri {{index "underscore character", "dollar sign", [binding, naming]}} -Binding names can be any sequence of one or more letters. Digits can be part of binding names—`catch22` is a valid name, for example—but the name must not start with a digit. A binding name may include dollar signs (`$`) or underscores (`_`) but no other punctuation or special characters. +Bağlantı adları bir veya daha fazla harf dizisi olabilir. Rakamlar bağlantı adlarının bir parçası olabilir - örneğin, `catch22` geçerli bir addır - ancak ad bir rakamla başlamamalıdır. Bir bağlantı adı, dolar işaretleri (`$`) veya alt çizgiler (`_`) içerebilir, ancak başka noktalama işaretleri veya özel karakterler içeremez. {{index [syntax, identifier], "implements (reserved word)", "interface (reserved word)", "package (reserved word)", "private (reserved word)", "protected (reserved word)", "public (reserved word)", "static (reserved word)", "void operator", "yield (reserved word)", "enum (reserved word)", "reserved word", [binding, naming]}} -Words with a special meaning, such as `let`, are _((keyword))s_, and may not be used as binding names. There are also a number of words that are "reserved for use" in ((future)) versions of JavaScript, which also can't be used as binding names. The full list of keywords and reserved words is rather long: +`let` gibi özel anlamlı kelimeler _((anahtar kelimeler))_ olarak adlandırılır ve bağlantı adları olarak kullanılamazlar. Ayrıca, bağlantı adları olarak kullanılamayan ((gelecek)) JavaScript sürümlerinde "kullanım için saklanmış" birkaç kelime daha vardır. Tüm anahtar kelimelerin ve saklanmış kelimelerin tam listesi oldukça uzundur: ```{lang: "null"} break case catch class const continue debugger default @@ -147,22 +148,22 @@ switch this throw true try typeof var void while with yield {{index [syntax, error]}} -Don't worry about memorizing this list. When creating a binding produces an unexpected syntax error, check whether you're trying to define a reserved word. +Merak etmeyin, bu listeyi ezberlemenize gerek yok. Bir bağlantı oluştururken beklenmeyen bir sözdizimi hatası oluşturursanız, kullanmaya çalıştığınızın bir saklanmış kelime olup olmadığını kontrol edin. -## The environment +## Çevre {{index "standard environment", [browser, environment]}} -The collection of bindings and their values that exist at a given time is called the _((environment))_. When a program starts up, this environment is not empty. It always contains bindings that are part of the language ((standard)), and most of the time, it also has bindings that provide ways to interact with the surrounding system. For example, in a browser, there are functions to interact with the currently loaded website and to read ((mouse)) and ((keyboard)) input. +Belirli bir zamanda var olan bağlantılar ve bu bağlantıların işaret ettiği değerler topluluğuna _((çevre))_ denir. Bir program başladığında, bu ortam artık boş değildir. Her zaman programlama dilinin bir parçası olan ((standart)) bağlantıları içerir ve çoğu zaman, çevrenin içinde bulunduğu çevre sistemle etkileşim sağlayan bağlantıları da içerir. Örneğin, bir web tarayıcısında, şu anda yüklenmiş web sitesi ile etkileşimde bulunmak ve ((mouse)) ve ((keyboard)) girişini okumak için işlevler vardır. -## Functions +## Fonksiyonlar {{indexsee "application (of functions)", [function, application]}} {{indexsee "invoking (of functions)", [function, application]}} {{indexsee "calling (of functions)", [function, application]}} {{index output, function, [function, application], [browser, environment]}} -A lot of the values provided in the default environment have the type _((function))_. A function is a piece of program wrapped in a value. Such values can be _applied_ in order to run the wrapped program. For example, in a browser environment, the binding `prompt` holds a function that shows a little ((dialog box)) asking for user input. It is used like this: +Ortamda sağlanan varsayılan değerlerin çoğu _((fonksiyon))_ türündedir. Bir fonksiyon, bir değerle sarılmış bir program parçasıdır. Bu tür değerler, sarılmış programı çalıştırmak için _çalıştırılabilir_. Örneğin, bir web tarayıcı ortamında, `prompt` bağlantısı, kullanıcı girişi isteyen küçük bir ((diyalog kutusu)) gösteren bir işleve işaret eder. Bunu şu şekilde kullanırız: ``` prompt("Enter passcode"); @@ -172,19 +173,20 @@ prompt("Enter passcode"); {{index parameter, [function, application], [parentheses, arguments]}} -Executing a function is called _invoking_, _calling_, or _applying_ it. You can call a function by putting parentheses after an expression that produces a function value. Usually you'll directly use the name of the binding that holds the function. The values between the parentheses are given to the program inside the function. In the example, the `prompt` function uses the string that we give it as the text to show in the dialog box. Values given to functions are called _((argument))s_. Different functions might need a different number or different types of arguments. +Bir fonksiyonu çalıştırmak, onu _çağırmak_ veya _uygulamak_ veya _uygulamak_ olarak adlandırılır. Bir fonksiyonu değeri üreten bir ifadeye parantez ekleyerek bir fonksiyonu çağırabilirsiniz. Bunun için, genellikle fonksiyonu tutan bağlantının adını doğrudan kullanırsınız. Fonksiyonu çağırırkenki kullandığınız parantezler arasında verdiğiniz değerler _((argümanlar))_ olarak adlandırılır. Farklı fonksiyonların farklı sayıda veya farklı türde argümanlara ihtiyacı olabilir. -The `prompt` function isn't used much in modern web programming, mostly because you have no control over the way the resulting dialog looks, but it can be helpful in toy programs and experiments. +`prompt` fonksiyonu, modern web programlamasında pek kullanılmaz, çoğunlukla sonuç olarak oluşan iletişim kutusunun görünümü üzerinde kontrol sahibi olmadığınızdan dolayı, ancak oyuncak programlar ve deneylerde faydalı olabilir. -## The console.log function +## console.log fonksiyonu {{index "JavaScript console", "developer tools", "Node.js", "console.log", output, [browser, environment]}} -In the examples, I used `console.log` to output values. Most JavaScript systems (including all modern web browsers and Node.js) provide a `console.log` function that writes out its arguments to _some_ text output device. In browsers, the output lands in the ((JavaScript console)). This part of the browser interface is hidden by default, but most browsers open it when you press F12 or, on a Mac, [command]{keyname}-[option]{keyname}-I. If that does not work, search through the menus for an item named Developer Tools or similar. +Örneklerde, değerleri çıktı olarak göstermek için `console.log` kullandım. Tüm modern web tarayıcıları ve Node.js dahil olmak üzere çoğu JavaScript sistemleri, argüman olarak verilen metinleri çıkış ortamına yazan bir `console.log` fonksiyonunu size sağlar. Tarayıcılarda yazılan bu çıktı, ((JavaScript konsolu))nda yer alır. Bu bölüm, varsayılan olarak gizlidir, ancak çoğu tarayıcı, genelde F12'ye veya bir Mac'te [command]{keyname}-[option]{keyname}-I tuşlarına bastığınızda açar. Bu çalışmazsa, Geliştirici Araçlar veya buna benzer bir öğe arayarak menüler arasında gezinin. {{if interactive When running the examples (or your own code) on the pages of this book, `console.log` output will be shown after the example, instead of in the browser's JavaScript console. +Bu kitabın sayfalarında örnekleri (veya kendi kodlarınızı) çalıştırırken, `console.log` çıktısı, tarayıcının JavaScript konsolu yerine, örneğin altında gösterilir. ``` let x = 30; @@ -196,14 +198,15 @@ if}} {{index [object, property], [property, access]}} -Though binding names cannot contain ((period character))s, `console.log` does have one. This is because `console.log` isn't a simple binding, but an expression that retrieves the `log` property from the value held by the `console` binding. We'll find out exactly what this means in [Chapter ?](data#properties). +Bağlama isimleri ((nokta karakteri)) içeremez, ancak `console.log`'ta bir tane vardır. Bu, `console.log`'un basit bir bağlantı olmadığı, ancak `console` bağlantısında tutulan değerden `log` özelliği alınan bir ifade olduğu içindir. Bunun ne anlama geldiğini [Bölüm ?](data#properties)'da öğreneceğiz. {{id return_values}} -## Return values + +## Döndürülen değerler {{index [comparison, "of numbers"], "return value", "Math.max function", maximum}} -Showing a dialog box or writing text to the screen is a _((side effect))_. Many functions are useful because of the side effects they produce. Functions may also produce values, in which case they don't need to have a side effect to be useful. For example, the function `Math.max` takes any amount of number arguments and gives back the greatest: +Bir iletişim kutusu göstermek veya ekrana metin yazmak, bir \_((yan etki))\_dir. Birçok fonksiyon, ürettikleri yan etkiler nedeniyle yararlıdır. Fonksiyonlar ayrıca değerler üretebilir, bu durumda yararlı olmak için bir yan etkiye ihtiyaçları yoktur. Örneğin, `Math.max` fonksiyonu, herhangi bir miktarda sayı argümanları alır ve bu verilen sayı argümanlar arasından en büyük olanını geri verir: ``` console.log(Math.max(2, 4)); @@ -212,20 +215,20 @@ console.log(Math.max(2, 4)); {{index [function, application], minimum, "Math.min function"}} -When a function produces a value, it is said to _return_ that value. Anything that produces a value is an ((expression)) in JavaScript, which means that function calls can be used within larger expressions. In the following code, a call to `Math.min`, which is the opposite of `Math.max`, is used as part of a plus expression: +Bir fonksiyon bir değer ürettiğinde, o değeri _döndürdüğü_ söylenir. Bir değer üreten her şey, JavaScript'te bir ((ifade)) olduğundan, fonksiyon çağrıları daha büyük ifadelerin içinde kullanılabilir. Aşağıdaki kodda, Math.max'in tam tersi olan Math.min bir artı ifadesinin parçası olarak kullanılmıştır: ``` console.log(Math.min(2, 4) + 100); // → 102 ``` -[Chapter ?](functions) will explain how to write your own functions. +[Bölüm ?](functions), kendi fonksiyonlarınızı nasıl yazacağınızı açıklayacaktır. -## Control flow +## Kontrol akışı {{index "execution order", program, "control flow"}} -When your program contains more than one ((statement)), the statements are executed as though they were a story, from top to bottom. For example, the following program has two statements. The first asks the user for a number, and the second, which is executed after the first, shows the ((square)) of that number: +Programınız birden fazla ((beyan)) içeriyorsa, beyanlar, bir hikaye gibi, üstten alta doğru çalıştırılır. Örneğin, aşağıdaki programda iki ifade bulunmaktadır. İlk olarak, kullanıcıdan bir sayı istenir ve ilk ifadenin ardından yürütülen ikinci beyan o sayının ((kare))sini gösterir: ``` let theNumber = Number(prompt("Pick a number")); @@ -235,23 +238,23 @@ console.log("Your number is the square root of " + {{index [number, "conversion to"], "type coercion", "Number function", "String function", "Boolean function", [Boolean, "conversion to"]}} -The function `Number` converts a value to a number. We need that conversion because the result of `prompt` is a string value, and we want a number. There are similar functions called `String` and `Boolean` that convert values to those types. +Number fonksiyonu, bir değeri bir sayıya dönüştürür. Bu dönüşüme ihtiyacımız var çünkü `prompt`'un sonucu bir dize değeri ve biz bir sayı istiyoruz. Benzer şekilde, bu türlerdeki değerleri dönüştüren `String` ve `Boolean` adında diğer fonksiyonlar da bulunmaktadır. -Here is the rather trivial schematic representation of straight-line control flow: +İşte oldukça basit doğrusal kontrol akışının şematik temsili: {{figure {url: "img/controlflow-straight.svg", alt: "Diagram showing a straight arrow", width: "4cm"}}} -## Conditional execution +## Koşullu çalıştırma {{index Boolean, ["control flow", conditional]}} -Not all programs are straight roads. We may, for example, want to create a branching road where the program takes the proper branch based on the situation at hand. This is called _((conditional execution))_. +Tüm programlar düz yollar değildir. Örneğin, elimizdeki ana yoldan sapan başka yollar oluşturmak isteyebilir ve programımızın belirli durumlarda bu yollardan gitmesini sağlayabiliriz. Buna _((koşullu çalıştırma))_ denir. {{figure {url: "img/controlflow-if.svg", alt: "Diagram of an arrow that splits in two, and then rejoins again",width: "4cm"}}} {{index [syntax, statement], "Number function", "if keyword"}} -Conditional execution is created with the `if` keyword in JavaScript. In the simple case, we want some code to be executed if, and only if, a certain condition holds. We might, for example, want to show the square of the input only if the input is actually a number: +Koşullu çalıştırma, JavaScript'te `if` anahtar kelimesiyle oluşturulur. Basit bir durumda, belirli bir koşulun geçerli olduğu durumda yalnızca bazı kodların yürütülmesini istiyoruz. Örneğin, yalnızca girdinin gerçekten bir sayı olduğu durumda karesini göstermek isteyebiliriz: ```{test: wrap} let theNumber = Number(prompt("Pick a number")); @@ -261,19 +264,19 @@ if (!Number.isNaN(theNumber)) { } ``` -With this modification, if you enter "parrot", no output is shown. +Bu değişiklikle, girdi olarak programa `"parrot"` dize değerini verirseniz, hiçbir çıktı gösterilmez. {{index [parentheses, statement]}} -The `if` keyword executes or skips a statement depending on the value of a Boolean expression. The deciding expression is written after the keyword, between parentheses, followed by the statement to execute. +`if` anahtar kelimesi, bir Boolean ifadesinin değerine bağlı olarak bir beyanı yürütür veya atlar. Karar vermek için kullanılan ifade anahtar kelimenin ardından, parantezler arasına, ardından da yürütülecek beyan veya beyanlar yazılır. {{index "Number.isNaN function"}} -The `Number.isNaN` function is a standard JavaScript function that returns `true` only if the argument it is given is `NaN`. The `Number` function happens to return `NaN` when you give it a string that doesn't represent a valid number. Thus, the condition translates to "unless `theNumber` is not-a-number, do this". +`Number.isNaN` işlevi, yalnızca ona verilen argüman `NaN` ise `true` değerini döndüren standart bir JavaScript fonksiyonudur. `Number` işlevi, geçerli bir sayıyı temsil etmeyen bir dize argüman olarak verildiğinde `NaN` değerini döndürür. Bu nedenle, koşul "eğer `theNumber` bir sayıysa, bunu yap" şeklinde çevrilir. {{index grouping, "{} (block)", [braces, "block"]}} -The statement after the `if` is wrapped in braces (`{` and `}`) in this example. The braces can be used to group any number of statements into a single statement, called a _((block))_. You could also have omitted them in this case, since they hold only a single statement, but to avoid having to think about whether they are needed, most JavaScript programmers use them in every wrapped statement like this. We'll mostly follow that convention in this book, except for the occasional one-liner. +`if`'den sonraki ifade bu örnekte süslü parantezlerle (`{` ve `}`) sarılmıştır. Süslü parantezler, herhangi bir sayıda beyanı tek bir beyana, yani bir _((blok))_'a gruplamak için kullanılabilir. Bu durumda onları kullanmayabilirdiniz çünkü yalnızca tek bir satır beyan içibde bulundurmaktalar, ancak ihtiyaç duyulup duyulmadığı konusunda düşünmekten kaçınmak için çoğu JavaScript programcısı bunları bu şekilde yine de sarar. Bu kitapta çoğunlukla bu kurala uymaya devam edeceğiz, tek satırlık ifadeler hariç. ``` if (1 + 1 == 2) console.log("It's true"); @@ -282,7 +285,7 @@ if (1 + 1 == 2) console.log("It's true"); {{index "else keyword"}} -You often won't just have code that executes when a condition holds true, but also code that handles the other case. This alternate path is represented by the second arrow in the diagram. You can use the `else` keyword, together with `if`, to create two separate, alternative execution paths: +Genellikle sadece bir koşul doğru olduğunda yürütülen kodunuz olmayacak, aynı zamanda doğru olmayan diğer durumu da ele alan kodunuz olacak. Bu alternatif yol, şemadaki ikinci okla temsil edilmiştir. İki ayrı, alternatif çalıştırma yolu oluşturmak için `else` anahtar kelimesini, `if` ile birlikte kullanabilirsiniz: ```{test: wrap} let theNumber = Number(prompt("Pick a number")); @@ -296,7 +299,7 @@ if (!Number.isNaN(theNumber)) { {{index ["if keyword", chaining]}} -If you have more than two paths to choose from, you can "chain" multiple `if`/`else` pairs together. Here's an example: +Birden fazla seçenekli yolu varsa, birden çok `if`/`else` çiftini birbirine "zincirleyebilirsiniz". İşte bir örnek: ``` let num = Number(prompt("Pick a number")); @@ -310,16 +313,17 @@ if (num < 10) { } ``` -The program will first check whether `num` is less than 10. If it is, it chooses that branch, shows `"Small"`, and is done. If it isn't, it takes the `else` branch, which itself contains a second `if`. If the second condition (`< 100`) holds, that means the number is at least 10 but below 100, and `"Medium"` is shown. If it doesn't, the second and last `else` branch is chosen. +Program önce `num`'un 10'dan küçük olup olmadığını kontrol edecek. Eğer öyleyse, o dalı seçer, `"Small"` dize değerini gösterir ve biter. Eğer değilse, `else` dalını alır, ki bu da kendi içinde ikinci bir `if` içerir. İkinci koşul `(< 100)` geçerliyse, bu, sayının en az 10 ancak 100'den küçük olduğu anlamına gelir ve `"Medium"` dize değeri gösterilir. Eğer geçerli değilse, ikinci ve son `else` dalı seçilir, `"Large"` dize değeri gösterilir. -The schema for this program looks something like this: +Bu program için şema şöyle görünebilir: {{figure {url: "img/controlflow-nested-if.svg", alt: "Diagram showing arrow that splits in two, with on the branches splitting again, before all branches rejoin again", width: "4cm"}}} {{id loops}} -## while and do loops -Consider a program that outputs all ((even number))s from 0 to 12. One way to write this is as follows: +## while ve do döngüleri + +0 ile 12 arasındaki tüm ((çift sayı))ları çıkaran bir programı düşünün. Bunu yazmanın bir yolu şu şekildedir: ``` console.log(0); @@ -333,13 +337,13 @@ console.log(12); {{index ["control flow", loop]}} -That works, but the idea of writing a program is to make something _less_ work, not more. If we needed all even numbers less than 1,000, this approach would be unworkable. What we need is a way to run a piece of code multiple times. This form of control flow is called a _((loop))_. +Bu çalışır, ancak bir program yazmanın fikri daha _az_ iş yapmaktır, daha fazla iş yapmak değil. Eğer 1.000'den küçük tüm çift sayılara ihtiyacımız olsaydı, bu yaklaşım işe yaramaz olurdu. İhtiyacımız olan şey, bir kod parçasını birden çok kez çalıştıracak bir yol. Bu kontrol akış biçimi bir ((döngü/loop)) olarak adlandırılır. {{figure {url: "img/controlflow-loop.svg", alt: "Diagram showing an arrow to a point which has a cyclic arrow going back to itself and another arrow going further", width: "4cm"}}} {{index [syntax, statement], "counter variable"}} -Looping control flow allows us to go back to some point in the program where we were before and repeat it with our current program state. If we combine this with a binding that counts, we can do something like this: +Döngü kontrol akışı, programın daha önce bulunduğumuz bir noktaya geri dönmesine ve mevcut program durumu ile tekrar etmesine izin verir. Bunu sayabilen bir bağlantı ile birleştirirsek, şunu yapabiliriz: ``` let number = 0; @@ -354,15 +358,15 @@ while (number <= 12) { {{index "while loop", Boolean, [parentheses, statement]}} -A ((statement)) starting with the keyword `while` creates a loop. The word `while` is followed by an ((expression)) in parentheses and then a statement, much like `if`. The loop keeps entering that statement as long as the expression produces a value that gives `true` when converted to Boolean. +`while` anahtar kelimesiyle başlayan bir ((beyan)), bir döngü oluşturur. `while` kelimesinin ardından parantez içinde bir ((ifade)) ve ardından bir beyan, sanki `if` gibi bir şekilde yazılır. Döngü, verilen ifade Boolean'a dönüştürüldüğünde `true` değerini ürettiği sürece, o beyanı tekrar eder. {{index [state, in binding], [binding, as state]}} -The `number` binding demonstrates the way a ((binding)) can track the progress of a program. Every time the loop repeats, `number` gets a value that is 2 more than its previous value. At the beginning of every repetition, it is compared with the number 12 to decide whether the program's work is finished. +`number` adlı bağlantı, bir programın ilerlemesini bir bağlantı aracılığıyla izlemenin bir yolunu gösterir. Her döngü tekrarı tekrarlandığında, `number` adlı bağlantı önceki değerinden 2 fazla bir değer alır. Her tekrarın başlangıcında, programın işinin bitip bitmediğini anlaması için 12 sayısı ile karşılaştırılır. {{index exponentiation}} -As an example that actually does something useful, we can now write a program that calculates and shows the value of 2^10^ (2 to the 10th power). We use two bindings: one to keep track of our result and one to count how often we have multiplied this result by 2. The loop tests whether the second binding has reached 10 yet and, if not, updates both bindings. +Bu sefer herhangi bir işe yarayan bir örnek olarak, artık 2^10^ (2'nin 10. kuvvetinin) değerini hesaplayan ve gösteren bir program yazabiliriz. İki bağlantıya ihtiyacımız var: sonucumuzu takip etmek için bir tane ve bu sonucu 2 ile kaç kez çarptığımızı saymak için bir tane. Döngü, ikinci bağlantının henüz 10 değerine ulaşıp ulaşmadığını test eder ve eğer ulaşmamışsa, her iki bağlantıyı da günceller. ``` let result = 1; @@ -376,14 +380,15 @@ console.log(result); ``` The counter could also have started at `1` and checked for `<= 10`, but for reasons that will become apparent in [Chapter ?](data#array_indexing), it is a good idea to get used to counting from 0. +`counter` bağlantısı `1` ile başlayabilir ve `<= 10` için kontrol edebilirdi, ancak [Bölüm ?](data#array_indexing)'da anlatılacak sebeplerden ötürü, 0'dan saymayı alışkanlık haline getirmek iyi bir fikirdir. {{index "** operator"}} -Note that JavaScript also has an operator for exponentiation (`2 ** 10`), which you would use to compute this in real code—but that would have ruined the example. +Unutmayın ki JavaScript'in de bir üs operatörü vardır (`2 ** 10`), bunu kodda hesaplamak için kullanabilirdiniz - ancak bu örneğin amacını bozardı. {{index "loop body", "do loop", ["control flow", loop]}} -A `do` loop is a control structure similar to a `while` loop. It differs only on one point: a `do` loop always executes its body at least once, and it starts testing whether it should stop only after that first execution. To reflect this, the test appears after the body of the loop: +`do` döngüsü, `while` döngüsüne benzer bir kontrol yapısıdır. Tek farkı: bir `do` döngüsü daima gövdesini en az bir kez çalıştırır ve yalnızca bu ilk yürütmeden sonra durması gerekip gerekmediğini test eder. Bunu yansıtmak için test koşul ifadesi, döngünün gövdesinden sonra gelir: ``` let yourName; @@ -395,15 +400,15 @@ console.log("Hello " + yourName); {{index [Boolean, "conversion to"], "! operator"}} -This program will force you to enter a name. It will ask again and again until it gets something that is not an empty string. Applying the `!` operator will convert a value to Boolean type before negating it, and all strings except `""` convert to `true`. This means the loop continues going round until you provide a non-empty name. +Bu program, bir isim girmenizi zorlayacak. Girdi olarak boş olmayan bir dize alana kadar tekrar ve tekrar sormaya devam edecek. `!` operatörünü uygulamak, bir değeri Boolean türüne dönüştürdükten sonra bu değeri tersine çevirecektir ve buradaki `""` dışında tüm dizeler `true` değerine dönüşecektir. Bu, döngünün boş olmayan bir dize girdisi verilene kadar devam etmesi anlamına gelir. -## Indenting Code +## Kod girintileme {{index [code, "structure of"], [whitespace, indentation], "programming style"}} -In the examples, I've been adding spaces in front of statements that are part of some larger statement. These spaces are not required—the computer will accept the program just fine without them. In fact, even the ((line)) breaks in programs are optional. You could write a program as a single long line if you felt like it. +Örneklerde, bazı daha büyük ifadelerin bir parçası olan ifadelerin önüne boşluklar ekliyorum. Bu boşluklar gerekli değildir - bilgisayar bunlarsız da programı kabul eder. Aslında, JavaScript programlarında hatta ((yeni satır karakterleri)) bile opsiyoneldir. Eğer isterseniz, tüm programınızı uzun bir satır olarak da yazabilirsiniz. -The role of this ((indentation)) inside ((block))s is to make the structure of the code stand out to human readers. In code where new blocks are opened inside other blocks, it can become hard to see where one block ends and another begins. With proper indentation, the visual shape of a program corresponds to the shape of the blocks inside it. I like to use two spaces for every open block, but tastes differ—some people use four spaces, and some people use ((tab character))s. The important thing is that each new block adds the same amount of space. +Bu ((blok)) içindeki bu ((girinti))lerin rolü, kodun yapısını insan okuyucuların dikkatine varabilmesi içinde. Yeni blokların diğer blokların içinde açıldığı kodlarda, bir bloğun nerede bittiğini ve diğerinin nerede başladığını görmek zor olabilir. Uygun girinti kullanımıyla, bir programın görsel şekli, içindeki blokların şekline karşılık gelir. Ben her açık blok için iki boşluk kullanmayı tercih ediyorum, ancak zevkler değişir - bazı insanlar dört boşluk kullanırken, bazıları ((tab karakter))lerini kullanır. Önemli olan, her yeni bloğun aynı miktarda boşluk eklemesidir. ``` if (false != true) { @@ -414,17 +419,18 @@ if (false != true) { } ``` -Most code ((editor)) programs[ (including the one in this book)]{if interactive} will help by automatically indenting new lines the proper amount. +Çoğu kod ((düzenleyici)) programı[ (bu kitaptaki gibi)]{if interactive} yeni satırları otomatik olarak uygun miktarda girintileme yaparak size yardımcı olacaktır. -## for loops +## for döngüleri {{index [syntax, statement], "while loop", "counter variable"}} Many loops follow the pattern shown in the `while` examples. First a "counter" binding is created to track the progress of the loop. Then comes a `while` loop, usually with a test expression that checks whether the counter has reached its end value. At the end of the loop body, the counter is updated to track progress. +Birçok döngü, `while` örneklerinde gösterilen deseni takip eder. İlk olarak, döngünün ilerlemesini takip etmek için bir `"counter"` bağlantısı oluşturulur. Ardından, genellikle `"counter"` bağlantısının hedef değerine ulaşıp ulaşmadığını kontrol eden bir test ifadesiyle birlikte bir `while` döngüsü gelir. Döngü gövdesinin sonunda, ilerlemeyi izlemek için `"counter"` bağlantısı güncellenir. {{index "for loop", loop}} -Because this pattern is so common, JavaScript and similar languages provide a slightly shorter and more comprehensive form, the `for` loop: +Bu desen o kadar yaygındır ki, JavaScript ve benzer diller bunun için biraz daha kısa ve kapsamlı bir form sağlar, `for` döngüsü: ``` for (let number = 0; number <= 12; number = number + 2) { @@ -438,14 +444,16 @@ for (let number = 0; number <= 12; number = number + 2) { {{index ["control flow", loop], state}} This program is exactly equivalent to the [earlier](program_structure#loops) even-number-printing example. The only change is that all the ((statement))s that are related to the "state" of the loop are grouped together after `for`. +Bu program, daha [önceki](program_structure#loops) çift sayıları yazdırma örneğine tam olarak eşdeğerdir. Tek fark, döngünün "durumu" ile ilgili olan tüm ((beyan))ların for'dan sonra gruplandırılmış olmasıdır. {{index [binding, as state], [parentheses, statement]}} The parentheses after a `for` keyword must contain two ((semicolon))s. The part before the first semicolon _initializes_ the loop, usually by defining a binding. The second part is the ((expression)) that _checks_ whether the loop must continue. The final part _updates_ the state of the loop after every iteration. In most cases, this is shorter and clearer than a `while` construct. +`for` anahtar kelimesinden sonra parantezlerin içinde iki ((noktalı virgül)) bulunmalıdır. İlk noktalı virgülden önceki kısım, genellikle bir bağlantı tanımlayarak döngüyü başlatır. İkinci kısım, döngünün devam edip etmemesini gerektiğini her seferinde kontrol eden ((ifade))dir. Son kısım, her iterasyondan sonra döngünün durumunu _günceller_. Çoğu durumda, bu, `while` yapısından daha kısa ve daha açıklayıcıdır. {{index exponentiation}} -This is the code that computes 2^10^ using `for` instead of `while`: +Bu, `while` kullanmak yerine `for` döngüsü yapısını kullanarak 2^10^ hesaplayan koddur: ```{test: wrap} let result = 1; @@ -456,11 +464,11 @@ console.log(result); // → 1024 ``` -## Breaking Out of a Loop +## Döngü içerisinden çıkmak {{index [loop, "termination of"], "break keyword"}} -Having the looping condition produce `false` is not the only way a loop can finish. The `break` statement has the effect of immediately jumping out of the enclosing loop. Its use is demonstrated in the following program, which finds the first number that is both greater than or equal to 20 and divisible by 7: +Döngü koşulunun `false` değerini üretmesini sağlamak bir döngünün bitmesi için tek yol değildir. `break` beyanı, dışındaki döngüden anında çıkmak etkisine sahiptir. Kullanımı aşağıdaki programda gösterilmiştir, bu program, hem 20'den büyük veya eşit olan ve hem de 7'ye bölünebilen ilk sayıyı bulur: ``` for (let current = 20; ; current = current + 1) { @@ -474,43 +482,43 @@ for (let current = 20; ; current = current + 1) { {{index "remainder operator", "% operator"}} -Using the remainder (`%`) operator is an easy way to test whether a number is divisible by another number. If it is, the remainder of their division is zero. +Modülo(%) operatörünü kullanmak, bir sayının başka bir sayıya bölünebilir olup olmadığını test etmenin kolay bir yoludur çünkü eğer öyleyse bölme işleminin kalanı sıfırdır. {{index "for loop"}} -The `for` construct in the example does not have a part that checks for the end of the loop. This means that the loop will never stop unless the `break` statement inside is executed. +Örnekteki `for` yapısı döngünün sona gelip gelmediğini kontrol eden bir parça içermez. Bu, döngünün içerisinde bir `break` ifadesi çalıştırılmadıkça döngünün hiçbir zaman durmayacağı anlamına gelir. -If you were to remove that `break` statement or you accidentally write an end condition that always produces `true`, your program would get stuck in an _((infinite loop))_. A program stuck in an infinite loop will never finish running, which is usually a bad thing. +Eğer o `break` ifadesini kaldırırsanız veya yanlışlıkla her zaman `true` değerini üreten bir bitiş koşulu yazarsanız, programınız bir _((sonsuz döngü))_'ye takılacaktır. Bir sonsuz döngüye takılan bir program asla çalışmayı bitiremez, bu genellikle kötü bir şeydir. {{if interactive -If you create an infinite loop in one of the examples on these pages, you'll usually be asked whether you want to stop the script after a few seconds. If that fails, you will have to close the tab that you're working in to recover. +Bu sayfalardaki örneklerden birinde sonsuz bir döngü oluşturursanız, genellikle birkaç saniye sonra scripti durdurmak isteyip istemediğiniz sorulur. Eğer bu başarısız olursa, kurtarmak için çalıştığınız sekmeyi kapatmanız zorunda kalırsınız. if}} {{index "continue keyword"}} -The `continue` keyword is similar to `break` in that it influences the progress of a loop. When `continue` is encountered in a loop body, control jumps out of the body and continues with the loop's next iteration. +`continue` anahtar kelimesi, `break` gibi bir döngünün ilerleyişini etkiler. Bir döngü gövdesinde `continue` bulunduğunda, kontrol gövdeden çıkar ve döngünün bir sonraki tekrarından devam eder. -## Updating bindings succinctly +## Kısa ve öz şekilde bağlantıları güncelleme {{index assignment, "+= operator", "-= operator", "/= operator", "*= operator", [state, in binding], "side effect"}} -Especially when looping, a program often needs to "update" a binding to hold a value based on that binding's previous value. +Özellikle döngü yapılırken, bir program genellikle bir bağlantının değerini o bağlantını önceki değerine dayalı olarak başka bir değerle "güncellemeye" ihtiyaç duyar. ```{test: no} counter = counter + 1; ``` -JavaScript provides a shortcut for this: +JavaScript, bunun için bir kısayol sağlar: ```{test: no} counter += 1; ``` -Similar shortcuts work for many other operators, such as `result *= 2` to double `result` or `counter -= 1` to count downward. +Benzer kısayollar, `result *= 2` ile `result` bağlantısının değerini iki katına çıkarmak veya `counter -= 1` ile geriye doğru saymak gibi birçok diğer aritmetik operatörle de çalışır. -This allows us to further shorten our counting example: +Bu, sayım örneğimizi daha da kısaltmamıza olanak tanır: ``` for (let number = 0; number <= 12; number += 2) { @@ -520,13 +528,13 @@ for (let number = 0; number <= 12; number += 2) { {{index "++ operator", "-- operator"}} -For `counter += 1` and `counter -= 1`, there are even shorter equivalents: `counter++` and `counter--`. +`counter += 1` ve `counter -= 1` için daha kısa aynı şeye denk gelen yazım şekilleri de mevcuttur: counter++ ve counter--. -## Dispatching on a value with switch +## switch aracılığıyla bir değere göre çalıştırmak {{index [syntax, statement], "conditional execution", dispatch, ["if keyword", chaining]}} -It is not uncommon for code to look like this: +Kodun şu şekilde görünmesi yaygındır: ```{test: no} if (x == "value1") action1(); @@ -537,7 +545,7 @@ else defaultAction(); {{index "colon character", "switch keyword"}} -There is a construct called `switch` that is intended to express such a "dispatch" in a more direct way. Unfortunately, the syntax JavaScript uses for this (which it inherited from the C/Java line of programming languages) is somewhat awkward—a chain of `if` statements may look better. Here is an example: +Buna benzer ancak daha doğrudan bir şekilde kod "çalıştırmayı" ifade etmek için tasarlanmış `switch` adında bir yapı vardır. Ne yazık ki, bu yapı için JavaScript'in kullandığı sözdizimi (C/Java programlama dillerinden miras aldığı) biraz garip gözükebilir ve bundan ötürü bir dizi `if` ifadesi daha iyi görünebilir. İşte bir örnek: ``` switch (prompt("What is the weather like?")) { @@ -557,13 +565,13 @@ switch (prompt("What is the weather like?")) { {{index fallthrough, "break keyword", "case keyword", "default keyword"}} -You may put any number of `case` labels inside the block opened by `switch`. The program will start executing at the label that corresponds to the value that `switch` was given, or at `default` if no matching value is found. It will continue executing, even across other labels, until it reaches a `break` statement. In some cases, such as the `"sunny"` case in the example, this can be used to share some code between cases (it recommends going outside for both sunny and cloudy weather). Be careful, though—it is easy to forget such a `break`, which will cause the program to execute code you do not want executed. +`switch` tarafından açılan bloğun içine istediğiniz sayıda `case` koyabilirsiniz. Program, `switch`'e verilen değere karşılık gelen etiketteki kodu veya eşleşen bir değer bulunamazsa `default` etiketindeki kodu çalıştırır. `break` ifadesine ulaşana kadar diğer etiketler de dahil olmak üzere karşılaştığı kodları çalıştırmaya devam eder. Örnekteki `"sunny"` durumunda olduğu gibi bazı durumlarda, bu kodu durumlar arasında paylaşmak için kullanılabilir (hem güneşli hem de bulutlu hava için dışarı çıkmanızı önerir). Ancak dikkatli olun - bu şekilde bir `break` ifadesini unutmak kolaydır ve istenmeyen şekilde kodun yürütülmesine sebep olmak kolaydır. -## Capitalization +## Büyük harf kullanımı {{index capitalization, [binding, naming], [whitespace, syntax]}} -Binding names may not contain spaces, yet it is often helpful to use multiple words to clearly describe what the binding represents. These are pretty much your choices for writing a binding name with several words in it: +Bağlantı adları arasında boşluk olmamalıdır, ancak bağlantının temsil ettiği şeyi açıkça tanımlamak için birden fazla kelime kullanmak faydalı olabilir. Birden fazla kelime içeren bir bağlantı adı yazmak için şu seçenekleriniz var: ```{lang: null} fuzzylittleturtle @@ -574,21 +582,21 @@ fuzzyLittleTurtle {{index "camel case", "programming style", "underscore character"}} -The first style can be hard to read. I rather like the look of the underscores, though that style is a little painful to type. The ((standard)) JavaScript functions, and most JavaScript programmers, follow the final style—they capitalize every word except the first. It is not hard to get used to little things like that, and code with mixed naming styles can be jarring to read, so we follow this ((convention)). +İlk stili okumak zor olabilir. Ben alt çizgilerin görünümünü oldukça beğeniyorum, ancak bu stili yazmak biraz zor olabilir. ((Standart)) JavaScript fonksiyonları ve çoğu JavaScript programcısı, sondaki stili takip eder - ilk kelime haricindeki her kelimenin ilk harfini büyük harfle yazarlar. Böyle küçük detaylara alışmak zor değildir ve karışık isimlendirme stilleri olan kodlar okunması zor olabilir, bu yüzden bu ((kuralı)) kullanıyoruz. {{index "Number function", constructor}} -In a few cases, such as the `Number` function, the first letter of a binding is also capitalized. This was done to mark this function as a constructor. It will become clear what a constructor is in [Chapter ?](object#constructors). For now, the important thing is not to be bothered by this apparent lack of ((consistency)). +Bazı durumlarda, `Number` fonksiyonu gibi, bağlantı isminin ilk harfi de büyük yazılır. Bu, bu fonskiyonu bir yapılandırıcı olarak işaretlemek içindir. Bir yapılandırıcının ne olduğu [Bölüm ?](object#constructors)'da netleşecektir. Şu anda, önemli olan bu belirgin ((tutarlılık)) eksikliğinden rahatsız olmamaktır. -## Comments +## Yorum satırları {{index readability}} -Often, raw code does not convey all the information you want a program to convey to human readers, or it conveys it in such a cryptic way that people might not understand it. At other times, you might just want to include some related thoughts as part of your program. This is what _((comment))s_ are for. +Sıklıkla, ham kod, bir programın insan okuyucularına iletmek istediğiniz tüm bilgileri iletemez veya bilgiyi anlaşılması zor veya kriptik bir şekilde iletebilir. Bazı zamanlarda, programınızın bir parçası olarak ilgili düşünceleri dahil etmek isteyebilirsiniz. \_((Yorum))\_lar bunun için vardır. {{index "slash character", "line comment"}} -A comment is a piece of text that is part of a program but is completely ignored by the computer. JavaScript has two ways of writing comments. To write a single-line comment, you can use two slash characters (`//`) and then the comment text after it: +Yorum, bir programın bir parçası olan ancak bilgisayar tarafından tamamen görmezden gelinen bir metin parçasıdır. JavaScript'in iki yorum yazma yöntemi vardır. Tek satırlık bir yorum yazmak için iki eğik çizgi karakteri (`//`) kullanabilir ve ardından yorum metnini ekleyebilirsiniz: ```{test: no} let accountBalance = calculateBalance(account); @@ -603,7 +611,7 @@ addToReport(accountBalance, report); {{index "block comment"}} -A `//` comment goes only to the end of the line. A section of text between `/*` and `*/` will be ignored in its entirety, regardless of whether it contains line breaks. This is useful for adding blocks of information about a file or a chunk of program: +`//` ile başlayan bir yorum yalnızca satırın sonuna kadar gider. `/*` ve `*/` arasındaki bir metin bölümü, yeni satır karakterlerini içinde barındırıp barındırmadığına bakılmaksızın tamamen görmezden gelinir. Bu, bir dosya veya program parçası hakkında satırlar yerine bloklar halinde bilgi eklemek için kullanışlıdır: ``` /* @@ -615,29 +623,29 @@ A `//` comment goes only to the end of the line. A section of text between `/*` const myNumber = 11213; ``` -## Summary +## Özet -You now know that a program is built out of statements, which themselves sometimes contain more statements. Statements tend to contain expressions, which themselves can be built out of smaller expressions. +Şimdi bir programın bazen içerisinde beyanlar barındıran beyanlardan oluştuğunu biliyorsunuz. Beyanlar da genellikle ifadeler barındıran ifadelerden oluşurlar. -Putting statements after one another gives you a program that is executed from top to bottom. You can introduce disturbances in the flow of control by using conditional (`if`, `else`, and `switch`) and looping (`while`, `do`, and `for`) statements. +İfadeleri ardışık olarak bir araya getirmek, üstten alta çalıştırılan bir program elde etmenizi sağlar. Koşullu (`if`, `else` ve `switch`) ve döngü (`while`, `do` ve `for`) ifadelerini kullanarak kontrol akışına farklı şekillerde değişiklikler ekleyebilirsiniz. -Bindings can be used to file pieces of data under a name, and they are useful for tracking state in your program. The environment is the set of bindings that are defined. JavaScript systems always put a number of useful standard bindings into your environment. +Bağlanlar, bir parça bilgiyi bir isim altında saklamak için kullanılabilir ve programınızdaki durumu takip etmek için de kullanışlıdır. Ortam, tanımlanan bağlantıların kümesidir. JavaScript sistemleri, ortamınıza birçok kullanışlı standart bağlantıları otomatik olarak yerleştirir. -Functions are special values that encapsulate a piece of program. You can invoke them by writing `functionName(argument1, argument2)`. Such a function call is an expression and may produce a value. +Fonksiyonlar, bir program parçasını kapsayan özel değerlerdir. Onları `fonksiyonAdı(argüman1, argüman2)` şeklinde yazarak çağırabilirsiniz. Böyle bir fonksiyon çağrısı bir ifade olup ayrıca bir değer üretebilir. -## Exercises +## Egzersizler {{index exercises}} -If you are unsure how to test your solutions to the exercises, refer to the [Introduction](intro). +Egzersiz çözümlerinizi nasıl test edeceğinizden emin değilseniz, [Giriş](intro)'e başvurun. -Each exercise starts with a problem description. Read this description and try to solve the exercise. If you run into problems, consider reading the hints [after the exercise]{if interactive}[at the [end of the book](hints)]{if book}. You can find full solutions to the exercises online at [_https://eloquentjavascript.net/code_](https://eloquentjavascript.net/code#2). If you want to learn something from the exercises, I recommend looking at the solutions only after you've solved the exercise, or at least after you've attacked it long and hard enough to have a slight headache. +Her egzersiz bir problem açıklaması ile başlar, bu açıklamayı okuyun ve egzersizi çözmeye çalışın. Sorunlarla karşılaşırsanız, [egzersizden sonra]{if interactive} [[kitabın sonundaki](hints)]{if book} ipuçlarını'ı okuyabilirsiniz. Egzersizlerin tam çözümlerini [_https://eloquentjavascript.net/code_](https://eloquentjavascript.net/code#2)'da çevrimiçi olarak bulabilirsiniz. Egzersizlerden bir şeyler öğrenmek istiyorsanız, egzersizi çözdükten sonra çözümlere bakmayı veya en azından biraz baş ağrısı yaşayana kadar çözüme saldırmanızı öneririm. -### Looping a triangle +### Bir üçgeni döngüye almak {{index "triangle (exercise)"}} -Write a ((loop)) that makes seven calls to `console.log` to output the following triangle: +Aşağıdaki üçgeni çıktıya yazdırmak için `console.log`'u yedi kere çağıran bir ((döngü)) yazın: ```{lang: null} # @@ -651,7 +659,7 @@ Write a ((loop)) that makes seven calls to `console.log` to output the following {{index [string, length]}} -It may be useful to know that you can find the length of a string by writing `.length` after it. +Bir dizinin uzunluğunu `.length` yazarak bulabileceğinizi bilmek faydalı olabilir. ``` let abc = "abc"; @@ -661,20 +669,21 @@ console.log(abc.length); {{if interactive -Most exercises contain a piece of code that you can modify to solve the exercise. Remember that you can click code blocks to edit them. +Çoğu egzersiz, egzersizi çözmek için değiştirebileceğiniz bir kod parçası içerir. Kod bloklarını düzenlemek için üzerlerine tıklayabileceğinizi unutmayın. ``` -// Your code here. +// Kodunuz buraya. ``` + if}} {{hint {{index "triangle (exercise)"}} -You can start with a program that prints out the numbers 1 to 7, which you can derive by making a few modifications to the [even number printing example](program_structure#loops) given earlier in the chapter, where the `for` loop was introduced. +1'den 7'ye kadar olan sayıları yazdıran bir programla başlayabilirsiniz. Bunun için, [bu bölümden önce tanıtılan `for` döngüsü örneğine](program_structure#loops) birkaç değişiklik yaparak türetebilirsiniz. -Now consider the equivalence between numbers and strings of hash characters. You can go from 1 to 2 by adding 1 (`+= 1`). You can go from `"#"` to `"##"` by adding a character (`+= "#"`). Thus, your solution can closely follow the number-printing program. +Şimdi, sayıların ve # karakterlerinden oluşan dizelerinin arasındaki bağlantıyı düşünün. 1'den 2'ye gitmek için 1 ekleyebilirsiniz (`+= 1`). "#" den "##" e gitmek için bir karakter ekleyebilirsiniz (`+= "#"`). Bu nedenle, çözümünüz yakından sayı yazdırma programını takip edebilir. hint}} @@ -682,73 +691,79 @@ hint}} {{index "FizzBuzz (exercise)", loop, "conditional execution"}} -Write a program that uses `console.log` to print all the numbers from 1 to 100, with two exceptions. For numbers divisible by 3, print `"Fizz"` instead of the number, and for numbers divisible by 5 (and not 3), print `"Buzz"` instead. +1'den 100'e kadar olan değerleri çıktı olarak `console.log` fonksiyonunu aracılığıyla yazdıracak ancak iki adet istisna sağlayacak bir program yaz. 3 sayısı ile bölünebilecek sayılar için sayıyı yazdırmak yerine `"Fizz"` ve 5 sayısı ile bölünüp 3 sayısı ile bölünmeyen sayılar için de sayı yerine `"Buzz"` yazdır. When you have that working, modify your program to print `"FizzBuzz"` for numbers that are divisible by both 3 and 5 (and still print `"Fizz"` or `"Buzz"` for numbers divisible by only one of those). +Çalışan bir şey elde ettiğinde gerektikçe değişiklikler yap ve programının `"FizzBuzz"` çıktısını 3 ve 5 ile bölünebilir sayılar için yazdırmasını sağla, ayrıca güncel sayı sadece 3 veya 5'e bölünebiliyorsa sadece `"Fizz"` veya `"Buzz"` çıktısını yazdırdığına emin ol. -(This is actually an ((interview question)) that has been claimed to weed out a significant percentage of programmer candidates. So if you solved it, your labor market value just went up.) +(Bu aslında bir ((mülakat sorusu)) ve iddia edildiğine göre programcı adaylarının önemli bir yüzdesini elemek için kullanılıyor. Dolayısıyla, eğer çözdüyseniz, bu sizin işgücü piyasası değerinizin arttığı anlamına geliyor.) {{if interactive + ``` -// Your code here. +// Kodunuz buraya. ``` + if}} {{hint {{index "FizzBuzz (exercise)", "remainder operator", "% operator"}} -Going over the numbers is clearly a looping job, and selecting what to print is a matter of conditional execution. Remember the trick of using the remainder (`%`) operator for checking whether a number is divisible by another number (has a remainder of zero). +Sayıları geçmek açıkça bir döngü işidir ve neyi yazdıracağını seçmek bir koşullu ifade meselesidir. Bir sayının başka bir sayıya bölünebilir olup olmadığını (kalanının sıfır olup olmadığını) kontrol etmek için modülo (%) operatörünü kullanmayı unutmayın. -In the first version, there are three possible outcomes for every number, so you'll have to create an `if`/`else if`/`else` chain. +İlk versiyonda, her sayı için üç olası sonuç vardır, bu nedenle bir `if`/`else if`/`else` zinciri oluşturmanız gerekecek. {{index "|| operator", ["if keyword", chaining]}} -The second version of the program has a straightforward solution and a clever one. The simple solution is to add another conditional "branch" to precisely test the given condition. For the clever solution, build up a string containing the word or words to output and print either this word or the number if there is no word, potentially by making good use of the `||` operator. +Programın ikinci versiyonunun basit bir çözümü ve zekice bir çözümü vardır. Basit çözüm, verilen koşulu kesin olarak test etmek için başka bir koşullu "dal" eklemektir. Zeki çözüm için, çıktılanacak kelime veya kelimeleri içeren bir dize oluşturun ve bu kelimeyi veya numarayı yazdırın eğer kelime yoksa potansiyel olarak || operatörünü iyi kullanarak sadece sayıyı yazdırın. hint}} -### Chessboard +### Satranç tahtası {{index "chessboard (exercise)", loop, [nesting, "of loops"], "newline character"}} -Write a program that creates a string that represents an 8×8 grid, using newline characters to separate lines. At each position of the grid there is either a space or a "#" character. The characters should form a chessboard. +Bir satır başına yeni satır karakterleri kullanarak satırları ayıran bir 8x8 ızgarayı temsil edecek dizeyi oluşturan bir program yazın. Izgaranın her bir konumunda ya bir boşluk ya da "#" karakteri bulunmalıdır. Karakterler bir satranç tahtası oluşturmalıdır. -Passing this string to `console.log` should show something like this: +Bu diziyi `console.log`'a verirseniz şuna benzer bir şey görüntülemelisiniz: ```{lang: null} # # # # -# # # # +# # # # # # # # -# # # # +# # # # # # # # -# # # # +# # # # # # # # -# # # # +# # # # ``` -When you have a program that generates this pattern, define a binding `size = 8` and change the program so that it works for any `size`, outputting a grid of the given width and height. +Bu deseni üreten bir programa sahip olduğunuzda, bir bağlantı `size = 8` tanımlayın ve programı verilen genişlik ve yükseklikteki bir ızgarayı çıkaracak şekilde değiştirin. {{if interactive + ``` -// Your code here. +// Kodunuz buraya. ``` + if}} {{hint {{index "chess board (exercise)"}} -You can build the string by starting with an empty one (`""`) and repeatedly adding characters. A newline character is written `"\n"`. +Dizeyi başlangıçta boş bir dize (`""`) ile başlayarak ve ardından karakterleri tekrar tekrar ekleyerek oluşturabilirsiniz. Bir satır sonu karakteri `"\n"` olarak yazılır. {{index [nesting, "of loops"], [braces, "block"]}} -To work with two ((dimensions)), you will need a ((loop)) inside of a loop. Put braces around the bodies of both loops to make it easy to see where they start and end. Try to properly indent these bodies. The order of the loops must follow the order in which we build up the string (line by line, left to right, top to bottom). So the outer loop handles the lines, and the inner loop handles the characters on a line. +İki ((boyut)) ile çalışmak için iç içe olan iki ((döngü))'ye ihtiyacınız olacak. Her iki döngünün vücutlarını görmeyi kolaylaştırmak için her iki döngünün de etrafına parantezler koyun. Bu vücutları uygun şekilde girintileyin. Döngülerin sırası, diziyi nasıl oluşturduğumuzun sırasını izlemelidir (satır satır, soldan sağa, yukarıdan aşağıya). Bu nedenle, dış döngü satırları ele alır ve iç içe döngü bir satırdaki karakterleri ele alır. {{index "counter variable", "remainder operator", "% operator"}} You'll need two bindings to track your progress. To know whether to put a space or a hash sign at a given position, you could test whether the sum of the two counters is even (`% 2`). +İlerlemenizi izlemek için iki farklı bağlantıya ihtiyacınız olacak. Belirli bir konumda bir boşluk mu yoksa bir "#" işareti mi ekleyeceğinizi belirlemeniz için, iki farklı sayaç olarak kullandığınız bağlantıların değerlerinin toplamı çift mi yoksa tek mi olduğunu test edebilirsiniz (`% 2`). -Terminating a line by adding a newline character must happen after the line has been built up, so do this after the inner loop but inside the outer loop. +Bir satırı sonlandırmak için yeni bir satır karakteri eklemeyi dış döngü içinde ancak iç içe olan döngünün dışında yapmalısınız. hint}} diff --git a/03_functions.md b/03_functions.md index ab8622ae..1e63fb02 100644 --- a/03_functions.md +++ b/03_functions.md @@ -1,8 +1,8 @@ -# Functions +# Fonksiyonlar {{quote {author: "Donald Knuth", chapter: true} -People think that computer science is the art of geniuses but the actual reality is the opposite, just many people doing things that build on each other, like a wall of mini stones. +İnsanlar bilgisayar biliminin sadece dahilerin ortaya koyabileceği bir sanat olduğunu düşünüyorlar ancak durum tam olarak öyle değil, sadece birbirini takip eden birçok insanın küçük taşlarla bir duvar oluşturması gibi. quote}} @@ -12,19 +12,19 @@ quote}} {{index function, [code, "structure of"]}} -Functions are one of the most central tools in JavaScript programming. The concept of wrapping a piece of program in a value has many uses. It gives us a way to structure larger programs, to reduce repetition, to associate names with subprograms, and to isolate these subprograms from each other. +Fonksiyonlar, JavaScript programlamasındaki en merkezi araçlardan biridir. Bir program parçasını bir değere sarma kavramının birçok yararlı kullanımı vardır. Daha büyük programları yapılandırmanın, tekrarı azaltmanın, alt programları isimlendirmenin ve bu alt programları birbirinden izole etmenin bir yolunu sağlar. -The most obvious application of functions is defining new ((vocabulary)). Creating new words in prose is usually bad style, but in programming, it is indispensable. +Fonksiyonların en açık uygulamalarından biri yeni ((kelime dağarcığı)) tanımlamaktır. Konuşma dilinde yeni kelimeler oluşturmak genellikle kötü bir stildir ancak programlamada bu bir vazgeçilmezdir. {{index abstraction, vocabulary}} -Typical adult English speakers have some 20,000 words in their vocabulary. Few programming languages come with 20,000 commands built in. And the vocabulary that _is_ available tends to be more precisely defined, and thus less flexible, than in human language. Therefore, we _have_ to introduce new words to avoid excessive verbosity. +Tipik yetişkin İngilizce konuşanların kelime dağarcığında yaklaşık 20.000 kelime bulunmaktadır ancak muhtemelen hiç bir programlama dili 20.000 komutla beraber gelmez. Ayrıca, mevcut olan kelime dağarcığı da daha kesin bir şekilde tanımlanmıştır ve bundan ötürü insan dilindeki kadar esnek olmaz. Bu nedenle, aşırı ayrıntıdan kaçınmak için yeni kelimeler tanıtmamız gerekmektedir. -## Defining a function +## Fonksiyonlar tanımlamak {{index "square example", [function, definition], [binding, definition]}} -A function definition is a regular binding where the value of the binding is a function. For example, this code defines `square` to refer to a function that produces the square of a given number: +Bir fonksiyon tanımı, değeri bir fonksiyon olan basit bir bağlantıdır. Örneğin, bu kod, `square` bağlantısını bir sayının karesini üreten bir fonksiyona atayacak sağlayacak şekilde tanımlar: ``` const square = function(x) { @@ -38,11 +38,11 @@ console.log(square(12)); {{indexsee "curly braces", braces}} {{index [braces, "function body"], block, [syntax, function], "function keyword", [function, body], [function, "as value"], [parentheses, arguments]}} -A function is created with an expression that starts with the keyword `function`. Functions have a set of _((parameter))s_ (in this case, only `x`) and a _body_, which contains the statements that are to be executed when the function is called. The body of a function created this way must always be wrapped in braces, even when it consists of only a single ((statement)). +Bir fonksiyon, `function` anahtar kelimesiyle başlayan bir ifade ile oluşturulur. Fonksiyonların bir dizi _((parametre))leri_ (bu durumda sadece `x`) ve çağrıldığında yürütülecek ((ifade))leri içeren bir _gövdesi_ vardır. Bu şekilde oluşturulan bir fonksiyonun gövdesi yalnızca tek bir ((beyan)) içerse bile her zaman süslü parantezlerle sarılmalıdır. {{index "roundTo example"}} -A function can have multiple parameters or no parameters at all. In the following example, `makeNoise` does not list any parameter names, whereas `roundTo` (which rounds `n` to the nearest multiple of `step`) lists two: +Bir fonksiyon birden fazla parametreye sahip olabilirken ayrıca hiç parametreye sahip olmayabilir. Aşağıdaki örnekte, `makeNoise` hiçbir parametre adı listelemezken (`n`'yi `step`'in en yakın katına yuvarlayan) `roundTo` iki parametre listeler: ``` const makeNoise = function() { @@ -63,26 +63,26 @@ console.log(roundTo(23, 10)); {{index "return value", "return keyword", undefined}} -Some functions, such as `roundTo` and `square`, produce a value, and some don't, such as `makeNoise`, whose only result is a ((side effect)). A `return` statement determines the value the function returns. When control comes across such a statement, it immediately jumps out of the current function and gives the returned value to the code that called the function. A `return` keyword without an expression after it will cause the function to return `undefined`. Functions that don't have a `return` statement at all, such as `makeNoise`, similarly return `undefined`. +Bazı `roundTo` ve `square` gibi fonksiyonlar bir değer üretirken bazılarıysa `makeNoise` gibi sadece bir ((yan etki))ye sebep olur. Bir `return` beyanı, fonksiyonun çalıştırıldığında döndüreceği değeri belirler. Program kontrolü böyle bir beyanla karşılaştığında, derhal mevcut fonksiyondan çıkar ve fonksiyonu çağıran koda o beyanda belirtilen değeri verir. Bir ifade verilmeden yazılan `return` anahtar kelimesi, fonksiyonun `undefined` değerini döndürmesine neden olur. `makeNoise` gibi hiçbir `return` beyanı olmayan fonksiyonlar da benzer şekilde `undefined` döndürürler. {{index parameter, [function, application], [binding, "from parameter"]}} -Parameters to a function behave like regular bindings, but their initial values are given by the _caller_ of the function, not the code in the function itself. +Bir fonksiyona gelen parametreler sıradan değişkenlerde olan bağlantılar gibi davranırlar ancak kendilerinin başlangıç değerlerini fonksiyon içindeki kod tarafından değil, fonksiyonun çağırıcısı tarafından alırlar. -## Bindings and scopes +## Bağlantılar ve kapsamlar {{indexsee "top-level scope", "global scope"}} {{index "var keyword", "global scope", [binding, global], [binding, "scope of"]}} -Each binding has a _((scope))_, which is the part of the program in which the binding is visible. For bindings defined outside of any function, block, or module (see [Chapter ?](modules)), the scope is the whole program—you can refer to such bindings wherever you want. These are called _global_. +Her bağlantının bir *((kapsam))*ı vardır ve belirli bağlantılar belirli kapsamların içinde görünürdürler. Herhangi bir fonksiyon, blok veya modül(bkz. [Bölüm ?](modules)) içinde olmayacak şekilde tanımlanmış bağlantılar için kapsam tüm programdır - bu tür bağlantılara istediğiniz yerden ulaşabilirsiniz. Bunlara _global_ denir. {{index "local scope", [binding, local]}} -Bindings created for function ((parameter))s or declared inside a function can be referenced only in that function, so they are known as _local_ bindings. Every time the function is called, new instances of these bindings are created. This provides some isolation between functions—each function call acts in its own little world (its local environment) and can often be understood without knowing a lot about what's going on in the global environment. +Ancak bir fonksiyon parametreleri için oluşturulan bağlantılar veya bir fonksiyon içinde oluşturulan bağlantılar yalnızca o fonksiyon içerisinden ulaşılabilir, bu yüzden _yerel_ bağlantılar olarak bilinirler. Her fonksiyon çağrıldığında, bu bağlamaların yeni kopyaları oluşturulur. Bu, fonksiyonlar arasında bir izolasyon sağlar - her fonksiyon çağrısı kendi küçük dünyasında (yerel ortamında) hareket eder ve genellikle global ortamda neler olduğunu çok fazla bilmeden anlaşılabilir. {{index "let keyword", "const keyword", "var keyword"}} -Bindings declared with `let` and `const` are in fact local to the _((block))_ in which they are declared, so if you create one of those inside of a loop, the code before and after the loop cannot "see" it. In pre-2015 JavaScript, only functions created new scopes, so old-style bindings, created with the `var` keyword, are visible throughout the whole function in which they appear—or throughout the global scope, if they are not in a function. +`let` ve `const` ile oluşturulan bağlantılar aslında oluşturuldukları _((blok))_ için yereldirler, bundan ötürü döngü içinde bir bağlantı oluşturursanız, döngüden önceki ve sonraki kod onu "göremez". 2015 öncesi JavaScript'te, fonksiyonlar yeni kapsam oluşturabilen tek yapı oldukları için, `var` anahtar kelimesiyle oluşturulan eski tarz bağlantılar, bulundukları fonksiyonun tamamında - veya bir fonksiyon içinde değillerse, global kapsamda görünürlerdi. ``` let x = 10; // global @@ -94,7 +94,7 @@ if (true) { {{index [binding, visibility]}} -Each ((scope)) can "look out" into the scope around it, so `x` is visible inside the block in the example. The exception is when multiple bindings have the same name—in that case, code can see only the innermost one. For example, when the code inside the `halve` function refers to `n`, it is seeing its _own_ `n`, not the global `n`. +Her ((kapsam)), çevresindeki kapsamlara "bakabilir", bu yüzden örnekteki bloğun içinde `x` görülebilir durumdadır. Tek istisna, birden fazla aynı isimli bağlantının durumda, kod yalnızca en içteki bağlantıyı görebilir. Örneğin, `halve` fonksiyonu içindeki kod `n`'ye atıfta bulunduğunda, global kapsamdaki `n` değerini değil, kendi `n` değerini görür. Buna içerideki aynı isimdeki bir bağlantının dışarıdaki aynı isimdeki bir bağlantıyı gölgelemesinden ötürü "gölgeleme" denir ve kafa karışıklığına sebep olabileceğinden ötürü önlenilmeye çalışılmalıdır. ``` const halve = function(n) { @@ -110,15 +110,15 @@ console.log(n); {{id scoping}} -## Nested scope +### Gömülü kapsamlar {{index [nesting, "of functions"], [nesting, "of scope"], scope, "inner function", "lexical scoping"}} -JavaScript distinguishes not just global and local bindings. Blocks and functions can be created inside other blocks and functions, producing multiple degrees of locality. +JavaScript, sadece _global_ ve _yerel_ bağlantıları ayırt etmez. Bloklar ve fonksiyonlar diğer bloklar ve fonksiyonlar içinde oluşturulabilir, böylece çoklu kapsamlar oluştururlar. {{index "landscape example"}} -For example, this function—which outputs the ingredients needed to make a batch of hummus—has another function inside it: +Örneğin, humus yapmak için gerekli malzemeleri çıkaran bu fonksiyon, içinde başka bir fonksiyona sahiptir: ``` const hummus = function(factor) { @@ -140,19 +140,19 @@ const hummus = function(factor) { {{index [function, scope], scope}} -The code inside the `ingredient` function can see the `factor` binding from the outer function, but its local bindings, such as `unit` or `ingredientAmount`, are not visible in the outer function. +`ingredient` fonksiyonunun içindeki kod, dış fonksiyon `factor` bağlantısını görebilir. Ancak, `unit` veya `ingredientAmount` gibi içerisinde barındırdığı yerel bağlantılar dış fonksiyondan görülemez. -The set of bindings visible inside a block is determined by the place of that block in the program text. Each local scope can also see all the local scopes that contain it, and all scopes can see the global scope. This approach to binding visibility is called _((lexical scoping))_. +Bir bloğun içinde görünür olan bağlantılar kümesi, o bloğun program metnindeki konumuna göre belirlenir. Her yerel kapsam, kendisini içeren tüm yerel kapsamları görebilir ve tüm kapsamlar da global kapsamı görebilir. Bu bağlantılardaki bu görünürlük yaklaşımına ((lexical scoping(sözcüksel kapsam belirleme))) denir. -## Functions as values +## Değer olarak fonksiyonlar {{index [function, "as value"], [binding, definition]}} -A function binding usually simply acts as a name for a specific piece of the program. Such a binding is defined once and never changed. This makes it easy to confuse the function and its name. +Bir fonksiyon bağlantısı genellikle basitçe programın belirli bir parçası için bir isim olarak işlev görür ve bu tür bir bağlantılar bir kez tanımlanıp asla tekrardan değiştirilmezler. Bu, fonksiyonu ve adını karıştırmayı kolaylaştırır. {{index [binding, assignment]}} -But the two are different. A function value can do all the things that other values can do—you can use it in arbitrary ((expression))s, not just call it. It is possible to store a function value in a new binding, pass it as an argument to a function, and so on. Similarly, a binding that holds a function is still just a regular binding and can, if not constant, be assigned a new value, like so: +Ancak, ikisi farklıdır. Bir fonksiyon değeri, diğer değerlerin yapabileceği tüm işleri yapabilir - onu sadece çağırmakla kalmaz, istediğiniz yerde kullanabilirsiniz. Bir fonksiyon değerini yeni bir bağlantıya depolamak ve bir fonksiyona bir argüman olarak iletmek vb. mümkündür. Benzer şekilde, fonksiyon tutan bir bağlantı, hala yalnızca sıradan bir bağlantıdır ve eğer sabit bir şekilde oluşturulmadıysa(`const`) kendisine şu şekilde yeni bir değer atanabilir: ```{test: no} let launchMissiles = function() { @@ -165,13 +165,13 @@ if (safeMode) { {{index [function, "higher-order"]}} -In [Chapter ?](higher_order), we'll discuss the interesting things that we can do by passing around function values to other functions. +[Bölüm ?](higher_order)'da, fonksiyon değerlerini diğer fonksiyonlara argüman olarak vererek yapılabilen ilginç şeyleri tartışacağız. -## Declaration notation +## Beyan notasyonu {{index [syntax, function], "function keyword", "square example", [function, definition], [function, declaration]}} -There is a slightly shorter way to create a function binding. When the `function` keyword is used at the start of a statement, it works differently: +Bir işlev bağlantısı oluşturmanın biraz daha kısa bir yolu vardır. `function` anahtar kelimesi bir ifadenin başında kullanıldığında, farklı şekilde çalışır. ```{test: wrap} function square(x) { @@ -181,9 +181,9 @@ function square(x) { {{index future, "execution order"}} -This is a function _declaration_. The statement defines the binding `square` and points it at the given function. It is slightly easier to write and doesn't require a semicolon after the function. +Bu bir fonksiyon _beyanıdır_. Beyan, `square` bağlantısını tanımlar ve onu verilen fonksiyona işaret eder. Yazması biraz daha kolaydır ve işlevden sonra noktalı virgül gerektirmez. -There is one subtlety with this form of function definition. +Bu fonksiyon tanımlama formuyla alakalı bir nüans vardır. ``` console.log("The future says:", future()); @@ -193,13 +193,13 @@ function future() { } ``` -The preceding code works, even though the function is defined _below_ the code that uses it. Function declarations are not part of the regular top-to-bottom flow of control. They are conceptually moved to the top of their scope and can be used by all the code in that scope. This is sometimes useful because it offers the freedom to order code in a way that seems the clearest, without worrying about having to define all functions before they are used. +Fonksiyon, kullanıldığı kodun _altında_ tanımlanmış olsa bile önceki kod çalışır. Fonksiyon bildirimleri, düzenli olarak yukarıdan aşağıya kontrol akışının bir parçası değildir. Kavramsal olarak içinde bulundukları kapsamın en üstüne taşınır ve bu kapsamdaki tüm kod tarafından kullanılabilir. Bu bazen yararlı olabilir çünkü tüm fonksiyonların kullanılmadan önce tanımlanması gerekmeksizin kodu en net sayılan şekilde düzenleme özgürlüğü sunar. -## Arrow functions +## Ok notasyonu {{index function, "arrow function"}} -There's a third notation for functions, which looks very different from the others. Instead of the `function` keyword, it uses an arrow (`=>`) made up of an equal sign and a greater-than character (not to be confused with the greater-than-or-equal operator, which is written `>=`): +Fonksiyonlar için diğerlerinden çok farklı görünen üçüncü bir gösterim var. `function` anahtar kelimesi yerine, büyük eşittir operatörüyle(`>=`) karıştırılmaması gereken eşitlik ve büyüktür işaretlerinden oluşan bir ok (`=>`) kullanır. ```{test: wrap} const roundTo = (n, step) => { @@ -210,11 +210,11 @@ const roundTo = (n, step) => { {{index [function, body]}} -The arrow comes _after_ the list of parameters and is followed by the function's body. It expresses something like "this input (the ((parameter))s) produces this result (the body)". +Ok, parametre listesinin ardından gelir ve işlevin gövdesi takip eder. "Bu giriş (parametreler) bu sonucu (gövdeyi) üretir" gibi bir şey ifade eder. {{index [braces, "function body"], "square example", [parentheses, arguments]}} -When there is only one parameter name, you can omit the parentheses around the parameter list. If the body is a single expression, rather than a ((block)) in braces, that expression will be returned from the function. So, these two definitions of `square` do the same thing: +Tek bir parametre adı olduğunda, parametre listesinin etrafındaki parantezleri yazmanıza gerek yoktur. Gövde, süslü parantezlerle oluşturulmuş bir blok yerine, tek satırlık bir ifade ise bu ifade fonksiyondan `return` anahtar kelimesini kullanmadan kullanmışçasına döndürmenizi sağlar. Bu nedenle, bu iki square tanımı aynı şeyi yapar: ``` const square1 = (x) => { return x * x; }; @@ -223,7 +223,7 @@ const square2 = x => x * x; {{index [parentheses, arguments]}} -When an arrow function has no parameters at all, its parameter list is just an empty set of parentheses. +Bir ok işlevinin hiç parametresi olmadığında, parametre listesi yalnızca boş bir parantez kümesidir. ``` const horn = () => { @@ -233,16 +233,16 @@ const horn = () => { {{index verbosity}} -There's no deep reason to have both arrow functions and `function` expressions in the language. Apart from a minor detail, which we'll discuss in [Chapter ?](object), they do the same thing. Arrow functions were added in 2015, mostly to make it possible to write small function expressions in a less verbose way. We'll use them often in [Chapter ?](higher_order). +Dilin bir fonksiyonu hem ok fonksiyonlarıyla hem de `function` anahtar kelimesiyle oluşturulma olasılığını sağlamasının derin bir nedeni yoktur. Küçük bir ayrıntı dışında, [Bölüm ?](object)'da da konuşacağımız gibi bunlar aynı işi yaparlar. Ok fonksiyonları 2015 yılında daha rahat bir şekilde küçük fonksiyon ifadelerini yazmayı mümkün kılmak adına eklendi. [Bölüm ?](higher_order)'da çokça kullanacağız. {{id stack}} -## The call stack +## Çağrı yığını {{indexsee stack, "call stack"}} {{index "call stack", [function, application]}} -The way control flows through functions is somewhat involved. Let's take a closer look at it. Here is a simple program that makes a few function calls: +Kontrolün fonksiyonlar arasında nasıl akış gösterdiği biraz karmaşıktır, hadi buna daha yakından bakalım. İşte birkaç fonksiyon çağrısı yapan basit bir program: ``` function greet(who) { @@ -254,29 +254,29 @@ console.log("Bye"); {{index ["control flow", functions], "execution order", "console.log"}} -A run through this program goes roughly like this: the call to `greet` causes control to jump to the start of that function (line 2). The function calls `console.log`, which takes control, does its job, and then returns control to line 2. There, it reaches the end of the `greet` function, so it returns to the place that called it—line 4. The line after that calls `console.log` again. After that returns, the program reaches its end. +Bu programın çalışması yaklaşık olarak şöyle gider: `greet` fonksiyonuna yapılan çağrı, kontrolün o fonksiyonun başına (2. satır) atlamasına neden olur. Fonksiyon, `console.log`'u çağırır, kontrolü alır, işini yapar ve ardından kontrolü 2. satıra geri verir. Orada `greet` fonksiyonunun sonuna ulaşır, bu nedenle onu çağıran yere geri döner, ki bu da 4. satırdır. Bundan sonra bir sonraki satır tekrar `console.log` çağrısı yapar. Dönüş yaptıktan sonra, program sonuna ulaşır. -We could show the flow of control schematically like this: +Kontrol akışını şematik olarak şöyle gösterebiliriz: ```{lang: null} not in function - in greet - in console.log - in greet + in greet + in console.log + in greet not in function - in console.log + in console.log not in function ``` {{index "return keyword", [memory, call stack]}} -Because a function has to jump back to the place that called it when it returns, the computer must remember the context from which the call happened. In one case, `console.log` has to return to the `greet` function when it is done. In the other case, it returns to the end of the program. +Bir fonksiyona dönüş yapıldığında çağrıldığı yere geri kontrol akışının geri dönebilmesi için, bilgisayarın, çağrının nereden yapıldığı bağlamını hatırlaması gerekir. Bir durumda, `console.log`, işi bittiğinde `greet` fonksiyonuna dönmelidir. Diğer bir durumdaysa programın sonuna dönmelidir. -The place where the computer stores this context is the _((call stack))_. Every time a function is called, the current context is stored on top of this stack. When a function returns, it removes the top context from the stack and uses that context to continue execution. +Bilgisayarın bu bağlamı sakladığı yer _((çağrı yığını))_ dır. Bir fonksiyon çağrıldığında, mevcut bağlam bu yığının üstüne depolanır. Bir işlev döndüğünde, yığının üstündeki bağlamı kaldırır ve kaldırdığı bu bağlamı programı yürütmeye devam etmek için kullanır. {{index "infinite loop", "stack overflow", recursion}} -Storing this stack requires space in the computer's memory. When the stack grows too big, the computer will fail with a message like "out of stack space" or "too much recursion". The following code illustrates this by asking the computer a really hard question that causes an infinite back-and-forth between two functions. Or rather, it _would_ be infinite, if the computer had an infinite stack. As it is, we will run out of space, or "blow the stack". +Bu yığını saklamak, bilgisayarın belleğinde yer gerektirir. Yığın çok büyük hale geldiğinde, bilgisayar "yığın depolama alanı kalmadı" veya "çok fazla özyineleme yapıldı" gibi bir hata mesajıyla başarısız olacaktır. Aşağıdaki kod, bilgisayara sonsuz geriye doğru gidip gelme gerektiren gerçekten zor bir soru sorarak bunu gösterir. Aslında, bilgisayarın gerçekten sonsuz bir yığını olsaydı _sonsuz olurdu_ ancak şu anki durumda alanı tüketir ve "yığı taşarız". ```{test: no} function chicken() { @@ -289,11 +289,11 @@ console.log(chicken() + " came first."); // → ?? ``` -## Optional Arguments +## Opsiyonel argümanlar {{index argument, [function, application]}} -The following code is allowed and executes without any problem: +Aşağıdaki koda izin verilir ve herhangi bir sorun olmaksızın çalışır: ``` function square(x) { return x * x; } @@ -301,13 +301,15 @@ console.log(square(4, true, "hedgehog")); // → 16 ``` -We defined `square` with only one ((parameter)). Yet when we call it with three, the language doesn't complain. It ignores the extra arguments and computes the square of the first one. +`square`'i yalnızca bir ((parametre)) ile tanımladık. Ancak üç adet argümanla çağırdığımızda JavaScript'in şikayet etmediğini ve ek argümanları yok sayıp ilk argümanın karesini hesapladığını gözlemliyoruz. {{index undefined}} -JavaScript is extremely broad-minded about the number of arguments you can pass to a function. If you pass too many, the extra ones are ignored. If you pass too few, the missing parameters are assigned the value `undefined`. +JavaScript, bir işleve kaç argüman geçirdiğiniz konusunda son derece açık fikirlidir. Çok fazla argüman verirseniz, fazladan olanlar yok sayılır. Çok az argüman verirseniz, eksik parametreler `undefined` değerine otomatik olarak atanır. -The downside of this is that it is possible—likely, even—that you'll accidentally pass the wrong number of arguments to functions. And no one will tell you about it. The upside is that you can use this behavior to allow a function to be called with different numbers of arguments. For example, this `minus` function tries to imitate the `-` operator by acting on either one or two arguments: +Bunun dezavantajı, fonksiyonlara olası olarak yanlış sayıda argüman verecek olursanız size kimsenin bundan haber vermeyecek olmasıdır. + +Avantajı ise, bu davranışın bir fonksiyonun farklı sayılarda argümanlarla çağrılmasına izin vermek için kullanılabilmesidir. Örneğin, bu `minus` fonksiyonu, bir veya iki argümanla etkileşime girerek `-` operatörünü taklit etmeye çalışır: ``` function minus(a, b) { @@ -324,7 +326,11 @@ console.log(minus(10, 5)); {{id roundTo}} {{index "optional argument", "default value", parameter, ["= operator", "for default value"] "roundTo example"}} -If you write an `=` operator after a parameter, followed by an expression, the value of that expression will replace the argument when it is not given. For example, this version of `roundTo` makes its second argument optional. If you don't provide it or pass the value `undefined`, it will default to one: +Bir parametrenin ardından `=` operatörünü yazar ve onu bir ifade ile takip ederseniz, o parametre için bir argüman değeri verilmediğinde o verdiğiniz ifade, parametrenin varsayılan argüman değeri haline gelir. + +{{index "roundTo example"}} + +Örneğin, bu versiyon `roundTo` fonksiyonunun ikinci argümanını opsiyonel hale getirir. Eğer `undefined` değerini argüman olarak vermezseniz, o ikinci parametrenin varsayılan argüman değeri 1 olacaktır. ```{test: wrap} function roundTo(n, step = 1) { @@ -340,20 +346,20 @@ console.log(roundTo(4.5, 2)); {{index "console.log"}} -The [next chapter](data#rest_parameters) will introduce a way in which a function body can get at the whole list of arguments it was passed. This is helpful because it allows a function to accept any number of arguments. For example, `console.log` does this, outputting all the values it is given: +[Sonraki bölümde](data#rest_parameters), bir fonksiyon gövdesinin aldığı tüm argüman listesine nasıl erişebileceğimizi göreceğiz. Bu, bir fonksiyonun herhangi bir sayıda argümanı kabul etmesini mümkün kılar. Örneğin, `console.log` bunu yapar ve kendisine verilen tüm değerleri çıktı olarak gösterir. ``` console.log("C", "O", 2); // → C O 2 ``` -## Closure +## Kapama {{index "call stack", "local binding", [function, "as value"], scope}} -The ability to treat functions as values, combined with the fact that local bindings are recreated every time a function is called, brings up an interesting question: what happens to local bindings when the function call that created them is no longer active? +Fonksiyonları herhangi bir değer olarak ele alabilme yeteneği ve fonksiyonların her çağrıldığında yerel bağlantılarının yeniden oluşturulması özellikleri ortaya ilginç bir soru çıkarır. Yerel bağlara onları oluşturan fonksiyon çağrısı artık etkin değilken ne olur? -The following code shows an example of this. It defines a function, `wrapValue`, that creates a local binding. It then returns a function that accesses and returns this local binding: +Aşağıdaki kod, bunun bir örneğini gösterir. Bir yerel bağlantı oluşturan `wrapValue` adında bir fonksiyon tanımlar. Ardından bu yerel bağlantıya erişen ve bunu döndüren bir fonksiyon döndürür. ``` function wrapValue(n) { @@ -369,13 +375,13 @@ console.log(wrap2()); // → 2 ``` -This is allowed and works as you'd hope—both instances of the binding can still be accessed. This situation is a good demonstration of the fact that local bindings are created anew for every call, and different calls don't affect each other's local bindings. +Bu izin verilir ve umduğunuz gibi çalışır - her iki ayrı yaratılmış bağlam hala erişilebilir. Bu durum, yerel bağlantıların her çağrı için yeniden oluşturulduğunu ve farklı çağrıların birbirlerinin yerel bağlantılarını etkilemediğini iyi bir şekilde gösterir. -This feature—being able to reference a specific instance of a local binding in an enclosing scope—is called _((closure))_. A function that references bindings from local scopes around it is called _a_ closure. This behavior not only frees you from having to worry about the lifetimes of bindings but also makes it possible to use function values in some creative ways. +Kapsayan bir kapsamdaki belirli bir yerel bağlantının yaratılmış spesifik bir değerine başvurabilmeyi sağlayan bu özellik _((kapama))_ olarak adlandırılır. Etrafındaki kapsamlardan yerel bağlantı veya bağlantılarını kullanan bir fonksiyonun kullandığı özelliğe kapama denir. Bu davranış, bağlantıların yaşam süreleri hakkında endişelenmenize gerek olmadığı için sizi serbest bırakmakla kalmaz, aynı zamanda fonksiyon değerlerini bazı yaratıcı şekillerde kullanmanızı mümkün kılar. {{index "multiplier function"}} -With a slight change, we can turn the previous example into a way to create functions that multiply by an arbitrary amount: +Önceki örneği hafif bir değişiklikle vereceğimiz herhangi bir miktarı istediğimiz herhangi bir miktarla çarpan fonksiyonlar oluştucak bir haline getirebiliriz. ``` function multiplier(factor) { @@ -389,19 +395,19 @@ console.log(twice(5)); {{index [binding, "from parameter"]}} -The explicit `local` binding from the `wrapValue` example isn't really needed, since a parameter is itself a local binding. +`wrapValue` örneğindeki `local` bağlantısı bir parametre zaten kendisi de yerel bir bağlantı olduğundan ötürü gerekli değildir. {{index [function, "model of"]}} -Thinking about programs like this takes some practice. A good mental model is to think of function values as containing both the code in their body and the environment in which they are created. When called, the function body sees the environment in which it was created, not the environment in which it is called. +Bu tür programları düşünmek biraz pratik gerektirir. İyi bir zihinsel model, fonksiyon değerlerininin hem içindeki kodu ve hem de oluşturuldukları ortamı içerdiklerini düşünmektir. Çağrıldığında, fonksiyon gövdesi oluşturulduğu ortamı görür, çağrıldığı yerin ortamını değil. -In the previous example, `multiplier` is called and creates an environment in which its `factor` parameter is bound to 2. The function value it returns, which is stored in `twice`, remembers this environment so that when that is called, it multiplies its argument by 2. +Örnekte, `multiplier` çağrılır ve `factor` parametresinin 2'ye bağlı olduğu bir ortam oluşturur. `twice` bağlantısı içinde depolanan bu döndürülen fonksiyon değeri, o ortamı hatırlar ki çağrıldığında argümanını 2 ile çarpar. -## Recursion +## Özyineleme {{index "power example", "stack overflow", recursion, [function, application]}} -It is perfectly okay for a function to call itself, as long as it doesn't do it so often that it overflows the stack. A function that calls itself is called _recursive_. Recursion allows some functions to be written in a different style. Take, for example, this `power` function, which does the same as the `**` (exponentiation) operator: +Bir fonksiyonun yığını taşırmadığı sürece kendini çağırması tamamen normaldir. Kendini çağıran bir fonskiyon _özyineleyici_ bir fonksiyon olarak adlandırılır. Özyineleyicilik, bazı işlevlerin farklı bir tarzda yazılmasına olanak tanır. Örneğin, `**` (üs alma) operatörü ile aynı işi yapan bu `power` adlı fonksiyona bakın: ```{test: wrap} function power(base, exponent) { @@ -418,36 +424,39 @@ console.log(power(2, 3)); {{index loop, readability, mathematics}} -This is rather close to the way mathematicians define exponentiation and arguably describes the concept more clearly than the loop we used in [Chapter ?](program_structure). The function calls itself multiple times with ever smaller exponents to achieve the repeated multiplication. +Bu, matematikçilerin üs alma işlemini tanımlama şekline oldukça yakındır ve tartışmaya açık bir şekilde [Bölüm ?](program_structure)'da kullandığımız döngüden daha açık bir şekilde kavramı tanımlar. Tekrarlı çarpma işlemini gerçekleştirmek için her seferinde daha küçük üslerle kendini birden çok kez çağırır. {{index [function, application], efficiency}} -This implementation has one problem, however: in typical JavaScript implementations, it's about three times slower than a version using a `for` loop. Running through a simple loop is generally cheaper than calling a function multiple times. +Ancak bu uygulamanın bir sorunu var: tipik JavaScript uygulamalarında, döngü kullanan bir versiyondan yaklaşık üç kat daha yavaştır. Basit bir döngüden geçmek, bir fonksiyonu birden çok kez çağırmaktan genellikle performans bakımından daha ucuzdur. {{index optimization}} -The dilemma of speed versus ((elegance)) is an interesting one. You can see it as a kind of continuum between human-friendliness and machine-friendliness. Almost any program can be made faster by making it bigger and more convoluted. The programmer has to find an appropriate balance. +Hızlılıkla ((zarafet)) arasındaki ikilem ilginçtir. Bu, insan dostu ve makine dostu olmak arasında bir tür devam eden bir durum olarak görülebilir. Neredeyse her program, onu daha büyük ve daha karmaşık hale getirerek daha hızlı hale getirilebilir. Programcının burada uygun bir dengeyi kendisinin belirlemesi gerekmektedir. -In the case of the `power` function, an inelegant (looping) version is still fairly simple and easy to read. It doesn't make much sense to replace it with a recursive function. Often, though, a program deals with such complex concepts that giving up some efficiency in order to make the program more straightforward is helpful. +Often, though, a program deals with such complex concepts that giving up some efficiency in order to make the program more straightforward is helpful. +`power` fonksiyonunun durumunda, zarif olmayan (döngü kullanan) bir versiyon hala oldukça basit ve okunması kolaydır. Onu özyinelemeli bir fonksiyonla değiştirmenin pek mantıklı değildir. Ancak, bir program genellikle öyle kompleks durumlarla ilgilenir ki programı daha anlaşılır hale getirmek için bazen verimliliğinden vazgeçmek daha mantıklıdır. {{index profiling}} -Worrying about efficiency can be a distraction. It's yet another factor that complicates program design, and when you're doing something that's already difficult, that extra thing to worry about can be paralyzing. +Verimlilik hakkında endişelenmek dikkati dağıtabilir. Bu, program tasarımını karmaşıklaştıran başka bir faktördür ve zaten zor olan bir şey yaparken, bu ekstra düşünme nedeniyle felç olabilirsiniz. {{index "premature optimization"}} -Therefore, you should generally start by writing something that's correct and easy to understand. If you're worried that it's too slow—which it usually isn't, since most code simply isn't executed often enough to take any significant amount of time—you can measure afterward and improve it if necessary. +Bu nedenle, genellikle doğru ve anlaşılması kolay olan bir şey yazarak başlamalısınız. Genellikle çoğu kod önemli miktarda çalıştırılmadığından ötürü aldığı zaman hakkında çok da endişelenmenize gerek yoktur, sonradan ölçebilir ve gerektiğinde iyileştirebilirsiniz. {{index "branching recursion"}} -Recursion is not always just an inefficient alternative to looping. Some problems really are easier to solve with recursion than with loops. Most often these are problems that require exploring or processing several "branches", each of which might branch out again into even more branches. +Özyineleme, sadece döngülerin verimsiz bir alternatifi değildir. Bazı problemler gerçekten özyineleme aracılığıyla döngülerden daha kolay bir şekilde çözülebilir. Çoğunlukla bunlar, birden çok "dal" keşfetmeyi veya işlemeyi gerektiren problemlerdir, her bir dal daha fazla dala ayrılabilir. {{id recursive_puzzle}} {{index recursion, "number puzzle example"}} -Consider this puzzle: by starting from the number 1 and repeatedly either adding 5 or multiplying by 3, an infinite set of numbers can be produced. How would you write a function that, given a number, tries to find a sequence of such additions and multiplications that produces that number? For example, the number 13 could be reached by first multiplying by 3 and then adding 5 twice, whereas the number 15 cannot be reached at all. +Bu bulmacayı düşünün: Sayı 1'den başlayarak ve tekrarlanarak ya 5 eklenerek ya da 3 ile çarpılarak, sonsuz bir sayı kümesi üretilebilir. Verilen bir sayıyı üreten böyle bir toplama ve çarpma dizisi bulmaya çalışan bir fonksiyonu nasıl yazarsınız? -Here is a recursive solution: +Örneğin, sayı 13'e, önce 3 ile çarpılarak ve ardından 5 iki kez eklenerek ulaşılabilirken, sayı 15 hiçbir şekilde ulaşılamaz. + +İşte bir özyinelemeli bir çözüm: ``` function findSolution(target) { @@ -468,19 +477,19 @@ console.log(findSolution(24)); // → (((1 * 3) + 5) * 3) ``` -Note that this program doesn't necessarily find the _shortest_ sequence of operations. It is satisfied when it finds any sequence at all. +Bu programın _en kısa_ işlem dizisini bulması gerekmediğini lütfen unutmayın, kendisi herhangi bir diziyi bulduğunda memnun olur. -It's okay if you don't see how this code works right away. Let's work through it, since it makes for a great exercise in recursive thinking. +Hemen nasıl çalıştığını görmüyorsanız endişelenmeyin. Bunun üzerinde çalışalım, çünkü bu, özyinelemeli düşünme pratiği için harika bir alıştırmadır. -The inner function `find` does the actual recursing. It takes two ((argument))s: the current number and a string that records how we reached this number. If it finds a solution, it returns a string that shows how to get to the target. If it can find no solution starting from this number, it returns `null`. +İçeride bulunan `find`, gerçek özyinelemeli işlemi yapmaktadır. İki ((argüman)) alır: mevcut sayı ve bu sayıya nasıl ulaştığımızı kaydeden bir dize. Bir çözüm bulursa, hedefe nasıl ulaşılacağını gösteren bir dize döndürür. Bu sayıdan başlayarak bir çözüm bulunamazsa, `null` döndürür. {{index null, "?? operator", "short-circuit evaluation"}} -To do this, the function performs one of three actions. If the current number is the target number, the current history is a way to reach that target, so it is returned. If the current number is greater than the target, there's no sense in further exploring this branch because both adding and multiplying will only make the number bigger, so it returns `null`. Finally, if we're still below the target number, the function tries both possible paths that start from the current number by calling itself twice, once for addition and once for multiplication. If the first call returns something that is not `null`, it is returned. Otherwise, the second call is returned, regardless of whether it produces a string or `null`. +Bunu yapmak için işlev üç eylemden birini gerçekleştirir. Eğer mevcut sayı hedef sayı ise, mevcut geçmiş, hedefe ulaşmanın bir yoludur, bu yüzden döndürülür. Eğer mevcut sayı hedeften büyükse, bu dalı daha fazla keşfetmenin bir anlamı yoktur çünkü hem eklemek hem de çarpmak sayıyı sadece daha büyük yapar, bu yüzden `null` döndürür. Son olarak, hala hedef sayıdan daha düşükse, fonksiyon mevcut sayıdan başlayan her iki olası yolu da denemek için kendisini iki kez çağırır, bir kez toplama ve bir kez çarpma için. İlk çağrı `null` döndürmeyen bir şey döndürürse, bu döndürülür. Aksi takdirde, ikinci çağrı, dize veya `null` üretip üretmediğine bakılmasızın döndürülür. {{index "call stack"}} -To better understand how this function produces the effect we're looking for, let's look at all the calls to `find` that are made when searching for a solution for the number 13: +Bu fonksiyonun istediğimiz etkiyi nasıl ürettiğini daha iyi anlamak için, 13 sayısı için bir çözüm ararken yapılan tüm `find` çağrılarına bakalım. ```{lang: null} find(1, "1") @@ -498,34 +507,34 @@ find(1, "1") found! ``` -The indentation indicates the depth of the call stack. The first time `find` is called, the function starts by calling itself to explore the solution that starts with `(1 + 5)`. That call will further recurse to explore _every_ continued solution that yields a number less than or equal to the target number. Since it doesn't find one that hits the target, it returns `null` back to the first call. There the `??` operator causes the call that explores `(1 * 3)` to happen. This search has more luck—its first recursive call, through yet _another_ recursive call, hits upon the target number. That innermost call returns a string, and each of the `??` operators in the intermediate calls passes that string along, ultimately returning the solution. +Girinti, çağrı yığınının derinliğini gösterir. `find` ilk kez çağrıldığında, `(1 + 5)` ile başlayan çözümü keşfetmek için kendisini çağırarak başlar. Bu çağrı, hedef sayıya eşit veya daha küçük bir sayı üreten _her_ çözümü keşfetmek için fonksiyonu tekrar eder. Hedefe ulaşan bir çözüm bulamadığından ötürü ilk çağrıya `null` döner. İlk çağrıda, `??` operatörü `(1 * 3)` ile keşfeden çağrının olmasını sağlar. Bu aramanın şansı yaver gider - ilk özyineleyici çağrısı, henüz başka bir özyineleyici çağrı aracılığıyla hedef sayıya ulaşır. En içteki çağrı bir dize döndürür, ve ara çağrılardaki her `??` operatörü bu diziyi çıktı olarak vererek sonunda çözümü döndürür. -## Growing functions +## Büyüyen fonksiyonlar {{index [function, definition]}} -There are two more or less natural ways for functions to be introduced into programs. +Programlara fonksiyonların tanıtılması için az buçuk doğal olan iki yol vardır. {{index repetition}} -The first occurs when you find yourself writing similar code multiple times. You'd prefer not to do that, as having more code means more space for mistakes to hide and more material to read for people trying to understand the program. So you take the repeated functionality, find a good name for it, and put it into a function. +İlk olarak, benzer kodları birden çok kez yazdığınızı fark edersiniz. Bunu yapmak istemezsiniz. Daha fazla kod, hataların saklanabileceği daha fazla alan ve programı anlamaya çalışan insanlar için okunacak daha fazla materyal demektir. Bu nedenle, tekrarlanan kodu alır, ona iyi bir isim bulur ve bir fonksiyon içine koyarsınız. -The second way is that you find you need some functionality that you haven't written yet and that sounds like it deserves its own function. You start by naming the function, then write its body. You might even start writing code that uses the function before you actually define the function itself. +İkinci yol, henüz yazmadığınız ancak kendi fonksiyonunu hak eden bazı koda ihtiyacınız olduğunu fark ettiğinizdir. Fonksiyonu adlandırmakla başlayacak ve ardından gövdesini yazacaksınız. Hatta fonksiyonu tanımlamadan önce fonksiyonu kullanan kodu yazmaya bile başlayabilirsiniz. {{index [function, naming], [binding, naming]}} -How difficult it is to find a good name for a function is a good indication of how clear a concept it is that you're trying to wrap. Let's go through an example. +Bir fonksiyon için iyi bir ad bulmanın ne kadar zor olduğu, kod yazmaya çalıştığınız kavramın ne kadar net olduğunun iyi bir göstergesidir. Bir örnek üzerinden geçelim. {{index "farm example"}} -We want to write a program that prints two numbers: the numbers of cows and chickens on a farm, with the words `Cows` and `Chickens` after them and zeros padded before both numbers so that they are always three digits long: +Bir çiftlikteki ineklerin ve tavukların sayısını, ardından her iki sayının yanına `Cows` ve `Chickens` kelimelerini ve her iki sayının da her zaman üç basamaklı olacak şekilde önceden doldurulmuş sıfırlarını yazdıran bir program yazmak istiyoruz. ```{lang: null} 007 Cows 011 Chickens ``` -This asks for a function of two arguments—the number of cows and the number of chickens. Let's get coding. +Bu, iki argümanlı bir fonksiyon gerektirir - ineklerin sayısı ve tavukların sayısı. Hadi kodlamaya başlayalım. ``` function printFarmInventory(cows, chickens) { @@ -545,13 +554,13 @@ printFarmInventory(7, 11); {{index ["length property", "for string"], "while loop"}} -Writing `.length` after a string expression will give us the length of that string. Thus, the `while` loops keep adding zeros in front of the number strings until they are at least three characters long. +Bir dize ifadesinin sonuna `.length` yazmak bize o dizenin uzunluğunu verecektir. Bu nedenle, `while` döngüleri, sayı dizelerinin en az üç karakter uzunluğunda olana kadar önüne sıfırlar eklemeye devam eder. -Mission accomplished! But just as we are about to send the farmer the code (along with a hefty invoice), she calls and tells us she's also started keeping pigs, and couldn't we please extend the software to also print pigs? +Görev tamamlandı! Ancak, çiftlik sahibine kodu (birlikte ciddi bir fatura ile) gönderecekken, bizi arar ve ayrıca domuzları da yazdırmak için yazılımı genişletemeyiz mi diye bize sorar. {{index "copy-paste programming"}} -We sure can. But just as we're in the process of copying and pasting those four lines one more time, we stop and reconsider. There has to be a better way. Here's a first attempt: +Tabii ki yapabiliriz. Ancak, o dört satırı bir kez daha kopyalayıp yapıştırma sürecindeyken durur ve yeniden düşünürüz. Daha iyi bir yol olmalı. İşte bu bizim ilk denememiz: ``` function printZeroPaddedWithLabel(number, label) { @@ -573,11 +582,11 @@ printFarmInventory(7, 11, 3); {{index [function, naming]}} -It works! But that name, `printZeroPaddedWithLabel`, is a little awkward. It conflates three things—printing, zero-padding, and adding a label—into a single function. +İşe yarıyor! Ancak, `printZeroPaddedWithLabel` adı biraz garip. Üç şeyi - yazdırma, sıfır dolgusu ve bir etiket ekleme - tek bir işlevde birleştiriyor gibi görünüyor. {{index "zeroPad function"}} -Instead of lifting out the repeated part of our program wholesale, let's try to pick out a single _concept_: +Programımızın tekrar eden kısmını toptan dışarı çıkarmak yerine, tek bir _kavram_ seçmeye çalışalım. ``` function zeroPad(number, width) { @@ -599,36 +608,38 @@ printFarmInventory(7, 16, 3); {{index readability, "pure function"}} -A function with a nice, obvious name like `zeroPad` makes it easier for someone who reads the code to figure out what it does. Such a function is also useful in more situations than just this specific program. For example, you could use it to help print nicely aligned tables of numbers. +`zeroPad` gibi güzel, açık bir adı olan bir fonksiyon, kodu okuyan birinin ne yaptığını anlamasını kolaylaştırır. Ve böyle bir fonksiyon, sadece bu belirli program için değil, daha fazla durumda da kullanışlıdır. Örneğin, sayıların güzelce hizalanmış tablolarını konsola yazdırmaya yardımcı olmak için de kullanabilirsiniz. {{index [interface, design]}} -How smart and versatile _should_ our function be? We could write anything, from a terribly simple function that can only pad a number to be three characters wide to a complicated generalized number-formatting system that handles fractional numbers, negative numbers, alignment of decimal dots, padding with different characters, and so on. +İşlevimiz ne kadar zeki ve çok yönlü olmalıdır? Çok basit sadece üç karakter genişliğinde bir sayı dolgusunu yapabilen bir fonksiyondan karmaşık genelleştirilmiş tam olmayan sayıları, negatif satıları, tam olmayan sayılardaki noktaları, farklı karakterlerle dolgu yapmayı da halledebilen bir sayı biçimlendirme sistemi oluşturmaya kadar her şeyi yazabiliriz. -A useful principle is to refrain from adding cleverness unless you are absolutely sure you're going to need it. It can be tempting to write general "((framework))s" for every bit of functionality you come across. Resist that urge. You won't get any real work done—you'll be too busy writing code that you never use. +Kullanışlı bir prensip, kesinlikle ihtiyacınız olduğundan emin olmadıkça, zekiğe girmemektir. Karşılaştığınız her işlev için genel "((çerçeve))ler" yazma dürtüsüne karşı koyun. Eğer bu prensipi takip etmezseniz gerçekten bir iş yapamayıp - sadece hiç kullanmayacağınız kod yazacaksınız. {{id pure}} -## Functions and side effects + +## Fonksiyonlar ve yan etkiler {{index "side effect", "pure function", [function, purity]}} -Functions can be roughly divided into those that are called for their side effects and those that are called for their return value (though it is also possible to both have side effects and return a value). +Fonksiyonlar, yan etkileri için çağrılanlar ve dönüş değeri için çağrılanlar olarak kabaca ikiye ayrılabilir. (Ancak hem yan etkilere sahip olmak ve hem de bir değer döndürmek kesinlikle mümkündür.) {{index reuse}} -The first helper function in the ((farm example)), `printZeroPaddedWithLabel`, is called for its side effect: it prints a line. The second version, `zeroPad`, is called for its return value. It is no coincidence that the second is useful in more situations than the first. Functions that create values are easier to combine in new ways than functions that directly perform side effects. +((Çiftlik örneğinde))ki ilk yardımcı fonksiyon olan `printZeroPaddedWithLabel`, yan etkisi için çağrılır: bir satır yazdırır. İkinci sürüm olan zeroPad`, dönüş değeri için çağrılır. İkincisinin birinciden daha fazla durumda kullanışlı olması tesadüf değildir. Değerler üreten fonksiyonlar, doğrudan yan etki yapan fonksiyonlardan daha kolay yeni şekillerde birleştirilebilmektedirler. {{index substitution}} -A _pure_ function is a specific kind of value-producing function that not only has no side effects but also doesn't rely on side effects from other code—for example, it doesn't read global bindings whose value might change. A pure function has the pleasant property that, when called with the same arguments, it always produces the same value (and doesn't do anything else). A call to such a function can be substituted by its return value without changing the meaning of the code. When you are not sure that a pure function is working correctly, you can test it by simply calling it and know that if it works in that context, it will work in any context. Nonpure functions tend to require more scaffolding to test. +Bir _saf_ fonksiyon, yalnızca yan etkisi olmayan belirli bir türde bir değer üreten bir fonksiyon değil, ayrıca diğer kodlardan yan etkileri de almayan bir işlevdir - örneğin, değeri değişebilecek global bağlantıları okumaz. Saflık fonksiyonu, aynı argümanlarla çağrıldığında her zaman aynı değeri üreten (ve başka bir şey yapmayan) hoş bir özelliğe sahiptir. Böyle bir fonksiyonun çağrısı, kodun anlamını değiştirmeden döndürdüğü değeri kullanarak değiştirilebilir. Bir saf fonksiyonun doğru çalışıp çalışmadığından emin değilseniz, onu sadece çağırarak test edebilir ve eğer bu bağlamda çalışıyorsa, herhangi bir bağlamda da çalışacağını bilirsiniz. Saf olmayan fonksiyonların test edilmesi daha fazla destekleme gerektirir. {{index optimization, "console.log"}} -Still, there's no need to feel bad when writing functions that are not pure. Side effects are often useful. There's no way to write a pure version of `console.log`, for example, and `console.log` is good to have. Some operations are also easier to express in an efficient way when we use side effects. +Yine de, saf olmayan fonksiyonlar yazdığınızda kötü hissetmenize gerek yok. Yan etkiler genellikle yararlıdır. Örneğin, `console.log`'un saf bir versiyonunu yazmanın bir yolu yoktur ve `console.log`'un olması iyidir. Bazı işlemler, yan etkileri kullanarak daha verimli bir şekilde ifade edilebilir. -## Summary +## Özet -This chapter taught you how to write your own functions. The `function` keyword, when used as an expression, can create a function value. When used as a statement, it can be used to declare a binding and give it a function as its value. Arrow functions are yet another way to create functions. +The `function` keyword, when used as an expression, can create a function value. When used as a statement, it can be used to declare a binding and give it a function as its value. Arrow functions are yet another way to create functions. +Bu bölüm, size kendi fonksiyonlarınızı yazmayı öğretti. `function` anahtar kelimesi, bir ifade olarak kullanıldığında bir fonksiyon değeri oluşturabilir. Bir beyan olarak kullanıldığında, bir bağlantıyı bildirmek ve ona bir fonksiyon değeri olarak vermek için kullanılabilir. Ok fonksiyonlarıysa fonksiyon oluşturmanın başka bir yoludur. ``` // Define f to hold a function value @@ -645,64 +656,65 @@ function g(a, b) { let h = a => a % 3; ``` -A key part of understanding functions is understanding scopes. Each block creates a new scope. Parameters and bindings declared in a given scope are local and not visible from the outside. Bindings declared with `var` behave differently—they end up in the nearest function scope or the global scope. +İşlevleri anlamanın temel yönlerinden biri kapsamları anlamaktır. Her blok yeni bir kapsam oluşturur. Bir kapsam içindeki parametreler ve bağlantılar yerel olup dışarıdan görünmez. `var` ile bildirilen bağlantılar farklı davranır - bunlar en yakın fonksiyon kapsamına veya global kapsama yerleşirler. -Separating the tasks your program performs into different functions is helpful. You won't have to repeat yourself as much, and functions can help organize a program by grouping code into pieces that do specific things. +Programınızın yaptığı görevleri farklı fonksiyonlara ayırmak yararlıdır. Kendinizi tekrar etmek zorunda kalmazsınız ve fonksiyonlar, kodu belirli şeyler yapan parçalara gruplayarak bir programı düzenlemenize yardımcı olabilir. -## Exercises +## Egzersizler ### Minimum {{index "Math object", "minimum (exercise)", "Math.min function", minimum}} -The [previous chapter](program_structure#return_values) introduced the standard function `Math.min` that returns its smallest argument. We can write a function like that ourselves now. Define the function `min` that takes two arguments and returns their minimum. +[Önceki bölüm](program_structure#return_values), en küçük verilen argümanını döndüren standart `Math.min` işlevini tanıttı. Şimdi buna benzer bir şey yapabiliriz. İki argüman alan ve bunların minimumunu döndüren `min` adında bir fonksiyon yazın. {{if interactive ```{test: no} -// Your code here. +// Kodunuz buraya. console.log(min(0, 10)); // → 0 console.log(min(0, -10)); // → -10 ``` + if}} {{hint {{index "minimum (exercise)"}} -If you have trouble putting braces and parentheses in the right place to get a valid function definition, start by copying one of the examples in this chapter and modifying it. +Eğer süslü parantezleri ve normal parantezleri doğru yerlere koyarak bir geçerli fonksiyon tanımı elde etmekte zorlanıyorsanız, bir önceki bölümdeki örneklerden birini kopyalayıp onu değiştirerek başlayabilirsiniz. {{index "return keyword"}} -A function may contain multiple `return` statements. +Bir fonksiyon birden fazla `return` beyanını içinde bulundurabilir. hint}} -### Recursion +### Özyineleme {{index recursion, "isEven (exercise)", "even number"}} -We've seen that we can use `%` (the remainder operator) to test whether a number is even or odd by using `% 2` to see whether it's divisible by two. Here's another way to define whether a positive whole number is even or odd: +`%` (kalan işlemcisi) operatörünün bir sayının çift mi yoksa tek mi olduğunu test etmek için 2'ye bölünüp bölünmediğini anlamak adına `% 2` kullanılabileceğini gördük. İşte bir pozitif tam sayının çift veya tek olup olmadığını tanımlamanın başka bir yolu: -- Zero is even. +- Sıfır çifttir. -- One is odd. +- Bir tektir. -- For any other number _N_, its evenness is the same as _N_ - 2. +- Herhangi bir _N_ sayısı için _N_ - 2 çifttir. -Define a recursive function `isEven` corresponding to this description. The function should accept a single parameter (a positive, whole number) and return a Boolean. +Bu tanıma karşılık gelen özyinelemeli bir fonksiyon olan `isEven` fonksiyonunu tanımlayın. Fonksiyon tek bir parametre kabul etmeli (pozitif, tam sayı) ve Bir Boole değeri döndürmelidir. {{index "stack overflow"}} -Test it on 50 and 75. See how it behaves on -1. Why? Can you think of a way to fix this? +Fonksiyonu 50 ve 75 üzerinde test edin. -1'de nasıl davrandığını görün. Neden? Bunun nasıl düzeltilebileceğini düşünebilir misiniz? {{if interactive ```{test: no} -// Your code here. +// Kodunuz buraya. console.log(isEven(50)); // → true @@ -718,28 +730,28 @@ if}} {{index "isEven (exercise)", ["if keyword", chaining], recursion}} -Your function will likely look somewhat similar to the inner `find` function in the recursive `findSolution` [example](functions#recursive_puzzle) in this chapter, with an `if`/`else if`/`else` chain that tests which of the three cases applies. The final `else`, corresponding to the third case, makes the recursive call. Each of the branches should contain a `return` statement or in some other way arrange for a specific value to be returned. +Fonksiyonunuz muhtemelen bu bölümdeki özyinelemeli `findSolution` [örneğindeki](functions#recursive_puzzle) iç `find` fonksiyona oldukça benzer görünecek ve üç durumdan hangisinin uygulandığını test eden bir `if/else` `if/else` zinciri ile olacak. Üçüncü duruma karşılık gelen son `else`, özyinelemeli çağrıyı yapar. Her bir dal, belirli bir değerin döndürülmesini sağlamak için bir `return` beyanı içermelidir veya başka bir şekilde düzenlenmelidir. {{index "stack overflow"}} -When given a negative number, the function will recurse again and again, passing itself an ever more negative number, thus getting further and further away from returning a result. It will eventually run out of stack space and abort. +Negatif bir sayı verildiğinde, fonksiyon kendisine negatif bir sayı vererek tekrar tekrar özyinelemeye girecek, böylece sonuç döndürmekten giderek daha uzaklaşacaktır. Sonunda, yığın alanı tükenecek ve işlem iptal edilecektir. hint}} -### Bean counting +### Fasulye sayımı {{index "bean counting (exercise)", [string, indexing], "zero-based counting", ["length property", "for string"]}} -You can get the *N*th character, or letter, from a string by writing `[N]` after the string (for example, `string[2]`). The resulting value will be a string containing only one character (for example, `"b"`). The first character has position 0, which causes the last one to be found at position `string.length - 1`. In other words, a two-character string has length 2, and its characters have positions 0 and 1. +Bir diziden (örneğin `string[2]` olarak) N'inci karakterini veya harfini alabilirsiniz. Elde edilen değer, yalnızca bir karakter içeren bir dizedir (örneğin, `"b"`). İlk karakterin konumu 0 olduğu için, son karakterin konumu `string.length - 1` pozisyonunda bulunur. Başka bir deyişle, iki karakterlik bir dizenin uzunluğu 2'dir ve karakterleri 0 ve 1 konumunda bulunur. -Write a function `countBs` that takes a string as its only argument and returns a number that indicates how many uppercase B characters there are in the string. +Tek bir argüman olarak bir dize alan ve dizide kaç büyük `"B"` karakteri olduğunu gösteren bir sayı döndüren `countBs` adında bir fonksiyon yazın. -Next, write a function called `countChar` that behaves like `countBs`, except it takes a second argument that indicates the character that is to be counted (rather than counting only uppercase B characters). Rewrite `countBs` to make use of this new function. +Sonraki adımda, `countBs` gibi davranan ancak sadece bütük "B" dizesini saymak yerine sayılacak karakteri de belirtecek ikinci bir argüman alan `countChar` adında bir fonksiyon yazın. `countBs` işlevini bu yeni işlevi kullanacak şekilde tekrar yazın. {{if interactive ```{test: no} -// Your code here. +// Kodunuz buraya. console.log(countBs("BOB")); // → 2 @@ -753,10 +765,10 @@ if}} {{index "bean counting (exercise)", ["length property", "for string"], "counter variable"}} -Your function will need a ((loop)) that looks at every character in the string. It can run an index from zero to one below its length (`< string.length`). If the character at the current position is the same as the one the function is looking for, it adds 1 to a counter variable. Once the loop has finished, the counter can be returned. +İşleviniz, dizedeki her karaktere bakan bir ((döngü)) gerektirecektir. Döngü, sıfırdan dizenin uzunluğunun bir altına kadar bir dizini çalıştırabilir (`< string.length`). Mevcut konumdaki karakter fonksiyonun aradığı karakterle aynıysa, sayaç bağlantısındaki değeri 1 artırır. Döngü tamamlandığında, sayaç sonuç olarak `return` beyanı aracılığıyla döndürülebilir. {{index "local binding"}} -Take care to make all the bindings used in the function _local_ to the function by properly declaring them with the `let` or `const` keyword. +Fonksiyonda kullanılan tüm bağlantıların `let` veya `const` anahtar kelimelerini kullanarak düzgün bir şekilde fonksiyon içerisinde yerel halde olmasını sağlayın. hint}} diff --git a/04_data.md b/04_data.md index 54e19c81..01fe2642 100644 --- a/04_data.md +++ b/04_data.md @@ -1,10 +1,10 @@ {{meta {load_files: ["code/journal.js", "code/chapter/04_data.js"], zip: "node/html"}}} -# Data Structures: Objects and Arrays +# Veri Yapıları: Objeler ve Diziler {{quote {author: "Charles Babbage", title: "Passages from the Life of a Philosopher (1864)", chapter: true} -On two occasions I have been asked, 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?' [...] I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question. +İki kez bana şu soruyu sordular, 'Eğer makineye yanlış rakamlar girerseniz, doğru cevaplar çıkar mı?' [...] Böyle bir sorunun sorulmasına sebep olan kafa karışıklığı dolu fikirleri anlayamıyorum. quote}} @@ -14,47 +14,47 @@ quote}} {{index object, "data structure"}} -Numbers, Booleans, and strings are the atoms from which ((data)) structures are built. Many types of information require more than one atom, though. _Objects_ allow us to group values—including other objects—to build more complex structures. +Sayılar, Boole değerleri ve dizeler, ((veri)) yapılarının oluşturulduğu atomlardır. Ancak, birçok bilgi türü, birden fazla atom gerektirir. _Objeler_ bize, daha karmaşık yapılar oluşturmak için obje değerleri de dahil olmak üzere değerleri gruplamamıza olanak sağlar. -The programs we have built so far have been limited by the fact that they were operating only on simple data types. After learning the basics of data structures in this chapter, you'll know enough to start writing useful programs. +Şimdiye kadar oluşturduğumuz programlar, yalnızca basit veri türleri üzerinde çalıştıkları için sınırlıydı. Bu bölüm, temel veri yapılarını tanıtacaktır. Sonunda, yararlı programlar yazmaya başlamak için yeterli bilgiye sahip olacaksınız. -The chapter will work through a more or less realistic programming example, introducing concepts as they apply to the problem at hand. The example code will often build on functions and bindings introduced earlier in the book. +Bölüm, bir miktar gerçekçi bir programlama örneği üzerinden çalışacak ve kavramları uygulandıkları sorunla ilişkilendirecektir. Örnek kodlar genellikle metinde daha önce tanıtılan fonksiyonlar ve bağlantılar üzerine kurulacaktır. {{if book -The online coding ((sandbox)) for the book ([_https://eloquentjavascript.net/code_](https://eloquentjavascript.net/code)) provides a way to run code in the context of a particular chapter. If you decide to work through the examples in another environment, be sure to first download the full code for this chapter from the sandbox page. +Kitabın çevrimiçi kodlama ((kum havuzu)) ([_https://eloquentjavascript.net/code_](https://eloquentjavascript.net/code)) belirli bir bölüm bağlamında kodu çalıştırmanın bir yolunu sağlar. Örnekleri başka bir ortamda çalıştırmaya karar verirseniz, önce bu bölüm için tam kodu kum havuzu sayfasından indirmeyi unutmayın. if}} -## The weresquirrel +## Sincap {{index "weresquirrel example", lycanthropy}} -Every now and then, usually between 8 p.m. and 10 p.m., ((Jacques)) finds himself transforming into a small furry rodent with a bushy tail. +Arada sırada, genellikle akşam 8 ile 10 arasında, ((Jacques)) kendisini tüylü kuyruklu küçük bir kemirgen haline dönüşürken bulur. -On one hand, Jacques is quite glad that he doesn't have classic lycanthropy. Turning into a squirrel does cause fewer problems than turning into a wolf. Instead of having to worry about accidentally eating the neighbor (_that_ would be awkward), he worries about being eaten by the neighbor's cat. After two occasions of waking up on a precariously thin branch in the crown of an oak, naked and disoriented, he has taken to locking the doors and windows of his room at night and putting a few walnuts on the floor to keep himself busy. +Bir yandan, Jacques klasik kurt adamlığına sahip olmadığına oldukça sevinir. Bir sincapa dönüşmek, bir kurt adama dönüşmekten daha az soruna neden olur. Komşuyu yanlışlıkla yemekten endişe etmek yerine (bu garip olurdu), komşunun kedisi tarafından yenilmekten endişe eder. Meşe ağacının tacındaki tehlikeli derecede ince bir dalda, çıplak ve oryantasyonunu yitirmiş olarak uyanmış ve gece odasının kapılarını, pencerelerini kapatmaya ve kendisini meşgul etmeyi birkaç ceviz koyarak başarmıştır. -But Jacques would prefer to get rid of his condition entirely. The irregular occurrences of the transformation make him suspect that they might be triggered by something. For a while, he believed that it happened only on days when he had been near oak trees. However, avoiding oak trees did not solve the problem. +Ancak Jacques, durumunu tamamen ortadan kaldırmayı tercih ederdi. Dönüşümün düzensiz oluşları, onları tetikleyen bir şeyin olabileceğini düşündürmektedir. Bir süre, sadece meşe ağaçlarına yaklaştığı günlerde olduğuna inandı. Ancak meşe ağaçlarından kaçınmak sorunu durdurmadı. {{index journal}} -Switching to a more scientific approach, Jacques has started keeping a daily log of everything he does on a given day and whether he changed form. With this data he hopes to narrow down the conditions that trigger the transformations. +Daha bilimsel bir yaklaşıma geçiş yaparak, Jacques, belirli bir günde yaptığı her şeyi ve dönüşüp dönüşmediğini günlük olarak kaydetmeye başladı. Bu verilerle dönüşümleri tetikleyen koşulları daraltmayı umuyor. -The first thing he needs is a data structure to store this information. +İhtiyacı olan ilk şey, bu bilgileri depolamak için bir veri yapısıdır. -## Data sets +## Veri setleri {{index ["data structure", collection], [memory, organization]}} -To work with a chunk of digital data, we first have to find a way to represent it in our machine's memory. Say, for example, that we want to represent a ((collection)) of the numbers 2, 3, 5, 7, and 11. +Dijital veri parçalarıyla çalışabilmek için, onu öncelikle makinenin belleğinde temsil etmenin bir yolunu bulmamız gerekecek. Örneğin, 2, 3, 5, 7 ve 11 sayılar ((koleksiyon))unu temsil etmek istediğimizi varsayalım. {{index string}} -We could get creative with strings—after all, strings can have any length, so we can put a lot of data into them—and use `"2 3 5 7 11"` as our representation. But this is awkward. We'd have to somehow extract the digits and convert them back to numbers to access them. +Dizelerle yaratıcı olabiliriz—sonuçta, dizelerin herhangi bir uzunluğu olabilir, bu yüzden içine çok fazla veri koyabiliriz—ve `"2 3 5 7 11"` değerini temsilimiz olarak kullanabiliriz. Ancak bu garip bir yaklaşım. Sayıları dizeden çıkarıp tekrar erişmek için onları sayı türü değerlere dönüştürmeniz gerekir. {{index [array, creation], "[] (array)"}} -Fortunately, JavaScript provides a data type specifically for storing sequences of values. It is called an _array_ and is written as a list of values between ((square brackets)), separated by commas: +Neyse ki, JavaScript, değer dizilerini depolamak için özel bir veri türü sağlar. Buna _dizi_ denir ve virgüllerle ayrılmış bir değer listesi olarak yazılır, ((köşeli parantezler)) arasında bulunur. ``` let listOfNumbers = [2, 3, 5, 7, 11]; @@ -68,24 +68,24 @@ console.log(listOfNumbers[2 - 1]); {{index "[] (subscript)", [array, indexing]}} -The notation for getting at the elements inside an array also uses ((square brackets)). A pair of square brackets immediately after an expression, with another expression inside of them, will look up the element in the left-hand expression that corresponds to the _((index))_ given by the expression in the brackets. +Bir dizideki elemanlara erişim için kullanılan gösterim için ((köşeli parantezler)) kullanılır. İfadeyi takip eden bir çift köşeli parantez ve bu köşeli parantezler içinde başka bir ifade ile dizi içerisindeki \_((index))\_e denk gelen elementi arayacaktır. {{id array_indexing}} {{index "zero-based counting"}} -The first index of an array is zero, not one, so the first element is retrieved with `listOfNumbers[0]`. Zero-based counting has a long tradition in technology and in certain ways makes a lot of sense, but it takes some getting used to. Think of the index as the number of items to skip, counting from the start of the array. +Bir dizinin ilk dizini sıfırdır, bir değil. Bu nedenle, ilk eleman `listOfNumbers[0]` ile alınır. Sıfır tabanlı sayma, teknolojide uzun bir geleneğe sahiptir ve belirli yönlerden oldukça mantıklıdır, ancak alışması biraz zaman alır. İndeksi, dizinin başlangıcından itibaren atlama miktarı olarak düşünün. {{id properties}} -## Properties +## Özellikler {{index "Math object", "Math.max function", ["length property", "for string"], [object, property], "period character", [property, access]}} -We've seen a few expressions like `myString.length` (to get the length of a string) and `Math.max` (the maximum function) in past chapters. These expressions access a _property_ of some value. In the first case, we access the `length` property of the value in `myString`. In the second, we access the property named `max` in the `Math` object (which is a collection of mathematics-related constants and functions). +Geçmiş bölümlerde `myString.length` (bir dizgenin uzunluğunu almak için) ve `Math.max` (maksimum fonksiyonu) gibi şüpheli görünen bazı ifadeler gördük. Bunlar, bir değerin _özelliğine_ erişen ifadelerdir. İlk durumda, `myString` değeri içindeki `length` özelliğine erişiriz. İkincisinde, matematikle ilgili sabitler ve fonksiyonlardan oluşan bir koleksiyon olan `Math` nesnesindeki `max` adlı özelliğe erişiriz. {{index [property, access], null, undefined}} -Almost all JavaScript values have properties. The exceptions are `null` and `undefined`. If you try to access a property on one of these nonvalues, you get an error: +Hemen hemen tüm JavaScript değerlerinin özellikleri vardır. İstisnalar `null` ve `undefined` değerleridir. Bu değer olmayan değerlerden birinde bir özelliğe erişmeye çalışırsanız, bir hata alırsınız. ```{test: no} null.length; @@ -95,23 +95,23 @@ null.length; {{indexsee "dot character", "period character"}} {{index "[] (subscript)", "period character", "square brackets", "computed property", [property, access]}} -The two main ways to access properties in JavaScript are with a dot and with square brackets. Both `value.x` and `value[x]` access a property on `value`—but not necessarily the same property. The difference is in how `x` is interpreted. When using a dot, the word after the dot is the literal name of the property. When using square brackets, the expression between the brackets is _evaluated_ to get the property name. Whereas `value.x` fetches the property of `value` named "x", `value[x]` takes the value of the variable named `x` and uses that, converted to a string, as the property name. +JavaScript'te özelliklere erişmenin iki temel yolu vardır: bir nokta ile ve köşeli parantezlerle. Hem `value.x` hem de `value[x]`, değer üzerinde bir özelliğe erişir—ancak erişilen özellik tam olarak aynı özellik olmayabilir. Fark, `x`'in nasıl yorumlandığındadır. Nokta kullanırken, noktanın sonrasındaki kelime, erişilmek istenen özelliğin adıdır. Köşeli parantezler kullanırken, parantezler arasındaki ifade, erişilmek istenen özelliğin adını almak için _değerlendirilir_. Nokta kullanılırken, `value.x` ifadesi `value` objesinin "x" adlı özelliğini alırken, köşeli parantezler kullanılan `value[x]` ifadesinde, `x` adındaki değişkenin değerini alır ve bunu bir dizeye dönüştürerek özellik adı olarak kullanır. -If you know that the property in which you are interested is called _color_, you say `value.color`. If you want to extract the property named by the value held in the binding `i`, you say `value[i]`. Property names are strings. They can be any string, but the dot notation works only with names that look like valid binding names—starting with a letter or underscore, and containing only letters, numbers, and underscores. If you want to access a property named _2_ or _John Doe_, you must use square brackets: `value[2]` or `value["John Doe"]`. +Yani eğer ilgilendiğiniz özelliğin adının _color_ olduğunu biliyorsanız, `value.color` yazarsınır. Eğer `i` adlı bağlantının sahip olduğunu değerin adını taşıyan özelliği çıkarmak istiyorsanız, `value[i]` yazarsınız. Özellik adları dizelerdir. Herhangi bir dize olabilirler, ancak nokta notasyonu yalnızca geçerli bağlantı adları gibi görünen adlarla çalışır. Dolayısıyla _2_ veya _John Doe_ adında bir özelliğe erişmek istiyorsanız, köşeli parantezleri kullanmanız gerekir: `value[2]` veya `value["John Doe"]`. -The elements in an ((array)) are stored as the array's properties, using numbers as property names. Because you can't use the dot notation with numbers and usually want to use a binding that holds the index anyway, you have to use the bracket notation to get at them. +Bir ((dizideki)) öğeler, dizi özelliklerinin bir parçasıdır ve sayıları özellik adları olarak kullanarak saklanır. Sayılarla nokta notasyonunu kullanamazsınız ve genellikle zaten index değerini tutan bir bağlantı kullanmak istersiniz, bu nedenle onlara erişmek için köşeli parantez notasyonunu kullanmanız gerekir. {{index ["length property", "for array"], [array, "length of"]}} -Just like strings, arrays have a `length` property that tells us how many elements the array has. +Dizilerin, dizelerin de sahip olduğu gibi kaç öğe olduğunu söyleyen bir `length` özelliği vardır. {{id methods}} -## Methods +## Metodlar {{index [function, "as property"], method, string}} -Both string and array values contain, in addition to the `length` property, a number of properties that hold function values. +Dizelerin ve dizilerin `length` özelliği ötesinde fonksiyon değerleri tutan bir dizi özelliklere de sahiptirler. ``` let doh = "Doh"; @@ -123,17 +123,17 @@ console.log(doh.toUpperCase()); {{index "case conversion", "toUpperCase method", "toLowerCase method"}} -Every string has a `toUpperCase` property. When called, it will return a copy of the string in which all letters have been converted to uppercase. There is also `toLowerCase`, going the other way. +Her dizenin bir `toUpperCase` özelliği vardır. Çağrıldığında, tüm harflerin büyük harfe dönüştürüldüğü bir dize kopyası döndürür. Ayrıca, tersi olan `toLowerCase` özelliği de vardır. {{index "this binding"}} -Interestingly, even though the call to `toUpperCase` does not pass any arguments, the function somehow has access to the string `"Doh"`, the value whose property we called. You'll find out how this works in [Chapter ?](object#obj_methods). +İlginç bir şekilde, `toUpperCase` özelliğine yapılan çağrıya herhangi bir argüman vermediğimiz halde fonksiyonunu çağırdığımız `"Doh"` dize değerine erişebilmektedir. Bunun nasıl çalıştığı, [Bölüm ?](object#obj_methods)'da açıklanmıştır. -Properties that contain functions are generally called _methods_ of the value they belong to, as in "`toUpperCase` is a method of a string". +Fonksiyonları içeren özellikler genellikle ait oldukları değerin _metodları_ olarak adlandırılır, örneğin `toUpperCase` bir dize değerinin yöntemidir. {{id array_methods}} -This example demonstrates two methods you can use to manipulate arrays: +Bu örnek dizileri manipüle etmek için kullanabileceğiniz iki metodu göstermektedir: ``` let sequence = [1, 2, 3]; @@ -149,21 +149,21 @@ console.log(sequence); {{index collection, array, "push method", "pop method"}} -The `push` method adds values to the end of an array. The `pop` method does the opposite, removing the last value in the array and returning it. +`push` metodu dizinin sonuna değerler eklerken `pop` metoduysa tam tersi yapar, yani sonundan bir değer çıkarıp bunu değer olarak döndürür. {{index ["data structure", stack]}} -These somewhat silly names are the traditional terms for operations on a _((stack))_. A stack, in programming, is a data structure that allows you to push values into it and pop them out again in the opposite order so that the thing that was added last is removed first. Stacks are common in programming—you might remember the function ((call stack)) from [the previous chapter](functions#stack), which is an instance of the same idea. +Bu biraz komik isimler, bir ((yığın)) üzerinde yapılan işlemler için geleneksel terimlerdir. Bir yığın, programlamada, değerleri yığına iterken ve sonra onları ters sırayla geri çekerken, en son eklenen şeyin ilk önce çıkarılmasına izin veren bir veri yapısıdır. Bunlar programlamada yaygındır—[önceki bölümden](functions#stack) hatırlayabileceğiniz gibi, buna bir örnek olan ((çağrı yığını))nı ele almıştık. -## Objects +## Objeler {{index journal, "weresquirrel example", array, record}} -Back to the weresquirrel. A set of daily log entries can be represented as an array, but the entries do not consist of just a number or a string—each entry needs to store a list of activities and a Boolean value that indicates whether Jacques turned into a squirrel or not. Ideally, we would like to group these together into a single value and then put those grouped values into an array of log entries. +Sincap hikayesine geri dönelim. Günlük yaşanan olayların bir küme olarak temsil edilmesi için dizi veri yapısı kullanılabilir. Ancak, girişler sadece bir sayı veya dize değildir—her girişin bir dizi etkinliği depolaması ve Jacques'nın bir sincapa dönüşüp dönüşmediğini gösteren bir Boolean değerini barındırması gerekir. İdeal olarak, bunları tek bir değere gruplamak ve sonra bu gruplanmış değerleri bir diziye teker teker koymaktır. {{index [syntax, object], [property, definition], [braces, object], "{} (object)"}} -Values of the type _((object))_ are arbitrary collections of properties. One way to create an object is by using braces as an expression: +_((Obje))_ türündeki değerler, farklı özelliklerden koleksiyonlarıdır. Nesne oluşturmanın bir yolu, süslü parantezler ifadesini kullanmaktır. ``` let day1 = { @@ -181,7 +181,7 @@ console.log(day1.wolf); {{index [quoting, "of object properties"], "colon character"}} -Inside the braces, you write a list of properties separated by commas. Each property has a name followed by a colon and a value. When an object is written over multiple lines, indenting it as shown in this example helps with readability. Properties whose names aren't valid binding names or valid numbers must be quoted: +Parantezlerin içinde, virgüllerle ayrılmış bir özellik listesi bulunur. Her özelliğin bir adı ve ardından iki nokta üst üste ve bir değeri vardır. Bir obje yazıldığında, örnekte olduğu gibi girintili yapmak, okunabilirlik konusunda yardımcı olur. Adları geçerli bağlantı adı olmayan veya geçerli olmayan bir sayı olan özellikler tırnak içine alınmalıdır. ``` let descriptions = { @@ -192,23 +192,23 @@ let descriptions = { {{index [braces, object]}} -This means that braces have _two_ meanings in JavaScript. At the start of a ((statement)), they begin a ((block)) of statements. In any other position, they describe an object. Fortunately, it is rarely useful to start a statement with an object in braces, so the ambiguity between these two is not much of a problem. The one case where this does come up is when you want to return an object from a short-hand arrow function—you can't write `n => {prop: n}`, since the braces will be interpreted as a function body. Instead, you have to put a set of parentheses around the object to make it clear that it is an expression. +Bu, parantezlerin JavaScript'te _iki_ anlama geldiği anlamına gelir. Bir ((beyan))ın başında olduklarında, bir beyanlar ((bloğunu)) başlatırlar. Herhangi bir başka konumda, bir nesnenin oluşturulmasını sağlarlar. Neyse ki, bir beyanı süslü parantezle başlatmak pek nadiren kullanışlıdır, bu yüzden bu ikisi arasındaki belirsizlik pek bir problem değildir. Bu iki durumun çakıştığı tek durum, bir kısayol ok fonksiyonundan değer olarak bir nesne döndürmek istediğinizde ortaya çıkar—`n => {prop: n}` yazamazsınız çünkü süslü parantezler fonksiyon gövdesi olarak yorumlanacaktır, obje olduğunu belirtmek için nesnenin etrafına bir parantez kümesi koymak zorundasınız. {{index undefined}} -Reading a property that doesn't exist will give you the value `undefined`. +Mevcut olmayan bir özelliği okumak size `undefined` değerini verecektir. {{index [property, assignment], mutability, "= operator"}} -It is possible to assign a value to a property expression with the `=` operator. This will replace the property's value if it already existed or create a new property on the object if it didn't. +Bir özellik ifadesine bir değer atamak mümkündür. Bu, özellik zaten varsa değerini değiştirir, eğer yoksa da verilend değeri barındıran yeni bir özellik oluşturur. {{index "tentacle (analogy)", [property, "model of"], [binding, "model of"]}} -To briefly return to our tentacle model of ((binding))s—property bindings are similar. They _grasp_ values, but other bindings and properties might be holding onto those same values. You can think of objects as octopuses with any number of tentacles, each of which has a name written on it. +Kısaca ((bağlantı))larımızın ahtapot dokungaç modeline geri dönersek—özellik bağlantılarının da onlara benzer olduğunu görürüz. Değerleri kavrarlar ve kavradıkları değerler diğer bağlantı ve özellikler tarafından da sahip olunabilirdir. Nesneleri herhangi bir sayıda üzerine isimler dövmelenmiş dokungaçları olan bir ahtapot olarak düşünebilirsiniz. {{index "delete operator", [property, deletion]}} -The `delete` operator cuts off a tentacle from such an octopus. It is a unary operator that, when applied to an object property, will remove the named property from the object. This is not a common thing to do, but it is possible. +`delete` operatörü, böyle bir ahtapotun dokungaçlarından birini keser. Bu tekil bir operatördür ve herhangi bir nesne özelliğine uygulandığında, adı verilen özelliği nesneden kaldırır. Bu yaygın bir şey değildir, ancak mümkündür. ``` let anObject = {left: 1, right: 2}; @@ -225,18 +225,18 @@ console.log("right" in anObject); {{index "in operator", [property, "testing for"], object}} -The binary `in` operator, when applied to a string and an object, tells you whether that object has a property with that name. The difference between setting a property to `undefined` and actually deleting it is that in the first case, the object still _has_ the property (it just doesn't have a very interesting value), whereas in the second case the property is no longer present and `in` will return `false`. +İkili `in` operatörü, bir dizeye veya bir nesneye uygulandığında, bu nesnenin o ada sahip bir özelliği olup olmadığını size söyler. Bir özelliği `undefined` değerini vermek ve gerçekten silmek arasındaki fark, ilk durumda nesnenin _hala özelliğe sahip olmasıdır_ (sadece çok ilginç bir değere sahip değil), ikinci durumda ise özelliğin artık mevcut olmaması ve `in` ikili operatörünün `false` değerini döndürmesidir. {{index "Object.keys function"}} -To find out what properties an object has, you can use the `Object.keys` function. Give the function an object and it will return an array of strings—the object's property names: +Bir nesnenin hangi özelliklere sahip olduğunu öğrenmek için `Object.keys` fonksiyonunu kullanabilirsiniz. Bu fonksiyona argüman olarak nesne verirsiniz ve size nesnenin özellik adlarını içnide barındıran bir dizi döndürür. ``` console.log(Object.keys({x: 0, y: 0, z: 2})); // → ["x", "y", "z"] ``` -There's an `Object.assign` function that copies all properties from one object into another: +Bir nesneden başka bir nesneye tüm özellikleri kopyalayan bir `Object.assign` fonksiyonu vardır. ``` let objectA = {a: 1, b: 2}; @@ -247,11 +247,11 @@ console.log(objectA); {{index array, collection}} -Arrays, then, are just a kind of object specialized for storing sequences of things. If you evaluate `typeof []`, it produces `"object"`. You can visualize arrays as long, flat octopuses with all their tentacles in a neat row, labeled with numbers. +Öyleyse dizileri belirli bir sırada olan şeylerin dizilerini depolamak için özelleştirilmiş bir nesne türü olarak düşünebiliriz. `typeof []` ifadesini değerlendirirseniz, `"object"` değerini ürettiğini gözlemlersiniz. Onları, uzun, tüm tentakülleri düzenli bir sırayla ve sayılarla dövmelenmiş düz ahtapotlar olarak da düşünebilirsiniz. {{index journal, "weresquirrel example"}} -Jacques will represent the journal that Jacques keeps as an array of objects: +Jacques'ın tuttuğu günlüğü, nesnelerden oluşan bir dizi olarak temsil edeceğiz. ```{test: wrap} let journal = [ @@ -264,23 +264,23 @@ let journal = [ {events: ["weekend", "cycling", "break", "peanuts", "beer"], squirrel: true}, - /* and so on... */ + /* And so on... */ ]; ``` -## Mutability +## Değiştirilebilirlik -We will get to actual programming soon, but first, there's one more piece of theory to understand. +Çok yakında _gerçek_ programlamaya geçeceğiz. İlk olarak, anlaşılması gereken biraz daha teori var. {{index mutability, "side effect", number, string, Boolean, [object, mutability]}} -We saw that object values can be modified. The types of values discussed in earlier chapters, such as numbers, strings, and Booleans, are all _((immutable))_—it is impossible to change values of those types. You can combine them and derive new values from them, but when you take a specific string value, that value will always remain the same. The text inside it cannot be changed. If you have a string that contains `"cat"`, it is not possible for other code to change a character in your string to make it spell `"rat"`. +Önceki bölümlerde tartışılan değer sayılar, dizeler ve Booleans gibi türlerinin tümü ((_değiştirilemezdir_)). Onları birleştirebilir ve onlardan yeni değerler türetebilirsiniz, ancak belirli bir dize değeri aldığınızda, o değer her zaman aynı kalacaktır. İçindeki metin değiştirilemez. İçinde `"cat"` yazan bir dizeniz olduğunda, başka bir kodun dizenizdeki bir karakteri değiştirerek `"rat"` şeklinde yazmasına izin verilmez. -Objects work differently. You _can_ change their properties, causing a single object value to have different content at different times. +Nesneler farklı çalışır. Özelliklerini _değiştirebilirsiniz_, böylece tek bir nesne değeri farklı zamanlarda farklı içeriğe sahip olabilir. {{index [object, identity], identity, [memory, organization], mutability}} -When we have two numbers, 120 and 120, we can consider them precisely the same number, whether or not they refer to the same physical bits. With objects, there is a difference between having two references to the same object and having two different objects that contain the same properties. Consider the following code: +120 ve 120 gibi iki sayımız olduğunda, onları depolandıkları fiziksel bitlerin yerlerinin aynı olup olmadığına bakmaksızın tam olarak aynı sayı olarak düşünebiliriz. Objelerde, aynı nesnenin depolandığı alana olan iki referansa sahip olmanın ve aynı özelliklere sahip iki farklı nesnenin bir farkı vardır. Aşağıdaki kodu düşünün: ``` let object1 = {value: 10}; @@ -301,11 +301,11 @@ console.log(object3.value); {{index "tentacle (analogy)", [binding, "model of"]}} -The `object1` and `object2` bindings grasp the _same_ object, which is why changing `object1` also changes the value of `object2`. They are said to have the same _identity_. The binding `object3` points to a different object, which initially contains the same properties as `object1` but lives a separate life. +`object1` ve `object2` bağlantıları aynı nesneyi tutar, bu yüzden `object1i` değiştirmek `object2` bağlantısının değerini değiştirir. Bunların aynı _kimliğe_ sahip oldukları söylenir. `object3` bağlantısı, başlangıçta `object1` ile aynı özellik ve değerlere sahip ancak ayrı bir yaşama sahip farklı bir objeye işaret eder. {{index "const keyword", "let keyword", [binding, "as state"]}} -Bindings can also be changeable or constant, but this is separate from the way their values behave. Even though number values don't change, you can use a `let` binding to keep track of a changing number by changing the value at which the binding points. Similarly, though a `const` binding to an object can itself not be changed and will continue to point at the same object, the _contents_ of that object might change. +Bağlantılar ayrıca değiştirilebilir veya sabit olabilir, ancak bu, değerlerinin nasıl davrandığından ayrıdır. Sayı değerleri değişmese de, bir `let` bağlantısını, bağlantının işaret ettiği değeri değiştirerek değişen bir sayıyı takip etmek için kullanabilirsiniz. Benzer şekilde, bir nesneye yapılan bir `const` bağlantısı kendisi değiştirilemeyip sadece aynı nesneye işaret etmeye devam etse de, o nesnenin içerisindeki özellikler değişebilir, bu durumda nesne aynı nesnedir ve kimliği değişmemiştir ancak aynı kimliğe sahip bu nesnenin içerisindeki özellikler değişmiştir gibi düşünebilirsiniz. ```{test: no} const score = {visitors: 0, home: 0}; @@ -317,13 +317,13 @@ score = {visitors: 1, home: 1}; {{index "== operator", [comparison, "of objects"], "deep comparison"}} -When you compare objects with JavaScript's `==` operator, it compares by identity: it will produce `true` only if both objects are precisely the same value. Comparing different objects will return `false`, even if they have identical properties. There is no "deep" comparison operation built into JavaScript that compares objects by contents, but it is possible to write it yourself (which is one of the [exercises](data#exercise_deep_compare) at the end of this chapter). +JavaScript'in `==` operatörüyle nesneleri karşılaştırdığınızda, kimliğe göre karşılaştırır: Yalnızca her iki nesne de tam olarak aynı değerse `true` değerini üretecektir. Farklı nesneleri karşılaştırmak içeriklerinin tamamen aynı özellik ve değerlerden oluşsa dahil `false` değerinin döndürülmesine sebep olur. JavaScript'e objeleri o objelerin içeriklerine göre karşılaştıran yerleşik "derin" bir karşılaştırma işlemi bulunmamaktadır, ancak içeriklerine göre nesneleri karşılaştıracak bir fonksiyonu kenidiniz yazmanız mümlündür(bu, bu bölümün sonundaki [alıştırmalardan](data#exercise_deep_compare) biridir). -## The lycanthrope's log +## Sincap kurtadamının günlüğü {{index "weresquirrel example", lycanthropy, "addEntry function"}} -Jacques starts up his JavaScript interpreter and sets up the environment he needs to keep his ((journal)): +Bu arada, Jacques JavaScript yorumlayıcısını başlatır ve ((günlüğünü)) tutması için gereken ortamı kurar. ```{includeCode: true} let journal = []; @@ -335,9 +335,9 @@ function addEntry(events, squirrel) { {{index [braces, object], "{} (object)", [property, definition]}} -Note that the object added to the journal looks a little odd. Instead of declaring properties like `events: events`, it just gives a property name: `events`. This is shorthand that means the same thing—if a property name in brace notation isn't followed by a value, its value is taken from the binding with the same name. +Günlüğe eklenen nesne biraz garip görünüyor. Özelliklerin `events: events` gibi bildirilmesi yerine, sadece bir özellik adı verilmiştir. Bu, aynı anlama gelir- eğer parantez notasyonundaki bir özellik adı bir değerle takip edilmiyorsa, değeri o özellik adıyla aynı adda olan bir bağlantının değerinden alınır. -Every evening at 10 p.m.—or sometimes the next morning, after climbing down from the top shelf of his bookcase—Jacques records the day: +Böylelikle, her akşam saat 10.00'da—veya bazen ertesi sabah, kitaplığının en üst rafından indikten sonra—Jacques günü kaydeder. ``` addEntry(["work", "touched tree", "pizza", "running", @@ -348,21 +348,21 @@ addEntry(["weekend", "cycling", "break", "peanuts", "beer"], true); ``` -Once he has enough data points, he intends to use statistics to find out which of these events may be related to the squirrelifications. +Yeterince veri noktasına sahip olduktan sonra, bu olaylardan hangilerinin sincaplaşmayla ilişkili olabileceğini bulmak için istatistikleri kullanmayı amaçlıyor. {{index correlation}} -_Correlation_ is a measure of ((dependence)) between statistical variables. A statistical variable is not quite the same as a programming variable. In statistics you typically have a set of _measurements_, and each variable is measured for every measurement. Correlation between variables is usually expressed as a value that ranges from -1 to 1. Zero correlation means the variables are not related. A correlation of 1 indicates that the two are perfectly related—if you know one, you also know the other. Negative 1 also means that the variables are perfectly related but are opposites—when one is true, the other is false. +_Korelasyon_, istatistiksel değişkenler arasındaki ((bağımlılık)) ölçüsüdür ve istatistiksel değişken programlamadaki değişkenle tam olarak aynı değildir. İstatistikte genelde belirli ölçümler vardır ve her değişken bu ölçümlerle ölçülmektedir. Değişkenler arasındaki korelasyon genellikle -1 ile 1 arasında değişen bir değer olarak ifade edilir. Sıfır korelasyon, değişkenlerin ilişkili olmadığı anlamına gelir. Değeri bir olan bir korelasyon, iki değişkenin mükemmel bir şekilde ilişkili olduğunu gösterir - birini bildiğinizde, diğerini de bilmenizi sağlar. Değeri eksi bir olan bir korelasyon, değişkenlerin mükemmel bir şekilde ilişkili olduğunu ancak bunların zıt olduğunu gösterir - biri doğru olduğunda, diğerinin olmadığını bilmenizi sağlar. {{index "phi coefficient"}} -To compute the measure of correlation between two Boolean variables, we can use the _phi coefficient_ (_ϕ_). This is a formula whose input is a ((frequency table)) containing the number of times the different combinations of the variables were observed. The output of the formula is a number between -1 and 1 that describes the correlation. +İki Boolean değişken arasındaki korelasyon ölçümünü hesaplamak için _fi katsayısını_ (_ϕ_) kullanabiliriz. Bu, girdisi değişkenlerin kaç kere gözlemlendiğini içinde barındıran bir ((frekans tablosu)) olan bir formüldür. Formülün çıktısı, korelasyonu açıklayan -1 ile 1 arasında bir sayıdır. -We could take the event of eating ((pizza)) and put that in a frequency table like this, where each number indicates the number of times that combination occurred in our measurements. +Yeme olayını içindeki her sayı ölçülerimizde o kombinasyonun kaç kez meydana geldiğini gösteren bir pizza frekans tablosuna yerleştirebiliriz: {{figure {url: "img/pizza-squirrel.svg", alt: "A two-by-two table showing the pizza variable on the horizontal, and the squirrel variable on the vertical axis. Each cell show how many time that combination occurred. In 76 cases, neither happened. In 9 cases, only pizza was true. In 4 cases only squirrel was true. And in one case both occurred.", width: "7cm"}}} -If we call that table _n_, we can compute _ϕ_ using the following formula: +Eğer o tabloya _n_ dersek, _ϕ_ değerini aşağıdaki formülle hesaplayabiliriz: {{if html @@ -376,27 +376,27 @@ if}} if}} -(If at this point you're putting the book down to focus on a terrible flashback to 10th grade math class—hold on! I do not intend to torture you with endless pages of cryptic notation—it's just this one formula for now. And even with this one, all we do is turn it into JavaScript.) +(Eğer bu noktada kitabı bırakıp 10. sınıf matematik dersine yoğunlaşmaya başladıysanız—bekleyin! Sizi anlaşılmaz işaretlerle dolu sonsuz sayfalık bir işkenceye tabi tutmak niyetinde değilim—şimdilik sadece bu formül. Ve bu formülle yapacağımız tek şey onu sadece JavaScript'e dönüştürmek.) -The notation [_n_~01~]{if html}[[$n_{01}$]{latex}]{if tex} indicates the number of measurements where the first variable (squirrelness) is false (0) and the second variable (pizza) is true (1). In the pizza table, [_n_~01~]{if html}[[$n_{01}$]{latex}]{if tex} is 9. +Notasyon [_n_~01~]{if html}[[$n_{01}$]{latex}]{if tex}, ilk değişkenin (sincaplık) yanlış (0) ve ikinci değişkenin (pizza) doğru (1) olduğu ölçümlerin sayısını gösterir. Pizza tablosunda, [_n_~01~]{if html}[[$n_{01}$]{latex}]{if tex} 9'dur. -The value [_n_~1•~]{if html}[[$n_{1\bullet}$]{latex}]{if tex} refers to the sum of all measurements where the first variable is true, which is 5 in the example table. Likewise, [_n_~•0~]{if html}[[$n_{\bullet0}$]{latex}]{if tex} refers to the sum of the measurements where the second variable is false. +Değer [_n_~1•~]{if html}[[$n_{1\bullet}$]{latex}]{if tex}, ilk değişkenin doğru olduğu tüm ölçümlerin toplamını ifade eder, örneğin tabloda 5'tir. Benzer şekilde, [_n_~•0~]{if html}[[$n_{\bullet0}$]{latex}]{if tex} değeri, ikinci değişkenin yanlış olduğu ölçümlerin toplamını ifade eder. {{index correlation, "phi coefficient"}} -So for the pizza table, the part above the division line (the dividend) would be 1×76−4×9 = 40, and the part below it (the divisor) would be the square root of 5×85×10×80, or [√340,000]{if html}[[$\sqrt{340,000}$]{latex}]{if tex}. This comes out to _ϕ_ ≈ 0.069, which is tiny. Eating ((pizza)) does not appear to have influence on the transformations. +Dolayısıyla pizza tablosu için, bölümün üst kısmı (pay) 1×76−4×9 = 40 olur ve alt kısmı (payda) 5×85×10×80'ın karekökü, veya [√340000]{if html}[[$\sqrt{340000}$]{latex}]{if tex}. Bu, ϕ ≈ 0.069 olur, yani çok küçüktür. Pizza yemenin dönüşümler üzerinde bir etkisi olmadığı görünmektedir. -## Computing correlation +## Korelasyonu hesaplama {{index [array, "as table"], [nesting, "of arrays"]}} -We can represent a two-by-two ((table)) in JavaScript with a four-element array (`[76, 9, 4, 1]`). We could also use other representations, such as an array containing two two-element arrays (`[[76, 9], [4, 1]]`) or an object with property names like `"11"` and `"01"`, but the flat array is simple and makes the expressions that access the table pleasantly short. We'll interpret the indices to the array as two-((bit)) ((binary number))s, where the leftmost (most significant) digit refers to the squirrel variable and the rightmost (least significant) digit refers to the event variable. For example, the binary number `10` refers to the case where Jacques did turn into a squirrel, but the event (say, "pizza") didn't occur. This happened four times. And since binary `10` is 2 in decimal notation, we will store this number at index 2 of the array. +JavaScript'te iki satır iki sütun ((tablo))'yu dört elemanlı bir dizi ile temsil edebiliriz (`[76, 9, 4, 1]`). Ayrıca, diğer temsilleri kullanabiliriz, örneğin, iki iki elemanlı dizi içeren bir dizi (`[[76, 9], [4, 1]]`) veya `"11"` ve `"01"` gibi özellik adlarına sahip bir nesne, ancak düz dizi basittir ve tabloya erişimi kolaylaştırır. Dizinin index değerlerini iki bitlik ((ikili sayı))lar olarak yorumlayacak, soldaki (en önemli) basamak sincap değişkenine ve sağdaki (en önemsiz) basamak olay değişkenine atıfta bulunmasını sağlayacağız. Örneğin, ikili sayı `10`, Jacques'nin bir sincap haline geldiği ancak olayın (örneğin, "pizza") gerçekleşmediği durumu ifade eder. Bu dört kez oldu. Ve iki gösterimdeki `10` sayısı ondalık gösterimde 2 olduğundan ötürü bu sayıyı dizinin 2. index değer pozisyonuna kaydedeceğiz. {{index "phi coefficient", "phi function"}} {{id phi_function}} -This is the function that computes the _ϕ_ coefficient from such an array: +Böyle bir diziyle ϕ katsayısını hesaplayan fonksiyon budur: ```{includeCode: strip_log, test: clip} function phi(table) { @@ -413,15 +413,15 @@ console.log(phi([76, 9, 4, 1])); {{index "square root", "Math.sqrt function"}} -This is a direct translation of the _ϕ_ formula into JavaScript. `Math.sqrt` is the square root function, as provided by the `Math` object in a standard JavaScript environment. We have to add two fields from the table to get fields like [n~1•~]{if html}[[$n_{1\bullet}$]{latex}]{if tex} because the sums of rows or columns are not stored directly in our data structure. +Bu, _ϕ_ formülünün JavaScript'e doğrudan çevirisidir. `Math.sqrt`, standart bir JavaScript ortamında `Math` nesnesi tarafından sağlanan karekök işlemidir. [n~1•~]{if html}[[$n_{1\bullet}$]{latex}]{if tex} gibi alanları elde etmek için tablodan iki alan eklememiz gerekmektedir çünkü satır veya sütunların toplamları doğrudan veri yapımızda saklanmamaktadır. -{{index "JOURNAL data set"}} +{{index "JOURNAL dataset"}} -Jacques keeps his journal for three months. The resulting ((data set)) is available in the [coding sandbox](https://eloquentjavascript.net/code#4) for this chapter[ ([_https://eloquentjavascript.net/code#4_](https://eloquentjavascript.net/code#4))]{if book}, where it is stored in the `JOURNAL` binding, and in a downloadable [file](https://eloquentjavascript.net/code/journal.js). +Jacques günlüğünü üç ay boyunca tuttu. Ortaya çıkan ((veri seti)), bu bölüm için[ ([_https://eloquentjavascript.net/code#4_](https://eloquentjavascript.net/code#4))]{if book} kod [kum havuzunda](https://eloquentjavascript.net/code#4) mevcuttur, burada `JOURNAL` bağlantısında saklanır ve bir [dosya](https://eloquentjavascript.net/code/journal.js) halinde indirilebilir. {{index "tableFor function"}} -To extract a two-by-two ((table)) for a specific event from the journal, we must loop over all the entries and tally how many times the event occurs in relation to squirrel transformations: +Günlükten belirli bir olay için iki satır iki sütun bir ((tablo)) çıkarmak adına tüm girişler üzerinde döngü yapıp olayın sincap dönüşümlerine göre kaç kere yaşandığını saymalıyız. ```{includeCode: strip_log} function tableFor(event, journal) { @@ -441,21 +441,21 @@ console.log(tableFor("pizza", JOURNAL)); {{index [array, searching], "includes method"}} -Arrays have an `includes` method that checks whether a given value exists in the array. The function uses that to determine whether the event name it is interested in is part of the event list for a given day. +Dizilerin `includes` metodu, verilen bir değerin dizide var olup olmadığını kontrol eder. Fonksiyon, bunu kullanır ilgilendiği olayın o günkü olay listesinin bir parçası olup olmadığını belirlemek için kullanır. {{index [array, indexing]}} -The body of the loop in `tableFor` figures out which box in the table each journal entry falls into by checking whether the entry contains the specific event it's interested in and whether the event happens alongside a squirrel incident. The loop then adds one to the correct box in the table. +`tableFor` içindeki döngünün gövdesi, her günlük girişinin özel olarak ilgilenilen olayı içerip içermediğini ve olayın bir sincap olayıyla aynı anda gerçekleşip gerçekleşmediğini kontrol ederek tablodaki hangi kutuya düştüğünü belirler. Döngü daha sonra tablodaki doğru kutuya bir ekler. -We now have the tools we need to compute individual ((correlation))s. The only step remaining is to find a correlation for every type of event that was recorded and see whether anything stands out. +Şimdi, bireysel ((korelasyon))ları hesaplamak için ihtiyacımız olan araçlara sahibiz. Kalan tek adım, kaydedilen her tür olay için bir korelasyon bulmak ve herhangi bir şeyin dikkat çekip çekmediğini görmektir. {{id for_of_loop}} -## Array loops +## Dizi döngüleri {{index "for loop", loop, [array, iteration]}} -In the `tableFor` function, there's a loop like this: +`tableFor` fonksiyonunda şöyle bir döngü var: ``` for (let i = 0; i < JOURNAL.length; i++) { @@ -464,9 +464,9 @@ for (let i = 0; i < JOURNAL.length; i++) { } ``` -This kind of loop is common in classical JavaScript—going over arrays one element at a time is something that comes up a lot, and to do that you'd run a counter over the length of the array and pick out each element in turn. +Bu tür bir döngü, klasik JavaScript'te yaygındır—dizilerin her bir elemanını tek tek geçmek sık sık karşılaşılan bir durumdur ve bunu yapmak için dizinin uzunluğu üzerinde bir sayaç çalıştırarak sırayla her elemanı seçersiniz. -There is a simpler way to write such loops in modern JavaScript: +Modern JavaScript'te böyle döngüleri daha basit bir şekilde yazmanın bir yolu var. ``` for (let entry of JOURNAL) { @@ -476,15 +476,15 @@ for (let entry of JOURNAL) { {{index "for/of loop"}} -When a `for` loop uses the word `of` after its variable definition, it will loop over the elements of the value given after `of`. This works not only for arrays but also for strings and some other data structures. We'll discuss _how_ it works in [Chapter ?](object). +Bir `for` döngüsü şu şekilde görünüyorsa, bir değişken tanımından sonra `of` kelimesi varsa, `of` kelimesinden sonra verilen değerin öğeleri üzerinde döngüyü başlatır. Bu yalnızca diziler için değil dizeler ve bazı diğer veri yapıları için de çalışır. Nasıl çalıştığını [Bölüm ?](object)’de tartışacağız. {{id analysis}} -## The final analysis +## Son analiz {{index journal, "weresquirrel example", "journalEvents function"}} -We need to compute a correlation for every type of event that occurs in the data set. To do that, we first need to _find_ every type of event. +Veri setinde bulunan her tür olay için bir korelasyon hesaplamamız gerekiyor. Bunun için önce her tür olayı _bulmalıyız_. {{index "includes method", "push method"}} @@ -505,9 +505,9 @@ console.log(journalEvents(JOURNAL)); // → ["carrot", "exercise", "weekend", "bread", …] ``` -By adding any event names that aren't already in it to the `events` array, the function collects every type of event. +Tüm olayların üzerinden geçerek, içinde var olmayanları olayları `events` dizisine ekleyerek, fonksiyon her tür olayı toplar. -Using that function, we can see all the ((correlation))s: +Bunu kullanarak, tüm ((korelasyon))ları görebiliriz. ```{test: no} for (let event of journalEvents(JOURNAL)) { @@ -518,10 +518,10 @@ for (let event of journalEvents(JOURNAL)) { // → weekend: 0.1371988681 // → bread: -0.0757554019 // → pudding: -0.0648203724 -// and so on... +// And so on... ``` -Most correlations seem to lie close to zero. Eating carrots, bread, or pudding apparently does not trigger squirrel-lycanthropy. The transformations _do_ seem to occur somewhat more often on weekends. Let's filter the results to show only correlations greater than 0.1 or less than -0.1: +Çoğu korelasyonun sıfıra yakın olduğu görünüyor. Havuç, ekmek veya puding yemek açıkça sincapa dönüşmeyi tetiklemiyor gibi görünüyor. Bununla birlikte, hafta sonlarında biraz daha sık meydana gelme eğiliminde olduğunu fark ediyoruz. Sonuçları, 0,1'den büyük veya -0,1'den küçük olan korelasyonları göstermek için filtreleyelim. ```{test: no, startCode: true} for (let event of journalEvents(JOURNAL)) { @@ -539,9 +539,9 @@ for (let event of journalEvents(JOURNAL)) { // → peanuts: 0.5902679812 ``` -Aha! There are two factors with a ((correlation)) clearly stronger than the others. Eating ((peanuts)) has a strong positive effect on the chance of turning into a squirrel, whereas brushing teeth has a significant negative effect. +Aha! Diğerlerinden açıkça daha güçlü bir ((korelasyon))a sahip olan iki faktör var. Fıstık yemek, bir sincap haline dönüşme şansı üzerinde güçlü bir pozitif etkiye sahipken, dişlerini fırçalamak ise önemli bir negatif etkiye sahiptir. -Interesting. Let's try something: +İlginç. Bir şey deneyelim. ``` for (let entry of JOURNAL) { @@ -554,23 +554,23 @@ console.log(phi(tableFor("peanut teeth", JOURNAL))); // → 1 ``` -That's a strong result. The phenomenon occurs precisely when Jacques eats ((peanuts)) and fails to brush his teeth. If only he weren't such a slob about dental hygiene, he'd never even have noticed his affliction. +Bu güçlü bir sonuç. Olay, Jacques fıstık yediği ve dişlerini fırçalamadığı zaman meydana geliyor. Keşke dental hijyen konusunda böylesine dikkatsiz olmasaydı, belki de bu hastalığını hiç fark etmeyecekti. -Knowing this, Jacques stops eating peanuts altogether and finds that his transformations stop. +Bunu öğrendikten sonra, Jacques fıstık yemeyi tamamen bırakır ve dönüşümlerinin durduğunu fark eder. {{index "weresquirrel example"}} -But it only takes a few months for him to notice that something is missing from this entirely human way of living. Without his feral adventures, Jacques hardly feels alive at all. He decides he'd rather be a full-time wild animal. After building a beautiful little tree house in the forest and equipping it with a peanut butter dispenser and a ten-year supply of peanut butter, he changes form one last time, and lives the short and energetic life of a squirrel. +Ancak, tamamen insanca yaşama şeklinde eksik bir şey olduğunu fark etmesi birkaç ayını alır. Vahşi maceraları olmadan Jacques kendini neredeyse hiç yaşamıyor gibi hisseder. Tam zamanlı bir vahşi hayvan olmayı tercih eder. Ormanda güzel bir ağaç ev inşa eder ve kurduğu bir fıstık ezmesi dağıtıcısına on yıllık fıstık ezmesi stoku sağladıktan sonra, son bir kez daha değişir ve bir sincap olarak kısa ve enerjik bir yaşam sürer. -## Further arrayology +## Diziler hakkında daha fazla bilgi {{index [array, methods], [method, array]}} -Before finishing the chapter, I want to introduce you to a few more object-related concepts. I'll start by introducing some generally useful array methods. +Bu bölümü bitirmeden önce, size birkaç daha objelerle ilgili kavramı tanıtmak istiyorum. Genel olarak kullanışlı birkaç dizi metodu tanıtarak başlayacağım. {{index "push method", "pop method", "shift method", "unshift method"}} -We saw `push` and `pop`, which add and remove elements at the end of an array, [earlier](data#array_methods) in this chapter. The corresponding methods for adding and removing things at the start of an array are called `unshift` and `shift`. +Bu bölümde [daha önce](data#array_methods) gördüğümüz `push` ve `pop` yöntemleri, bir dizinin sonuna eleman ekler ve kaldırır. Bir dizinin başına şeyler eklemek ve kaldırmak için karşılık gelen yöntemler `unshift` ve `shift` olarak adlandırılır. ``` let todoList = []; @@ -587,11 +587,11 @@ function rememberUrgently(task) { {{index "task management example"}} -This program manages a queue of tasks. You add tasks to the end of the queue by calling `remember("groceries")`, and when you're ready to do something, you call `getTask()` to get (and remove) the front item from the queue. The `rememberUrgently` function also adds a task but adds it to the front instead of the back of the queue. +Bu program, görevlerden oluşan bir kuyruğu yönetir. `remember("groceries")` çağrısıyla görevleri kuyruğun sonuna eklersiniz ve bir şey yapmaya hazır olduğunuzda, `getTask()` çağrısıyla kuyruğun önündeki öğeyi alırsınız (ve kaldırırsınız). `rememberUrgently` fonksiyonu da bir görev ekler ancak bunu kuyruğun sonuna değil önüne ekler. {{index [array, searching], "indexOf method", "lastIndexOf method"}} -To search for a specific value, arrays provide an `indexOf` method. The method searches through the array from the start to the end and returns the index at which the requested value was found—or -1 if it wasn't found. To search from the end instead of the start, there's a similar method called `lastIndexOf`: +Belirli bir değeri aramak için, diziler `indexOf` metodunu sağlar. Bu yöntem, istenen değerin bulunduğu dizinin indexini bulur ve döndürür - veya bulunamadıysa -1 değerini döndürür. Arama için dizinin sonundan başlamak isterseniz, benzer bir yöntem olan `lastIndexOf` vardır. ``` console.log([1, 2, 3, 2, 1].indexOf(2)); @@ -600,11 +600,11 @@ console.log([1, 2, 3, 2, 1].lastIndexOf(2)); // → 3 ``` -Both `indexOf` and `lastIndexOf` take an optional second argument that indicates where to start searching. +`indexOf` ve `lastIndexOf` her ikisi de başlamak için opsiyonel olan ikinci argüman alır ve nereden aramaya başlanacağını belirtir. {{index "slice method", [array, indexing]}} -Another fundamental array method is `slice`, which takes start and end indices and returns an array that has only the elements between them. The start index is inclusive, the end index exclusive. +Başka bir temel dizi metodu olan `slice`, başlangıç ve bitiş index değerlerini alır ve yalnızca bunlar arasındaki öğeleri içeren bir dizi döndürür. Başlangıç index değerinde bulunan değer döndürülen diziye dahilken bitiş index değerindeki değer hariçtir. ``` console.log([0, 1, 2, 3, 4].slice(2, 4)); @@ -615,13 +615,13 @@ console.log([0, 1, 2, 3, 4].slice(2)); {{index [string, indexing]}} -When the end index is not given, `slice` will take all of the elements after the start index. You can also omit the start index to copy the entire array. +Bitiş dizini verilmediğinde, `slice` başlangıç index değerinden sonraki tüm öğeleri alır. Ayrıca tüm diziyi kopyalamak adına başlangıç index değerini de vermeyebilirsiniz. {{index concatenation, "concat method"}} -The `concat` method can be used to append arrays together to create a new array, similar to what the `+` operator does for strings. +`concat` metodu dizileri bir araya getirerek yeni bir dizi oluşturmada da kullanılabilir, bu işlem `+` operatörünün dizinlere yaptığı işleme benzerdir. -The following example shows both `concat` and `slice` in action. It takes an array and an index and returns a new array that is a copy of the original array with the element at the given index removed: +Aşağıdaki örnek, hem `concat` hem de `slice` metodlarının kullanımını gösteriyor. Bir dizi ve bir index değeri alıp verilen index değerindeki öğe çıkarılmış olan orijinal dizinin bir kopyasını döndürür. ``` function remove(array, index) { @@ -632,13 +632,13 @@ console.log(remove(["a", "b", "c", "d", "e"], 2)); // → ["a", "b", "d", "e"] ``` -If you pass `concat` an argument that is not an array, that value will be added to the new array as if it were a one-element array. +`concat` metoduna bir dizi olmayan bir argüman verirseniz, bu değer yeni diziye tek bir öğe barındıran bir diziymiş gibi eklenecektir. -## Strings and their properties +## Dizeler ve özellikleri {{index [string, properties]}} -We can read properties like `length` and `toUpperCase` from string values. But if we try to add a new property, it doesn't stick. +Dizin değerlerinden `length` ve `toUpperCase` gibi özellikleri okuyabiliriz. Ancak yeni bir özellik eklemeye çalışırsanız, yapışmaz. ``` let kim = "Kim"; @@ -647,11 +647,11 @@ console.log(kim.age); // → undefined ``` -Values of type string, number, and Boolean are not objects, and though the language doesn't complain if you try to set new properties on them, it doesn't actually store those properties. As mentioned earlier, such values are immutable and cannot be changed. +Dize, sayı ve Boolean türlerinin değerleri nesneler değildir ve dil bunlara yeni özellikler eklemeye çalışırsanız şikayet etmese de aslında bu özellikleri saklamaz. Daha önce belirtildiği gibi, bu tür değerler değiştirilemezler. {{index [string, methods], "slice method", "indexOf method", [string, searching]}} -But these types do have built-in properties. Every string value has a number of methods. Some very useful ones are `slice` and `indexOf`, which resemble the array methods of the same name: +Ancak, bu türlerin yerleşik özellikleri vardır. Her dize değeri bir belirli özelliklere sahiptir. Bazı çok kullanışlı olanları `slice` ve `indexOf` metodlarıdır ve aynı isimde olan dizi metodlarına benzerler. ``` console.log("coconuts".slice(4, 7)); @@ -660,7 +660,7 @@ console.log("coconut".indexOf("u")); // → 5 ``` -One difference is that a string's `indexOf` can search for a string containing more than one character, whereas the corresponding array method looks only for a single element: +Bir fark, bir dizenin `indexOf` metodunun birden fazla karakter içeren bir dizeyi arayabilmesidir, oysa ilgili dizi metodu yalnızca tek bir öğe arar. ``` console.log("one two three".indexOf("ee")); @@ -669,7 +669,7 @@ console.log("one two three".indexOf("ee")); {{index [whitespace, trimming], "trim method"}} -The `trim` method removes whitespace (spaces, newlines, tabs, and similar characters) from the start and end of a string: +`trim` metodu, bir dizinin başından ve sonundan boşlukları (boşluklar, yeni satırlar, tab vb. karakterler) kaldırır. ``` console.log(" okay \n ".trim()); @@ -678,7 +678,7 @@ console.log(" okay \n ".trim()); {{id padStart}} -The `zeroPad` function from the [previous chapter](functions) also exists as a method. It is called `padStart` and takes the desired length and padding character as arguments: +[Önceki bölüm](functions)'deki `zeroPad` fonksiyonu aynı zamanda bir metod olarak da mevcuttur. `padStart` olarak adlandırılır ve istenen uzunluğu ve dolgu karakterini argüman olarak alır. ``` console.log(String(6).padStart(3, "0")); @@ -689,7 +689,7 @@ console.log(String(6).padStart(3, "0")); {{index "split method"}} -You can split a string on every occurrence of another string with `split` and join it again with `join`: +Bir dizeyi başka bir dizenin her görünümünde `split` aracılıyla bölebilir ve onu tekrar `join` ile birleştirebilirsiniz. ``` let sentence = "Secretarybirds specialize in stomping"; @@ -702,7 +702,7 @@ console.log(words.join(". ")); {{index "repeat method"}} -A string can be repeated with the `repeat` method, which creates a new string containing multiple copies of the original string, glued together: +Bir dizeyi `repeat` metodunu kullanarak tekrarlayabilirsiniz, böylelikle eski dizeyi birden fazla kez içerisinde barındıran başka yeni bir dize oluşturmuş olursunuz. ``` console.log("LA".repeat(3)); @@ -711,7 +711,7 @@ console.log("LA".repeat(3)); {{index ["length property", "for string"], [string, indexing]}} -We have already seen the string type's `length` property. Accessing the individual characters in a string looks like accessing array elements (with a complication that we'll discuss in [Chapter ?](higher_order#code_units)). +Dize türünün `length` özelliğini zaten gördük. Bir dizideki bireysel karakterlere erişmek, dizi öğelerine erişmek gibi görünür ([bölüm ?](higher_order#code_units)'da inceleyeceğimiz bir karmaşıklıkla). ``` let string = "abc"; @@ -723,11 +723,15 @@ console.log(string[1]); {{id rest_parameters}} -## Rest parameters +## Kalan parametreleri {{index "Math.max function", "period character", "max example", spread, [array, "of rest arguments"]}} -It can be useful for a function to accept any number of ((argument))s. For example, `Math.max` computes the maximum of _all_ the arguments it is given. To write such a function, you put three dots before the function's last ((parameter)), like this: +Bir fonksiyonunun belirli olmayan, herhangi bir sayıda argüman kabul etmesi yararlı olabilir. Örneğin, `Math.max`, verildiğinde tüm verilen argümanların maksimumunu hesaplar. + +{{index "period character", "max example", spread, [array, "of rest arguments"]}} + +Böyle bir fonksiyon yazmak için, fonksiyonun son ((parametresi))nın önüne üç nokta koyarsınız: ```{includeCode: strip_log} function max(...numbers) { @@ -741,11 +745,11 @@ console.log(max(4, 1, 9, -2)); // → 9 ``` -When such a function is called, the _((rest parameter))_ is bound to an array containing all further arguments. If there are other parameters before it, their values aren't part of that array. When, as in `max`, it is the only parameter, it will hold all arguments. +Böyle bir fonksiyon çağrıldığında, _((kalan parametre))_ tüm diğer argümanları içeren bir diziyle ilişkilendirilir. Eğer ondan önce başka parametreler varsa, bu değerler bu dizinin bir parçası olmayacaktır ancak eğer `max` fonksiyonda olduğu gibi tek başına bir kalan parametresi varsa o zaman tüm değişkenleri içerecektir. {{index [function, application]}} -You can use a similar three-dot notation to _call_ a function with an array of arguments: +Benzer bir üç nokta gösterimi kullanarak bir fonksiyonu bir dizi argümanla çağırmak da mümkündür. ``` let numbers = [5, 1, 7]; @@ -753,11 +757,11 @@ console.log(max(...numbers)); // → 7 ``` -This "((spread))s" out the array into the function call, passing its elements as separate arguments. It is possible to include an array like that along with other arguments, as in `max(9, ...numbers, 2)`. +Bu, diziyi fonksiyon çağrısına (("yayarak")) öğelerini ayrı argümanlar olarak geçirir. Bu şekilde, `max(9, ...numbers, 2)` şeklinde hem bir diziyi yayarak hem de yaymayarak farklı argümanlar vermek mümkündür. {{index "[] (array)"}} -Square bracket array notation similarly allows the triple-dot operator to spread another array into the new array: +Köşeli parantez dizisi gösterimi, üç nokta operatörünü başka bir diziyi yeni diziye yaymak için de kullanılabilir. ``` let words = ["never", "fully"]; @@ -767,7 +771,7 @@ console.log(["will", ...words, "understand"]); {{index "{} (object)"}} -This works even in curly brace objects, where it adds all properties from another object. If a property is added multiple times, the last value to be added wins: +Bu süslü parantez nesnelerinde de çalışmaktadır ve başka bir nesnedeki tüm özellikleri diğer nesneye ekler. Eğer aynı addaki bir özellik aynı objeye tekrar ve tekrar farklı değerlerle eklenirse, en son eklenmiş olan değer o isimdeki özelliğin değeri olacaktır. ``` let coordinates = {x: 10, y: 0}; @@ -775,29 +779,29 @@ console.log({...coordinates, y: 5, z: 1}); // → {x: 10, y: 5, z: 1} ``` -## The Math object +## Math nesnesi {{index "Math object", "Math.min function", "Math.max function", "Math.sqrt function", minimum, maximum, "square root"}} -As we've seen, `Math` is a grab bag of number-related utility functions such as `Math.max` (maximum), `Math.min` (minimum), and `Math.sqrt` (square root). +Gördüğümüz gibi, `Math`, `Math.max` (maksimum), `Math.min` (minimum) ve `Math.sqrt` (karekök) gibi sayılarla ilgili yardımcı fonksiyonları bir arada barındıran bir nesnedir. {{index namespace, [object, property]}} {{id namespace_pollution}} -The `Math` object is used as a container to group a bunch of related functionality. There is only one `Math` object, and it is almost never useful as a value. Rather, it provides a _namespace_ so that all these functions and values do not have to be global bindings. +`Math` nesnesi, bir dizi ilgili fonksiyonaliteyi gruplamak için bir konteyner olarak kullanılır. Yalnızca bir `Math` nesnesi vardır ve hemen hemen hiç bir zaman değer olarak yararlı değildir. Daha çok, tüm bu fonksiyonların ve değerlerin global bağlantıları olmasına gerek kalmaması için bir _ad alanı_ sağlar. {{index [binding, naming]}} -Having too many global bindings "pollutes" the namespace. The more names have been taken, the more likely you are to accidentally overwrite the value of some existing binding. For example, it's not unlikely you'll want to name something `max` in one of your programs. Since JavaScript's built-in `max` function is tucked safely inside the `Math` object, you don't have to worry about overwriting it. +Çok fazla global bağlantıların varlığı ad alanını "kirletir". Ne kadar çok isim alındıysa, bir varolan bağlantının değerini yanlışlıkla değiştirme olasılığınız o kadar artar. Örneğin, programlarınızdan birinde bir şeyi `max` olarak adlandırmak istemek olasıdır. JavaScript'in yerleşik `max` işlevi güvenli bir şekilde `Math` nesnesinin içine gizlenmiş olduğundan ötürü onun değerini istemeden değiştirmemiz olasılığı üzerine endişelenmemize gerek yoktur. {{index "let keyword", "const keyword"}} -Many languages will stop you, or at least warn you, when you are defining a binding with a name that is already taken. JavaScript does this for bindings you declared with `let` or `const` but—perversely—not for standard bindings nor for bindings declared with `var` or `function`. +Birçok dil, zaten alınmış bir isme sahip bir bağlantı tanımladığınızda sizi durdurur veya en azından uyarır. JavaScript bunu, `let` veya `const` ile tanımladığınız bağlanmalar için yapar ama tuhaf bir şekilde standart bağlantılar ya da `var` veya `function` ile tanımlanan bağlantılar için yapmaz. {{index "Math.cos function", "Math.sin function", "Math.tan function", "Math.acos function", "Math.asin function", "Math.atan function", "Math.PI constant", cosine, sine, tangent, "PI constant", pi}} -Back to the `Math` object. If you need to do ((trigonometry)), `Math` can help. It contains `cos` (cosine), `sin` (sine), and `tan` (tangent), as well as their inverse functions, `acos`, `asin`, and `atan`, respectively. The number π (pi)—or at least the closest approximation that fits in a JavaScript number—is available as `Math.PI`. There is an old programming tradition of writing the names of ((constant)) values in all caps: +`Math` nesnesine geri dönelim. Eğer ((trigonometri)) yapmanız gerekiyorsa, `Math` size yardımcı olabilir. `cos` (kosinüs), `sin` (sinüs) ve `tan` (tanjant) gibi trigonometrik fonksiyonları, ayrıca bunların ters fonksiyonlarını, sırasıyla `acos`, `asin` ve `atan` içerir. Pi sayısı—veya en azından bir JavaScript sayısına sığan en yakın yaklaşım—`Math.PI` olarak mevcuttur. Sabit değerlerin adlarını tamamı büyük harflerle yazma gibi eski bir programlama geleneği vardır. ```{test: no} function randomPointOnCircle(radius) { @@ -809,11 +813,11 @@ console.log(randomPointOnCircle(2)); // → {x: 0.3667, y: 1.966} ``` -If you're not familiar with sines and cosines, don't worry. I'll explain them when they are used in this book, in [Chapter ?](dom#sin_cos). +Eğer sinüs ve kosinüslerle aşina değilseniz, endişelenmeyin. Kitapta kullanıldıklarında, [bölümün ?](dom#sin_cos)'da açıklayacağım. {{index "Math.random function", "random number"}} -The previous example used `Math.random`. This is a function that returns a new pseudorandom number between zero (inclusive) and one (exclusive) every time you call it: +Önceki örnek, `Math.random` kullanıyordu. Bu, her çağrıldığında sıfır (dahil) ile bir (hariç) arasında bir yarı rastgele sayı döndüren bir fonksiyondur. ```{test: no} console.log(Math.random()); @@ -826,28 +830,28 @@ console.log(Math.random()); {{index "pseudorandom number", "random number"}} -Though computers are deterministic machines—they always react the same way if given the same input—it is possible to have them produce numbers that appear random. To do that, the machine keeps some hidden value, and whenever you ask for a new random number, it performs complicated computations on this hidden value to create a new value. It stores a new value and returns some number derived from it. That way, it can produce ever new, hard-to-predict numbers in a way that _seems_ random. +Bilgisayarlar deterministik makinelerdir—her zaman aynı giriş verildiğinde her zaman aynı şekilde tepki verirler—ancak onları rastgele görünen sayılar üretmeleri için yönlendirebilirsiniz. Bunun için, makine bazı gizli bir değeri saklar ve yeni bir rastgele sayı istediğinizde, bu gizli değer üzerinde karmaşık hesaplamalar yaparak yeni bir değer oluşturur. Yeni bir değer saklar ve ondan türetilmiş bir sayı döndürür. Bu şekilde her zaman rastgele gibi görünen yeni ve tahmin edilmesi zor sayılar üretebilir. {{index rounding, "Math.floor function"}} -If we want a whole random number instead of a fractional one, we can use `Math.floor` (which rounds down to the nearest whole number) on the result of `Math.random`: +Kesirli bir sayı yerine bütün rastgele bir sayı istiyorsak, `Math.random` fonksiyonunun sonucuna `Math.floor` (en yakın tam sayıya yuvarlar) kullanabiliriz. ```{test: no} console.log(Math.floor(Math.random() * 10)); // → 2 ``` -Multiplying the random number by 10 gives us a number greater than or equal to 0 and below 10. Since `Math.floor` rounds down, this expression will produce, with equal chance, any number from 0 through 9. +Rastgele sayıyı 10 ile çarptığımızda, 0 veya daha büyük bir sayı ve 10'un altında bir sayı elde ederiz. `Math.floor` yuvarladığı için, bu ifade, eşit bir şansla, 0 ile 9 arasındaki herhangi bir sayıyı üretecektir. {{index "Math.ceil function", "Math.round function", "Math.abs function", "absolute value"}} -There are also the functions `Math.ceil` (for "ceiling", which rounds up to a whole number), `Math.round` (to the nearest whole number), and `Math.abs`, which takes the absolute value of a number, meaning it negates negative values but leaves positive ones as they are. +`Math.ceil`(en yakın bir üst tam sayıya yuvarlar), `Math.round`(en yakın tam sayıya yuvarlar) ve `Math.abs` gibi bir sayının mutlak değerini alan, yani verilen sayıyı eksi ile çarpan ancak verilen sayı zaten pozitifse olduğu gibi bırakan fonksiyonlar da vardır. -## Destructuring +## Parçalara ayırma {{index "phi function"}} -Let's return to the `phi` function for a moment. +Bir an için `phi` fonksiyonuna geri dönelim. ```{test: wrap} function phi(table) { @@ -861,7 +865,7 @@ function phi(table) { {{index "destructuring binding", parameter}} -One reason this function is awkward to read is that we have a binding pointing at our array, but we'd much prefer to have bindings for the _elements_ of the array—that is, `let n00 = table[0]` and so on. Fortunately, there is a succinct way to do this in JavaScript: +Bu fonksiyonun okunması zor olmasının bir nedeni, dizimize işaret eden bir bağlantımızın olması, ancak dizinin elemanları için `let n00 = table[0]` benzeri bir bağlantımızın olmasını bize okunurlukta çok daha yardımcı olacaktır. Neyse ki, JavaScript'te bunu kısa ve öz bir şekilde yapmanın yolu bulunmakta. ``` function phi([n00, n01, n10, n11]) { @@ -873,11 +877,11 @@ function phi([n00, n01, n10, n11]) { {{index "let keyword", "var keyword", "const keyword", [binding, destructuring]}} -This also works for bindings created with `let`, `var`, or `const`. If you know that the value you are binding is an array, you can use ((square brackets)) to "look inside" of the value, binding its contents. +Bu, `let`, `var` veya `const` ile oluşturulan bağlantılar için çalışmaktadır. Bağlantı oluşturduğunuz değerin bir dizi olduğunu bildiğinizde, içeriğine "bakmak" için ((köşeli parantezleri)) kullanabilir ve içeriğindeki değerlere bağlantılar oluşturabilirsiniz. {{index [object, property], [braces, object]}} -A similar trick works for objects, using braces instead of square brackets: +Köşeli parantezler yerine süslü parantezler kullanılan ve nesneler için çalışan diğer bir yöntem. ``` let {name} = {name: "Faraji", age: 23}; @@ -887,13 +891,13 @@ console.log(name); {{index null, undefined}} -Note that if you try to destructure `null` or `undefined`, you get an error, much as you would if you directly try to access a property of those values. +Unutmayın ki, `null` veya `undefined`'i ayrıştırmaya çalışırsanız, bu değerlerin özelliklerine doğrudan erişmeye çalıştığınızdan ötürü bir hata alırsınız. -## Optional property access +## Opsiyonel özellik erişimi {{index "optional chaining", "period character"}} -When you aren't sure whether a given value produces an object but still want to read a property from it when it does, you can use a variant of the dot notation: `object?.property`. +Belirli bir nesnenin var olduğundan emin değilseniz, ancak var olduğunda ondan bir özelliği okumak istiyorsanız, nokta notasyonunun bir varyantını kullanabilirsiniz: `object?.property`. ``` function city(object) { @@ -905,9 +909,9 @@ console.log(city({name: "Vera"})); // → undefined ``` -The expression `a?.b` means the same as `a.b` when `a` isn't null or undefined. When it is, it evaluates to undefined. This can be convenient when, as in the example, you aren't sure that a given property exists or when a variable might hold an undefined value. +`a?.b` ifadesi, `a` değeri `null` veya `undefined` değilse `a.b` ifadesiyle aynı anlamına gelir ancak eğer `null` veya `undefined` ise o zaman, değeri `undefined` olur. Örnekte de olduğu gibi, belirli bir özelliğin varlığından emin olmadığınızda kullanışlı olabilir. -A similar notation can be used with square bracket access, and even with function calls, by putting `?.` in front of the parentheses or brackets: +Benzer bir notasyon `?.` koyularak köşeli parantez erişimi ile köşeli parantezlerden önce, hatta fonksiyon çağrılarında parantezlerden önce de kullanılabilir. ``` console.log("string".notAMethod?.()); @@ -920,21 +924,21 @@ console.log({}.arrayProp?.[0]); {{index [array, representation], [object, representation], "data format", [memory, organization]}} -Because properties grasp their value rather than contain it, objects and arrays are stored in the computer's memory as sequences of bits holding the _((address))es_—the place in memory—of their contents. An array with another array inside of it consists of (at least) one memory region for the inner array and another for the outer array, containing (among other things) a number that represents the address of the inner array. +Özellikler değerlerini içermek yerine kavradığındna ötürü, nesneler ve diziler bilgisayarın belleğinde, içeriklerinin _adresini_ bit dizileri halinde depolamaktadır. Dolayısıyla, içinde başka bir dizi bulunan bir dizi, iç dizi için en az bir bellek bölgesi ve iç dizenin adresini temsil eden bir numara içeren dış dizi için başka bir bellek bölgesinden oluşur. -If you want to save data in a file for later or send it to another computer over the network, you have to somehow convert these tangles of memory addresses to a description that can be stored or sent. You _could_ send over your entire computer memory along with the address of the value you're interested in, I suppose, but that doesn't seem like the best approach. +Veriyi daha sonra bir dosyada saklamak veya ağ üzerinden başka bir bilgisayara göndermek istiyorsanız, bu bellek adreslerinin karmakarışık dizilerini saklanabilir veya gönderilebilir bir açıklamaya dönüştürmek zorundasınız. Tahminimce, ilgilendiğiniz değerin adresiyle birlikte tüm bilgisayar belleğinizi gönderebilirsiniz, ancak bu en iyi yaklaşım gibi görünmüyor. {{indexsee "JavaScript Object Notation", JSON}} {{index serialization, "World Wide Web"}} -What we can do is _serialize_ the data. That means it is converted into a flat description. A popular serialization format is called _((JSON))_ (pronounced "Jason"), which stands for JavaScript Object Notation. It is widely used as a data storage and communication format on the Web, even in languages other than JavaScript. +Yapabileceğimiz şey, veriyi _serileştirmek_. Bu, verinin düz bir açıklamaya dönüştürülmesi anlamına gelir. Popüler bir seri hale getirme biçimi, _((JSON))_ olarak adlandırılan (ceysın olarak telaffuz edilen) bir biçimdir ve JavaScript Nesne Notasyonu anlamına gelir. Web'de JavaScript dışındaki dillerde bile veri depolama ve iletişim biçimi olarak geniş bir şekilde kullanılmaktadır. {{index [array, notation], [object, creation], [quoting, "in JSON"], comment}} -JSON looks similar to JavaScript's way of writing arrays and objects, with a few restrictions. All property names have to be surrounded by double quotes, and only simple data expressions are allowed—no function calls, bindings, or anything that involves actual computation. Comments are not allowed in JSON. +JSON, JavaScript'in dizileri ve nesneleri yazma şekline benzer, ancak bazı kısıtlamaları vardır. Tüm özellik adları çift tırnaklarla çevrelenmelidir ve yalnızca basit veri ifadelerine izin verilir - fonksiyon çağrıları, bağlantılar veya gerçek hesaplamayı içeren hiçbir şey yoktur. JSON'da yorum satırlarına da izin verilmemektedir. -A journal entry might look like this when represented as JSON data: +Bir günlük girişi, JSON verisi olarak temsil edildiğinde şöyle görünebilir: ```{lang: "json"} { @@ -945,7 +949,7 @@ A journal entry might look like this when represented as JSON data: {{index "JSON.stringify function", "JSON.parse function", serialization, deserialization, parsing}} -JavaScript gives us the functions `JSON.stringify` and `JSON.parse` to convert data to and from this format. The first takes a JavaScript value and returns a JSON-encoded string. The second takes such a string and converts it to the value it encodes: +JavaScript, veriyi bu formata dönüştürmek ve bu formattan dönüştürmek için `JSON.stringify` ve `JSON.parse` fonksiyonlarını sağlar. İlki bir JavaScript değerini alır ve bir JSON formatında kodlanmış bir dize döndürür. İkincisi, JSON formatında kodlanmış bir dizeyi alır ve onu kodlandığı değere dönüştürür. ``` let string = JSON.stringify({squirrel: false, @@ -956,23 +960,23 @@ console.log(JSON.parse(string).events); // → ["weekend"] ``` -## Summary +## Özet -Objects and arrays provide ways to group several values into a single value. This allows us to put a bunch of related things in a bag and run around with the bag instead of wrapping our arms around all of the individual things and trying to hold on to them separately. +Nesneler ve diziler(ki diziler de belirli bir tür nesnedir) birden fazla değeri tek bir değere gruplama yolları sağlar. Kavramsal olarak, bu bize tüm bireysel şeylerin etrafına kollarımızı sarmak ve bunları ayrı ayrı tutmaya çalışmak yerine bir grup ilgili şeyi bir çantaya koyup çantayla koşmamıza olanak tanır. -Most values in JavaScript have properties, with the exceptions being `null` and `undefined`. Properties are accessed using `value.prop` or `value["prop"]`. Objects tend to use names for their properties and store more or less a fixed set of them. Arrays, on the other hand, usually contain varying amounts of conceptually identical values and use numbers (starting from 0) as the names of their properties. +`null` ve `undefined` değerleri dışında JavaScript'teki değerlerler özelliklere sahiptir. Özelliklere `value.prop` veya `value["prop"]` kullanılarak erişilir. Nesneler özelliklerinin adlarını kullanır ve bunların sabit bir kümesini saklar. Diziler ise genellikle kavramsal olarak aynı değerlerin değişen miktarlarını içerebilir ve özelliklerinin adları olarak sayıları (0'dan başlayarak) kullanır. -There _are_ some named properties in arrays, such as `length` and a number of methods. Methods are functions that live in properties and (usually) act on the value of which they are a property. +Dizilerde bazı adlandırılmış özellikler _vardır_, bunlar `length` ve metod isimleridir. Yöntemler, özelliklerde yaşayan ve genellikle özelliği oldukları değer üzerinde hareket eden fonksiyonlardır. -You can iterate over arrays using a special kind of `for` loop: `for (let element of array)`. +Diziler üzerinde bir tür özel `for` döngüsü kullanarak yineleme yapabilirsiniz, `for (let element of array)`. -## Exercises +## Egzersizler -### The sum of a range +### Belirli bir sayı aralığının toplamı {{index "summing (exercise)"}} -The [introduction](intro) of this book alluded to the following as a nice way to compute the sum of a range of numbers: +Bu kitabın [giriş](intro) kısmı, aşağıdakini bir aralıktaki sayıların toplamını hesaplamanın güzel bir yol olduğunu size söyledi: ```{test: no} console.log(sum(range(1, 10))); @@ -980,18 +984,18 @@ console.log(sum(range(1, 10))); {{index "range function", "sum function"}} -Write a `range` function that takes two arguments, `start` and `end`, and returns an array containing all the numbers from `start` up to and including `end`. +`start` ve `end` adında iki argüman alan `range` adlı bir fonksiyon yazın ki `start` argümanında verilen değerden başlayarak `end` argümanında bitecek şekilde her ikisini ve aralarındaki sayıları da içinde barındıracak bir dizi döndürsün. -Next, write a `sum` function that takes an array of numbers and returns the sum of these numbers. Run the example program and see whether it does indeed return 55. +Sonra, `sum` adlı içinde numaralar barındıran bir diziyi alan ve bunların toplamını hesaplayan bir fonksiyon yazın. Bunları bir araya getirip örnek programı çalıştırdığınızda 55 değerinin döndürülüp döndürülmediğini kontrol edin. {{index "optional argument"}} -As a bonus assignment, modify your `range` function to take an optional third argument that indicates the "step" value used when building the array. If no step is given, the elements should go up by increments of one, corresponding to the old behavior. The function call `range(1, 10, 2)` should return `[1, 3, 5, 7, 9]`. Make sure this also works with negative step values so that `range(5, 2, -1)` produces `[5, 4, 3, 2]`. +Bonus bir görev olarak, `range` fonksiyonunuzu, diziyi oluşturulurken kullanılan "adım" değerini belirten isteğe bağlı üçüncü bir argümanı alacak şekilde değiştirin. Adım verilmediğinde, öğeler normal davranış olan bir bir artırılarak gider. Fonksiyon çağrısı `range(1, 10, 2)`, `[1, 3, 5, 7, 9]` değerini döndürmelidir. Negatif adım değerleriyle de çalıştığından emin olmak için `aralık(5, 2, -1)` fonksiyon çağrısı `[5, 4, 3, 2]` değerini üretmelidir. {{if interactive ```{test: no} -// Your code here. +// Kodunuz buraya. console.log(range(1, 10)); // → [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] @@ -1007,38 +1011,38 @@ if}} {{index "summing (exercise)", [array, creation], "square brackets"}} -Building up an array is most easily done by first initializing a binding to `[]` (a fresh, empty array) and repeatedly calling its `push` method to add a value. Don't forget to return the array at the end of the function. +Bir dizi oluşturmanın en kolay yolu, öncelikle [] (temiz, boş bir dizi) için bir bağlantıyla başlamak ve bir değer eklemek için tekrar tekrar `push` metodunu çağırmaktır. Fonksiyonun sonunda diziyi döndürmeyi unutmayın. {{index [array, indexing], comparison}} -Since the end boundary is inclusive, you'll need to use the `<=` operator rather than `<` to check for the end of your loop. +Son sınır için verilen numara da dahil olduğu için, döngünün bitip bitmediğini kontrol etmek için `<` yerine `<=` operatörünü kullanmanız gerekecek. {{index "arguments object"}} -The step parameter can be an optional parameter that defaults (using the `=` operator) to 1. +`step`, varsayılan olarak 1 olan bir parametre olabilir (`=` operatörünü kullanarak). {{index "range function", "for loop"}} -Having `range` understand negative step values is probably best done by writing two separate loops—one for counting up and one for counting down—because the comparison that checks whether the loop is finished needs to be `>=` rather than `<=` when counting downward. +Negatif adım değerlerini `range` fonksiyonun anlaması için iki biri yukarı biri aşağı doğru sayan iki ayrı döngü yazılabilir. Döngünün bitip bitmediğini kontrol eden karşılaştırmanın, aşağı doğru sayarken `<=` yerine `>=` olması gerektiğini unutmamak önemlidir. -It might also be worthwhile to use a different default step, namely, -1, when the end of the range is smaller than the start. That way, `range(5, 2)` returns something meaningful, rather than getting stuck in an ((infinite loop)). It is possible to refer to previous parameters in the default value of a parameter. +Bitiş noktası, başlangıçtan küçük olduğunda farklı bir varsayılan `step` parametresi değeri, yani, -1 kullanmak da faydalı olabilir. Bu şekilde, `range(5, 2)` anlamlı bir şey döndürür ve sonsuz bir döngüye sıkışmaz. Bir parametrenin varsayılan değerinde önceki parametre değerlerine başvurmak mümkündür. hint}} -### Reversing an array +### Bir diziyi tersine çevirmek {{index "reversing (exercise)", "reverse method", [array, methods]}} -Arrays have a `reverse` method that changes the array by inverting the order in which its elements appear. For this exercise, write two functions, `reverseArray` and `reverseArrayInPlace`. The first, `reverseArray`, should take an array as argument and produce a _new_ array that has the same elements in the inverse order. The second, `reverseArrayInPlace`, should do what the `reverse` method does: _modify_ the array given as argument by reversing its elements. Neither may use the standard `reverse` method. +Dizilerin, öğelerin sırasını tersine çeviren bir `reverse` yöntemi vardır. Bu alıştırma için, `reverseArray` ve `reverseArrayInPlace` olmak üzere iki fonksiyon yazın. İlk fonksiyon, `reverseArray`, bir dizi alır ve ters sıradaki aynı öğelere sahip _yeni_ bir dizi üretir. İkinci fonksiyon, `reverseArrayInPlace`, `reverse` yönteminin yaptığı şeyi yapar: argüman olarak verilen diziyi öğelerini tersine çevirerek değiştirir. Hiçbiri standart `reverse` yöntemini kullanamaz. {{index efficiency, "pure function", "side effect"}} -Thinking back to the notes about side effects and pure functions in the [previous chapter](functions#pure), which variant do you expect to be useful in more situations? Which one runs faster? +[Önceki bölümde](functions#pure) yan etkiler ve saf fonksiyonlar hakkındaki notlara geri dönüp düşünerek, hangi varyantın daha fazla durumda kullanışlı olacağını ve hangisinin daha hızlı çalışmasını beklersiniz? {{if interactive ```{test: no} -// Your code here. +// Kodunuz buraya. let myArray = ["A", "B", "C"]; console.log(reverseArray(myArray)); @@ -1057,23 +1061,24 @@ if}} {{index "reversing (exercise)"}} -There are two obvious ways to implement `reverseArray`. The first is to simply go over the input array from front to back and use the `unshift` method on the new array to insert each element at its start. The second is to loop over the input array backwards and use the `push` method. Iterating over an array backwards requires a (somewhat awkward) `for` specification, like `(let i = array.length - 1; i >= 0; i--)`. +Iterating over an array backwards requires a (somewhat awkward) `for` specification, like `(let i = array.length - 1; i >= 0; i--)`. +`reverseArray`'yı uygulamanın iki belirgin yolu vardır. İlk yöntem, verilen diziyi baştan sona doğru geçmek ve her öğeyi başlangıcına yerleştirmek için yeni dizi üzerinde `unshift` metodunu kullanmaktır. İkincisi, giriş dizisini tersten geçmek ve `push` yöntemini kullanmaktır. Bir diziyi tersten yinelemek için biraz garip bir `for` döngüsü gerektirir, örneğin `(let i = array.length - 1; i >= 0; i--)`. {{index "slice method"}} -Reversing the array in place is harder. You have to be careful not to overwrite elements that you will later need. Using `reverseArray` or otherwise copying the whole array (`array.slice()` is a good way to copy an array) works but is cheating. +Diziyi yerinde ters çevirmek daha zordur. Daha sonra ihtiyacınız olacak öğelerin üzerine yanlışlıkla yazıp onları kaybetmemeye dikkat etmelisiniz. `reverseArray` kullanmak veya aksi takdirde tüm diziyi kopyalamak (`array.slice()` bir diziyi kopyalamanın iyi bir yoludur) çalışır ancak hile yapmaktır. -The trick is to _swap_ the first and last elements, then the second and second-to-last, and so on. You can do this by looping over half the length of the array (use `Math.floor` to round down—you don't need to touch the middle element in an array with an odd number of elements) and swapping the element at position `i` with the one at position `array.length - 1 - i`. You can use a local binding to briefly hold on to one of the elements, overwrite that one with its mirror image, and then put the value from the local binding in the place where the mirror image used to be. +Püf noktası, ilk ve son öğeleri, ikinci ve sondan bir önceki öğeleri ve böylece devam ederek _değiştirmektir_. Bunun için dizinin uzunluğunun yarısı kadar döngü yapmanız gerekir (`Math.floor` kullanarak aşağı yuvarlama yapın - tek sayıda öğeye sahip bir dizide ortadaki öğeye dokunmanıza gerek yoktur) ve pozisyon `i` bağlantısındaki öğeyi `array.length - 1 - i` pozisyonundaki ile değiştirmektir. Bir öğeyi geçici olarak tutmak için yerel bir bağlantı kullanabilir, bunu aynasıyla değiştirerek üzerine yazabilir ve daha sonra yerel bağlantının değerini aynanın yerine koyabilirsiniz. hint}} {{id list}} -### A list +### Bir liste {{index ["data structure", list], "list (exercise)", "linked list", array, collection}} -As generic blobs of values, objects can be used to build all sorts of data structures. A common data structure is the _list_ (not to be confused with arrays). A list is a nested set of objects, with the first object holding a reference to the second, the second to the third, and so on: +Nesneler, genel değer birikintileri olarak, çeşitli veri yapılarını oluşturmak için kullanılabilir. Yaygın bir veri yapısı, dizi ile karıştırılmaması gereken listedir. Bir liste, birbirini referans alan nesnelerin iç içe geçmiş bir kümesidir, ilk nesne ikinciyi, ikinci nesne üçüncüyü ve böyle devam eder. ```{includeCode: true} let list = { @@ -1088,24 +1093,25 @@ let list = { }; ``` -The resulting objects form a chain, as shown in the following diagram: +Oluşan nesneler şu şekilde bir zincir oluşturur: {{figure {url: "img/linked-list.svg", alt: "A diagram showing the memory structure of a linked list. There are 3 cells, each with a value field holding a number, and a 'rest' field with an arrow to the rest of the list. The first cell's arrow points at the second cell, the second cell's arrow at the last cell, and the last cell's 'rest' field holds null.",width: "8cm"}}} {{index "structure sharing", [memory, structure sharing]}} -A nice thing about lists is that they can share parts of their structure. For example, if I create two new values `{value: 0, rest: list}` and `{value: -1, rest: list}` (with `list` referring to the binding defined earlier), they are both independent lists, but they share the structure that makes up their last three elements. The original list is also still a valid three-element list. +Listelerin güzel bir özelliği, yapılarının bir kısmını paylaşabilmesidir. Örneğin, `{value: 0, rest: list}` ve `{value: -1, rest: list}` (önceki bağlantıya referansta bulunarak) gibi iki yeni değer oluşturursam, bunlar bağımsız listelerdir, ancak son üç öğeyi oluşturan yapıyı paylaşırlar. Orjinal liste hala geçerli bir üç öğeli listedir. -Write a function `arrayToList` that builds up a list structure like the one shown when given `[1, 2, 3]` as argument. Also write a `listToArray` function that produces an array from a list. Add the helper functions `prepend`, which takes an element and a list and creates a new list that adds the element to the front of the input list, and `nth`, which takes a list and a number and returns the element at the given position in the list (with zero referring to the first element) or `undefined` when there is no such element. +Then add the helper functions `prepend`, which takes an element and a list and creates a new list that adds the element to the front of the input list, and `nth`, which takes a list and a number and returns the element at the given position in the list (with zero referring to the first element) or `undefined` when there is no such element. +`[1, 2, 3]` olarak verildiğinde gösterilen gibi bir liste yapısı oluşturan `arrayToList` adlı fonksiyonu yazın. Ayrıca, bir listeden bir dizi üreten `listToArray` adlı fonksiyonu da yazın. Ardından, bir öğe ve bir liste alıp öğeyi giriş listesinin önüne ekleyen yeni bir liste oluşturan `prepend`, bir liste ve bir sayı alıp listenin verilen konumundaki öğeyi (sıfır ilk öğeyi belirtir) veya böyle bir öğe yoksa `undefined` değeri döndüren `nth` yardımcı fonksiyonlarını ekleyin. {{index recursion}} -If you haven't already, also write a recursive version of `nth`. +Henüz yapmadıysanız, `nth` fonksiyonunun özyineli bir sürümünü de yazın. {{if interactive ```{test: no} -// Your code here. +// Kodunuz buraya. console.log(arrayToList([10, 20])); // → {value: 10, rest: {value: 20, rest: null}} @@ -1123,46 +1129,46 @@ if}} {{index "list (exercise)", "linked list"}} -Building up a list is easier when done back to front. So `arrayToList` could iterate over the array backwards (see the previous exercise) and, for each element, add an object to the list. You can use a local binding to hold the part of the list that was built so far and use an assignment like `list = {value: X, rest: list}` to add an element. +Bir listeyi arkadan öne doğru oluşturmak daha kolaydır. Bu nedenle, `arrayToList`, her öğe için bir nesne ekleyerek diziyi tersten geçebilir (önceki alıştırmaya bakın), bunu yaparken her öğe için listeye bir nesne ekleyin. O ana kadar akümüle edilmiş listeyi tutabilmek adına lokal bir bağlantı kullanabilir ve bir element eklemek adına `list = {value: X, rest: list}` gibi bir atama işlemi yapabilirsiniz. {{index "for loop"}} -To run over a list (in `listToArray` and `nth`), a `for` loop specification like this can be used: +Bir listenin üzerinden geçebilmek için(`listToArray` ve `nth` fonksiyonlarını kullanarak) bir `for` döngüsü kullanılabilir: ``` for (let node = list; node; node = node.rest) {} ``` -Can you see how that works? Every iteration of the loop, `node` points to the current sublist, and the body can read its `value` property to get the current element. At the end of an iteration, `node` moves to the next sublist. When that is null, we have reached the end of the list, and the loop is finished. +Nasıl çalıştığını görebiliyor musunuz? Döngünün her bir iterasyonunda `node` adlı bağlantı güncel alt listeye sahip ve böylelikle döngü gövdesi `value` özelliğini okuyarak güncel elementi alabiliyor. Döngü sonunda, `node` diğer alt listeye geçmekte. O değer `null` olduğunda listenin sonuna gelmiş ve döngüyü bitirmiş oluyoruz. {{index recursion}} -The recursive version of `nth` will, similarly, look at an ever smaller part of the "tail" of the list and at the same time count down the index until it reaches zero, at which point it can return the `value` property of the node it is looking at. To get the zeroth element of a list, you simply take the `value` property of its head node. To get element _N_ + 1, you take the *N*th element of the list that's in this list's `rest` property. +`nth` fonksiyonunun özyinelemeli sürümü, benzer şekilde, listenin "kuyruğunun" giderek daha küçük bir kısmına bakacak ve aynı zamanda dizini sıfıra kadar azaltacak ve sıfır olduğunda, baktığı düğümün `value` özelliğini döndürebilecektir. Bir listenin sıfırıncı öğesini almak için, baş düğümünün `value` özelliğini alırsınız. _N_ + 1 öğeyi almak için, bu listenin `rest` özelliğindeki listenin N'inci öğesini alırsınız. hint}} {{id exercise_deep_compare}} -### Deep comparison +### Derin karşılaştırma {{index "deep comparison (exercise)", [comparison, deep], "deep comparison", "== operator"}} -The `==` operator compares objects by identity, but sometimes you'd prefer to compare the values of their actual properties. +`==` operatörü nesneleri kimliğine göre karşılaştırır. Ancak bazen, gerçek özelliklerinin değerlerini karşılaştırmayı tercih edebilirsiniz. -Write a function `deepEqual` that takes two values and returns true only if they are the same value or are objects with the same properties, where the values of the properties are equal when compared with a recursive call to `deepEqual`. +`deepEqual` adında iki değeri alıp yalnızca aynı değer olduklarında veya özellikleri aynı olan nesneler olduklarında ve özelliklerin değerleri, `deepEqual` fonksiyonuna özyinelemeli bir çağrı ile karşılaştırıldığında eşitse true döndüren bir fonksiyon yazın. {{index null, "=== operator", "typeof operator"}} -To find out whether values should be compared directly (using the `===` operator for that) or have their properties compared, you can use the `typeof` operator. If it produces `"object"` for both values, you should do a deep comparison. But you have to take one silly exception into account: because of a historical accident, `typeof null` also produces `"object"`. +Değerlerin doğrudan karşılaştırılıp karşılaştırılmaması gerektiğini (`===` operatörünü kullanarak) veya özelliklerinin karşılaştırılması gerektiğini belirlemek için `typeof` operatörünü kullanabilirsiniz. İki değer için de `"object"` üretirse, derin bir karşılaştırma yapmalısınız. Ancak, bir saçma istisnayı hesaba katmanız gerekir: bir tarih öncesi kazadan dolayı, `typeof null` da "object" üretir. {{index "Object.keys function"}} -The `Object.keys` function will be useful when you need to go over the properties of objects to compare them. +`Object.keys` fonksiyonu nesnelerin özelliklerini karşılaştırmak için özelliklerin üzerinden geçmeniz gerektiğinde faydalı olacaktır. {{if interactive ```{test: no} -// Your code here. +// Kodunuz buraya. let obj = {here: {is: "an"}, object: 2}; console.log(deepEqual(obj, obj)); @@ -1179,14 +1185,14 @@ if}} {{index "deep comparison (exercise)", [comparison, deep], "typeof operator", "=== operator"}} -Your test for whether you are dealing with a real object will look something like `typeof x == "object" && x != null`. Be careful to compare properties only when _both_ arguments are objects. In all other cases you can just immediately return the result of applying `===`. +Gerçek bir nesne ile ilgilendiğinizi belirlemek için testiniz, `typeof x == "object" && x != null` gibi görünecektir. Özellikleri yalnızca _her iki_ argümanın da nesneler olduğunda karşılaştırmaya dikkat edin. Diğer tüm durumlarda, sadece `===` uygulamanın sonucunu hemen döndürebilirsiniz. {{index "Object.keys function"}} -Use `Object.keys` to go over the properties. You need to test whether both objects have the same set of property names and whether those properties have identical values. One way to do that is to ensure that both objects have the same number of properties (the lengths of the property lists are the same). And then, when looping over one of the object's properties to compare them, always first make sure the other actually has a property by that name. If they have the same number of properties and all properties in one also exist in the other, they have the same set of property names. +Özelliklerin üzerinden geçmek için Object.keys kullanın. İki nesnenin aynı özellik isim kümesine sahip olup olmadığını ve bu özelliklerin aynı değerlere sahip olup olmadığını test etmeniz gerekir. Bunu yapmanın bir yolu, her iki nesnenin de aynı sayıda özellik ismine sahip olmasını sağlamaktır (özellik listelerinin uzunlukları aynıdır). Ve sonra, onları karşılaştırmak için bir nesnenin özelliklerini dolaşırken, diğerinin o adla bir özelliğe sahip olduğundan emin olun. Eğer iki nesnenin de aynı sayıda özelliği varsa ve birindeki tüm özellik adları diğerinde de varsa, aynı özellik kümesine sahiptirler. {{index "return value"}} -Returning the correct value from the function is best done by immediately returning false when a mismatch is found and returning true at the end of the function. +Fonksiyondan doğru değeri döndürmek, bir eşleşme bulunduğunda hemen `false` döndürerek ve fonksiyonun sonunda `true` döndürerek en iyi şekilde yapılır. hint}} diff --git a/05_higher_order.md b/05_higher_order.md index 1dc9d912..4b437442 100644 --- a/05_higher_order.md +++ b/05_higher_order.md @@ -1,12 +1,12 @@ {{meta {load_files: ["code/scripts.js", "code/chapter/05_higher_order.js", "code/intro.js"], zip: "node/html"}}} -# Higher-Order Functions +# Higher-Order Fonksiyonlar {{quote {author: "C.A.R. Hoare", title: "1980 ACM Turing Award Lecture", chapter: true} {{index "Hoare, C.A.R."}} -There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. +Yazılım tasarımını iki şekilde oluşturmak mümkündür: Bir yolu, o kadar basit yapmaktır ki herhangi bir eksiklik olmasın, diğer yolu ise o kadar karmaşık yapmaktır ki açıkça herhangi bir eksiklik olmasın. quote}} @@ -14,11 +14,11 @@ quote}} {{index "program size"}} -A large program is a costly program, and not just because of the time it takes to build. Size almost always involves ((complexity)), and complexity confuses programmers. Confused programmers, in turn, introduce mistakes (_((bug))s_) into programs. A large program then provides a lot of space for these bugs to hide, making them hard to find. +Büyük bir program maliyetli bir programdır ve bunun yalnızca inşa etme süresiyle ilgili olduğunu söylemek yanlış olur. Boyut neredeyse her zaman karmaşıklığı içerir ve karmaşıklık programcıları kafası karıştırır. Kafası karışık olan programcılar da hatalar (bug) eklerler. Büyük bir program, bu hataların gizlenmesi için çok fazla alan sağlar ve onları bulmayı zorlaştırır. {{index "summing example"}} -Let's briefly go back to the final two example programs in the introduction. The first is self-contained and six lines long. +Girişteki son iki örnek programı kısaca gözden geçirelim. İlki kendine özgüdür ve altı satırdır. ``` let total = 0, count = 1; @@ -29,67 +29,67 @@ while (count <= 10) { console.log(total); ``` -The second relies on two external functions and is one line long. +İkincisi iki harici fonksiyona dayanır ve bir satır uzunluğundadır. ``` console.log(sum(range(1, 10))); ``` -Which one is more likely to contain a bug? +Hangisinin hata içerme olasılığı daha yüksektir? {{index "program size"}} -If we count the size of the definitions of `sum` and `range`, the second program is also big—even bigger than the first. But still, I'd argue that it is more likely to be correct. +`sum` ve `range` tanımlarının boyutunu sayarsak, ikinci program da büyüktür - hatta birincisinden daha büyüktür. Ancak yine de, doğru olma olasılığının daha yüksek olduğunu iddia ederim. {{index [abstraction, "with higher-order functions"], "domain-specific language"}} -This is because the solution is expressed in a ((vocabulary)) that corresponds to the problem being solved. Summing a range of numbers isn't about loops and counters. It is about ranges and sums. +Doğru olma olasılığı daha yüksektir çünkü çözüm, çözülen problemle uyumlu bir ((kelime dağarcığıyla)) ifade edilmiştir. Bir sayı aralığının toplanması döngüler ve sayıcılar hakkında değildir. Aralıklar ve toplamlar hakkındadır. -The definitions of this vocabulary (the functions `sum` and `range`) will still involve loops, counters, and other incidental details. But because they are expressing simpler concepts than the program as a whole, they are easier to get right. +Bu kelime dağarcığının tanımları (`sum` ve `range` fonksiyonları) hala döngüler, sayıcılar ve diğer tesadüfi ayrıntılar içerecektir. Ancak, programın tamamından daha basit kavramları ifade ettikleri için anlaşılmaları daha kolaydır. -## Abstraction +## Soyutlama -In the context of programming, these kinds of vocabularies are usually called _((abstraction))s_. Abstractions give us the ability to talk about problems at a higher (or more abstract) level, without getting sidetracked by uninteresting details. +Programlama bağlamında, bu tür kavramlar genellikle ((soyutlama)) olarak adlandırılır. Soyutlamalar, bizi, ilginç olmayan ayrıntılarla uğraştırmadan daha yüksek (veya daha soyut) bir seviyede problemleri tartışma yeteneği verir. {{index "recipe analogy", "pea soup"}} -As an analogy, compare these two recipes for pea soup. The first goes like this: +Bir benzetme olarak, bezelye çorbası için bu iki tarifi karşılaştırın. İlk tarif şöyle: {{quote -Put 1 cup of dried peas per person into a container. Add water until the peas are well covered. Leave the peas in water for at least 12 hours. Take the peas out of the water and put them in a cooking pan. Add 4 cups of water per person. Cover the pan and keep the peas simmering for two hours. Take half an onion per person. Cut it into pieces with a knife. Add it to the peas. Take a stalk of celery per person. Cut it into pieces with a knife. Add it to the peas. Take a carrot per person. Cut it into pieces. With a knife! Add it to the peas. Cook for 10 more minutes. +Her kişi başına 1 su bardağı kuru bezelye bir kaba koyun. Bezelyeler suyla iyi bir şekilde kaplanana kadar su ekleyin. Bezelyeleri en az 12 saat suyun içinde bırakın. Bezelyeleri sudan çıkarın ve bir tencereye koyun. Her kişi başına 4 su bardağı su ekleyin. Tencereyi kapatın ve bezelyelerin kısık ateşte iki saat boyunca kaynamasını sağlayın. Her kişi başına yarım soğan alın. Bir bıçakla parçalara kesin. Bezelyelere ekleyin. Her kişi başına bir sap kereviz alın. Bir bıçakla parçalara kesin. Bezelyelere ekleyin. Her kişi başına bir havuç alın. Parçalara kesin. Bir bıçakla! Bezelyelere ekleyin. 10 dakika daha pişirin. quote}} -And this is the second recipe: +Ve bu da ikinci tarif: {{quote -Per person: 1 cup dried split peas, 4 cups of water, half a chopped onion, a stalk of celery, and a carrot. +Her kişi başına: 1 su bardağı kuru bezelye, 4 su bardağı su, yarım doğranmış soğan, bir sap kereviz ve bir havuç. -Soak peas for 12 hours. Simmer for 2 hours. Chop and add vegetables. Cook for 10 more minutes. +Bezelyeleri 12 saat bekletin. 2 saat kaynatın. Sebzeleri doğrayın ve ekleyin. 10 dakika daha pişirin. quote}} {{index vocabulary}} -The second is shorter and easier to interpret. But you do need to understand a few more cooking-related words such as _soak_, _simmer_, _chop_, and, I guess, _vegetable_. +İkincisi daha kısa ve yorumlaması daha kolaydır. Ancak, _bekletme_, _kaynatma_, _doğrama_ ve sanırım _sebze_ gibi birkaç daha fazla yemekle ilgili kelimeyi anlamanız gerekecek. -When programming, we can't rely on all the words we need to be waiting for us in the dictionary. Thus, we might fall into the pattern of the first recipe—work out the precise steps the computer has to perform, one by one, blind to the higher-level concepts they express. +Programlama yaparken, ihtiyacımız olan tüm kelimelerin sözlükte bizi beklediğine güvenemeyiz. Bu nedenle, birinci tarifin kalıbına düşebiliriz - bilgisayarın adım adım yapması gereken kesin adımları çıkarırken, bunların ifade ettiği daha yüksek düzeydeki kavramlara kör oluruz. {{index abstraction}} -It is a useful skill, in programming, to notice when you are working at too low a level of abstraction. +Programlama yaparken, ne zaman çok düşük veya çok yüksek bir soyutlama seviyesinde çalıştığınızı fark etmek faydalı bir beceridir. -## Abstracting repetition +## Tekrarı soyutlama {{index [array, iteration]}} -Plain functions, as we've seen them so far, are a good way to build abstractions. But sometimes they fall short. +Şimdiye kadar gördüğümüz gibi düz fonksiyonlar, soyutlamalar oluşturmanın iyi bir yoludur. Ancak bazen yetersiz kalabilirler. {{index "for loop"}} -It is common for a program to do something a given number of times. You can write a `for` ((loop)) for that, like this: +Programın belirli bir sayıda bir şey yapması yaygındır. Bunu şöyle bir `for` ((döngüsü)) ile yapabilirsiniz: ``` for (let i = 0; i < 10; i++) { @@ -97,7 +97,7 @@ for (let i = 0; i < 10; i++) { } ``` -Can we abstract "doing something _N_ times" as a function? Well, it's easy to write a function that calls `console.log` _N_ times: +İşlemi "_N_ kez bir şey yapmak" şeklinde soyutlayabilir miyiz? Evet, bir `console.log` ifadesini _N_ kez çağıran bir fonksiyon yazmak oldukça kolaydır. ``` function repeatLog(n) { @@ -111,7 +111,7 @@ function repeatLog(n) { {{indexsee "higher-order function", "function, higher-order"}} -But what if we want to do something other than logging the numbers? Since "doing something" can be represented as a function and functions are just values, we can pass our action as a function value: +Ancak, sayıları görüntülemek dışında başka bir şey yapmak istersek? "bir şey yapmak" bir fonksiyon olarak temsil edilebilir ve fonksiyonlar sadece değerler olduklarına göre, eylemimizi bir fonksiyon değeri olarak iletebiliriz. ```{includeCode: "top_lines: 5"} function repeat(n, action) { @@ -126,7 +126,7 @@ repeat(3, console.log); // → 2 ``` -We don't have to pass a predefined function to `repeat`. Often, it is easier to create a function value on the spot instead: +`repeat` fonksiyonuna önceden tanımlanmış bir fonksiyon geçmek zorunda değiliz. Genellikle, yerinde bir fonksiyon değeri oluşturmak daha kolaydır. ``` let labels = []; @@ -139,17 +139,17 @@ console.log(labels); {{index "loop body", [braces, body], [parentheses, arguments]}} -This is structured a little like a `for` loop—it first describes the kind of loop and then provides a body. However, the body is now written as a function value, which is wrapped in the parentheses of the call to `repeat`. This is why it has to be closed with the closing brace _and_ closing parenthesis. In cases like this example where the body is a single small expression, you could also omit the braces and write the loop on a single line. +Bu, `for` döngüsüne biraz benzeyen bir şekilde yapılandırılmıştır - önce döngü türünü tanımlar, ardından bir gövde sağlar. Ancak, gövde artık bir fonksiyon değeri olarak yazılmıştır ve çağrının parantezleri içine alınmıştır. Bu nedenle kapatılması gereken süslü parantez ve kapanan normal parantezle kapatılmalıdır. Bu örnekte olduğu gibi, gövde tek bir küçük ifade ise süslü parantezleri atlayabilir ve döngüyü tek bir satırda da yazabilirsiniz. -## Higher-order functions +## Higher-order fonksiyonlar {{index [function, "higher-order"], [function, "as value"]}} -Functions that operate on other functions, either by taking them as arguments or by returning them, are called _higher-order functions_. Since we have already seen that functions are regular values, there is nothing particularly remarkable about the fact that such functions exist. The term comes from ((mathematics)), where the distinction between functions and other values is taken more seriously. +Başka fonksiyonlar üzerinde, fonskiyonu argüman olarak alarak ya da fonksiyon döndürerek işlem yapan fonksiyonlara _higher-order fonksiyonlar_ denir. Fonksiyonların sıradan değerler olduğunu zaten gördüğümüze göre, bu tür fonksiyonların varlığıyla ilgili olarak özellikle dikkate değer bir şey fark etmişizdir. Terim ((matematik))ten gelir, burada fonksiyonlar ve diğer değerler arasındaki ayrım daha ciddiye alınır. {{index abstraction}} -Higher-order functions allow us to abstract over _actions_, not just values. They come in several forms. For example, we can have functions that create new functions: +Higher-order fonksiyonlar, sadece değerleri değil _eylemleri_ soyutlamamıza izin verir. Birkaç formda gelirler. Mesela, yeni fonksiyonlar oluşturan fonksiyonlar oluşturabiliriz. ``` function greaterThan(n) { @@ -160,7 +160,7 @@ console.log(greaterThan10(11)); // → true ``` -We can also have functions that change other functions: +Ve diğer fonksiyonları değiştiren fonksiyonlara sahip olabiliriz. ``` function noisy(f) { @@ -176,7 +176,7 @@ noisy(Math.min)(3, 2, 1); // → called with [3, 2, 1] , returned 1 ``` -We can even write functions that provide new types of ((control flow)): +Yeni türlerde ((kontrol akışı)) sağlayan fonksiyonlar bile yazabiliriz. ``` function unless(test, then) { @@ -194,7 +194,7 @@ repeat(3, n => { {{index [array, methods], [array, iteration], "forEach method"}} -There is a built-in array method, `forEach`, that provides something like a `for`/`of` loop as a higher-order function: +`for`/`of` döngüsü gibi bir yapıyı higher-order fonksiyon olarak tanımlayan `forEach` adında yerleşik bir array metodu vardır. ``` ["A", "B"].forEach(l => console.log(l)); @@ -204,20 +204,19 @@ There is a built-in array method, `forEach`, that provides something like a `for {{id scripts}} -## Script data set +## Script data seti -One area where higher-order functions shine is data processing. To process data, we'll need some actual example data. This chapter will use a ((data set)) about scripts—((writing system))s such as Latin, Cyrillic, or Arabic. +Higher-order fonksiyonların parladığı bir alan veri işlemektir. Verileri işlemek için gerçek verilere ihtiyacımız olacak. Bu bölüm, Latin, Kiril veya Arap gibi ((yazı sistemileri)) hakkında((veri seti)) kullanacağız. -Remember ((Unicode)) from [Chapter ?](values#unicode), the system that assigns a number to each character in written language? Most of these characters are associated with a specific script. The standard contains 140 different scripts, of which 81 are still in use today and 59 are historic. +[Bölüm ?'ten](values#unicode) ((Unicode)) sistemini hatırladığınız mı? Şu konuşulan dillerdeki her karaktere bir sayı atayan sistem hani? Bu karakterlerin çoğu bir alfabeyle ilişkilidir. Standart, 140 farklı alfabeyi barındırır - 81'i hala günümüzde kullanılırken 59'u tarihidir. -Though I can fluently read only Latin characters, I appreciate the fact that people are writing texts in at least 80 other writing systems, many of which I wouldn't even recognize. For example, here's a sample of ((Tamil)) handwriting: +Ben sadece Latin karakterlerini akıcı bir şekilde okuyabilirim, ancak insanların en az 80 farklı yazı sistemine ait metinler yazdıklarını takdir ediyorum, bunların çoğunu bile tanımam. Örneğin, işte ((Tamil)) el yazısı örneği: {{figure {url: "img/tamil.png", alt: "A line of verse in Tamil handwriting. The characters are relatively simple, and neatly separated, yet completely different from Latin."}}} -{{index "SCRIPTS data set"}} - -The example ((data set)) contains some pieces of information about the 140 scripts defined in Unicode. It is available in the [coding sandbox](https://eloquentjavascript.net/code#5) for this chapter[ ([_https://eloquentjavascript.net/code#5_](https://eloquentjavascript.net/code#5))]{if book} as the `SCRIPTS` binding. The binding contains an array of objects, each of which describes a script: +{{index "SCRIPTS dataset"}} +Örnek ((data seti)), Unicode'da tanımlanan 140 yazı hakkında bazı bilgiler içerir. Bu, bu bölümde[ ([_https://eloquentjavascript.net/code#5_](https://eloquentjavascript.net/code#5))]{if book} `SCRIPTS` bağlantısı olarak [kod kum havuzunda](https://eloquentjavascript.net/code#5) mevcuttur. Bağlantı, her biri bir alfabeyi tanımlayan nesnelerin bir dizisini içerir. ```{lang: "json"} { @@ -230,17 +229,17 @@ The example ((data set)) contains some pieces of information about the 140 scrip } ``` -Such an object tells us the name of the script, the Unicode ranges assigned to it, the direction in which it is written, the (approximate) origin time, whether it is still in use, and a link to more information. The direction may be `"ltr"` for left to right, `"rtl"` for right to left (the way Arabic and Hebrew text are written), or `"ttb"` for top to bottom (as with Mongolian writing). +Böyle bir nesne, alfabenin adını, ona atanmış Unicode aralıklarını, yazıldığı yönu, (yaklaşık) köken zamanını, hala kullanılıp kullanılmadığını ve daha fazla bilgiye yönlendiren bir bağlantının linkini bize bildirir. Yön, soldan sağa için `"ltr"`, sağdan sola için `"rtl"`(Arapça ve İbranice metinlerin yazıldığı yöntem), veya üstten alta için `"ttb"`(Moğolca yazı gibi) olabilir. {{index "slice method"}} -The `ranges` property contains an array of Unicode character ((range))s, each of which is a two-element array containing a lower bound and an upper bound. Any character codes within these ranges are assigned to the script. The lower ((bound)) is inclusive (code 994 is a Coptic character) and the upper bound is non-inclusive (code 1008 isn't). +`ranges` özelliği, her biri bir alt sınır ve bir üst sınır içeren iki öğeli bir dizi içeren Unicode karakter ((aralık))larının bir dizisini içerir. Bu aralıklar içindeki herhangi bir karakter kodu yazıya atanır. Alt ((sınır)) kapsayıcıdır (kod 994 bir Kıpti karakteridir), üst sınır kapsayıcı değildir (kod 1008 değildir). -## Filtering arrays +## Dizileri filtrelemek {{index [array, methods], [array, filtering], "filter method", [function, "higher-order"], "predicate function"}} -If we want to find the scripts in the data set that are still in use, the following function might be helpful. It filters out elements in an array that don't pass a test. +Veri kümesinde kullanımda olan yazı sistemlerini bulmak istiyorsak, aşağıdaki fonksiyon faydalı olabilir. Bu, bir dizide bir testi geçmeyen öğeleri filtreler. ``` function filter(array, test) { @@ -259,13 +258,13 @@ console.log(filter(SCRIPTS, script => script.living)); {{index [function, "as value"], [function, application]}} -The function uses the argument named `test`, a function value, to fill a "gap" in the computation—the process of deciding which elements to collect. +Fonksiyon, hesaplama içinde bir "boşluk" doldurmak için `test` adlı fonksiyon değerindeki verilen argümanı kullanır. Böylelikle hangi elementi tutmak istediğine karar verir. {{index "filter method", "pure function", "side effect"}} -Note how the `filter` function, rather than deleting elements from the existing array, builds up a new array with only the elements that pass the test. This function is _pure_. It does not modify the array it is given. +Varolan diziden öğeleri silmek yerine, `filter` fonksiyonu, yalnızca testi geçen öğelerle yeni bir dizi oluşturur. Bu işlev \_saf_tır. Verilen diziyi değiştirmez. -Like `forEach`, `filter` is a ((standard)) array method. The example defined the function only to show what it does internally. From now on, we'll use it like this instead: +`forEach` gibi, `filter` bir ((standart)) dizi yöntemidir. Örnek, fonskiyonun içerisinde ne yaptığını göstermek için tanımlanmıştır. Bundan sonra, bunu şu şekilde kullanacağız: ``` console.log(SCRIPTS.filter(s => s.direction == "ttb")); @@ -274,15 +273,15 @@ console.log(SCRIPTS.filter(s => s.direction == "ttb")); {{id map}} -## Transforming with map +## map ile dönüştürmek {{index [array, methods], "map method"}} -Say we have an array of objects representing scripts, produced by filtering the `SCRIPTS` array somehow. We want an array of names instead, which is easier to inspect. +Diyelim ki `SCRIPTS` dizisini filtreleme işlemiyle üretilmiş olan yazı sistemlerini temsil eden nesnelerden bir dizimiz var. Ancak obje dizisi yerine, incelemesi daha kolay olan bir isim dizisi istiyoruz. {{index [function, "higher-order"]}} -The `map` method transforms an array by applying a function to all of its elements and building a new array from the returned values. The new array will have the same length as the input array, but its content will have been _mapped_ to a new form by the function: +`map` yöntemi, tüm öğelerine bir fonksiyon uygulayarak bir diziyi dönüştürür ve döndürülen değerlerden yeni bir dizi oluşturur. Yeni dizi, giriş dizisiyle aynı uzunluğa sahip olacak, ancak içeriği verilen fonksiyon tarafından yeni bir forma _haritalanmış_ olacak. ``` function map(array, transform) { @@ -298,21 +297,21 @@ console.log(map(rtlScripts, s => s.name)); // → ["Adlam", "Arabic", "Imperial Aramaic", …] ``` -Like `forEach` and `filter`, `map` is a standard array method. +`forEach` ve `filter` gibi, `map` bir standart dizi yöntemidir. -## Summarizing with reduce +## reduce aracılığıyla özetleme {{index [array, methods], "summing example", "reduce method"}} -Another common thing to do with arrays is to compute a single value from them. Our recurring example, summing a collection of numbers, is an instance of this. Another example is finding the script with the most characters. +Dizilerle yapılacak başka yaygın bir işlem, onlardan tek bir değer hesaplamaktır. Tekrarlayan bir örnek olan sayılardan oluşan bir dizinin toplamını bulmak, bunun bir örneğidir. Diğer bir örnek ise en fazla karaktere sahip yazıyı bulmaktır. {{indexsee "fold", "reduce method"}} {{index [function, "higher-order"], "reduce method"}} -The higher-order operation that represents this pattern is called _reduce_ (sometimes also called _fold_). It builds a value by repeatedly taking a single element from the array and combining it with the current value. When summing numbers, you'd start with the number zero and, for each element, add that to the sum. +Bu kalıbı temsil eden higher-order işlem _reduce_ (bazen _fold_ olarak da adlandırılır) adını taşır. Bu, bir diziden bir öğeleri tane tane alarak ve mevcut değerle birleştirerek bir değer oluşturur. Sayıları toplarken, sıfır sayısıyla başlayacak ve her öğeyi toplama ekleyeceksiniz. -The parameters to `reduce` are, apart from the array, a combining function and a start value. This function is a little less straightforward than `filter` and `map`, so take a close look at it: +`reduce`'un parametreleri, üzerinden geçilecek dizi dışında birleştirme fonksiyonu ve bir başlangıç değeri gerektirmektedir. Bu fonksiyon `filter`ve `map` fonskiyonlarından daha karmaşıktır, lütfen bu örneği dikkatlice bakın: ``` function reduce(array, combine, start) { @@ -327,9 +326,9 @@ console.log(reduce([1, 2, 3, 4], (a, b) => a + b, 0)); // → 10 ``` -{{index "reduce method", "SCRIPTS data set"}} +{{index "reduce method", "SCRIPTS dataset"}} -The standard array method `reduce`, which of course corresponds to this function, has an added convenience. If your array contains at least one element, you are allowed to leave off the `start` argument. The method will take the first element of the array as its start value and start reducing at the second element. +Standart dizi metodu ve örnekteki fonksiyonalite ile eşleşen `reduce`, ek bir rahatlığa sahiptir. Eğer diziniz en az bir elementten oluşmaktaysa, `start` argümanını kullanmak zorunda değilsiniz. Metod dizideki ilk elementi başlangıç değeri oalrak alır ve değeri döngüye devam ederek indirgemeye ikinci değerden başlar. ``` console.log([1, 2, 3, 4].reduce((a, b) => a + b)); @@ -338,7 +337,7 @@ console.log([1, 2, 3, 4].reduce((a, b) => a + b)); {{index maximum, "characterCount function"}} -To use `reduce` (twice) to find the script with the most characters, we can write something like this: +En çok karakteri barındıran yazı sistemini bulmak adına `reduce` fonksiyonunu kullanarak (ikinci kere) şöyle bir şey yazabiliriz: ``` function characterCount(script) { @@ -353,15 +352,15 @@ console.log(SCRIPTS.reduce((a, b) => { // → {name: "Han", …} ``` -The `characterCount` function reduces the ranges assigned to a script by summing their sizes. Note the use of destructuring in the parameter list of the reducer function. The second call to `reduce` then uses this to find the largest script by repeatedly comparing two scripts and returning the larger one. +`characterCount` fonksiyonu aralıkları boyutları toplayarak indirgemektedir. Parametre listesinde gerçekteştirilen destructuring işlemine dikkat edin. `reduce` fonksiyonuna olan ikinci çağrı bunu kullanarak her iki yazı sistemini karşılaştırarak daha büyük olan yazı sistemini döndürmektedir. -The Han script has more than 89,000 characters assigned to it in the Unicode standard, making it by far the biggest writing system in the data set. Han is a script sometimes used for Chinese, Japanese, and Korean text. Those languages share a lot of characters, though they tend to write them differently. The (US-based) Unicode Consortium decided to treat them as a single writing system to save character codes. This is called _Han unification_ and still makes some people very angry. +Han yazısı, Unicode standardında ona atanan 89.000'den fazla karakterle, veri kümesindeki en büyük yazı sistemidir. Han, bazen Çince, Japonca ve Korece metinlerde kullanılır. Bu diller birçok karakteri paylaşır, ancak genellikle farklı yazılır. (ABD merkezli) Unicode Konsorsiyumu, karakter kodlarını kaydetmek için bunları tek bir yazı sistemi olarak ele almaya karar verdi. Buna _Han birleşimi_ denir ve hala bazı insanları çok kızdırıyor. -## Composability +## Şekillendirilebilirlik {{index loop, maximum}} -Consider how we would have written the previous example (finding the biggest script) without higher-order functions. The code is not that much worse: +Daha önceki örneği (en büyük betiği bulma) higher-order fonksiyonlar olmadan nasıl yazacağımızı düşünelim. Kod pek de kötü değil. ```{test: no} let biggest = null; @@ -375,13 +374,13 @@ console.log(biggest); // → {name: "Han", …} ``` -There are a few more bindings, and the program is four lines longer, but it is still very readable. +Birkaç daha fazla bağlantı var ve program dört satır daha uzun. Ama yine de okunaklı. {{index "average function", composability, [function, "higher-order"], "filter method", "map method", "reduce method"}} {{id average_function}} -The abstractions provided by these functions really shine when you need to _compose_ operations. As an example, let's write code that finds the average year of origin for living and dead scripts in the data set: +Bu fonksiyonlar tarafından sağlanan soyutlamalar, işlemleri _birleştirmeniz_ gerektiğinde gerçekten parlar. Örneğin, veri setindeki yaşayan ve ölü betiklerin ortalama köken yıllarını bulan bir kod yazalım. ``` function average(array) { @@ -396,9 +395,9 @@ console.log(Math.round(average( // → 204 ``` -As you can see, the dead scripts in Unicode are, on average, older than the living ones. This is not a terribly meaningful or surprising statistic. But I hope you'll agree that the code used to compute it isn't hard to read. You can see it as a pipeline: we start with all scripts, filter out the living (or dead) ones, take the years from those, average them, and round the result. +Böylelikle, Unicode'deki ölü betiklerin ortalama olarak yaşayanlardan daha eski olduğunu görüyoruz. Bu çok da anlamlı veya şaşırtıcı bir istatistik değil. Ancak umarım bunun hesaplanmasında kullanılan kodun okunmasının zor olmadığını görmüşüzdür. Onu bir boru hattı olarak görebilirsiniz: tüm betiklerle başlıyoruz, yaşayan (veya ölü) olanları filtreliyoruz, onlardan yılları alıyoruz, bunların ortalamasını alıyoruz ve sonucu yuvarlıyoruz. -You could definitely also write this computation as one big ((loop)): +Bu hesaplamayı kesinlikle tek bir büyük ((döngü)) olarak da yazabilirdiniz. ``` let total = 0, count = 0; @@ -412,19 +411,19 @@ console.log(Math.round(total / count)); // → 1165 ``` -However, it is harder to see what was being computed and how. And because intermediate results aren't represented as coherent values, it'd be a lot more work to extract something like `average` into a separate function. +Ancak hesaplanan şeyin ne olduğunu ve nasıl olduğunu görmek daha zordur. Ve ara sonuçlar tutarlı değerler olarak temsil edilmediğinden, `average` gibi bir şeyi ayrı bir fonksiyona çıkarmak daha zor bir iş olurdu. {{index efficiency, [array, creation]}} -In terms of what the computer is actually doing, these two approaches are also quite different. The first will build up new arrays when running `filter` and `map`, whereas the second computes only some numbers, doing less work. You can usually afford the readable approach, but if you're processing huge arrays and doing so many times, the less abstract style might be worth the extra speed. +Bilgisayarın gerçekte ne yaptığı açısından, bu iki yaklaşım da oldukça farklıdır. İlk yaklaşım, `filter` ve `map` çalıştığında yeni diziler oluştururken, ikincisi sadece bazı sayıları hesaplar, daha az iş yapar. Okunabilir yaklaşımı genellikle seçebilirsiniz ancak devasa dizileri işliyorsanız ve bunu birçok kez yapıyorsanız, daha az soyut tarz, ek hız için değer olabilir. -## Strings and character codes +## Dize ve karakter kodları -{{index "SCRIPTS data set"}} +{{index "SCRIPTS dataset"}} -One interesting use of this data set would be figuring out what script a piece of text is using. Let's go through a program that does this. +Bu veri setinin ilginç bir kullanımı, bir metnin hangi betiği kullandığını bulmak olurdu. Hadi bunu yapan bir programı inceleyelim. -Remember that each script has an array of character code ranges associated with it. Given a character code, we could use a function like this to find the corresponding script (if any): +Her betiğin ilişkilendirilmiş bir karakter kodu aralığı dizisi olduğunu unutmayın. Bunun sayesinde, bir karakter kodu verildiğinde, varsa ilgili betiği bulmak için böyle bir fonksiyon kullanabiliriz: {{index "some method", "predicate function", [array, methods]}} @@ -444,21 +443,21 @@ console.log(characterScript(121)); // → {name: "Latin", …} ``` -The `some` method is another higher-order function. It takes a test function and tells you whether that function returns true for any of the elements in the array. +`some` metodu başka bir higher-order fonksiyondur. Bir test fonksiyonunu alır ve bu fonksiyonun dizideki öğelerden herhangi biri için doğru olup olmadığını size söyler. {{id code_units}} -But how do we get the character codes in a string? +Ancak bir dize içindeki karakter kodlarını nasıl alırız? -In [Chapter ?](values) I mentioned that JavaScript ((string))s are encoded as a sequence of 16-bit numbers. These are called _((code unit))s_. A ((Unicode)) ((character)) code was initially supposed to fit within such a unit (which gives you a little over 65,000 characters). When it became clear that wasn't going to be enough, many people balked at the need to use more memory per character. To address these concerns, ((UTF-16)), the format also used by JavaScript strings, was invented. It describes most common characters using a single 16-bit code unit but uses a pair of two such units for others. +[Bölüm ? içinde](values) belirtildiği gibi JavaScript ((dize))leri, bir dizi 16-bit numarası olarak kodlanmıştır. Bunlar ((kod birimi)) olarak adlandırılır. Bir ((Unicode)) ((karakter)) kodunun başlangıçta böyle bir birime sığması bekleniyordu (bu size birazdan 65.000'in üzerinde karakter verir). Ancak bu yeterli olmayacağını anlaşılınca, birçok kişi karakter başına daha fazla bellek kullanma gereksinimine itiraz etti. Bu endişeleri ele almak için, JavaScript dizeleri tarafından da kullanılan format olan ((UTF-16)) icat edildi. Bu, yaygın olarak kullanılan çoğu karakteri tek bir 16-bit kod birimi kullanarak açıklar, ancak diğerleri için bu birimden iki adet kullanır. {{index error}} -UTF-16 is generally considered a bad idea today. It seems almost intentionally designed to invite mistakes. It's easy to write programs that pretend code units and characters are the same thing. And if your language doesn't use two-unit characters, that will appear to work just fine. But as soon as someone tries to use such a program with some less common ((Chinese characters)), it breaks. Fortunately, with the advent of ((emoji)), everybody has started using two-unit characters, and the burden of dealing with such problems is more fairly distributed. +UTF-16 genellikle bugün kötü bir fikir olarak kabul edilir. Hemen hemen kasıtlı olarak hatalara davet etmek için tasarlanmış gibi görünüyor. Kod birimlerini ve karakterleri aynı şey gibi düşündüren programlar yazmak kolaydır. Ve diliniz iki birimli karakterler kullanmıyorsa, bu çalışır gibi görünecektir. Ancak birisi böyle bir programı bazı daha az yaygın ((Çin karakterleri)) ile kullanmaya çalıştığında, bozulur. Neyse ki, ((emoji))'lerin ortaya çıkmasıyla, herkes iki birimli karakterleri kullanmaya başladı ve bu tür sorunlarla başa çıkmanın yükü daha adil bir şekilde dağıtılmıştır. {{index [string, length], [string, indexing], "charCodeAt method"}} -Unfortunately, obvious operations on JavaScript strings, such as getting their length through the `length` property and accessing their content using square brackets, deal only with code units. +Maalesef, JavaScript dizilerindeki `length` özelliği aracılığıyla uzunluklarını almak ve içeriğine kare parantez kullanarak erişmek gibi işlemler yalnızca kod birimleriyle ilgilenir. ```{test: no} // Two emoji characters, horse and shoe @@ -475,11 +474,11 @@ console.log(horseShoe.codePointAt(0)); {{index "codePointAt method"}} -JavaScript's `charCodeAt` method gives you a code unit, not a full character code. The `codePointAt` method, added later, does give a full Unicode character, so we could use that to get characters from a string. But the argument passed to `codePointAt` is still an index into the sequence of code units. To run over all characters in a string, we'd still need to deal with the question of whether a character takes up one or two code units. +JavaScript'in `charCodeAt` yöntemi size bir kod birimi verir, tam bir karakter kodu vermez. Daha sonra eklenen `codePointAt` metodu, tam bir Unicode karakteri verir. Bu nedenle, bir diziden karakterleri almak için bunu kullanabiliriz. Ancak `codePointAt`'e verilen argüman hala bir kod birimleri dizisine verilen bir indekstir. Bu nedenle, bir dizedeki tüm karakterlerin üzerinden geçmek için hala bir karakterin bir veya iki kod birimi kapladığı sorunuyla ilgilenmemiz gerekir. {{index "for/of loop", character}} -In the [previous chapter](data#for_of_loop), I mentioned that a `for`/`of` loop can also be used on strings. Like `codePointAt`, this type of loop was introduced at a time when people were acutely aware of the problems with UTF-16. When you use it to loop over a string, it gives you real characters, not code units: +[Önceki bölümde](data#for_of_loop), bir `for/of` döngüsünün aynı zamanda dizelerde de kullanılabileceğini belirtmiştim. `codePointAt` gibi, bu tür bir döngü, UTF-16 ile ilgili sorunların farkında olunan bir dönemde tanıtıldı. Bir dize üzerinde döngü yapmak için kullandığınızda, size kod birimleri değil gerçek karakterler verir. ``` let roseDragon = "🌹🐉"; @@ -490,13 +489,13 @@ for (let char of roseDragon) { // → 🐉 ``` -If you have a character (which will be a string of one or two code units), you can use `codePointAt(0)` to get its code. +Eğer bir karakteriniz varsa (ki bu bir veya iki kod birimi uzunluğunda bir dizedir), kodunu almak için `codePointAt(0)` fonksiyonunu kullanabilirsiniz. -## Recognizing text +## Metni tanıma -{{index "SCRIPTS data set", "countBy function", [array, counting]}} +{{index "SCRIPTS dataset", "countBy function", [array, counting]}} -We have a `characterScript` function and a way to correctly loop over characters. The next step is to count the characters that belong to each script. The following counting abstraction will be useful there: +Bir `characterScript` fonksiyonumuz ve karakterler üzerinde doğru bir şekilde döngü yapmanın bir yolu var. Sonraki adım, her betiğe ait karakterlerin sayısını saymaktır. Aşağıdaki sayma soyutlaması burada yararlı olacaktır: ```{includeCode: strip_log} function countBy(items, groupName) { @@ -517,15 +516,15 @@ console.log(countBy([1, 2, 3, 4, 5], n => n > 2)); // → [{name: false, count: 2}, {name: true, count: 3}] ``` -The `countBy` function expects a collection (anything that we can loop over with `for`/`of`) and a function that computes a group name for a given element. It returns an array of objects, each of which names a group and tells you the number of elements that were found in that group. +`countBy` fonksiyonu bir koleksiyon (herhangi bir `for/of` döngüsü ile döngü yapabileceğimiz bir şey) ve bir öğe için bir grup adı hesaplayan bir fonksiyon bekler. Bir grup adını belirten ve bu grupta bulunan öğelerin sayısını söyleyen nesnelerden oluşan bir dizi döndürür. {{index "find method"}} -It uses another array method, `find`, which goes over the elements in the array and returns the first one for which a function returns true. It returns `undefined` when no such element is found. +Başka bir dizi yöntemi olan `find` kullanır. Bu yöntem, dizideki öğeleri gezinir ve verilen fonksiyonun true döndürdüğü ilk öğeyi döndürür. Böyle bir öğe bulunamadığında `undefined` döndürür. {{index "textScripts function", "Chinese characters"}} -Using `countBy`, we can write the function that tells us which scripts are used in a piece of text: +`countBy` kullanarak, bir metinde hangi betiklerin kullanıldığını söyleyen fonksiyonu yazabiliriz. ```{includeCode: strip_log, startCode: true} function textScripts(text) { @@ -548,47 +547,48 @@ console.log(textScripts('英国的狗说"woof", 俄罗斯的狗说"тяв"')); {{index "characterScript function", "filter method"}} -The function first counts the characters by name, using `characterScript` to assign them a name and falling back to the string `"none"` for characters that aren't part of any script. The `filter` call drops the entry for `"none"` from the resulting array since we aren't interested in those characters. +Fonksiyon önce karakterleri adlarına göre sayar, onlara bir isim atamak için `characterScript`'i kullanır ve herhangi bir betiğin parçası olmayan karakterler için `"none"` dizesini kullanır. `filter` çağrısı, sonuç dizisinden `"none"` girişlerini bu karakterlerle ilgilenmediğimiz için ayıklar. {{index "reduce method", "map method", "join method", [array, methods]}} -To be able to compute ((percentage))s, we first need the total number of characters that belong to a script, which we can compute with `reduce`. If no such characters are found, the function returns a specific string. Otherwise it transforms the counting entries into readable strings with `map` and then combines them with `join`. +((Yüzde))lerin hesaplanabilmesi için öncelikle bir betiğe ait toplam karakter sayısına ihtiyacımız var, bunu `reduce` ile hesaplayabiliriz. Eğer böyle bir karakter bulunmazsa, fonksiyon belirli bir dize döndürür. Aksi takdirde, sayma girişlerini `map` kullanarak okunabilir dizelere dönüştürür ve ardından bunları `join` ile birleştirir. -## Summary +## Özet -Being able to pass function values to other functions is a deeply useful aspect of JavaScript. It allows us to write functions that model computations with "gaps" in them. The code that calls these functions can fill in the gaps by providing function values. +Başka fonksiyon değerlerini diğer fonksiyonlara argüman olarka verebilmek, JavaScript'in derinlemesine kullanışlı bir yönüdür. Bu, aralarında "boşluklar" olan hesaplamaları modelleyen fonksiyonlar yazmamıza olanak tanır. Bu fonksiyonları çağıran kod, fonksiyon değerlerini sağlayarak boşlukları doldurabilir. -Arrays provide a number of useful higher-order methods. You can use `forEach` to loop over the elements in an array. The `filter` method returns a new array containing only the elements that pass the ((predicate function)). Transforming an array by putting each element through a function is done with `map`. You can use `reduce` to combine all the elements in an array into a single value. The `some` method tests whether any element matches a given predicate function, while `find` finds the first element that matches a predicate. +Diziler bir dizi kullanışlı higher-order metodlar sağlar. Bir dizideki öğeler üzerinde döngü yapmak için `forEach` kullanabilirsiniz. `filter` yöntemi, yalnızca ((test fonksiyonundan)) true değeriyle geçen öğeleri içeren yeni bir dizi döndürür. Her bir öğeyi bir işlemden geçirerek bir diziyi dönüştürmek için `map` kullanılır. Bir dizi içindeki tüm öğeleri birleştirmek bir değer elde etmek için `reduce` kullanabilirsiniz. `some` yöntemi, belirli bir test fonksiyonundan true değerini alan herhangi bir öğe olup olmadığını test eder. Ve `find`, bir test fonksiyonunu karşılayan ilk öğeyi bulur. -## Exercises +## Egzersizler -### Flattening +### Düzleştirme {{index "flattening (exercise)", "reduce method", "concat method", [array, flattening]}} -Use the `reduce` method in combination with the `concat` method to "flatten" an array of arrays into a single array that has all the elements of the original arrays. +Dizi içinde olan dizilerin tüm öğelerini içeren bir diziyi düzleştirerek oluşturabilmek için `reduce` yöntemini `concat` yöntemiyle beraber kullanın. {{if interactive ```{test: no} let arrays = [[1, 2, 3], [4, 5], [6]]; -// Your code here. +// Kodunuz buraya. // → [1, 2, 3, 4, 5, 6] ``` + if}} -### Your own loop +### Kendi döngün {{index "your own loop (example)", "for loop"}} -Write a higher-order function `loop` that provides something like a `for` loop statement. It should take a value, a test function, an update function, and a body function. Each iteration, it should first run the test function on the current loop value and stop if that returns false. It should then call the body function, giving it the current value, then finally call the update function to create a new value and start over from the beginning. +Bir `loop` adlı bir higher-order fonksiyon yazın ki bu fonksiyon, bir `for` döngüsü ifadesine benzer bir işlev sağlasın. Bir değer, bir test fonksiyonu, bir güncelleme fonksiyonu ve bir gövde fonksiyonunu parametre olarak almasını sağlayın. Her döngüde, önce mevcut döngü değerinde test fonksiyonunu çalıştırır ve bu yanıtın false döndüğü durumda durur. Ardından, mevcut değeri vererek gövde fonksiyonunu çağırır. Son olarak, yeni bir değer oluşturmak için güncelleme fonksiyonunu çağırır ve baştan başlar. -When defining the function, you can use a regular loop to do the actual looping. +Fonksiyonu tanımlarken gerçek döngüyü yapmak için normal bir döngü kullanabilirsiniz. {{if interactive ```{test: no} -// Your code here. +// Kodunuz buraya. loop(3, n => n > 0, n => n - 1, console.log); // → 3 @@ -598,19 +598,19 @@ loop(3, n => n > 0, n => n - 1, console.log); if}} -### Everything +### Her şey {{index "predicate function", "everything (exercise)", "every method", "some method", [array, methods], "&& operator", "|| operator"}} -Arrays also have an `every` method analogous to the `some` method. This method returns true when the given function returns true for _every_ element in the array. In a way, `some` is a version of the `||` operator that acts on arrays, and `every` is like the `&&` operator. +`some` metoduna benzer şekilde, dizilerin bir de `every` yöntemi vardır. Bu, verilen fonksiyonun dizideki _her öğe_ için true döndüğünde true döndürür. Bir bakıma, `some`, diziler üzerinde çalışan `||` operatörünün bir versiyonu gibidir ve `every` ise `&&` operatörüne benzer. -Implement `every` as a function that takes an array and a predicate function as parameters. Write two versions, one using a loop and one using the `some` method. +`every` metodunu bir dizi ve bir test fonksiyonunu parametre olarak alan bir fonksiyon yazarak uygulayın. Bir döngü kullanan ve bir de `some` yöntemini kullanan iki versiyon yazın. {{if interactive ```{test: no} function every(array, test) { - // Your code here. + // Kodunuz buraya. } console.log(every([1, 3, 5], n => n < 10)); @@ -627,27 +627,27 @@ if}} {{index "everything (exercise)", "short-circuit evaluation", "return keyword"}} -Like the `&&` operator, the `every` method can stop evaluating further elements as soon as it has found one that doesn't match. So the loop-based version can jump out of the loop—with `break` or `return`—as soon as it runs into an element for which the predicate function returns false. If the loop runs to its end without finding such an element, we know that all elements matched and we should return true. +`&&` operatörü gibi, `every` metodu, eşleşmeyen bir öğe bulur bulmaz daha fazla öğeyi değerlendirmeyi durdurabilir. Bu nedenle, döngü tabanlı versiyon, test fonksiyonunun false döndürdüğü bir öğe ile karşılaştığında döngüden çıkabilir—`break` veya `return` kullanarak. Döngü, böyle bir öğe bulmadan sonuna kadar çalışırsa, tüm öğelerin eşleştiğini ve `true` döndürmemiz gerektiğini biliriz. -To build `every` on top of `some`, we can apply _((De Morgan's laws))_, which state that `a && b` equals `!(!a || !b)`. This can be generalized to arrays, where all elements in the array match if there is no element in the array that does not match. +`every` metodunu `some` üzerine inşa etmek için, _De Morgan kanunlarını_ uygulayabiliriz, bu, `a && b`'nin `!(!a || !b)` ifadesine eşit olduğunu belirtir. Bu, dizide hiç eşleşmeyen bir öğe yoksa dizideki tüm öğelerin eşleştiği diziler için genelleştirilebilir. hint}} -### Dominant writing direction +### Baskın yazma yönü -{{index "SCRIPTS data set", "direction (writing)", "groupBy function", "dominant direction (exercise)"}} +{{index "SCRIPTS dataset", "direction (writing)", "groupBy function", "dominant direction (exercise)"}} -Write a function that computes the dominant writing direction in a string of text. Remember that each script object has a `direction` property that can be `"ltr"` (left to right), `"rtl"` (right to left), or `"ttb"` (top to bottom). +Metin içindeki baskın yazma yönünü hesaplayan bir fonksiyon yazın. Unutmayın ki her betik nesnesinin bir `direction` özelliği vardır ve bu `"ltr"` (soldan sağa), `"rtl"` (sağdan sola) veya `"ttb"` (üstden alta) olabilir. {{index "characterScript function", "countBy function"}} -The dominant direction is the direction of a majority of the characters that have a script associated with them. The `characterScript` and `countBy` functions defined earlier in the chapter are probably useful here. +Baskın yön, betiği olan karakterlerin çoğunluğunun yönüdür. Bölümde önceden tanımlanan `characterScript` ve `countBy` fonksiyonları burada muhtemelen kullanışlı olacaktır. {{if interactive ```{test: no} function dominantDirection(text) { - // Your code here. + // Kodunuz buraya. } console.log(dominantDirection("Hello!")); @@ -655,16 +655,17 @@ console.log(dominantDirection("Hello!")); console.log(dominantDirection("Hey, مساء الخير")); // → rtl ``` + if}} {{hint {{index "dominant direction (exercise)", "textScripts function", "filter method", "characterScript function"}} -Your solution might look a lot like the first half of the `textScripts` example. You again have to count characters by a criterion based on `characterScript` and then filter out the part of the result that refers to uninteresting (script-less) characters. +Çözümünüz, `textScripts` örneğinin ilk yarısına çok benzeyebilir. Yine, `characterScript` fonksiyonuna dayalı bir kriterle karakterları saymanız ve ardından ilginç olmayan (betiksiz) karakterleri filtrelemeniz gerekecektir. {{index "reduce method"}} -Finding the direction with the highest character count can be done with `reduce`. If it's not clear how, refer to the example earlier in the chapter, where `reduce` was used to find the script with the most characters. +En fazla karakter sayısına sahip yönu bulmak için `reduce` kullanılabilir. Nasıl yapılacağı açık değilse, bölümde daha önce en fazla karaktere sahip betiği bulmak için kullanılan `reduce` örneğine başvurun. hint}} diff --git a/06_object.md b/06_object.md index f1d9e228..bd1b1944 100644 --- a/06_object.md +++ b/06_object.md @@ -1,49 +1,51 @@ {{meta {load_files: ["code/chapter/06_object.js"], zip: "node/html"}}} -# The Secret Life of Objects +# Nesnelerin Gizli Yaşamı {{quote {author: "Barbara Liskov", title: "Programming with Abstract Data Types", chapter: true} -An abstract data type is realized by writing a special kind of program […] which defines the type in terms of the operations which can be performed on it. +Bir soyut veri türü, üzerinde gerçekleştirilebilecek işlemler açısından türü tanımlayan bir programı […] yazarak gerçekleştirilir. quote}} {{index "Liskov, Barbara", "abstract data type"}} -{{figure {url: "img/chapter_picture_6.jpg", alt: "Illustration of a rabbit next to its prototype, a schematic representation of a rabbit", chapter: framed}}} +{{figure {url: "img/chapter_picture_6.jpg", alt: "Bir tavşanın prototipinin yanında bir tavşanın şematik temsili resmi", chapter: framed}}} -[Chapter ?](data) introduced JavaScript's objects as containers that hold other data. +[Chapter ?](data) introduced JavaScript's objects, as containers that hold other data. -In programming culture, _((object-oriented programming))_ is a set of techniques that use objects as the central principle of program organization. Though no one really agrees on its precise definition, object-oriented programming has shaped the design of many programming languages, including JavaScript. This chapter describes the way these ideas can be applied in JavaScript. +Programlama kültüründe, _((nesne yönelimli programlama))_ adında bir şey var, nesneleri program organizasyonunun merkezi prensibi olarak kullanan bir teknik seti. Kesin tanımı hakkında herkes gerçekten anlaşmıyor olsa da, nesne yönelimli programlama birçok programlama dilinin tasarımını şekillendirmiştir, bunlar arasında JavaScript de bulunur. Bu bölüm, bu fikirlerin JavaScript'te nasıl uygulanabileceğini açıklanmaktadır. -## Abstract Data Types +## Soyut Veri Türleri {{index "abstract data type", type, "mixer example"}} -The main idea in object-oriented programming is to use objects, or rather _types_ of objects, as the unit of program organization. Setting up a program as a number of strictly separated object types provides a way to think about its structure and thus to enforce some kind of discipline, preventing everything from becoming entangled. +Nesne yönelimli programlamadaki ana fikir, nesneleri veya daha doğrusu nesne türlerini, program organizasyonunun birimi olarak kullanmaktır. Programı birkaç sıkı şekilde ayrılmış nesne türü olarak ayarlamak, yapısını düşünmenin bir yolunu sağlar ve böylece her şeyin karışmasını önleyerek bir tür disiplin uygular. -The way to do this is to think of objects somewhat like you'd think of an electric mixer or other consumer ((appliance)). The people who design and assemble a mixer have to do specialized work requiring material science and understanding of electricity. They cover all that up in a smooth plastic shell so that the people who only want to mix pancake batter don't have to worry about all that—they only have to understand the few knobs that the mixer can be operated with. +Bunu yapmanın yolu, nesneleri bir elektrikli mikser veya diğer tüketici ((alet)) gibi düşünmektir. Bir mikser tasarlayan ve monte eden insanlar vardır ve bunlar malzeme bilimi ve elektrik anlayışı gerektiren özelleşmiş işleri yapmak zorundadır. Tüm bunları pürüzsüz bir plastik kabuk içine kapatırlar, böylece sadece pancake hamurunu karıştırmak isteyen insanların bunlarla ilgilenmesine gerek kalmaz—sadece mikserin çalıştırılabilmesi için birkaç düğmeyi anlamaları yeterlidir. {{index "class"}} -Similarly, an _abstract data type_, or _object class_, is a subprogram that may contain arbitrarily complicated code but exposes a limited set of methods and properties that people working with it are supposed to use. This allows large programs to be built up out of a number of appliance types, limiting the degree to which these different parts are entangled by requiring them to only interact with each other in specific ways. +Benzer şekilde, bir soyut veri türü veya nesne sınıfı, onunla çalışan kişilerin kullanması gereken sınırlı bir yöntem ve özellik setini açığa çıkarabilen, ancak karmaşık kod içerebilen bir alt programdır. Bu, büyük programların birçok alet türü üzerine kurulabilmesine olanak tanır ve bu farklı parçaların sadece belirli yollarla birbirleriyle etkileşime girmesini gerektirerek bu parçaların birbirleriyle karışmasını sınırlar. {{index encapsulation, isolation, modularity}} -If a problem is found in one such object class, it can often be repaired or even completely rewritten without impacting the rest of the program. Even better, it may be possible to use object classes in multiple different programs, avoiding the need to recreate their functionality from scratch. You can think of JavaScript's built-in data structures, such as arrays and strings, as such reusable abstract data types. +Eğer bir nesne sınıfında bir problem bulunursa, genellikle bu, programın geri kalanını etkilemeden onarılabilir veya tamamen yeniden yazılabilir. + +Daha da iyisi, farklı programlardaki birden çok nesne sınıflarını kullanmak mümkün olabilir, bu da bunların işlevselliğini baştan başlatmaya gerek kalmadan kullanılabilir hale getirir. JavaScript'in dahili veri yapılarını, diziler ve dizeler gibi, böyle yeniden kullanılabilir soyut veri türleri olarak düşünebilirsiniz. {{id interface}} {{index [interface, object]}} -Each abstract data type has an _interface_, the collection of operations that external code can perform on it. Even basic things like numbers can be thought of as an abstract data type whose interface allows us to add them, multiply them, compare them, and so on. In fact, the fixation on single _objects_ as the main unit of organization in classical object-oriented programming is somewhat unfortunate, since useful pieces of functionality often involve a group of different object classes working closely together. +Her soyut veri türünün bir _arayüzü_ vardır, bu dış kodun onun üzerinde gerçekleştirebileceği işlemlerin koleksiyonudur. Sayılar gibi temel şeyler bile, onları ekleyebilme, çarpabilme, karşılaştırabilme gibi işlemleri gerçekleştirebileceğimiz bir arayüz olarak düşünülebilir. Aslında, klasik nesne yönelimli programlamada ana organizasyon birimi olarak tek _nesnelerin_ odaklanılması biraz talihsizdir çünkü sıklıkla kullanışlı işlev parçaları bir grup farklı nesne sınıfının bir araya gelmesiyle gerçekleşmektedir. {{id obj_methods}} -## Methods +## Metodlar {{index "rabbit example", method, [property, access]}} -In JavaScript, methods are nothing more than properties that hold function values. This is a simple method: +JavaScript'te metodlar, yalnızca fonksiyon değerlerini tutan özelliklerdir. Bu, basit bir metottur: ```{includeCode: "top_lines:6"} function speak(line) { @@ -60,24 +62,24 @@ hungryRabbit.speak("Got any carrots?"); {{index "this binding", "method call"}} -Typically a method needs to do something with the object on which it was called. When a function is called as a method—looked up as a property and immediately called, as in `object.method()`—the binding called `this` in its body automatically points at the object on which it was called. +Tipik olarak, bir yöntem, üzerinde çağrıldığı nesneyle bir şeyler yapması gerekir. Bir işlev bir yöntem olarak çağrıldığında—`object.method()` ifadesinde de olduğu gibi bir özellik aranıp çağırılır— `this` adlı bağlantı çağırılan fonksiyonun vücudu içinde otomatik olarak çağrıldığı nesneye işaret eder. {{id call_method}} {{index "call method"}} -You can think of `this` as an extra ((parameter)) that is passed to the function in a different way than regular parameters. If you want to provide it explicitly, you can use a function's `call` method, which takes the `this` value as its first argument and treats further arguments as normal parameters. +`this` değerini, normal parametrelerden farklı bir şekilde bir fonskiyona verilen bir ek ((parametre)) olarak düşünebilirsiniz. Açıkça sağlamak isterseniz, bir fonksiyonun `call` metodunu kullanabilirsiniz, bu yöntem `this` değerini ilk argümanı olarak alır ve diğer argümanları normal parametreler olarak işler. ``` speak.call(whiteRabbit, "Hurry"); // → The white rabbit says 'Hurry' ``` -Since each function has its own `this` binding whose value depends on the way it is called, you cannot refer to the `this` of the wrapping scope in a regular function defined with the `function` keyword. +Her fonksiyonun, değeri nasıl çağrıldığına bağlı olan kendi `this` bağlantısı olduğundan, bir `function` anahtar sözcüğü ile tanımlanan sıradan bir fonksiyonda kapsamın dışındaki `this` değerine başvuramazsınız. {{index "this binding", "arrow function"}} -Arrow functions are different—they do not bind their own `this` but can see the `this` binding of the scope around them. Thus, you can do something like the following code, which references `this` from inside a local function: +Ok fonksiyonları farklıdır—kendi `this` değerlerini bağlamazlar, ancak etraflarındaki kapsamın `this` bağlamını görebilirler. Bu nedenle, yerel bir fonksiyonun içinden `this` değerine ulaşan aşağıdaki gibi bir kod yazabilirsiniz: ``` let finder = { @@ -90,21 +92,21 @@ console.log(finder.find([4, 5])); // → true ``` -A property like `find(array)` in an object expression is a shorthand way of defining a method. It creates a property called `find` and gives it a function as its value. +Nesne ifadesindeki `find(array)` gibi bir özellik, bir metod tanımlamanın kısa yoludur. `find` adında bir özellik oluşturur ve değeri olarak bir fonksiyon verir. -If I had written the argument to `some` using the `function` keyword, this code wouldn't work. +Eğer `some` metoduna geçirilen argümanı `function` anahtar kelimesini kullanarak yazmış olsaydım, bu kod çalışmazdı. {{id prototypes}} -## Prototypes +## Prototipler -One way to create a rabbit object type with a `speak` method would be to create a helper function that has a rabbit type as parameter and returns an object holding that as its `type` property and our speak function in its `speak` property. +Bir `speak` metoduna sahip soyut bir tavşan türü oluşturmanın bir yolu, tavşan türünü parametre olarak alan ve bu türün tip özelliği ve konuşma fonksiyonunu içeren bir nesneyi döndüren bir yardımcı fonksiyon oluşturmaktır. -All rabbits share that same method. Especially for types with many methods, it would be nice if there was a way to keep a type's methods in a single place, rather than adding them to each object individually. +Tüm tavşanlar aynı yöntemi paylaşırlar. Özellikle çok sayıda metoda sahip türler için, bir türün yöntemlerini her nesneye ayrı ayrı eklemek yerine tek bir yerde tutmanın bir yolu olsa iyi olurdu. {{index [property, inheritance], [object, property], "Object prototype"}} -In JavaScript, _((prototype))s_ are the way to do that. Objects can be linked to other objects, to magically get all the properties that other object has. Plain old objects created with `{}` notation are linked to an object called `Object.prototype`. +JavaScript'te, _((prototipler))_ bunu yapmanın yoludur. Nesneler, diğer nesnelere bağlanarak diğer nesnenin sahip olduğu tüm özellikleri sihirli bir şekilde alabilirler. `{}` gösterimiyle oluşturulan normal nesneler, `Object.prototype` olarak adlandırılan bir nesneye bağlıdır. {{index "toString method"}} @@ -116,9 +118,9 @@ console.log(empty.toString()); // → [object Object] ``` -It looks like we just pulled a property out of an empty object. But in fact, `toString` is a method stored in `Object.prototype`, meaning it is available in most objects. +Boş bir nesneden bir özellik çıkardık gibi görünüyor. Ancak aslında `toString`, `Object.prototype` içinde depolanan bir yöntemdir, bu da çoğu nesnede mevcut olduğu anlamına gelir. -When an object gets a request for a property that it doesn't have, its prototype will be searched for the property. If that doesn't have it, the _prototype's_ prototype is searched, and so on until an object without prototype is reached (`Object.prototype` is such an object). +Bir nesne sahip olmadığı bir özelliğe istek aldığında, prototipi içinde bu özellik aranır. Eğer o prototip de bu özelliğe sahip değilse, _onun da_ prototipi aranır ve `Object.prototype` gibi artık bir prototip barındırmayan objeye kadar bu arama devam eder. ``` console.log(Object.getPrototypeOf({}) == Object.prototype); @@ -129,11 +131,11 @@ console.log(Object.getPrototypeOf(Object.prototype)); {{index "getPrototypeOf function"}} -As you'd guess, `Object.getPrototypeOf` returns the prototype of an object. +Tahmin edebileceğiniz gibi, `Object.getPrototypeOf` bir nesnenin prototipini döndürür. {{index inheritance, "Function prototype", "Array prototype", "Object prototype"}} -Many objects don't directly have `Object.prototype` as their ((prototype)) but instead have another object that provides a different set of default properties. Functions derive from `Function.prototype` and arrays derive from `Array.prototype`. +Birçok nesnenin ((prototipi)) olarak doğrudan `Object.prototype`'a sahip olmadığı, ancak farklı bir varsayılan özellik kümesi sağlayan başka bir nesneye sahip olduğu durumlar vardır. Fonksiyonlar `Function.prototype`'tan, diziler ise `Array.prototype`'tan türemiştir. ``` console.log(Object.getPrototypeOf(Math.max) == @@ -145,11 +147,11 @@ console.log(Object.getPrototypeOf([]) == Array.prototype); {{index "Object prototype"}} -Such a prototype object will itself have a prototype, often `Object.prototype`, so that it still indirectly provides methods like `toString`. +Bu tür bir prototip nesnesinin kendisinin de genellikle `Object.prototype` gibi bir prototipi olacaktır ki böylece hala `toString` gibi yöntemlere erişim sağlayabilsin. {{index "rabbit example", "Object.create function"}} -You can use `Object.create` to create an object with a specific ((prototype)): +Belirli bir ((prototip)) ile bir nesne oluşturmak için `Object.create`'i kullanabilirsiniz. ```{includeCode: "top_lines: 7"} let protoRabbit = { @@ -165,23 +167,23 @@ blackRabbit.speak("I am fear and darkness"); {{index "shared property"}} -The "proto" rabbit acts as a container for the properties shared by all rabbits. An individual rabbit object, like the black rabbit, contains properties that apply only to itself—in this case its type—and derives shared properties from its prototype. +"proto" tavşanı, tüm tavşanlar tarafından paylaşılan özellikleri içeren bir konteyner olarak davranır. Bir bireysel tavşan nesnesi, kendisine sadece kendi üzerine uygulanan özellikleri içerir—bu durumda tipi—ve paylaşılan özellikleri prototipinden türetir. {{id classes}} -## Classes +## Class'lar {{index "object-oriented programming", "abstract data type"}} -JavaScript's ((prototype)) system can be interpreted as a somewhat free-form take on abstract data types or ((class))es. A _class_ defines the shape of a type of object—what methods and properties it has. Such an object is called an _((instance))_ of the class. +JavaScript'in ((prototip)) sistemi, soyut veri tipleri veya ((sınıf))larının biraz serbest bir şekilde ele alınmış hali olarak yorumlanabilir. Bir sınıf, bir nesne türünün şeklini tanımlar—hangi yöntemlere ve özelliklere sahip olduğunu belirtir. Bu tür bir nesne, sınıfın bir ((örneği)) olarak adlandırılır. {{index [property, inheritance]}} -Prototypes are useful for defining properties for which all instances of a class share the same value. Properties that differ per instance, such as our rabbits' `type` property, need to be stored directly in the objects themselves. +Prototipler, bir sınıfın tüm örneklerinin aynı değere sahip olmasını istediğiniz özelliklerin tanımlanması için kullanışlıdır. Örneğin tavşanlarımızın tip özelliği gibi örnek başına farklı olan özellikler, doğrudan nesnelerin kendilerinde saklanmalıdır. {{id constructors}} -To create an instance of a given class, you have to make an object that derives from the proper prototype, but you _also_ have to make sure it itself has the properties that instances of this class are supposed to have. This is what a _((constructor))_ function does. +Belirli bir sınıfın bir örneğini oluşturmak için, uygun prototipten türeyen bir nesne yapmak zorundasınız, ancak ayrıca, kendisinin de bu sınıfın örneklerinin sahip olması gereken özelliklere sahip olduğundan emin olmanız gerekir. Bu, bir ((constructor)) fonksiyonun ne yaptığını gösterir. ``` function makeRabbit(type) { @@ -191,7 +193,7 @@ function makeRabbit(type) { } ``` -JavaScript's ((class)) notation makes it easier to define this type of function, along with a ((prototype)) object. +JavaScript'in ((sınıf)) notasyonu, bu tür bir fonksiyonu tanımlamayı ((prototip)) nesnesiyle kolaylaştırır. {{index "rabbit example", constructor}} @@ -208,17 +210,17 @@ class Rabbit { {{index "prototype property", [braces, class]}} -The `class` keyword starts a ((class declaration)), which allows us to define a constructor and a set of methods together. Any number of methods may be written inside the declaration's braces. This code has the effect of defining a binding called `Rabbit`, which holds a function that runs the code in `constructor` and has a `prototype` property which holds the `speak` method. +`class` anahtar kelimesi, bir ((sınıf bildirimi)) başlatır ve bir constructor ve bir dizi yöntemi bir arada tanımlamamıza olanak tanır. Bildirimin parantezleri içinde herhangi bir sayıda yöntem yazılabilir. Bu kod, `constructor` içindeki kodu çalıştıran ve `speak` yöntemini içeren bir `prototype` özelliğini tutan Rabbit adında bir bağlantı tanımlar. {{index "new operator", "this binding", [object, creation]}} -This function cannot be called like a normal function. Constructors, in JavaScript, are called by putting the keyword `new` in front of them. Doing so creates a fresh instance object whose prototype is the object from the function's `prototype` property, then runs the function with `this` bound to the new object, and finally returns the object. +Bu fonksiyon normal bir şekilde çağrılamaz. JavaScript'te, constructor'ları çağırmak için önlerine `new` anahtar kelimesini koymak gerekir. Bunu yapınca, fonksiyonun `prototype` özelliğini prototip olarak barındıran yeni bir obje oluşturulur ve fonksiyonun `this` bağlamını bu yeni oluşturulan objeye bağlayarak fonksiyonu çağırır, son olarak objeyi döndürür. ```{includeCode: true} let killerRabbit = new Rabbit("killer"); ``` -In fact, `class` was only introduced in the 2015 edition of JavaScript. Any function can be used as a constructor, and before 2015, the way to define a class was to write a regular function and then manipulate its `prototype` property. +Aslında, `class` JavaScript'in 2015 versiyonunda tanıtıldı. Herhangi bir fonksiyon bir constructor olarak kullanılabilir, ki zaten 2015'ten önce class tanımlamanın yolu normal bir fonksiyon yazıp ardından onun prototype özelliğini manipüle etmekti. ``` function ArchaicRabbit(type) { @@ -230,15 +232,15 @@ ArchaicRabbit.prototype.speak = function(line) { let oldSchoolRabbit = new ArchaicRabbit("old school"); ``` -For this reason, all non-arrow functions start with a `prototype` property holding an empty object. +Ok notasyonunda yazılmayan tüm fonksiyonların boş bir obje barındıran `prototype` özelliğiyle başlamasının sebebi budur. {{index capitalization}} -By convention, the names of constructors are capitalized so that they can easily be distinguished from other functions. +Geleneksel olarak, constructor adları diğer fonksiyonlardan kolayca ayırt edilebilmeleri için büyük harfle yazılır. {{index "prototype property", "getPrototypeOf function"}} -It is important to understand the distinction between the way a prototype is associated with a constructor (through its `prototype` property) and the way objects _have_ a prototype (which can be found with `Object.getPrototypeOf`). The actual prototype of a constructor is `Function.prototype` since constructors are functions. The constructor function's `prototype` _property_ holds the prototype used for instances created through it. +Bir ((prototipin)) bir constructor ile ilişkilendirilme şekli (onun prototype _özelliği_ aracılığıyla) ve bir nesnenin zaten var olan prototipi(bu, `Object.getPrototypeOf` ile bulunabilir) arasındaki farkı anlamanız önemlidir. Bir constructor gerçek prototipi, constructor'lar fonksiyon olduklarından ötürü `Function.prototype`'dır. `prototype` _özelliği_, bunun aracılığıyla oluşturulan örnekler için kullanılan prototipi tutar. ``` console.log(Object.getPrototypeOf(Rabbit) == @@ -251,7 +253,7 @@ console.log(Object.getPrototypeOf(killerRabbit) == {{index constructor}} -Constructors will typically add some per-instance properties to `this`. It is also possible to declare properties directly in the ((class declaration)). Unlike methods, such properties are added to ((instance)) objects, not the prototype. +Constructor'lar, genellikle `this`'e örnek başı değer atanacak birkaç özellik ekler. Özellikleri ayrıca ((sınıf bildirimi)) içinde doğrudan bildirmek de mümkündür. Metodların aksine, böyle özellikler ((örnek)) nesnelere eklenir, prototipe değil. ``` class Particle { @@ -262,7 +264,7 @@ class Particle { } ``` -Like `function`, `class` can be used both in statements and in expressions. When used as an expression, it doesn't define a binding but just produces the constructor as a value. You are allowed to omit the class name in a class expression. +`function` gibi, `class` hem beyanlarda hem de ifadelerde kullanılabilir. Bir ifade olarak kullanıldığında, bir bağlantı tanımlamaz, ancak sadece constructor'ı bir değer olarak üretir. Bir sınıf ifadesinde sınıf adının atlanması mümkündür. ``` let object = new class { getWord() { return "hello"; } }; @@ -270,16 +272,15 @@ console.log(object.getWord()); // → hello ``` - -## Private Properties +## Özel Özellikler {{index [property, private], [property, public], "class declaration"}} -It is common for classes to define some properties and ((method))s for internal use that are not part of their ((interface)). These are called _private_ properties, as opposed to _public_ ones, which are part of the object's external interface. +Sınıfların iç kullanım için ((arayüzlerinin)) bir parçası olmayan bazı özellik ve ((metodlar)) oluşturması yaygındır. Bunlara arayüzün parçası olan _public_ özelliklerin aksine _private_ özellikler denir. {{index [method, private]}} -To declare a private method, put a `#` sign in front of its name. Such methods can only be called from inside the `class` declaration that defines them. +Private metod tanımlamak için isminin başına `#` işareti koy. Bu metodlar sadece onları tanımlayan sınıf içerisinden çağırılabilir. ``` class SecretiveObject { @@ -293,13 +294,11 @@ class SecretiveObject { } ``` -When a class does not declare a constructor, it will automatically get an empty one. +Eğer `#getSecret`'ı sınıf dışından çağımaya çalışırsan bir hata alırsın çünkü onun varlığı sıvıf içerisinde tamamen dış dünyadan saklıdır. -If you try to call `#getSecret` from outside the class, you get an error. Its existence is entirely hidden inside the class declaration. +Private örnek özelliklerini kullanabilmek için onları önce tanımlamalısın. Normal özellikler onlara sadece bir değer vererek tanımlanabilir ancak private özellikler sınıf içerisinde tanımlanmak zorundadırlar. -To use private instance properties, you must declare them. Regular properties can be created by just assigning to them, but private properties _must_ be declared in the class declaration to be available at all. - -This class implements an appliance for getting random whole number below a given maximum number. It only has one ((public)) property: `getNumber`. +Bu sınıf verilen bir maksimum sayının altında rastgele bir sayı gösterecek bir cihazı implemente etmektedir ve sadece bir ((public)) özelliği vardır: `getNumber`. ``` class RandomSource { @@ -313,11 +312,11 @@ class RandomSource { } ``` -## Overriding derived properties +## Türetilmiş özellikleri geçersiz kılma {{index "shared property", overriding, [property, inheritance]}} -When you add a property to an object, whether it is present in the prototype or not, the property is added to the object _itself_. If there was already a property with the same name in the prototype, this property will no longer affect the object, as it is now hidden behind the object's own property. +Bir nesneye bir özellik eklediğinde içerisinde o özellik zaten var olsa da olmasa da o özellik nesnenin _kendisine_ eklenir. Eğer prototipte zaten aynı adda bir özellik varsa bu özellik artık o nesneyi o özelliğin başka bir nesneye ait olmasından ötürü etkilemeyecektir. ``` Rabbit.prototype.teeth = "small"; @@ -334,17 +333,17 @@ console.log(Rabbit.prototype.teeth); {{index [prototype, diagram]}} -The following diagram sketches the situation after this code has run. The `Rabbit` and `Object` ((prototype))s lie behind `killerRabbit` as a kind of backdrop, where properties that are not found in the object itself can be looked up. +Aşağıdaki diyahram durumu kod çalıştıktan sonra açıklamakta. `Rabbit` ve `Object` ((prototip))leri `killerRabbit`'te aranan özelliklerin kendisinde bulunamayınca bakılacak yedek yerler olarak durmaktadırlar. {{figure {url: "img/rabbits.svg", alt: "A diagram showing the object structure of rabbits and their prototypes. There is a box for the 'killerRabbit' instance (holding instance properties like 'type'), with its two prototypes, 'Rabbit.prototype' (holding the 'speak' method) and 'Object.prototype' (holding methods like 'toString') stacked behind it.",width: "8cm"}}} {{index "shared property"}} -Overriding properties that exist in a prototype can be a useful thing to do. As the rabbit teeth example shows, overriding can be used to express exceptional properties in instances of a more generic class of objects while letting the nonexceptional objects take a standard value from their prototype. +Prototipte var olan özelliklere yeni değerler atamak faydalı olabilir. `rabbit.teeth` örneği bunu göstermektedir, yeni değerler atamak istisnai olmayan nesnelerin prototiplerinden standart bir değeri almasına izin verirken, daha genel nesne sınıfının örneklerinde istisnai özellikleri ifade etmek için kullanılabilir. {{index "toString method", "Array prototype", "Function prototype"}} -Overriding is also used to give the standard function and array prototypes a different `toString` method than the basic object prototype. +Var olan bir özelliğe yeni bir değer atamak, standart fonksiyon ve dizi prototiplerine temel nesne prototipinden farklı bir `toString` metodu vermek için de kullanılır. ``` console.log(Array.prototype.toString == @@ -356,22 +355,22 @@ console.log([1, 2].toString()); {{index "toString method", "join method", "call method"}} -Calling `toString` on an array gives a result similar to calling `.join(",")` on it—it puts commas between the values in the array. Directly calling `Object.prototype.toString` with an array produces a different string. That function doesn't know about arrays, so it simply puts the word _object_ and the name of the type between square brackets. +Bir dizide `toString` çağırmak, ona `.join(",")` çağırmakla benzer bir sonuç verir—dizideki değerler arasına virgül koyar. Bir diziye doğrudan `Object.prototype.toString` çağırmak farklı bir dize üretir. Bu fonksiyon diziler hakkında bilgi sahibi değildir, bu nedenle sadece _object_ kelimesini ve türün adını köşeli parantezler arasına koyar. ``` console.log(Object.prototype.toString.call([1, 2])); // → [object Array] ``` -## Maps +## Map'ler {{index "map method"}} -We saw the word _map_ used in the [previous chapter](higher_order#map) for an operation that transforms a data structure by applying a function to its elements. Confusing as it is, in programming the same word is used for a related but rather different thing. +Bir [önceki bölümde](higher_order#map) _map_ kelimesini, öğelerine bir fonksiyon uygulayarak bir veri yapısını dönüştüren bir işlem için kullanıldığını gördük. Kafa karıştırıcı olmasına rağmen, programlamada aynı kelime ilişkili ancak farklı bir şey için de kullanılır. {{index "map (data structure)", "ages example", ["data structure", map]}} -A _map_ (noun) is a data structure that associates values (the keys) with other values. For example, you might want to map names to ages. It is possible to use objects for this. +Bir _map_ (isim) değerleri (anahtarlar) diğer değerlerle ilişkilendiren bir veri yapısıdır. Örneğin, isimleri yaşlara eşlemek isteyebilirsiniz. Bunun için nesneleri kullanmak mümkündür. ``` let ages = { @@ -390,11 +389,11 @@ console.log("Is toString's age known?", "toString" in ages); {{index "Object.prototype", "toString method"}} -Here, the object's property names are the people's names and the property values are their ages. But we certainly didn't list anybody named toString in our map. Yet, because plain objects derive from `Object.prototype`, it looks like the property is there. +Burada, nesnenin özellik adları insanların isimleri, özellik değerleri ise yaşlarıdır. Ancak kesinlikle haritamızda `toString` adında birini listelemedik. Yine de basit nesneler `Object.prototype`'tan türedikleri için, özellik orada gibi görünüyor. {{index "Object.create function", prototype}} -As such, using plain objects as maps is dangerous. There are several possible ways to avoid this problem. First, you can create objects with _no_ prototype. If you pass `null` to `Object.create`, the resulting object will not derive from `Object.prototype` and can safely be used as a map. +Bu nedenle, basit nesneleri haritalar olarak kullanmak tehlikelidir. Bu sorunu önlemenin birkaç olası yolu vardır. İlk olarak, hiçbir prototipe sahip olmayan nesneler oluşturmak mümkündür. `Object.create`'e `null` verirseniz, sonuçta elde edilen nesne `Object.prototype`'tan türetilmez ve güvenli bir şekilde bir map olarak kullanılabilir. ``` console.log("toString" in Object.create(null)); @@ -403,11 +402,11 @@ console.log("toString" in Object.create(null)); {{index [property, naming]}} -Object property names must be strings. If you need a map whose keys can't easily be converted to strings—such as objects—you cannot use an object as your map. +Nesne özellik adları dize olmalıdır. Anahtarları kolayca dizilere dönüştürülemeyen bir map'e ihtiyacınız varsa—örneğin nesneler—bir nesneyi map'iniz olarak kullanamazsınız. {{index "Map class"}} -Fortunately, JavaScript comes with a class called `Map` that is written for this exact purpose. It stores a mapping and allows any type of keys. +Neyse ki, JavaScript, tam olarak bu amaca yönelik olan `Map` adında bir sınıf ile gelir. Bir eşleme saklar ve her türden anahtara izin verir. ``` let ages = new Map(); @@ -425,11 +424,11 @@ console.log(ages.has("toString")); {{index [interface, object], "set method", "get method", "has method", encapsulation}} -The methods `set`, `get`, and `has` are part of the interface of the `Map` object. Writing a data structure that can quickly update and search a large set of values isn't easy, but we don't have to worry about that. Someone else did it for us, and we can go through this simple interface to use their work. +`set`, `get` ve `has` yöntemleri, `Map` nesnesinin arayüzünün bir parçasıdır. Büyük bir değer kümesini hızlı bir şekilde güncelleme ve arama yapabilen bir veri yapısı yazmak kolay değildir, ancak bununla ilgilenmemiz gerekmez. Başkası bunu bizim için yaptı ve bu basit arayüzü kullanarak çalışmalarını kullanabiliriz. {{index "hasOwn function", "in operator"}} -If you do have a plain object that you need to treat as a map for some reason, it is useful to know that `Object.keys` returns only an object's _own_ keys, not those in the prototype. As an alternative to the `in` operator, you can use the `Object.hasOwn` function, which ignores the object's prototype. +Herhangi bir nedenden ötürü basit bir nesneye bir map gibi davranmanız gerekiyorsa, `Object.keys`'in yalnızca bir nesnenin kendi anahtarlarını döndürdüğünü, prototiptekilerini döndürmediğini bilmeniz faydalı olabilir. `in` operatörü yerine, nesnenin prototipini yok sayan `Object.hasOwn` fonksiyonunu kullanabilirsiniz. ``` console.log(Object.hasOwn({x: 1}, "x")); @@ -438,11 +437,11 @@ console.log(Object.hasOwn({x: 1}, "toString")); // → false ``` -## Polymorphism +## Polimorfizm {{index "toString method", "String function", polymorphism, overriding, "object-oriented programming"}} -When you call the `String` function (which converts a value to a string) on an object, it will call the `toString` method on that object to try to create a meaningful string from it. I mentioned that some of the standard prototypes define their own version of `toString` so they can create a string that contains more useful information than `"[object Object]"`. You can also do that yourself. +Bir değeri dizeye dönüştüren `String` fonksiyonunu bir nesne üzerinde çağırdığınızda, bu nesne üzerinde `toString` yöntemini çağırarak ondan anlamlı bir dize oluşturmaya çalışır. Bazı standart prototiplerin kendi `toString` versiyonlarını tanımladığını belirttim, böylece `"[object Object]"`'ten daha kullanışlı bilgiler içeren bir dize oluşturabilirler. Kendiniz de bunu yapabilirsiniz. ```{includeCode: "top_lines: 3"} Rabbit.prototype.toString = function() { @@ -455,13 +454,13 @@ console.log(String(killerRabbit)); {{index "object-oriented programming", [interface, object]}} -This is a simple instance of a powerful idea. When a piece of code is written to work with objects that have a certain interface—in this case, a `toString` method—any kind of object that happens to support this interface can be plugged into the code and will be able to work with it. +Bu, güçlü bir fikrin basit bir örneğidir. Bir kod parçası, belirli bir arayüzü olan nesnelerle çalışmak üzere yazıldığında—bu durumda bir `toString` yöntemi—bu arayüzü destekleyen herhangi bir nesne kodun içine eklenerek ve onunla çalışabilir. -This technique is called _polymorphism_. Polymorphic code can work with values of different shapes, as long as they support the interface it expects. +Bu teknik, _polimorfizm_ olarak adlandırılır. Polimorfik kod, beklediği arayüzü destekleyen farklı şekillerdeki değerlerle çalışabilir. {{index "forEach method"}} -An example of a widely used interface is that of ((array-like object))s which have a `length` property holding a number, and numbered properties for each of their elements. Both arrays and strings support this interface, as do various other objects, some of which we'll see later in the chapters about the browser. Our implementation of `forEach` from [Chapter ?](higher_order) works on anything that provides this interface. In fact, so does `Array.prototype.forEach`. +Yaygın olarak kullanılan örnek olarak verilebilecek bir arayüz örneği, `length` özelliği tutan ve her bir eleman için numaralandırılmış özelliklere sahip ((dizi benzeri nesneler))'in arayüzüdür. Diziler ve dizeler bu arayüzü destekler, aynı şekilde bazı diğer nesneler de destekler, bunlardan bazılarını daha sonra browser hakkındaki bölümlerde göreceğiz. [Bölüm ?](higher_order) içindeki `forEach` uygulamamız, bu arayüzü sağlayan her şeyde çalışır. Aslında, `Array.prototype.forEach` da aynı şekilde çalışır. ``` Array.prototype.forEach.call({ @@ -473,13 +472,13 @@ Array.prototype.forEach.call({ // → B ``` -## Getters, setters, and statics +## Getter'lar, setter'lar, and static'ler {{index [interface, object], [property, definition], "Map class"}} -Interfaces often contain plain properties, not just methods. For example, `Map` objects have a `size` property that tells you how many keys are stored in them. +Arayüzler sadece yöntemler değil, genellikle özellikler içerir. Örneğin, `Map` nesnelerinin bir `size` özelliği vardır ve içlerinde saklanan anahtarların sayısını belirtir. -It is not necessary for such an object to compute and store such a property directly in the instance. Even properties that are accessed directly may hide a method call. Such methods are called _((getter))s_ and are defined by writing `get` in front of the method name in an object expression or class declaration. +Böyle bir bir nesnenin bir özelliği doğrudan örnekte hesaplaması ve saklaması gerekli değildir. Doğrudan erişilen özellikler bile bir yöntem çağrısını gizleyebilir. Böyle yöntemlere ((getter)) denir ve bunlar bir nesne ifadesi veya sınıf bildirimi içinde yöntem adının önüne `get` yazarak tanımlanır. ```{test: no} let varyingSize = { @@ -496,7 +495,7 @@ console.log(varyingSize.size); {{index "temperature example"}} -Whenever someone reads from this object's `size` property, the associated method is called. You can do a similar thing when a property is written to, using a _((setter))_. +Bu nesnenin `size` özelliğinden okuma yapıldığında, ilişkili yöntem çağrılır. Bir özelliğe bir değer atandığında _((setter))_ kullanarak benzer bir şey yapabilirsiniz. ```{startCode: true, includeCode: "top_lines: 16"} class Temperature { @@ -523,33 +522,27 @@ console.log(temp.celsius); // → 30 ``` -The `Temperature` class allows you to read and write the temperature in either degrees ((Celsius)) or degrees ((Fahrenheit)), but internally it stores only Celsius and automatically converts to and from Celsius in the `fahrenheit` getter and setter. +`Temperature` sınıfı, sıcaklığı ((°C)) veya ((°F)) olarak okumaya ve yazmaya izin verir, ancak içsel olarak sadece °C'ı depolar ve °F değerini değiştirmek veya okumak istediğinde °C değerini getter ve setter'da formüller kullanarak °F'a çevirir. {{index "static method", "static property"}} -Sometimes you want to attach some properties directly to your constructor function, rather than to the prototype. Such methods won't have access to a class instance but can, for example, be used to provide additional ways to create instances. +Bazen, yöntemleri prototip yerine doğrudan constructor fonksiyona eklemek istersiniz. Bu tür yöntemlerin bir sınıf örneğine erişimi olmaz ancak örneğin başka yollarla oluşturulması için kullanılabilirler. -Inside a class declaration, methods or properties that have `static` written before their name are stored on the constructor. For example, the `Temperature` class allows you to write `Temperature.fromFahrenheit(100)` to create a temperature using degrees Fahrenheit: +Sınıf bildirimi içinde, adlarının önünde `static` yazılı olan yöntemler veya özellikler kurucuda saklanır. Bu nedenle, `Temperature` sınıfı, °F cinsinden bir sıcaklık oluşturmak için `Temperature.fromFahrenheit(100)` yazmanıza izin verir. -``` -let boil = Temperature.fromFahrenheit(212); -console.log(boil.celsius); -// → 100 -``` - -## Symbols +## Symbol'ler {{index "for/of loop", "iterator interface"}} -I mentioned in [Chapter ?](data#for_of_loop) that a `for`/`of` loop can loop over several kinds of data structures. This is another case of polymorphism—such loops expect the data structure to expose a specific interface, which arrays and strings do. And we can also add this interface to our own objects! But before we can do that, we need to briefly take a look at the symbol type. +[Bölüm ?](data#for_of_loop) içinde bir `for/of` döngüsünün çeşitli veri yapıları üzerinde döngü yapabileceğini belirttim. Bu, başka bir polimorfizm örneğidir—bu tür döngüler, beklenen arayüzü ortaya koyan veri yapısını bekler, diziler ve dizeler de buna uyum sağlar. Ve kendi nesnelerimize de bu arayüzü ekleyebiliriz! Ancak bunu yapmadan önce, sembol türüne kısaca bir göz atmak gerekir. -It is possible for multiple interfaces to use the same property name for different things. For example, on array-like objects, `length` refers to the number of elements in the collection. But an object interface describing a hiking route could use `length` to provide the length of the route in meters. It would not be possible for an object to conform to both these interfaces. +Birden çok arayüzün, farklı şeyler için aynı özellik adını kullanması mümkündür. Örneğin, dizi benzeri nesnelerde, `length` koleksiyondaki öğelerin miktarına atıfta bulunur. Ancak bir yürüyüş rotasını tanımlayan bir nesne arayüzü, `length`'i rotanın metre cinsinden uzunluğunu sağlamak için kullanabilir. Böyle bir objenin bu iki arayüze uyum sağlaması mümkün değildir. -An object trying to be a route and array-like (maybe to enumerate its waypoints) is somewhat far-fetched, and this kind of problem isn't that common in practice. For things like the iteration protocol, though, the language designers needed a type of property that _really_ doesn't conflict with any others. So in 2015, _((symbol))s_ were added to the language. +Bir nesnenin hem rota hem de dizilere benzer arayüze sahip olmaya çalışması (belki de noktalarını numaralandırmak için) biraz abartılıdır ve bu tür bir sorun pratikte o kadar yaygın değildir. Ancak iterasyon protokolü gibi şeyler için, dil tasarımcıları bu tür bir özellik türüne _gerçekten_ başka hiçbir şeyle çelişmeyen bir tür özellik türüne ihtiyaç duyuyordu. Bu nedenle, 2015 yılında _((semboller))_ dilin bir parçası olarak eklendi. {{index "Symbol function", [property, naming]}} -Most properties, including all those we have seen so far, are named with strings. But it is also possible to use symbols as property names. Symbols are values created with the `Symbol` function. Unlike strings, newly created symbols are unique—you cannot create the same symbol twice. +Şimdiye kadar gördüğümüz tüm özellikler de dahil olmak üzere, çoğu özellik dizelerle adlandırılır. Ancak sembollerin özellik adı olarak da kullanılması mümkündür. Semboller, `Symbol` fonksiyonuyla oluşturulan değerlerdir. Dizelerin aksine, yeni oluşturulan semboller benzersizdir—aynı sembolü iki kez oluşturamazsınız. ``` let sym = Symbol("name"); @@ -560,9 +553,9 @@ console.log(killerRabbit[sym]); // → 55 ``` -The string you pass to `Symbol` is included when you convert it to a string and can make it easier to recognize a symbol when, for example, showing it in the console. But it has no meaning beyond that—multiple symbols may have the same name. +`Symbol`'e verdiğiniz dize, onu bir dizeye dönüştürdüğünüzde dahil edilir ve bir sembolü, örneğin, konsolda gösterirken tanımayı daha kolay hale getirir. Ancak bundan başka bir anlamı yoktur—birden çok sembol aynı adı taşıyabilir. -Being both unique and usable as property names makes symbols suitable for defining interfaces that can peacefully live alongside other properties, no matter what their names are. +Hem benzersiz hem de özellik adları olarak kullanılabilir olmaları, sembollerin adları ne olursa olsun diğer özelliklerle bir arada barış içinde yaşayabilen arayüzleri tanımlamak için uygun olmalarını sağlar. ```{includeCode: "top_lines: 1"} const length = Symbol("length"); @@ -576,7 +569,7 @@ console.log([1, 2][length]); {{index [property, naming]}} -It is possible to include symbol properties in object expressions and classes by using ((square bracket))s around the property name. That causes the expression between the brackets to be evaluated to produce the property name, analogous to the square bracket property access notation. +Nesne ifadelerinde ve sınıflarda sembol özelliklerini kullanmak için ((köşeli parantez))lerle sararak özellik adını kullanmak mümkündür. Bu, köşeli parantez özelliği erişim notasyonuna benzer şekilde, parantezler arasındaki ifadenin değerlendirilerek özellik adının oluşturulmasını sağlar. ``` let myTrip = { @@ -589,19 +582,19 @@ console.log(myTrip[length], myTrip.length); // → 21500 2 ``` -## The iterator interface +## Yineleyici arayüzü {{index "iterable interface", "Symbol.iterator symbol", "for/of loop"}} -The object given to a `for`/`of` loop is expected to be _iterable_. This means it has a method named with the `Symbol.iterator` symbol (a symbol value defined by the language, stored as a property of the `Symbol` function). +`for/of` döngüsüne verilen nesnenin _yinelenilebilir_ olması beklenir. Bu, `Symbol.iterator` sembolü ile adlandırılmış bir metoda (dil tarafından tanımlanan bir sembol değeri, `Symbol` fonksiyonunun bir özelliği olarak saklanır) sahip olması anlamına gelir. {{index "iterator interface", "next method"}} -When called, that method should return an object that provides a second interface, _iterator_. This is the actual thing that iterates. It has a `next` method that returns the next result. That result should be an object with a `value` property that provides the next value, if there is one, and a `done` property, which should be true when there are no more results and false otherwise. +Çağrıldığında, bu yöntem, ikinci bir arayüz olan _yineleyiciyi_ sağlayan bir nesne döndürmelidir. Bu, gerçekten yineleyen şeydir. Bir sonraki sonucu döndüren `next` yöntemine sahiptir. Bu sonuç, bir sonraki değeri sağlayan bir `value` özelliği ve daha çok sonuçların olup olmadığını belirten `done` özelliğine sahip bir nesne olmalıdır. -Note that the `next`, `value`, and `done` property names are plain strings, not symbols. Only `Symbol.iterator`, which is likely to be added to a _lot_ of different objects, is an actual symbol. +`next`, `value`, ve `done` özellik adlarının düz dize olduğunu, semboller olmadığını unutmayın. Yalnızca _birçok_ farklı nesnelere eklenebilecek olan `Symbol.iterator` gerçek bir semboldür. -We can directly use this interface ourselves. +Bu arayüzü doğrudan kendimiz kullanabiliriz. ``` let okIterator = "OK"[Symbol.iterator](); @@ -615,7 +608,7 @@ console.log(okIterator.next()); {{index ["data structure", list], "linked list", collection}} -Let's implement an iterable data structure similar to the linked list from the exercise in [Chapter ?](data). We'll write the list as a class this time. +[Chapter ?](data) alıştırmasındaki linked list benzeri bir yinelenebilir veri yapısı uygulayalım. Bu sefer listeyi bir sınıf olarak yazacağız. ```{includeCode: true} class List { @@ -638,9 +631,9 @@ class List { } ``` -Note that `this`, in a static method, points at the constructor of the class, not an instance—there is no instance around when a static method is called. +Statik bir yöntemdeki `this`, bir örneğe değil, sınıfın constructor fonksiyonuna işaret eder—bir statik yöntem çağrıldığında bir örnek yoktur. -Iterating over a list should return all the list's elements from start to end. We'll write a separate class for the iterator. +Bir liste üzerinde yinelendiğinde, listenin tüm öğeleri baştan sona döndürülmelidir. Yineleyici için ayrı bir sınıf yazacağız. {{index "ListIterator class"}} @@ -661,9 +654,9 @@ class ListIterator { } ``` -The class tracks the progress of iterating through the list by updating its `list` property to move to the next list object whenever a value is returned and reports that it is done when that list is empty (null). +`ListIterator` sınıfı, bir değer döndürüldüğünde `list` özelliğini güncelleyerek listedeki öğelerin üzerinden yinelenebilme ilerlemesini takip eder ve bu liste boş olduğunda (null) işlemi tamamlandığını bildirir. -Let's set up the `List` class to be iterable. Throughout this book, I'll occasionally use after-the-fact prototype manipulation to add methods to classes so that the individual pieces of code remain small and self-contained. In a regular program, where there is no need to split the code into small pieces, you'd declare these methods directly in the class instead. +`List` sınıfını yinelemeli hale getirelim. Bu kitap boyunca, kod parçalarının küçük ve kendi kendine yeten kalmasını sağlamak için sınıflara yöntemler eklemek adına prototip manipülasyonunu zaman zaman kullanacağım. Normal bir programda, kodun küçük parçalara ayrılmasına gerek olmadığında, bu yöntemleri doğrudan sınıfta bildirirsiniz. ```{includeCode: true} List.prototype[Symbol.iterator] = function() { @@ -673,7 +666,7 @@ List.prototype[Symbol.iterator] = function() { {{index "for/of loop"}} -We can now loop over a list with `for`/`of`. +Artık bir liste üzerinde `for`/`of` ile döngü yapabiliriz. ``` let list = List.fromArray([1, 2, 3]); @@ -687,26 +680,26 @@ for (let element of list) { {{index spread}} -The `...` syntax in array notation and function calls similarly works with any iterable object. For example, you can use `[...value]` to create an array containing the elements in an arbitrary iterable object. +Array notasyonunda ve fonksiyon çağrılarında `...` herhangi bir yinelemeli nesneyle çalışır. Bu nedenle örneğin, `[...value]` kullanarak bir yinelenebilir nesnedeki öğeleri içeren bir dizi oluşturabilirsiniz. ``` console.log([..."PCI"]); // → ["P", "C", "I"] ``` -## Inheritance +## Kalıtım {{index inheritance, "linked list", "object-oriented programming", "LengthList class"}} -Imagine we need a list type much like the `List` class we saw before, but because we will be asking for its length all the time, we don't want it to have to scan through its `rest` every time. Instead, we want to store the length in every instance for efficient access. +`List` sınıfında gördüğümüz gibi, bir listeye benzer bir liste tipine ihtiyacımız olduğunu hayal edin, ancak sürekli olarak uzunluğunu isteyeceğimiz için, her seferinde `rest` özelliğini taramasını istemiyoruz ve bunun yerine her örnekte uzunluğu verimli bir erişim için saklamak istiyoruz. {{index overriding, prototype}} -JavaScript's prototype system makes it possible to create a _new_ class, much like the old class but with new definitions for some of its properties. The prototype for the new class derives from the old prototype but adds a new definition for, say, the `length` getter. +JavaScript'in prototip sistemi, bir sınıfa, eskiden olduğu gibi, ancak bazı özelliklerinin yeni tanımları ile bir _yeni_ sınıf oluşturmayı mümkün kılar. Yeni sınıfın prototipi, eski prototipten türetilir ancak, diyelim ki, `length` getter metodu için için yeni bir tanım ekler. -In object-oriented programming terms, this is called _((inheritance))_. The new class inherits properties and behavior from the old class. +Nesne tabanlı programlama terimleriyle, buna _((kalıtım))_ denir. Yeni sınıf, eski sınıftan özellikler ve davranış alır. -```{includeCode: "top_lines: 17"} +```{includeCode: "top_lines: 12"} class LengthList extends List { #length; @@ -724,23 +717,23 @@ console.log(LengthList.fromArray([1, 2, 3]).length); // → 3 ``` -The use of the word `extends` indicates that this class shouldn't be directly based on the default `Object` prototype but on some other class. This is called the _((superclass))_. The derived class is the _((subclass))_. +`extends` kelimesinin kullanımı, bu sınıfın doğrudan varsayılan `Object` prototipi yerine başka bir sınıfa dayandırılması gerektiğini gösterir. Buna _((üst sınıf))_ denir. Türetilmiş sınıf, _((alt sınıf))_ tır. -To initialize a `LengthList` instance, the constructor calls the constructor of its superclass through the `super` keyword. This is necessary because if this new object is to behave (roughly) like a `List`, it is going to need the instance properties that lists have. +Bir `LengthList` örneğini başlatmak için, constructor, `super` anahtar kelimesi aracılığıyla üst sınıfının constructor fonksiyonunu çağırır. Bu, bu yeni nesne bir `List` gibi davranacaksa, listelerin sahip olduğu örnek özelliklere ihtiyacı olacağı için gereklidir. -The constructor then stores the list's length in a private property. If we had written `this.length` there, the class's own getter would have been called, which doesn't work yet, since `#length` hasn't been filled in yet. We can use `super.something` to call methods and getters on the superclass's prototype, which is often useful. +Constructor fonksiyonu, ardından listenin uzunluğunu private bir özelliğe saklar. Orada `this.length` yazsaydık, sınıfın kendi getter metodu çağrılırdı, ki bu henüz çalışmaz, çünkü `#length` henüz doldurulmadı. `super.something` kullanarak üst sınıfın prototipi üzerinde metodlar ve getter metodları çağırmak sıkça kullanışlıdır. -Inheritance allows us to build slightly different data types from existing data types with relatively little work. It is a fundamental part of the object-oriented tradition, alongside encapsulation and polymorphism. But while the latter two are now generally regarded as wonderful ideas, inheritance is more controversial. +Kalıtım, var olan veri türlerinden kolayca biraz farklı veri türleri oluşturmamıza izin verir. Bu, kapsülleme ve polimorfizm ile birlikte nesne tabanlı geleneğin temel bir parçasıdır. Ancak, son ikisi şimdi genellikle harika fikirler olarak kabul edilirken, kalıtım daha tartışmalıdır. {{index complexity, reuse, "class hierarchy"}} -Whereas ((encapsulation)) and polymorphism can be used to _separate_ pieces of code from one another, reducing the tangledness of the overall program, ((inheritance)) fundamentally ties classes together, creating _more_ tangle. When inheriting from a class, you usually have to know more about how it works than when simply using it. Inheritance can be a useful tool to make some types of programs more succinct, but it shouldn't be the first tool you reach for, and you probably shouldn't actively go looking for opportunities to construct class hierarchies (family trees of classes). +((Kapsülleme)) ve polimorfizm kodları birbirinden _ayırmak_ için kullanılabilirken, ((kalıtım)) temel olarak sınıfları birbirine bağlar, ve birbirine daha bağlı kodlar yaratır. Bir sınıftan kalıtım alırken, sınıfı sadece kullanmak yerine genellikle nasıl çalıştığı hakkında daha fazla bilgi sahibi olmanız gerekir. Kalıtım, bazı türdeki programları daha kısa hale getirmek için kullanışlı bir araç olabilir, ancak bunu kullanmaya yeltendiğiniz ilk araç olmamalıdır ve daha çok sınıf hiyerarşileri (sınıf ağaçları) oluşturma fırsatlarını aktif olarak aramamalısınız. -## The instanceof operator +## instanceof operatörü {{index type, "instanceof operator", constructor, object}} -It is occasionally useful to know whether an object was derived from a specific class. For this, JavaScript provides a binary operator called `instanceof`. +Nesnenin belirli bir sınıftan türetildiğini bilmek zaman zaman faydalı olabilir. Bunun için JavaScript, `instanceof` adında bir ikili operatör sağlar. ``` console.log( @@ -756,44 +749,44 @@ console.log([1] instanceof Array); {{index inheritance}} -The operator will see through inherited types, so a `LengthList` is an instance of `List`. The operator can also be applied to standard constructors like `Array`. Almost every object is an instance of `Object`. +Operatör, kalıtılmış türleri görür, bu nedenle bir `LengthList`, `List` sınıfının bir örneğidir. Operatör ayrıca `Array` gibi standart constructor fonksiyonlarına da uygulanabilir. Hemen hemen her nesne `Object` sınıfının bir örneğidir. -## Summary +## Özet -Objects do more than just hold their own properties. They have prototypes, which are other objects. They'll act as if they have properties they don't have as long as their prototype has that property. Simple objects have `Object.prototype` as their prototype. +Nesneler, kendi özelliklerini tutmanın ötesinde daha fazlasını yaparlar. Başka nesneler olan prototipleri vardır. Prototiplerinde bulunduğu sürece, sahip olmadıkları bir özelliğe sahipmiş gibi davranırlar. Basit nesnelerin prototipi `Object.prototype`'dır. -Constructors, which are functions whose names usually start with a capital letter, can be used with the `new` operator to create new objects. The new object's prototype will be the object found in the `prototype` property of the constructor. You can make good use of this by putting the properties that all values of a given type share into their prototype. There's a `class` notation that provides a clear way to define a constructor and its prototype. +Genellikle büyük harfle başlayan adları olan constructor fonksiyonlar, `new` operatörünün kullanımıyla yeni nesneler oluşturmak için kullanılabilir. Yeni nesnenin prototipi, constructor fonksiyonunun `prototype` özelliğinde bulunan nesne olacaktır. Verilen bir veri türün paylaştığı tüm özellikleri prototip nesnesine koyarak bundan fayda sağlayabilirsiniz. Bir constructor fonksiyonu ve onun prototipini net bir şekilde tanımlamanın temiz bir yolunu sağlayan `class` notasyonunu kullanabilirsiniz. -You can define getters and setters to secretly call methods every time an object's property is accessed. Static methods are methods stored in a class's constructor rather than its prototype. +Herhangi bir nesnenin herhangi bir özelliği erişildiğinde gizlice çağırılacak getter ve setter metodları tanımlayabilirsiniz. Statik metodlar, bir sınıfın constructor fonksiyonunda saklanan metodlardır, prototipinde değil. -The `instanceof` operator can, given an object and a constructor, tell you whether that object is an instance of that constructor. +`instanceof` operatörüne bir nesne ve bir constructor fonksiyonu verildiğinde, nesnenin o constructor fonksiyonunun bir örneği olup olmadığını size söyler. -One useful thing to do with objects is to specify an interface for them and tell everybody that they are supposed to talk to your object only through that interface. The rest of the details that make up your object are now _encapsulated_, hidden behind the interface. You can use private properties to hide a part of your object from the outside world. +Nesnelerle yapılacak yararlı şeylerden biri, onlar için bir arayüz belirtmek ve herkesin nesnenizle sadece o arayüz aracılığıyla iletişim kurması gerektiğini söylemektir. Nesnenizi oluşturan diğer ayrıntılar artık _kapsülleme_ aracılığıyla gizlenmiş olur ve arayüzün arkasında saklanır. Nesnenizin bir kısmını dış dünyadan gizlemek için private özellikler kullanabilirsiniz. -More than one type may implement the same interface. Code written to use an interface automatically knows how to work with any number of different objects that provide the interface. This is called _polymorphism_. +Birden fazla tür aynı arayüzü implemente edebilir. Bir arayüzü kullanmak için yazılmış kod, arayüzü sağlayan herhangi bir sayıda farklı nesneyle nasıl çalışılacağını otomatik olarak bilir. Buna _polimorfizm_ denir. -When implementing multiple classes that differ in only some details, it can be helpful to write the new classes as _subclasses_ of an existing class, _inheriting_ part of its behavior. +Birbirinden yalnızca bazı ayrıntılarda farklılık gösteren birden çok sınıfı implemente ederken, yeni sınıfları var olan bir sınıfın alt sınıfları olarak yazmak, davranışlarının bir kısmını kalıtım yoluyla alarak kullanmanıza yardımcı olabilir. -## Exercises +## Egzersizler {{id exercise_vector}} -### A vector type +### Bir vektör türü {{index dimensions, "Vec class", coordinates, "vector (exercise)"}} -Write a ((class)) `Vec` that represents a vector in two-dimensional space. It takes `x` and `y` parameters (numbers), that it saves to properties of the same name. +İki boyutlu uzayda bir vektörü temsil eden bir `Vec` adında ((Sınıf)) yazın. Parametre olarak `x` ve `y` (sayılar) alır ve bunları aynı adla özelliklere kaydeder. {{index addition, subtraction}} -Give the `Vec` prototype two methods, `plus` and `minus`, that take another vector as a parameter and return a new vector that has the sum or difference of the two vectors' (`this` and the parameter) _x_ and _y_ values. +`Vec` prototipine `plus` ve `minus` adında başka bir vektörü parametre olarak alan ve iki vektörün (`this` ve parametre) _x_ ve _y_ değerlerinin toplamını veya farkını döndüren iki ((metod)) tanımlayın. -Add a ((getter)) property `length` to the prototype that computes the length of the vector—that is, the distance of the point (_x_, _y_) from the origin (0, 0). +Prototipe, vektörün uzunluğunu hesaplayan `length` adında ((getter)) özelliği ekleyin - yani, noktanın (x, y) başlangıç noktasından (0, 0) uzaklığını hesaplar. {{if interactive ```{test: no} -// Your code here. +// Kodunuz buraya. console.log(new Vec(1, 2).plus(new Vec(2, 3))); // → Vec{x: 3, y: 5} @@ -802,45 +795,46 @@ console.log(new Vec(1, 2).minus(new Vec(2, 3))); console.log(new Vec(3, 4).length); // → 5 ``` + if}} {{hint {{index "vector (exercise)"}} -Look back to the `Rabbit` class example if you're unsure how `class` declarations look. +Eğer `class` beyanlarının nasıl göründüğünden emin değilseniz `Rabbit` sınıfı örneğine geri dönün. {{index Pythagoras, "defineProperty function", "square root", "Math.sqrt function"}} -Adding a getter property to the constructor can be done by putting the word `get` before the method name. To compute the distance from (0, 0) to (x, y), you can use the Pythagorean theorem, which says that the square of the distance we are looking for is equal to the square of the x-coordinate plus the square of the y-coordinate. Thus, [√(x^2^ + y^2^)]{if html}[[$\sqrt{x^2 + y^2}$]{latex}]{if tex} is the number you want. `Math.sqrt` is the way you compute a square root in JavaScript and `x ** 2` can be used to square a number. +Constructor fonksiyonuna bir ((getter)) özelliği eklemek, metod adından önce `get` kelimesini koymak suretiyle yapılabilir. (0, 0) ile (x, y) arasındaki mesafeyi hesaplamak için, aradığımız mesafenin karesinin, x-koordinatının karesi artı y-koordinatının karesiyle eşit olduğunu söyleyen Pisagor teoremini kullanabilirsiniz. Böylece, [√(x^2^ + y^2^)]{if html}[[$\sqrt{x^2 + y^2}$]{latex}]{if tex} istediğiniz sayıdır. JavaScript'te karekökü hesaplamak için `Math.sqrt` kullanılır ve bir sayının karesini almak için `x ** 2` kullanılanılır. hint}} -### Groups +### Gruplar {{index "groups (exercise)", "Set class", "Group class", "set (data structure)"}} {{id groups}} -The standard JavaScript environment provides another data structure called `Set`. Like an instance of `Map`, a set holds a collection of values. Unlike `Map`, it does not associate other values with those—it just tracks which values are part of the set. A value can be part of a set only once—adding it again doesn't have any effect. +Standart JavaScript ortamı, `Set` adında başka bir veri yapısı sağlar. Bir `Map` örneği gibi, bir küme bir değerler koleksiyonunu tutar. `Map`'in aksine, bunlarla ilişkilendirilmiş başka değerlerle ilgilenmez - sadece hangi değerlerin kümenin bir parçası olduğunu izler. Bir değer sadece bir kez kümenin parçası olabilir - tekrar eklenmesinin herhangi bir etkisi olmaz. {{index "add method", "delete method", "has method"}} -Write a class called `Group` (since `Set` is already taken). Like `Set`, it has `add`, `delete`, and `has` methods. Its constructor creates an empty group, `add` adds a value to the group (but only if it isn't already a member), `delete` removes its argument from the group (if it was a member), and `has` returns a Boolean value indicating whether its argument is a member of the group. +`Set` ismi zaten alınmış olduğundan ötürü `Group` adında bir sınıf yazın. `Set` gibi, `add`, `delete` ve `has` metodlarına sahip olsun. Constructor fonksiyonu boş bir grup oluştursun, `add` bir değeri eğer zaten bir üye değilse gruba eklesin, `delete` argümanını eğer bir üyeyse grubun içinden kaldırsın ve `has` argümanının grubun bir üyesi olup olmadığını gösteren bir Boolean değeri döndürsün. {{index "=== operator", "indexOf method"}} -Use the `===` operator, or something equivalent such as `indexOf`, to determine whether two values are the same. +İki değerin aynı olup olmadığını belirlemek için `===` operatörünü veya `indexOf` gibi bir şeyi kullanın. {{index "static method"}} -Give the class a static `from` method that takes an iterable object as argument and creates a group that contains all the values produced by iterating over it. +Sınıfta, bir yinelenebilen bir nesneyi argüman olarak alan ve üzerinde yinelemeyi gerçekleştirerek üretilen tüm değerleri içeren bir grup oluşturan bir statik `from` ((metodu)) oluşturun. {{if interactive ```{test: no} class Group { - // Your code here. + // Kodunuz buraya. } let group = Group.from([10, 20]); @@ -860,38 +854,38 @@ if}} {{index "groups (exercise)", "Group class", "indexOf method", "includes method"}} -The easiest way to do this is to store an array of group members in an instance property. The `includes` or `indexOf` methods can be used to check whether a given value is in the array. +Bunu yapmanın en kolay yolu, bir örnek özelliğinde grup üyelerinin bir dizisini depolamaktır. `includes` veya `indexOf` metotları, verilen bir değerin dizide olup olmadığını kontrol etmek için kullanılabilir. {{index "push method"}} -Your class's ((constructor)) can set the member collection to an empty array. When `add` is called, it must check whether the given value is in the array or add it, for example with `push`, otherwise. +Sınıfınızın ((constructor)) fonksiyonu, üye koleksiyonunu boş bir diziye atayabilir. `add` çağrıldığında, verilen değerin dizide olup olmadığını kontrol etmeli ve `push` gibi bir fonksiyonla eklemelidir. {{index "filter method"}} -Deleting an element from an array, in `delete`, is less straightforward, but you can use `filter` to create a new array without the value. Don't forget to overwrite the property holding the members with the newly filtered version of the array. +Diziden bir öğe silmek, `delete` daha karmaşıktır, ancak o değerin içinde bulunmadığı yeni bir dizi oluşturmak için `filter` kullanabilirsiniz. Üyeleri tutan özelliği, dizinin bu yeniden filtrelenmiş versiyonuyla atamayı unutmayın. {{index "for/of loop", "iterable interface"}} -The `from` method can use a `for`/`of` loop to get the values out of the iterable object and call `add` to put them into a newly created group. +`from` metodu, yinelenebilir nesneden değerleri almak ve bunları yeni oluşturulan bir gruba `add` metodu aracılığıyla koymak için `for`/`of` döngüsünü kullanabilir. hint}} -### Iterable groups +### Yinelenebilir gruplar {{index "groups (exercise)", [interface, object], "iterator interface", "Group class"}} {{id group_iterator}} -Make the `Group` class from the previous exercise iterable. Refer to the section about the iterator interface earlier in the chapter if you aren't clear on the exact form of the interface anymore. +Önceki alıştırmadan `Group` sınıfını yinelenebilir yapın. Eğer arayüzün tam olarak nasıl olduğundan emin değilseniz, bölümdeki yineleme arayüzünün yapısı hakkındaki bölüme bakın. -If you used an array to represent the group's members, don't just return the iterator created by calling the `Symbol.iterator` method on the array. That would work, but it defeats the purpose of this exercise. +Grubun üyelerini temsil etmek için bir dizi kullandıysanız, dizideki direk `Symbol.iterator` metodunu çağırarak oluşturulan yineleyiciyi döndürmeyin. Bu çalışır, ancak bu alıştırmanın amacını boşa çıkarır. -It is okay if your iterator behaves strangely when the group is modified during iteration. +Grubun yinelenme sırasında grubun değiştirilmesi durumunda yineleyicinizin garip davranması sorun değil. {{if interactive ```{test: no} -// Your code here (and the code from the previous exercise) +// Kodunuz buraya.(önceki egzersizden olan kodunuz da dahil olmak üzere) for (let value of Group.from(["a", "b", "c"])) { console.log(value); @@ -907,8 +901,8 @@ if}} {{index "groups (exercise)", "Group class", "next method"}} -It is probably worthwhile to define a new class `GroupIterator`. Iterator instances should have a property that tracks the current position in the group. Every time `next` is called, it checks whether it is done and, if not, moves past the current value and returns it. +Muhtemelen yeni bir `GroupIterator` sınıfını tanımlamak faydalı olacaktır. `Iterator` örnekleri, grubun mevcut konumunu izleyen bir özelliğe sahip olmalıdır. `next` her çağırıldığında tamamlanıp tamamlanmadığını kontrol eder ve tamamlanmadıysa mevcut değerin ötesine geçip onu döndürür. -The `Group` class itself gets a method named by `Symbol.iterator` that, when called, returns a new instance of the iterator class for that group. +`Group` sınıfı `Symbol.iterator` tarafından adlandırılan bir ((metod)) alır ve çağrıldığında, o grup için yeni bir `Iterator` sınıfı örneğini döndürür. hint}} diff --git a/07_robot.md b/07_robot.md index 4ba48840..5d70a924 100644 --- a/07_robot.md +++ b/07_robot.md @@ -1,28 +1,28 @@ {{meta {load_files: ["code/chapter/07_robot.js", "code/animatevillage.js"], zip: html}}} -# Project: A Robot +# Proje: Robot -{{quote {author: "Edsger Dijkstra", title: "The Threats to Computing Science", chapter: true} +{{quote {author: "Edsger Dijkstra", title: "Bilgisayar Bilimine Yönelik Tehditler", chapter: true} -The question of whether Machines Can Think [...] is about as relevant as the question of whether Submarines Can Swim. +[...] Makinelerin Düşünüp Düşünemeyeceği sorusu [...] Denizaltıların Yüzüp Yüzemeyeceği sorusu kadar alakalıdır. quote}} {{index "artificial intelligence", "Dijkstra, Edsger"}} -{{figure {url: "img/chapter_picture_7.jpg", alt: "Illustration of a robot holding a stack of packages", chapter: framed}}} +{{figure {url: "img/chapter_picture_7.jpg", alt: "Bir paket yığınını tutan bir robotun illüstrasyonu", chapter: framed}}} {{index "project chapter", "reading code", "writing code"}} -In "project" chapters, I'll stop pummeling you with new theory for a brief moment, and instead we'll work through a program together. Theory is necessary to learn to program, but reading and understanding actual programs is just as important. +"Proje" bölümlerinde, sizi kısa bir an için yeni teorilerle sıkmayı bırakacağım ve bunun yerine birlikte bir program üzerinden çalışacağız. Programlama öğrenmek için teoriye ihtiyaç vardır, ancak gerçek programları okuyup anlamak da en az teori kadar önemlidir. -Our project in this chapter is to build an ((automaton)), a little program that performs a task in a ((virtual world)). Our automaton will be a mail-delivery ((robot)) picking up and dropping off parcels. +Bu bölümdeki projemiz, bir ((otomasyon)) inşa etmek olacak, bir ((sanal dünya))da görev gerçekleştiren küçük bir program. Otomasyon, paketleri teslim alıp bırakan bir posta teslim ((robotu)) olacak. ## Meadowfield {{index "roads array"}} -The village of ((Meadowfield)) isn't very big. It consists of 11 places with 14 roads between them. It can be described with this array of roads: +((Meadowfield)) köyü çok büyük değil. 11 yer ve aralarında 14 yoldan oluşur. Köyün yollarını tanımlayan bu yol dizisi ile tanımlanabilir: ```{includeCode: true} const roads = [ @@ -36,13 +36,13 @@ const roads = [ ]; ``` -{{figure {url: "img/village2x.png", alt: "Pixel art illustration of a small village with 11 locations, labeled with letters, and roads going being them"}}} +{{figure {url: "img/village2x.png", alt: "11 konumlu, harflerle etiketlenmiş ve yolların onlara ait olduğu küçük bir köyün piksel sanat illüstrasyonu"}}} -The network of roads in the village forms a _((graph))_. A graph is a collection of points (places in the village) with lines between them (roads). This graph will be the world that our robot moves through. +Köydeki yol ağı bir _((grafik))_ oluşturur. Bir grafik, noktaların (köydeki yerler) ve aralarındaki çizgilerin (yollar) olduğu bir koleksiyonudur. Bu grafik, robotumuzun hareket ettiği dünya olacak. {{index "roadGraph object"}} -The array of strings isn't very easy to work with. What we're interested in is the destinations that we can reach from a given place. Let's convert the list of roads to a data structure that, for each place, tells us what can be reached from there. +Dize dizisiyle çalışmak pek kolay değildir. İlgilendiğimiz şey, belirli bir yerden ulaşılabilen hedeflerdir. Hadi bu yol dizisini bize her yer için nereye gidilebileceğini söyleyen bir veri tipine çevirelim. ```{includeCode: true} function buildGraph(edges) { @@ -64,33 +64,35 @@ function buildGraph(edges) { const roadGraph = buildGraph(roads); ``` +Kenarlar dizisi verildiğinde, `buildGraph` her bir düğüm için bağlı düğümlerin bir dizisini depolayan bir map nesnesi oluşturur. + {{index "split method"}} -Given an array of edges, `buildGraph` creates a map object that, for each node, stores an array of connected nodes. It uses the `split` method to go from the road strings—which have the form `"Start-End"`)—to two-element arrays containing the start and end as separate strings. +`"Başlangıç-Bitiş"` şeklinde olan yol dizelerinden başlangıç ve bitişi ayrı dizeler olarak içeren iki öğeli dizilere gitmek için `split` metodunu kullanır. -## The task +## Görev -Our ((robot)) will be moving around the village. There are parcels in various places, each addressed to some other place. The robot picks up parcels when it comes across them and delivers them when it arrives at their destinations. +((Robotumuz)) köyde dolaşacak. Çeşitli yerlerde paketler var, her biri başka bir yere adreslenmiş. Robot, onlara geldiğinde paketleri alır ve varış noktalarına vardığında teslim eder. -The automaton must decide, at each point, where to go next. It has finished its task when all parcels have been delivered. +Her noktada, otomasyon bir sonraki hamlesinde nereye gideceğine karar vermelidir. Görevi, tüm paketler teslim edildiğinde tamamlanmış olur. {{index simulation, "virtual world"}} -To be able to simulate this process, we must define a virtual world that can describe it. This model tells us where the robot is and where the parcels are. When the robot has decided to move somewhere, we need to update the model to reflect the new situation. +Bu işlemi simüle edebilmek için, bunu açıklayabilen bir sanal dünya tanımlamamız gerekir. Bu model, robotun nerede olduğunu ve paketlerin nerede olduğunu bize söyler. Robot bir yere gitmeye karar verdiğinde, yeni durumu yansıtmak için modeli güncellememiz gerekir. {{index [state, in objects]}} -If you're thinking in terms of ((object-oriented programming)), your first impulse might be to start defining objects for the various elements in the world: a ((class)) for the robot, one for a parcel, maybe one for places. These could then hold properties that describe their current ((state)), such as the pile of parcels at a location, which we could change when updating the world. +Eğer ((nesne tabanlı programlama)) terimleriyle düşünüyorsanız, ilk düşünceniz dünyadaki çeşitli unsurlar için nesneleri tanımlamaya başlamak olabilir: bir robot için bir ((sınıf)), bir paket için bir tane, belki yerler için bir tane. Bunlar daha sonra dünyayı güncellerken değişen ((durumlarını)) açıklayan özellikler içerebilir. -This is wrong. At least, it usually is. The fact that something sounds like an object does not automatically mean that it should be an object in your program. Reflexively writing classes for every concept in your application tends to leave you with a collection of interconnected objects that each have their own internal, changing state. Such programs are often hard to understand and thus easy to break. +Bu yanlış. En azından genellikle öyledir. Bir şeyin bir nesne gibi görünmesi, otomatik olarak programınızdaki bir nesne olması gerektiği anlamına gelmez. Uygulamanızdaki her kavram için otomatik olarak sınıflar yazmak, genellikle birbirine bağlı ve kendi iç değişen durumlarına sahip nesneler koleksiyonuyla sonuçlanır. Bu tür programlar genellikle anlaşılması zor ve bu nedenle hata vermesi daha kolaydır. {{index [state, in objects]}} -Instead, let's condense the village's state down to the minimal set of values that define it. There's the robot's current location and the collection of undelivered parcels, each of which has a current location and a destination address. That's it. +Bunun yerine, köyün durumunu, onu tanımlayan minimum değerler kümesine indirgeyelim. Robotun şu anki konumu ve teslim edilmemiş paketlerin koleksiyonu var, her biri bir güncel konuma ve bir hedef adresine sahip. Bu kadar. {{index "VillageState class", "persistent data structure"}} -While we're at it, let's make it so that we don't _change_ this state when the robot moves but rather compute a _new_ state for the situation after the move. +Ayrıca köydeki durum değerini _değiştirmek_ yerine hareketten sonra durumu _yeni_ bir değer olarak tekrardan hesaplayalım. ```{includeCode: true} class VillageState { @@ -113,13 +115,13 @@ class VillageState { } ``` -The `move` method is where the action happens. It first checks whether there is a road going from the current place to the destination, and if not, it returns the old state since this is not a valid move. +`move` metodu aksiyonun olduğu yerdir. Öncelikle, mevcut yerden varış noktasına giden bir yol olup olmadığını kontrol eder ve yoksa, bu geçerli bir hamle değil olduğundan eski durumu döndürür. {{index "map method", "filter method"}} -Next, the method creates a new state with the destination as the robot's new place. It also needs to create a new set of parcels—parcels that the robot is carrying (that are at the robot's current place) need to be moved along to the new place. And parcels that are addressed to the new place need to be delivered—that is, they need to be removed from the set of undelivered parcels. The call to `map` takes care of the moving, and the call to `filter` does the delivering. +Sonra, robotun yeni yeri barındıracak şekilde yeni bir durum oluşturur. Ancak aynı zamanda yeni bir paket seti oluşturması gerekir — robotun taşıdığı paketler (robotun şu anki yerinde olanlar) yeni yere taşınmalıdır. Ve yeni yere adreslenen paketler teslim edilmelidir — yani, teslim edilmemiş paketler setinden kaldırılmalıdır. `map` çağrısı taşımayı, `filter` çağrısı ise teslimi yapar. -Parcel objects aren't changed when they are moved but re-created. The `move` method gives us a new village state but leaves the old one entirely intact. +Paket nesneleri taşındığında değiştirilmez, yeniden oluşturulur. `move` metodu bize yeni bir köy durumu verir ancak eski durumu tamamen bırakır. ``` let first = new VillageState( @@ -136,15 +138,15 @@ console.log(first.place); // → Post Office ``` -The move causes the parcel to be delivered, which is reflected in the next state. But the initial state still describes the situation where the robot is at the post office and the parcel is undelivered. +Hareket, paketin teslim edilmesine neden olur ve bu, sonraki durumda yansıtılır. Ancak, başlangıç durumu hala robotun postanede olduğu ve paketin teslim edilmediği durumu açıklar. -## Persistent data +## Kalıcı veriler {{index "persistent data structure", mutability, ["data structure", immutable]}} -Data structures that don't change are called _((immutable))_ or _persistent_. They behave a lot like strings and numbers in that they are who they are and stay that way, rather than containing different things at different times. +Veri yapıları, değişmeyen (_((değişmez))_ veya _kalıcı_) olarak adlandırılır. Onlar, oldukları gibi olan ve her zaman aynı kalan diziler ve sayılar gibi davranırlar, farklı zamanlarda farklı şeyler içermezler. -In JavaScript, just about everything _can_ be changed, so working with values that are supposed to be persistent requires some restraint. There is a function called `Object.freeze` that changes an object so that writing to its properties is ignored. You could use that to make sure your objects aren't changed, if you want to be careful. Freezing does require the computer to do some extra work, and having updates ignored is just about as likely to confuse someone as having them do the wrong thing. I usually prefer to just tell people that a given object shouldn't be messed with and hope they remember it. +JavaScript'te, neredeyse her şey değiştirilebilir olduğu için, kalıcı olması gereken değerlerle çalışmak bazı kısıtlamalar gerektirir. Nesnenin özelliklerine yazma özelliğini yok sayacak şekilde bir nesneyi değiştiren `Object.freeze` adında bir fonksiyon vardır. Dikkatli olmak isterseniz nesnelerinizin değişmediğinden emin olmak için bunu kullanabilirsiniz. Dondurma, bilgisayarın ekstra bir iş yapmasını gerektirir, ayrıca güncellemelerin yok sayılması yanlış bir şey yapmak kadar kafa karıştırabilir. Bu yüzden genellikle belirli bir nesnenin değiştirilmemesi gerektiğini söylemeyi tercih eder ve bunu hatırlamalarını umarım. ``` let object = Object.freeze({value: 5}); @@ -153,21 +155,23 @@ console.log(object.value); // → 5 ``` -Why am I going out of my way to not change objects when the language is obviously expecting me to? Because it helps me understand my programs. This is about complexity management again. When the objects in my system are fixed, stable things, I can consider operations on them in isolation—moving to Alice's house from a given start state always produces the same new state. When objects change over time, that adds a whole new dimension of complexity to this kind of reasoning. +Dil açıkça benden neden nesneleri değiştirmememi bekliyorken neden yolumdan sapıp değişmemeleri için ekstra efor sarf ediyorum ki? + +Çünkü bu, programlarımı anlamama yardımcı olur. Bu yine karmaşıklık yönetimi hakkında. Sistemimdeki nesneler sabit, istikrarlı şeyler olduğunda, bunlar üzerindeki işlemleri izole bir şekilde düşünebilirim - belirli bir başlangıç durumundan Alice'in evine gitmek her zaman aynı yeni durumu üretir. Nesnelerin zamanla değişmesi, bu tür bir akıl yürütme için tamamen yeni bir karmaşıklık boyutu ekler. -For a small system like the one we are building in this chapter, we could handle that bit of extra complexity. But the most important limit on what kind of systems we can build is how much we can understand. Anything that makes your code easier to understand makes it possible to build a more ambitious system. +Bu bölümde inşa ettiğimiz küçük bir sistem için, bu biraz ekstra karmaşıklığı idare edebiliriz. Ancak inşa edebileceğimiz sistemlerin ne tür olduğunu belirleyen en önemli sınırlama, ne kadar anlayabileceğimizdir. Kodunuzu anlamayı kolaylaştıran her şey, daha iddialı bir sistem inşa etmeyi mümkün kılar. -Unfortunately, although understanding a system built on persistent data structures is easier, _designing_ one, especially when your programming language isn't helping, can be a little harder. We'll look for opportunities to use persistent data structures in this book, but we'll also be using changeable ones. +Ne yazık ki, kalıcı veri yapıları üzerine inşa edilmiş bir sistemi anlamak daha kolay olsa da, özellikle programlama dili yardımcı olmadığında, bunu _tasarlamak_ biraz daha zor olabilir. Bu kitapta kalıcı veri yapılarını kullanma fırsatlarını arayacağız, ancak değiştirilebilir olanları da kullanacağız. -## Simulation +## Simülasyon {{index simulation, "virtual world"}} -A delivery ((robot)) looks at the world and decides in which direction it wants to move. As such, we could say that a robot is a function that takes a `VillageState` object and returns the name of a nearby place. +Bir teslimat ((robotu)), dünyaya bakar ve hangi yöne gitmek istediğine karar verir. Bu nedenle, bir robotun, bir `VillageState` nesnesini alıp yakınlardaki bir yerin adını döndüren bir fonksiyon olduğunu söyleyebiliriz. {{index "runRobot function"}} -Because we want robots to be able to remember things so they can make and execute plans, we also pass them their memory and allow them to return a new memory. Thus, the thing a robot returns is an object containing both the direction it wants to move in and a memory value that will be given back to it the next time it is called. +Robotların plan yapabilmeleri ve uygulayabilmeleri adına şeyleri hatırlayabilmelerini istiyor ve onlara belleklerini verip yeni bellek döndürmelerine izin veriyoruz. Dolayısıyla, robotun döndürdüğü şey, hem hareket etmek istediği yön hem de bir sonraki çağrıldığında geri verilecek bir bellek değeri içeren bir nesnedir. ```{includeCode: true} function runRobot(state, robot, memory) { @@ -184,13 +188,13 @@ function runRobot(state, robot, memory) { } ``` -Consider what a robot has to do to "solve" a given state. It must pick up all parcels by visiting every location that has a parcel and deliver them by visiting every location to which a parcel is addressed, but only after picking up the parcel. +Verilen bir durumu "çözmek" için bir robotun ne yapması gerektiğini düşünün. Tüm paketleri toplamalı, her bir paket alındıktan sonra paketin adreslendiği her yer ziyaret edilerek teslim edilmelidir. -What is the dumbest strategy that could possibly work? The robot could just walk in a random direction every turn. That means, with great likelihood, it will eventually run into all parcels and then also at some point reach the place where they should be delivered. +Çalışması mümkün olan en aptalca strateji nedir? Robot her turda rastgele bir yöne yürüyebilir. Bu, büyük olasılıkla, sonunda tüm paketlere rastlayacak ve sonra onları teslim etmeleri gereken yere ulaşacak demektir. {{index "randomPick function", "randomRobot function"}} -Here's what that could look like: +İşte o fikir bu şekilde görünebilir: ```{includeCode: true} function randomPick(array) { @@ -205,11 +209,11 @@ function randomRobot(state) { {{index "Math.random function", "Math.floor function", [array, "random element"]}} -Remember that `Math.random()` returns a number between zero and one—but always below one. Multiplying such a number by the length of an array and then applying `Math.floor` to it gives us a random index for the array. +`Math.random()`'ın her zaman sıfır ve bir arasında ancak birin altında bir sayı döndürdüğünü hatırlayın. Böyle bir bir sayıyı bir dizi uzunluğu ile çarpmak ve ardından `Math.floor` uygulamak bize dizi için rastgele bir index verir. -Since this robot does not need to remember anything, it ignores its second argument (remember that JavaScript functions can be called with extra arguments without ill effects) and omits the `memory` property in its returned object. +Bu robotun herhangi bir şeyi hatırlamasına gerek olmadığı için, ikinci argümanını görmezden gelir (JavaScript fonksiyonlarının ek argümanlarla çağrılması herhangi bir olumsuz etkiye neden olmadığını hatırlayın) ve döndürdüğü nesnesinde `memory` özelliğini dahil etmez. -To put this sophisticated robot to work, we'll first need a way to create a new state with some parcels. A static method (written here by directly adding a property to the constructor) is a good place to put that functionality. +Bu sofistike robota iş vermek için önce bazı paketlerle yeni bir durum oluşturmanın bir yoluna ihtiyacımız var. Bir statik metod (burada doğrudan bir özelliği constructor fonksiyonuna ekleyerek yazıldı) bu işlevselliği koymak için iyi bir yerdir. ```{includeCode: true} VillageState.random = function(parcelCount = 5) { @@ -228,9 +232,9 @@ VillageState.random = function(parcelCount = 5) { {{index "do loop"}} -We don't want any parcels to be sent from the same place that they are addressed to. For this reason, the `do` loop keeps picking new places when it gets one that's equal to the address. +Gönderildiği ve adreslendiği yerin aynı olduğu herhangi bir paket istemiyoruz. Bu nedenle, `do` döngüsü, adresle eşit olan bir yer aldığında yeni yerler almaya devam ediyor. -Let's start up a virtual world. +Hadi sanal bir dünya başlatalım. ```{test: no} runRobot(VillageState.random(), randomRobot); @@ -240,25 +244,25 @@ runRobot(VillageState.random(), randomRobot); // → Done in 63 turns ``` -It takes the robot a lot of turns to deliver the parcels because it isn't planning ahead very well. We'll address that soon. +Paketlerin teslim edilmesi için robota birçok tur gerekir çünkü ileriye dönük iyi plan yapmıyor. Bunun için yakında bir çözüm bulacağız. {{if interactive -For a more pleasant perspective on the simulation, you can use the `runRobotAnimation` function that's available in [this chapter's programming environment](https://eloquentjavascript.net/code/#7). This runs the simulation, but instead of outputting text, it shows you the robot moving around the village map. +Simülasyon üzerinde daha hoş bir bakış açısı için, [bu bölümün programlama ortamında](https://eloquentjavascript.net/code/#7) bulunan `runRobotAnimation` fonksiyonunu kullanabilirsiniz. Bu, simülasyonu çalıştırır, ancak metin çıktısı yerine robotun köy haritasında dolaştığını size gösterir. ```{test: no} runRobotAnimation(VillageState.random(), randomRobot); ``` -The way `runRobotAnimation` is implemented will remain a mystery for now, but after you've read the [later chapters](dom) of this book, which discuss JavaScript integration in web browsers, you'll be able to guess how it works. +`runRobotAnimation`'ın nasıl uygulandığı şimdilik bir sır olarak kalacak, ancak bu kitabın [daha sonraki bölümlerinde](dom), tarayıcılardaki JavaScript entegrasyonunu tartıştığı zaman, nasıl çalıştığını tahmin edebileceksiniz. if}} -## The mail truck's route +## Posta kamyonunun rotası {{index "mailRoute array"}} -We should be able to do a lot better than the random ((robot)). An easy improvement would be to take a hint from the way real-world mail delivery works. If we find a route that passes all places in the village, the robot could run that route twice, at which point it is guaranteed to be done. Here is one such route (starting from the post office): +Rastgele bir ((robot))tan çok daha iyi yapabilmeliyiz. Kolay bir iyileştirme, gerçek dünya posta teslimatının çalışma şeklinden bir ipucu almak olacaktır. Köydeki tüm yerlerden geçen bir rota bulursak, robot bu rotayı iki kez çalıştırabilir ve bu noktada işinin bitmiş olacağı garantilenir. İşte böyle bir rota (posta ofisinden başlayarak): ```{includeCode: true} const mailRoute = [ @@ -271,7 +275,7 @@ const mailRoute = [ {{index "routeRobot function"}} -To implement the route-following robot, we'll need to make use of robot memory. The robot keeps the rest of its route in its memory and drops the first element every turn. +Rota takip eden robotu uygulamak için, robot hafızasını kullanmamız gerekecek. Robot, her turda hafızasındaki geri kalan rotayı saklar ve her turda ilk öğeyi bırakır. ```{includeCode: true} function routeRobot(state, memory) { @@ -282,7 +286,7 @@ function routeRobot(state, memory) { } ``` -This robot is a lot faster already. It'll take a maximum of 26 turns (twice the 13-step route) but usually less. +Bu robot zaten şimdiden çok daha hızlı. En fazla 26 tur alacak (13 adımlık rotanın iki katı) ama genellikle daha az. {{if interactive @@ -292,25 +296,25 @@ runRobotAnimation(VillageState.random(), routeRobot, []); if}} -## Pathfinding +## Yol bulma -Still, I wouldn't really call blindly following a fixed route intelligent behavior. The ((robot)) could work more efficiently if it adjusted its behavior to the actual work that needs to be done. +Yine de, sabit bir rotayı körü körüne takip etmeyi gerçekten akıllı davranış olarak adlandırmayız. ((Robot)), gerçekten yapılması gereken işe göre davranışını ayarlayarak daha verimli çalışabilir. {{index pathfinding}} -To do that, it has to be able to deliberately move toward a given parcel or toward the location where a parcel has to be delivered. Doing that, even when the goal is more than one move away, will require some kind of route-finding function. +Bunu yapabilmek için, belirli bir parselin yanına veya bir parselin teslim edilmesi gereken yere bilerek hareket edebilmesi gerekir. Bunun yapılması, hedef bir hamleden fazla uzakta olsa bile, bir tür rota bulma fonksiyonu gerektirir. -The problem of finding a route through a ((graph)) is a typical _((search problem))_. We can tell whether a given solution (a route) is valid, but we can't directly compute the solution the way we could for 2 + 2. Instead, we have to keep creating potential solutions until we find one that works. +((Graf)) içinden bir rota bulma problemi tipik bir _((arama problemi))_'dir. Verilen bir çözümün (bir rota) geçerli bir çözüm olup olmadığını söyleyebiliriz, ancak 2 + 2 için olduğu gibi doğrudan çözümü hesaplayamayız. Bunun yerine, işe yarayan bir tane bulana kadar potansiyel çözümler oluşturmaya devam etmeliyiz. -The number of possible routes through a graph is infinite. But when searching for a route from _A_ to _B_, we are interested only in the ones that start at _A_. We also don't care about routes that visit the same place twice—those are definitely not the most efficient route anywhere. So that cuts down on the number of routes that the route finder has to consider. +Bir graf içinden mümkün olan rotaların sayısı sonsuzdur. Ancak _A_ noktasından _B_ noktasına bir rota ararken, sadece _A_ noktasından başlayanlarla ilgileniriz. Ayrıca aynı yeri iki kez ziyaret eden rotaları umursamıyoruz - bunlar kesinlikle herhangi bir yerdeki en verimli rota değil. Bu, rota bulucunun düşünmesi gereken rota sayısını azaltır. -In fact, since we are mostly interested in the _shortest_ route, we want to make sure we look at short routes before we look at longer ones. A good approach would be to "grow" routes from the starting point, exploring every reachable place that hasn't been visited yet until a route reaches the goal. That way, we'll only explore routes that are potentially interesting, and we know that the first route we find is the shortest route (or one of the shortest routes, if there are more than one). +Aslında, genellikle _en kısa_ rotaya ilgi duyarız. Bu nedenle, daha uzun olanlara bakmadan önce kısa rotalara bakmak istiyoruz. Bir rota hedefine ulaşana kadar rotaları başlangıç noktasından büyüterek her henüz ziyaret edilmemiş erişilebilir yeri keşfetmek bu durumda iyi bir yaklaşım olurdu. Bu şekilde, potansiyel olarak ilginç olan rotaları keşfetmiş oluruz ve ilk bulduğumuz rotanın en kısa veya birden fazlaysa en kısalarından biri olan rota olduğunu biliyoruz. {{index "findRoute function"}} {{id findRoute}} -Here is a function that does this: +İşte bunu yapan bir fonksiyon: ```{includeCode: true} function findRoute(graph, from, to) { @@ -327,17 +331,17 @@ function findRoute(graph, from, to) { } ``` -The exploring has to be done in the right order—the places that were reached first have to be explored first. We can't immediately explore a place as soon as we reach it because that would mean places reached _from there_ would also be explored immediately, and so on, even though there may be other, shorter paths that haven't yet been explored. +Keşfetme işlemi doğru sırayla yapılmalıdır - ilk önce ulaşılan yerlerin öncelikle keşfedilmesi gerekir. Bir yeri ona ulaştığımız anda hemen keşfetmemeliyiz çünkü bu, _oradan ulaşılan yerlerin_ de hemen keşfedilmesi anlamına gelir ve bu böyle devam eder ancak oysa ki daha önceden keşfedilmemiş diğer daha kısa yollar olabilir. -Therefore, the function keeps a _((work list))_. This is an array of places that should be explored next, along with the route that got us there. It starts with just the start position and an empty route. +Bu nedenle, fonksiyon bir _((çalışma listesi))_ tutar. Bu, keşfedilmesi gereken yerlerin ve bizi oraya götüren rotanın bir listesidir. Sadece başlangıç pozisyonu ve boş bir rota ile başlar. -The search then operates by taking the next item in the list and exploring that, which means it looks at all roads going from that place. If one of them is the goal, a finished route can be returned. Otherwise, if we haven't looked at this place before, a new item is added to the list. If we have looked at it before, since we are looking at short routes first, we've found either a longer route to that place or one precisely as long as the existing one, and we don't need to explore it. +Arama, daha sonraki öğeyi listeye alarak ve bunu keşfeterek çalışır, yani o yerden giden tüm yollar incelenir. Eğer bunlardan biri hedefse, tamamlanmış bir rota döndürülebilir. Aksi takdirde, bu yeri daha önce görmediysek, yeni bir öğe listeye eklenir. Daha önce gördüysek, kısa rotalara önce baktığımız için, o yere daha uzun bir rota veya mevcut rotanın tam olarak uzunluğunda bir rota bulduk ve bunu keşfetmemize gerek yoktur. -You can visualize this as a web of known routes crawling out from the start location, growing evenly on all sides (but never tangling back into itself). As soon as the first thread reaches the goal location, that thread is traced back to the start, giving us our route. +Bunu, bilinen rotaların başlangıç konumundan dışarıya doğru her tarafından eşit büyüyen ve kendisine geri dönmeyecek bir şekilde yayılan bir ağ gibi görsel olarak hayal edebilirsiniz. İlk ipliğin hedef konumunu bulduğu anda, bu iplik başlangıç noktasına geri izlenir, böylece rotamızı alırız. {{index "connected graph"}} -Our code doesn't handle the situation where there are no more work items on the work list because we know that our graph is _connected_, meaning that every location can be reached from all other locations. We'll always be able to find a route between two points, and the search can't fail. +Kodumuz, iş listesinde artık iş öğeleri olmadığında nasıl başa çıkacağını ele almaz çünkü grafımızın _bağlı_ olduğunu biliyoruz, yani her konuma diğer tüm konumlardan ulaşılabilir. İki nokta arasında bir rota bulabileceğiz ve arama başarısız olamaz. ```{includeCode: true} function goalOrientedRobot({place, parcels}, route) { @@ -355,11 +359,11 @@ function goalOrientedRobot({place, parcels}, route) { {{index "goalOrientedRobot function"}} -This robot uses its memory value as a list of directions to move in, just like the route-following robot. Whenever that list is empty, it has to figure out what to do next. It takes the first undelivered parcel in the set and, if that parcel hasn't been picked up yet, plots a route toward it. If the parcel _has_ been picked up, it still needs to be delivered, so the robot creates a route toward the delivery address instead. +Bu robot hafıza değerini gideceği rotayı takip etmek amacıyla kullanır, aynı rota takıp eden robot gibi. Liste boş olduğunda, ne yapacağını bulmak zorundadır. Kümesindeki ilk teslim edilmemiş parseli alır ve bu parsel henüz alınmadıysa, ona doğru bir rota çizer. Pakelet _alınmışsa_, hala teslim edilmesi gerektiğinden, robot teslim adresine doğru bir rota oluşturur. {{if interactive -Let's see how it does. +Hadi bunu nasıl yaptığını görelim. ```{test: no, startCode: true} runRobotAnimation(VillageState.random(), @@ -368,53 +372,54 @@ runRobotAnimation(VillageState.random(), if}} -This robot usually finishes the task of delivering 5 parcels in about 16 turns. That's slightly better than `routeRobot` but still definitely not optimal. We'll continue refining it in the exercises. +Bu robot, genellikle 5 paketi teslim etme görevini yaklaşık 16 turda tamamlar. Bu, `routeRobottan` biraz daha iyidir, ancak kesinlikle olabilecek en iyi durum değil. -## Exercises +## Egzersizler -### Measuring a robot +### Bir robotun ölçülmesi {{index "measuring a robot (exercise)", testing, automation, "compareRobots function"}} -It's hard to objectively compare ((robot))s by just letting them solve a few scenarios. Maybe one robot just happened to get easier tasks or the kind of tasks that it is good at, whereas the other didn't. +((Robot))ları sadece birkaç senaryoyu çözmelerine izin vererek nesnel bir şekilde karşılaştırmak zordur. Belki de bir robot tesadüfen daha kolay görevler aldı ve diğeri alamadı ya da belki de bir robot tesadüfen daha iyi olduğu türde görevler alırken diğeri alamadı. -Write a function `compareRobots` that takes two robots (and their starting memory). It generates 100 tasks and lets each of the robots solve each of these tasks. When done, it outputs the average number of steps each robot took per task. +`compareRobots` adında iki ((robot)) (ve başlangıç hafızaları) alan bir fonksiyon yazın. Bu, 100 görev oluşturmalı ve her bir robotun bu görevleri çözmesine izin vermelidir. Bittiğinde, her robotun görev başına ortalama adım sayısını çıkarmalıdır. -For the sake of fairness, make sure you give each task to both robots, rather than generating different tasks per robot. +Adil olmak için, her robotu farklı görevlere değil, aynı görevlere yönlendirdiğinizden emin olmalısınız. {{if interactive ```{test: no} function compareRobots(robot1, memory1, robot2, memory2) { - // Your code here + // Kodunuz buraya. } compareRobots(routeRobot, [], goalOrientedRobot, []); ``` + if}} {{hint {{index "measuring a robot (exercise)", "runRobot function"}} -You'll have to write a variant of the `runRobot` function that, instead of logging the events to the console, returns the number of steps the robot took to complete the task. +Her iki robot için de görev veren `runRobot` fonksiyonunun bir varyantını yazmalısınız. Bu fonksiyon, konsola olayları kaydetmek yerine, robotun görevi tamamlamak için attığı adım sayısını döndürmelidir. -Your measurement function can then, in a loop, generate new states and count the steps each of the robots takes. When it has generated enough measurements, it can use `console.log` to output the average for each robot, which is the total number of steps taken divided by the number of measurements. +Ölçüm fonksiyonunuz ardından, bir döngü içinde yeni durumlar oluşturmalı ve her bir robotun attığı adımları saymalıdır. Yeterince ölçüm yapıldığında, her robot için ortalama adım sayısı olan toplam adım sayısı bölü ölçümlerin sayısının sonucunu `console.log` kullanarak çıkarmalıdır. hint}} -### Robot efficiency +### Robot verimliliği {{index "robot efficiency (exercise)"}} -Can you write a robot that finishes the delivery task faster than `goalOrientedRobot`? If you observe that robot's behavior, what obviously stupid things does it do? How could those be improved? +`goalOrientedRobottan` daha hızlı teslimat görevini tamamlayan bir robot yazabilir misiniz? O robotun davranışını gözlemlediğinizde, açıkça aptalca şeyler nelerdir? Onları nasıl iyileştirebilirsiniz? -If you solved the previous exercise, you might want to use your `compareRobots` function to verify whether you improved the robot. +Önceki egzersizi çözdüyseniz, robotu iyileştirip iyileştirmediğinizi doğrulamak için `compareRobots` fonksiyonunuzu kullanmak isteyebilirsiniz. {{if interactive ```{test: no} -// Your code here +// Kodunuz buraya. runRobotAnimation(VillageState.random(), yourRobot, memory); ``` @@ -425,35 +430,37 @@ if}} {{index "robot efficiency (exercise)"}} -The main limitation of `goalOrientedRobot` is that it considers only one parcel at a time. It will often walk back and forth across the village because the parcel it happens to be looking at happens to be at the other side of the map, even if there are others much closer. +`goalOrientedRobot`'un ana kısıtlaması, aynı anda yalnızca bir parseli düşünmesidir. Çoğu zaman, üzerinde durduğu parselin teslim noktasının haritanın diğer tarafında olması nedeniyle köyde ileri geri yürür ancak oysa ki o bulunduğu anda teslim edebileceği daha yakın noktalarda bulunan noktalar vardır. -One possible solution would be to compute routes for all packages and then take the shortest one. Even better results can be obtained, if there are multiple shortest routes, by preferring the ones that go to pick up a package instead of delivering a package. +Bir çözüm, tüm paketler için rotaları hesaplamak ve ardından en kısa olanı almak olabilir. Birden fazla en kısa rota varsa, bir paket almak yerine bir paketi teslim etmeyi tercih edenleri tercih ederek daha iyi sonuçlar elde edilebilir. hint}} -### Persistent group +### Kalıcı grup {{index "persistent group (exercise)", "persistent data structure", "Set class", "set (data structure)", "Group class", "PGroup class"}} -Most data structures provided in a standard JavaScript environment aren't very well suited for persistent use. Arrays have `slice` and `concat` methods, which allow us to easily create new arrays without damaging the old one. But `Set`, for example, has no methods for creating a new set with an item added or removed. +Standart bir JavaScript ortamında sağlanan çoğu veri yapısı, kalıcı kullanım için çok uygun değildir. Diziler, eskiyi bozmadan yeni diziler oluşturmamızı sağlayan `slice` ve `concat` metodlarına sahiptir. Ancak, `Set` örneğin, bir öğe eklenmiş veya kaldırılmış yeni bir set oluşturmak için yöntemlere sahip değildir. + +[? Bölüm](object#groups) içinden alınan `Group` sınıfına benzer yeni bir sınıf olan ve bir set değerler depolayan `PGroup` adında bir sınıf yazın. `Group` gibi, `add`, `delete` ve `has` metodlarına sahiptir. -Write a new class `PGroup`, similar to the `Group` class from [Chapter ?](object#groups), which stores a set of values. Like `Group`, it has `add`, `delete`, and `has` methods. Its `add` method, however, returns a _new_ `PGroup` instance with the given member added and leaves the old one unchanged. Similarly, `delete` creates a new instance without a given member. +Ancak, `add` metodunun, verilen üye eklenmiş bir yeni `PGroup` örneği döndürmesi ve eskiyi değiştirmemesi gerekir. Benzer şekilde, `delete` belirli bir üye olmadan yeni bir örnek oluşturur. -The class should work for values of any type, not just strings. It does _not_ have to be efficient when used with large numbers of values. +Sınıf, sadece dizeler değil, herhangi bir türün değerleri için çalışmalıdır. Büyük miktarda değerle kullanıldığında etkin olmak zorunda _değildir_. {{index [interface, object]}} -The ((constructor)) shouldn't be part of the class's interface (though you'll definitely want to use it internally). Instead, there is an empty instance, `PGroup.empty`, that can be used as a starting value. +((Constructor)), sınıfın arabirimine dahil edilmemelidir (ancak içsel olarak kullanmak isteyeceksinizdir). Bunun yerine, kullanılabilecek bir başlangıç değeri olan `PGroup.empty` adında bir boş örnek vardır. {{index singleton}} -Why do you need only one `PGroup.empty` value, rather than having a function that creates a new, empty map every time? +Neden her seferinde yeni, boş bir harita oluşturan bir işlev yerine yalnızca bir `PGroup.empty` değerine ihtiyacınız var? {{if interactive ```{test: no} class PGroup { - // Your code here + // Kodunuz buraya. } let a = PGroup.empty.add("a"); @@ -474,18 +481,18 @@ if}} {{index "persistent map (exercise)", "Set class", [array, creation], "PGroup class"}} -The most convenient way to represent the set of member values is still as an array since arrays are easy to copy. +Üye değerlerinin kümesini temsil etmenin en uygun yolu kopyalaması kolay olduğundan ötürü hala dizilerdir. {{index "concat method", "filter method"}} -When a value is added to the group, you can create a new group with a copy of the original array that has the value added (for example, using `concat`). When a value is deleted, you filter it from the array. +Bir değer grubuna eklendiğinde, eklenen değere sahip orijinal dizinin bir kopyası ile yeni bir grup oluşturabilirsiniz (örneğin, `concat` kullanarak). Bir değer silindiğinde, onu diziden filtreleyerek çıkarabilirsiniz. -The class's ((constructor)) can take such an array as argument and store it as the instance's (only) property. This array is never updated. +Sınıfın ((constructor)) fonksiyonu böyle bir diziyi (tek) özelliği olarak alabilir ve bunu örneğin özelliği olarak depolayabilir. Bu dizi asla güncellenmez. {{index "static property"}} -To add the `empty` property to the constructor, you can declare it as a static property. +`empty` özelliğini constructor fonksiyonuna eklemek adına bunu bir statik özellik olarak bildirebilirsiniz. -You need only one `empty` instance because all empty groups are the same and instances of the class don't change. You can create many different groups from that single empty group without affecting it. +Sadece bir `empty` örneğine ihtiyacınız vardır çünkü tüm boş gruplar aynıdır ve sınıfın örnekleri değişmez. Bu tek boş grubu etkilemeden kullanarak birçok farklı grup oluşturabilirsiniz. hint}} diff --git a/08_error.md b/08_error.md index dfb889b1..924ab623 100644 --- a/08_error.md +++ b/08_error.md @@ -1,46 +1,46 @@ {{meta {load_files: ["code/chapter/08_error.js"]}}} -# Bugs and Errors +# Sorun ve hatalar -{{quote {author: "Brian Kernighan and P.J. Plauger", title: "The Elements of Programming Style", chapter: true} +{{quote {author: "Brian Kernighan and P.J. Plauger", title: "Programlama Stilinin Unsurları", chapter: true} -Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. +Hata ayıklama, kodu yazmaktan iki kat daha zordur. Bu nedenle, mümkün olduğunca zeki bir şekilde kod yazarsanız, onu ayıklamak için yeterince zeki olmayacaksınız. quote}} -{{figure {url: "img/chapter_picture_8.jpg", alt: "Illustration showing various insects and a centipede", chapter: framed}}} +{{figure {url: "img/chapter_picture_8.jpg", alt: "Çeşitli böcekleri ve bir kırkayağı gösteren illüstrasyon", chapter: framed}}} {{index "Kernighan, Brian", "Plauger, P.J.", debugging, "error handling"}} -Flaws in computer programs are usually called _((bug))s_. It makes programmers feel good to imagine them as little things that just happen to crawl into our work. In reality, of course, we put them there ourselves. +Bilgisayar programlarındaki hatalar genellikle _((hata))_ olarak adlandırılır. Onları işimizin içine sürünen küçük şeyler olarak hayal etmek programcıların kendilerini iyi hissetmelerini sağlar. Gerçekte ise, tabii ki, onları kendimiz koyarız. -If a program is crystallized thought, we can roughly categorize bugs into those caused by the thoughts being confused and those caused by mistakes introduced while converting a thought to code. The former type is generally harder to diagnose and fix than the latter. +Bir program kristalleşmiş düşüncelerse, hataları düşüncelerin karıştırılması nedeniyle veya bir düşüncenin kod haline getirilirken yapılan hatalar nedeniyle oluşan hatalar olarak kabaca sınıflandırabilirsiniz. İlk tür genellikle ikincisinden daha zor teşhis edilir ve düzeltilir. -## Language +## Dil {{index parsing, analysis}} -Many mistakes could be pointed out to us automatically by the computer, if it knew enough about what we're trying to do. But here JavaScript's looseness is a hindrance. Its concept of bindings and properties is vague enough that it will rarely catch ((typo))s before actually running the program. Even then, it allows you to do some clearly nonsensical things without complaint, such as computing `true * "monkey"`. +Bilgisayar, ne yapmaya çalıştığımız hakkında yeterince bilgiye sahip olsaydı, birçok hatayı otomatik olarak bize gösterebilirdi. Ancak burada JavaScript'in gevşekliği bir engeldir. Bağlantılarının ve özelliklerinin kavramlarının belirsizliği, programı çalıştırmadan önce nadiren ((yazım hatalarını)) yakalar. Ve hatta öyle olsa bile, size `true * "monkey"` gibi açıkça mantıksız şeyleri yapmanıza izin verir, şikayet etmez. {{index [syntax, error], [property, access]}} -There are some things that JavaScript does complain about. Writing a program that does not follow the language's ((grammar)) will immediately make the computer complain. Other things, such as calling something that's not a function or looking up a property on an ((undefined)) value, will cause an error to be reported when the program tries to perform the action. +JavaScript'in şikayet ettiği bazı şeyler vardır. Dilin ((sözdizimi))ni izlemeyen bir program yazmak bilgisayarın hemen şikayet etmesini sağlar. Başka şeylere olarak örneğin fonksiyon olmayan bir şeyi çağırmak veya bir ((undefined)) değerinde özellik aramak, program harekete geçtiğinde bir hataya neden olur. {{index NaN, error}} -Often, however, your nonsense computation will merely produce `NaN` (not a number) or an undefined value, while the program happily continues, convinced that it's doing something meaningful. The mistake will manifest itself only later, after the bogus value has traveled through several functions. It might not trigger an error at all but silently cause the program's output to be wrong. Finding the source of such problems can be difficult. +Ancak genellikle, bu saçma hesaplama sadece `NaN` (sayı değil) veya tanımsız bir değer üretirken, program yaptığı şeyin anlamlı olduğuna ikna olmuş ve mutlu bir halde devam eder. Hata, sadece sahte değer birkaç fonksiyondan geçtikten sonra kendini gösterir. Hata hiç tetiklenmeyebilir, ancak sessizce programın çıktısını yanlış yapabilir. Bu tür sorunların kaynağını bulmak zor olabilir. -The process of finding mistakes—bugs—in programs is called _((debugging))_. +Programlardaki hataları bulma sürecine ((hata ayıklama)) denir. -## Strict mode +## Katı mod {{index "strict mode", [syntax, error], function}} {{indexsee "use strict", "strict mode"}} -JavaScript can be made a _little_ stricter by enabling _strict mode_. This can done by putting the string `"use strict"` at the top of a file or a function body. Here's an example: +JavaScript, _katı modu_ etkinleştirilerek _biraz_ daha katı hale getirilebilir. Bunun için dosyanın veya fonksiyon gövdesinin üstüne `"use strict"` dizesini koymak yeterlidir. İşte bir örnek: -```{test: "error \"ReferenceError: counter is not defined\""} +```{test: "error "ReferenceError: counter is not defined""} function canYouSpotTheProblem() { "use strict"; for (counter = 0; counter < 10; counter++) { @@ -54,17 +54,17 @@ canYouSpotTheProblem(); {{index ECMAScript, compatibility}} -Code inside classes and modules (which we will discuss in [Chapter ?](modules)) is automatically strict. The old non-strict behavior still exists only because some old code might depend on it, and the language designers work hard to avoid breaking any existing programs. +Code inside classes and modules (which we will discuss in [Chapter ?](modules)) is automatically strict. The old nonstrict behavior still exists only because some old code might depend on it, and the language designers work hard to avoid breaking any existing programs. {{index "let keyword", [binding, global]}} -Normally, when you forget to put `let` in front of your binding, as with `counter` in the example, JavaScript quietly creates a global binding and uses that. In strict mode, an ((error)) is reported instead. This is very helpful. It should be noted, though, that this doesn't work when the binding in question already exists somewhere in scope. In that case, the loop will still quietly overwrite the value of the binding. +Normalde, örnekte olduğu gibi bağlantının önüne `let` koymayı unuttuğunuzda, JavaScript sessizce genel bir bağlantı oluşturur ve onu kullanır. Katı modda ise, bir ((hata)) bildirilir. Bu çok yardımcı olur. Bununla birlikte, söz konusu bağlantı zaten kapsamın başka bir yerinde varsa, bu durumda döngü hala sessizce bağlantının değerini üzerine yazar. {{index "this binding", "global object", undefined, "strict mode"}} -Another change in strict mode is that the `this` binding holds the value `undefined` in functions that are not called as ((method))s. When making such a call outside of strict mode, `this` refers to the global scope object, which is an object whose properties are the global bindings. So if you accidentally call a method or constructor incorrectly in strict mode, JavaScript will produce an error as soon as it tries to read something from `this`, rather than happily writing to the global scope. +Katı moddaki başka bir değişiklik, `this` bağlantısının, ((metod)) olarak çağrılmayan fonksiyonlarda `undefined` değerini taşımasıdır. Bu tür bir çağrıyı katı mod dışında yaparken, `this` küresel kapsam nesnesine atıfta bulunur, bu da özellikleri küresel bağlantılardan oluşan bir nesnedir. Dolayısıyla, katı modda bir yöntemi veya `constructor` fonksiyonunu yanlışlıkla yanlış bir şekilde çağırırsanız, JavaScript, küresel kapsama değerler yazmak yerine `this` bağlantısından bir şey okumaya çalışıldığında hemen bir hata üretir. -For example, consider the following code, which calls a ((constructor)) function without the `new` keyword so that its `this` will _not_ refer to a newly constructed object: +Örneğin aşağıdaki kodu düşünün, `new` anahtar kelimesi olmadan ((constructor)) fonksiyonunu çağırır, böylece `this` bağlantısı _yeni_ oluşturulan bir nesneye atanmaz: ``` function Person(name) { this.name = name; } @@ -75,34 +75,34 @@ console.log(name); {{index error}} -The bogus call to `Person` succeeded but returned an undefined value and created the global binding `name`. In strict mode, the result is different. +Bu nedenle, `Person` constructor fonksiyonuna yapılan yanlış çağrı başarılı oldu, ancak tanımsız bir değer döndü ve `name` adında bir küresel bir bağlantı oluşturdu. Katı modda, sonuç farklıdır. -```{test: "error \"TypeError: Cannot set properties of undefined (setting 'name')\""} +```{test: "error "TypeError: Cannot set properties of undefined (setting 'name')""} "use strict"; function Person(name) { this.name = name; } let ferdinand = Person("Ferdinand"); // forgot new // → TypeError: Cannot set property 'name' of undefined ``` -We are immediately told that something is wrong. This is helpful. +Hemen bir şeyin yanlış olduğu bize bildirilir. Bu yardımcı olur. -Fortunately, constructors created with the `class` notation will always complain if they are called without `new`, making this less of a problem even in non-strict mode. +Neyse ki, `class` notasyonuyla oluşturulan constructor fonksiyonları `new` olmadan çağrıldığında her zaman bir şikayet bildirir, bu da bu sorunun katı mod dışında olmamıza rağmen engellenmesini sağlar. {{index parameter, [binding, naming], "with statement"}} -Strict mode does a few more things. It disallows giving a function multiple parameters with the same name and removes certain problematic language features entirely (such as the `with` statement, which is so wrong it is not further discussed in this book). +Katı mod birkaç başka şey daha yapar. Bir fonksiyona aynı isimli birden fazla parametre vermenizi engeller ve bazı sorunlu dil özelliklerini tamamen kaldırır (örneğin, çok yanlış olan ve bu kitapta daha fazla tartışılmayacak olan `with` ifadesi gibi). {{index debugging}} -In short, putting `"use strict"` at the top of your program rarely hurts and might help you spot a problem. +Kısacası, programınızın başına `"use strict"` koymak nadiren zarar verir ve bir sorunu fark etmenize yardımcı olabilir. -## Types +## Tipler -Some languages want to know the types of all your bindings and expressions before even running a program. They will tell you right away when a type is used in an inconsistent way. JavaScript considers types only when actually running the program, and even there often tries to implicitly convert values to the type it expects, so it's not much help. +Bazı diller, bir programı çalıştırmadan önce tüm bağlantılarınızın ve ifadelerinizin türlerini bilmek ister. Bir türün tutarsız bir şekilde kullanıldığı durumlar hemen belirtilir. JavaScript, türleri sadece programı çalıştırırken dikkate alır ve hatta orada bile sıklıkla değerleri beklediği türe implicit bir şekilde dönüştürmeye çalışır, bu yüzden çok yardımcı olmaz. -Still, types provide a useful framework for talking about programs. A lot of mistakes come from being confused about the kind of value that goes into or comes out of a function. If you have that information written down, you're less likely to get confused. +Yine de türler programlar hakkında konuşmak adına kullanışlı bir çerçeve sağlar. Birçok hata, bir fonksiyona giren veya çıkan değer türü hakkında kafanız karıştığında gelir. Bu bilgiyi yazılı olarak belirtirseniz, kafanız karışma olasılığınız daha az olur. -You could add a comment like the following before the `findRoute` function from the previous chapter to describe its type: +Önceki bölümdeki `findRoute` fonksiyonunun türünü açıklamak için, aşağıdaki gibi bir yorum ekleyebilirsiniz: ``` // (graph: Object, from: string, to: string) => string[] @@ -111,31 +111,31 @@ function findRoute(graph, from, to) { } ``` -There are a number of different conventions for annotating JavaScript programs with types. +JavaScript programlarını türlerle işaretlemenin birkaç farklı üzerine anlaşılmış ve sıklıkla kullanılan yolları vardır. -One thing about types is that they need to introduce their own complexity to be able to describe enough code to be useful. What do you think would be the type of the `randomPick` function that returns a random element from an array? You'd need to introduce a _((type variable))_, _T_, which can stand in for any type, so that you can give `randomPick` a type like `(T[]) → T` (function from an array of *T*s to a *T*). +Türler hakkında bir şey, yararlı olacak kadar yeterli kodu açıklayabilmeleri için kendi karmaşıklıklarını tanıtmaları gerektiğidir. Bir diziden rastgele bir öğe döndüren `randomPick` fonksiyonunun türü sizce ne olmalıdır? Bunun için `randomPick` fonksiyonuna herhangi bir tür değeri alabilecek bir ((tür değişkeni)) `T` tanıtmalısınız ki `randomPick` fonksiyonuna `(T[]) → T` (_T_ türünde bir dizi alan ve bir _T_ türünde veri döndüren fonksiyon) gibi bir tür verebilin. {{index "type checking", TypeScript}} {{id typing}} -When the types of a program are known, it is possible for the computer to _check_ them for you, pointing out mistakes before the program is run. There are several JavaScript dialects that add types to the language and check them. The most popular one is called [TypeScript](https://www.typescriptlang.org/). If you are interested in adding more rigor to your programs, I recommend you give it a try. +Bir programın türleri bilindiğinde, bilgisayarın bunları kontrol edebilir ve program çalıştırılmadan önce hataları belirtebilir. Dilin türler ekleyen ve bunları kontrol eden birkaç JavaScript lehçeleri vardır. En popüler olanı [TypeScript](https://www.typescriptlang.org/) olarak adlandırılır. Programlarınıza daha fazla titizlik eklemek istiyorsanız, denemenizi öneririm. -In this book, we'll continue using raw, dangerous, untyped JavaScript code. +Bu kitapta, ham, tehlikeli, türsüz JavaScript kodunu kullanmaya devam edeceğiz. -## Testing +## Test yapma {{index "test suite", "run-time error", automation, testing}} -If the language is not going to do much to help us find mistakes, we'll have to find them the hard way: by running the program and seeing whether it does the right thing. +Dilin kendisi hataları bulmamıza çok yardımcı olmayacaksa, zor yoldan hataları bulmak için programı çalıştırıp doğru şeyi yapıp yapmadığına bakmak durumunda kalacağız. -Doing this by hand, again and again, is a really bad idea. Not only is it annoying, it also tends to be ineffective since it takes too much time to exhaustively test everything every time you make a change. +Bunu el ile tekrar tekrar yapmak gerçekten kötü bir fikirdir. Sadece can sıkıcı olmakla kalmaz, aynı zamanda her değişiklik yaptığınızda her şeyi kapsamlı bir şekilde test etmek çok zaman alacağından genellikle etkisiz olur. -Computers are good at repetitive tasks, and testing is the ideal repetitive task. Automated testing is the process of writing a program that tests another program. Writing tests is a bit more work than testing manually, but once you've done it, you gain a kind of superpower: it takes you only a few seconds to verify that your program still behaves properly in all the situations you wrote tests for. When you break something, you'll immediately notice, rather than randomly running into it at some later time. +Bilgisayarlar tekrarlayan görevlerde iyidir ve test etme ideal bir tekrarlayan görevdir. Otomatik test, başka bir programı test eden bir program yazma sürecidir. Testleri yazmak manuel olarak test etmekten biraz daha fazla çalışma gerektirir, ancak bir kez yaptıktan sonra, bir tür süper güç kazanırsınız: programınızın hala yazdığınız tüm durumlarda doğru şekilde davrandığını doğrulamak için sadece birkaç saniyenizi alır. Bir şeyi bozarsanız başka bir zamanda rastgele karşılaşmak yerine hemen fark edersiniz. {{index "toUpperCase method"}} -Tests usually take the form of little labeled programs that verify some aspect of your code. For example, a set of tests for the (standard, probably already tested by someone else) `toUpperCase` method might look like this: +Testler genellikle kodunuzun bazı yönlerini doğrulayan küçük etiketli programlar şeklinde olur. Örneğin, (standart olarak dilin içinde bulunan ve zaten muhtemelen başka biri tarafından zaten test edilmiş olan) `toUpperCase` metodunun bir dizi testi şöyle olabilir: ``` function test(label, body) { @@ -155,27 +155,28 @@ test("don't convert case-less characters", () => { {{index "domain-specific language"}} -Writing tests like this tends to produce rather repetitive, awkward code. Fortunately, there exist pieces of software that help you build and run collections of tests (_((test suites))_) by providing a language (in the form of functions and methods) suited to expressing tests and by outputting informative information when a test fails. These are usually called _((test runners))_. +Böyle testler yazmak genellikle oldukça tekrarlayan garip kodlar üretir. Neyse ki, test koleksiyonları oluşturmanıza ve çalıştırmanıza yardımcı olan yazılım parçaları vardır (_((test paketleri))_), testleri ifade etmek için fonksiyonlar ve metotlar şeklinde uygun bir dil sağlayar ve bir test başarısız olduğunda bilgilendirici bilgiler verir. Bunlar genellikle _((test çalıştırıcıları))_ olarak adlandırılır. {{index "persistent data structure"}} -Some code is easier to test than other code. Generally, the more external objects that the code interacts with, the harder it is to set up the context in which to test it. The style of programming shown in the [previous chapter](robot), which uses self-contained persistent values rather than changing objects, tends to be easy to test. +Bazı kodlar diğer kodlardan daha kolay test edilir. Genellikle, kodun etkileşimde bulunduğu daha fazla harici nesne varsa, test etmek için o çevreyi kurmak daha zordur. [Önceki bölümde](robot) gösterilen programlama tarzı, değişen nesneler yerine kendi başına kalıcı değerler kullandığı için test etmesi daha kolaydır. -## Debugging +## Hata ayıklama {{index debugging}} -Once you notice there is something wrong with your program because it misbehaves or produces errors, the next step is to figure out _what_ the problem is. +Programınızın yanlış davrandığını veya hatalar ürettiğini fark ettiğinizde, bir sonraki adım sorunun _ne_ olduğunu bulmaktır. -Sometimes it is obvious. The ((error)) message will point at a specific line of your program, and if you look at the error description and that line of code, you can often see the problem. +Bazen bu açıktır. ((Hata)) mesajı programınızın belirli bir satırına işaret eder ve hata açıklamasıyla o kod satırına baktığınızda, genellikle sorunu görebilirsiniz. {{index "run-time error"}} -But not always. Sometimes the line that triggered the problem is simply the first place where a flaky value produced elsewhere gets used in an invalid way. If you have been solving the ((exercises)) in earlier chapters, you will probably have already experienced such situations. +Ancak her zaman değil. Bazen sorunu tetikleyen satır, başka bir yerde üretilen bir tutarsız değerin geçersiz bir şekilde kullanıldığı ilk yerdir. Daha önceki bölümlerdeki ((alıştırmaları)) çözüyorsanız, muhtemelen böyle durumlarla zaten karşılaşmışsınızdır. {{index "decimal number", "binary number"}} -The following example program tries to convert a whole number to a string in a given base (decimal, binary, and so on) by repeatedly picking out the last ((digit)) and then dividing the number to get rid of this digit. But the strange output that it currently produces suggests that it has a ((bug)). +The following example program tries to convert a whole number to a stri ng in a given base (decimal, binary, and so on) by repeatedly picking out the last ((digit)) and then dividing the number to get rid of this digit. But the strange output that it currently produces suggests that it has a ((bug)). +Aşağıdaki örnek program, bir tam sayıyı son ((basamağı)) seçip bu basamağı atmak için numarayı bölerek verilen bir tabandaki (onluk, ikili, vb.) bir dizeye dönüştürmeyi deniyor. Ancak şu anda tuhaf çıktılar ürettiği için bir ((hata)) olduğunu gösterir. ``` function numberToString(n, base = 10) { @@ -196,15 +197,15 @@ console.log(numberToString(13, 10)); {{index analysis}} -Even if you see the problem already, pretend for a moment that you don't. We know that our program is malfunctioning, and we want to find out why. +Sorunu zaten görseniz bile, bir an için görmemiş gibi davranın. Programımızın yanlış çalıştığını biliyoruz ve neden olduğunu bulmak istiyoruz. {{index "trial and error"}} -This is where you must resist the urge to start making random changes to the code to see whether that makes it better. Instead, _think_. Analyze what is happening and come up with a ((theory)) of why it might be happening. Then make additional observations to test this theory—or, if you don't yet have a theory, make additional observations to help you come up with one. +Burada kodu rastgele değiştirerek durumu düzeltecek mi girişimlerine direnmelisiniz. Bunun yerine _düşünün_. Neler olduğunu analiz edin ve neden olduğuna dair bir ((teori)) ortaya koyun. Daha sonra, bu teoriyi test etmek için ek gözlemler yapın—veya henüz bir teoriniz yoksa, bir teori üretmenize yardımcı olacak ek gözlemler yapın. {{index "console.log", output, debugging, logging}} -Putting a few strategic `console.log` calls into the program is a good way to get additional information about what the program is doing. In this case, we want `n` to take the values `13`, `1`, and then `0`. Let's write out its value at the start of the loop. +Programa stratejik birkaç `console.log` çağrısı eklemek, programın ne yaptığı hakkında ek bilgi almanın iyi bir yoludur. Bu durumda, `n`'in `13`, `1` ve ardından `0` değerlerini almasını istiyoruz. Hadi döngünün başında değerini konsola yazdıralım. ```{lang: null} 13 @@ -217,31 +218,31 @@ Putting a few strategic `console.log` calls into the program is a good way to ge {{index rounding}} -_Right_. Dividing 13 by 10 does not produce a whole number. Instead of `n /= base`, what we actually want is `n = Math.floor(n / base)` so that the number is properly "shifted" to the right. +_Doğru_. 13'ü 10'a bölmek bir tam sayı üretmez. `n /= base` yerine, `n = Math.floor(n / taban)` istediğimiz şeydir, böylece sayı uygun şekilde sağa "kaydırılır". {{index "JavaScript console", "debugger statement"}} -An alternative to using `console.log` to peek into the program's behavior is to use the _debugger_ capabilities of your browser. Browsers come with the ability to set a _((breakpoint))_ on a specific line of your code. When the execution of the program reaches a line with a breakpoint, it is paused, and you can inspect the values of bindings at that point. I won't go into details, as debuggers differ from browser to browser, but look in your browser's ((developer tools)) or search the Web for instructions. +Programın davranışına bakmanın `console.log` kullanmaktan başka bir yolu da, tarayıcınızın _hata ayıklayıcı_ yeteneklerini kullanmaktır. Tarayıcılar, kodunuzun belirli bir satırında _((kesme noktası))_ ayarlama yeteneğine sahiptir. Programın yürütmesi, bir kesme noktası olan bir satıra ulaştığında durur ve bu noktadaki bağlantıların değerlerini inceleyebilirsiniz. Ayrıntılara girmeyeceğim çünkü hata ayıklayıcılar tarayıcıdan tarayıcıya değişir, ancak tarayıcınızın ((geliştirici araçları))nda arayın veya Web'de talimatları arayın. -Another way to set a breakpoint is to include a `debugger` statement (consisting simply of that keyword) in your program. If the ((developer tools)) of your browser are active, the program will pause whenever it reaches such a statement. +Başka bir kesme noktası ayarlamak için programınıza bir `debugger` ifadesi (yalnızca bu anahtar kelime) eklemektir. Tarayıcınızın ((geliştirici araçları)) etkinse, program böyle bir ifadeye ulaştığında duracaktır. -## Error propagation +## Hata yayılımı {{index input, output, "run-time error", error, validation}} -Not all problems can be prevented by the programmer, unfortunately. If your program communicates with the outside world in any way, it is possible to get malformed input, to become overloaded with work, or to have the network fail. +Üzülerek söylemeliyim ki, tüm sorunlar programcı tarafından önlenebilir değildir. Programınızın dış dünya ile iletişim kurması durumunda, hatalı giriş almak, iş yüküyle aşırı yüklenmek veya internet ağının başarısız olması mümkündür. {{index "error recovery"}} -If you're programming only for yourself, you can afford to just ignore such problems until they occur. But if you build something that is going to be used by anybody else, you usually want the program to do better than just crash. Sometimes the right thing to do is take the bad input in stride and continue running. In other cases, it is better to report to the user what went wrong and then give up. In either situation the program has to actively do something in response to the problem. +Sadece kendiniz için programlama yapıyorsanız, bu tür sorunları oluşuncaya kadar görmezden gelebilirsiniz. Ancak başkaları tarafından kullanılacak bir şey inşa ederseniz, genellikle programın sadece çökmekten daha iyi bir şey yapmasını istersiniz. Bazen doğru şey, verilen yanlış değeri kabul edip çalışmaya devam etmektir. Diğer durumlarda, kullanıcıya neyin yanlış gittiğini bildirmek ve ardından vazgeçmektir. Ancak her iki durumda da, program, soruna yanıt olarak aktif olarak bir şey yapmak zorundadır. {{index "promptNumber function", validation}} -Say you have a function `promptNumber` that asks the user for a number and returns it. What should it return if the user inputs "orange"? +Örneğin, kullanıcıdan bir sayı isteyen ve onu döndüren bir `promptNumber` fonksiyonunuz olsun. Kullanıcı "orange" yazarsa ne yapmalıdır? {{index null, undefined, "return value", "special return value"}} -One option is to make it return a special value. Common choices for such values are `null`, `undefined`, or `-1`. +Bir seçenek, ona özel bir değer döndürmektir. Bu tür değerler için yaygın seçimler `null`, `undefined` veya `-1`'dir. ```{test: no} function promptNumber(question) { @@ -253,11 +254,11 @@ function promptNumber(question) { console.log(promptNumber("How many trees do you see?")); ``` -Now any code that calls `promptNumber` must check whether an actual number was read and, failing that, must somehow recover—maybe by asking again or by filling in a default value. Or it could again return a special value to _its_ caller to indicate that it failed to do what it was asked. +Şimdi, `promptNumber` çağıran kodun, gerçekten bir sayı alınıp alınmadığını kontrol etmesi ve bunun başarısız olduğu durumda nasıl kurtarılacağını bir şekilde düzeltmesi gerekir—belki tekrar sorarak veya bir varsayılan bir değerle doldurarak. Ya da istenilenin yapılamadığını belirtmek için tekrar _kendisini çağrıran_ yere özel bir değer döndürebilir. {{index "error handling"}} -In many situations, mostly when ((error))s are common and the caller should be explicitly taking them into account, returning a special value is a good way to indicate an error. It does, however, have its downsides. First, what if the function can already return every possible kind of value? In such a function, you'll have to do something like wrap the result in an object to be able to distinguish success from failure, the way the `next` method on the iterator interface does. +Bir genellikle hata döndüren bir fonksiyonu çağıran ve bu hataları dikkate alan fonksiyonlar için, başarısız olan çağırılan fonksiyondan özel değerler döndürmek hatayı belirtmek için iyi bir yöntemdir. Ancak tabii ki, bunun da olumsuz yanları var. Birinci olarak, ya çağırılan bu fonksiyon her türlü herhangi bir değer döndürebiliyorsa? Böyle bir fonksiyonda başarıyı başarısızlıktan ayırt etmek için iterator arayüzündeki `next` metodunda da olduğu gibi sonucu bir nesnenin içine almak gibi bir şey yapmanız gerekir. ``` function lastElement(array) { @@ -271,25 +272,26 @@ function lastElement(array) { {{index "special return value", readability}} -The second issue with returning special values is that it can lead to awkward code. If a piece of code calls `promptNumber` 10 times, it has to check 10 times whether `null` was returned. If its response to finding `null` is to simply return `null` itself, callers of the function will in turn have to check for it, and so on. +Özel değerler döndürmenin ikinci sorunu, garip gözüken kodla sonuçlanabilir olmasıdır. Bir kod parçası `promptNumber`'ı 10 kez çağırırsa, 10 kez `null` değerinin döndürülüp döndürülmediğini kontrol etmesi gerekir. Ve eğer `null` bulursa verdiği yanıt sadece `null`'u döndürmekse, o fonksiyonu çağıran fonksiyonlar da onu kontrol etmek zorunda kalacak ve bu da böylece devam edecek. -## Exceptions +## İstisnalar {{index "error handling"}} -When a function cannot proceed normally, what we would often _like_ to do is just stop what we are doing and immediately jump to a place that knows how to handle the problem. This is what _((exception handling))_ does. +Bir fonksiyon normal olarak devam edemezse, genellikle yapmak _istediğimiz_ şey, yaptığımız işi durdurmak ve hemen sorunu nasıl ele alacağını bilen bir yere atlamaktır. Bu _((istisna işleme))_ dediğimiz şeydir. {{index ["control flow", exceptions], "raising (exception)", "throw keyword", "call stack"}} -Exceptions are a mechanism that makes it possible for code that runs into a problem to _raise_ (or _throw_) an exception. An exception can be any value. Raising one somewhat resembles a super-charged return from a function: it jumps out of not just the current function but also its callers, all the way down to the first call that started the current execution. This is called _((unwinding the stack))_. You may remember the stack of function calls mentioned in [Chapter ?](functions#stack). An exception zooms down this stack, throwing away all the call contexts it encounters. +İstisnalar, bir sorunla karşılaşan kodun bir istisna _oluşturmasını_ (veya _fırlatmasını_) mümkün kılan bir mekanizmadır. Bir istisna herhangi bir değer olabilir. Bir istisna oluşturmak, bir fonksiyondan geri dönüş yapmanın hızlandırılmış bir versiyonunu andırır: sadece mevcut fonksiyondan çıkmakla kalmaz, mevcut yürütmeyi başlatan ilk çağrıya kadar olan tüm çağıran fonksiyonlardan da çıkar. Buna _((yığını açma))_ denir. [Bölüm ?](functions#stack) içinde bahsedilen fonksiyon çağrılarının yığınını hatırlıyor olabilirsiniz. Bir istisna bu yığından hızla aşağı iner ve karşılaştığı tüm çağrı bağlamlarını atar. {{index "error handling", [syntax, statement], "catch keyword"}} -If exceptions always zoomed right down to the bottom of the stack, they would not be of much use. They'd just provide a novel way to blow up your program. Their power lies in the fact that you can set "obstacles" along the stack to _catch_ the exception as it is zooming down. Once you've caught an exception, you can do something with it to address the problem and then continue to run the program. +Eğer istisnalar her zaman yığının en altına doğru ilerleselerdi, pek faydalı olmazlardı. Sadece programınızı patlatmanın yeni bir yolunu sağlarlardı. Güçleri, istisnayı aşağı inerken yığında engeller ayarlayarak onları _yakalayabilmeniz_ gerçeğinde yatar. Bir istisnayı yakaladıktan sonra, onunla bir şeyler yapabilir ve ardından programı çalıştırmaya devam edebilirsiniz. -Here's an example: +Bir örnek: {{id look}} + ``` function promptDirection(question) { let result = prompt(question); @@ -315,29 +317,29 @@ try { {{index "exception handling", block, "throw keyword", "try keyword", "catch keyword"}} -The `throw` keyword is used to raise an exception. Catching one is done by wrapping a piece of code in a `try` block, followed by the keyword `catch`. When the code in the `try` block causes an exception to be raised, the `catch` block is evaluated, with the name in parentheses bound to the exception value. After the `catch` block finishes—or if the `try` block finishes without problems—the program proceeds beneath the entire `try/catch` statement. +`throw` anahtar kelimesi bir istisna oluşturmak için kullanılır. Bir istisna yakalamak, bir parçayı kodu `try` bloğu içine alarak yapılır, ardından `catch` anahtar kelimesi gelir. `try` bloğundaki kod bir istisna oluşturursa, `catch` bloğu, parantez içindeki ismi istisna değeri ile bağlar şekilde değerlendirilir. `catch` bloğu sorunsuz şekilde tamamlandıktan sonra—veya sorun olmadan `try` bloğu tamamlanırsa—program tüm `try/catch` ifadesinin altından devam eder. {{index debugging, "call stack", "Error type"}} -In this case, we used the `Error` ((constructor)) to create our exception value. This is a ((standard)) JavaScript constructor that creates an object with a `message` property. Instances of `Error` also gather information about the call stack that existed when the exception was created, a so-called _((stack trace))_. This information is stored in the `stack` property and can be helpful when trying to debug a problem: it tells us the function where the problem occurred and which functions made the failing call. +Bu durumda, istisna değerimizi oluşturmak için `Error` ((constructor)) fonksiyonunu kullandık. Bu, bir `message` özelliğine sahip bir nesne oluşturan ((standart)) bir JavaScript constructor fonksiyonudur. `Error` örnekleri, istisna oluşturulurken var olan çağrı yığını hakkında da ayrıca bilgi toplar ve buna ((yığın izi)) denir. Bu bilgi `stack` özelliğinde depolanır ve bir sorunu gidermeye çalışırken yardımcı olabilir: bize sorunun hangi fonksiyonda meydana geldiğini ve başarısız olan çağrıyı hangi fonksiyonların yaptığını söyler. {{index "exception handling"}} -Note that the `look` function completely ignores the possibility that `promptDirection` might go wrong. This is the big advantage of exceptions: error-handling code is necessary only at the point where the error occurs and at the point where it is handled. The functions in between can forget all about it. +`look` fonksiyonunun `promptDirection` fonksiyonunun yanlış gitme olasılığını tamamen göz ardı ettiğine dikkat edin. Bu, istisnaların büyük avantajı: hata işleme kodu, yalnızca hata meydana geldiği noktada ve onun ele alındığı noktada gereklidir. Aradaki işlevlerin hepsi bu sorunları unutabilir. -Well, almost... +Yani, neredeyse... -## Cleaning up after exceptions +## İstisnalardan sonra temizlik {{index "exception handling", "cleaning up", ["control flow", exceptions]}} -The effect of an exception is another kind of control flow. Every action that might cause an exception, which is pretty much every function call and property access, might cause control to suddenly leave your code. +Bir istisnanın etkisi başka bir tür kontrol akışıdır. Bir istisnaya neden olabilecek her eylem, yani neredeyse her fonksiyon çağrısı ve özellik erişimi, kontrolünüzü aniden kodunuzdan çıkabilir. -This means when code has several side effects, even if its "regular" control flow looks like they'll always all happen, an exception might prevent some of them from taking place. +Bu, kodun birden fazla yan etkiye sahip olduğu durumlarda, "düzenli" kontrol akışı her zaman gerçekleşecek gibi görünse bile, bir istisna bazılarını gerçekleştirmeyi engelleyebilir demektir. {{index "banking example"}} -Here is some really bad banking code: +İşte gerçekten kötü bir bankacılık kodu. ```{includeCode: true} const accounts = { @@ -361,17 +363,17 @@ function transfer(from, amount) { } ``` -The `transfer` function transfers a sum of money from a given account to another, asking for the name of the other account in the process. If given an invalid account name, `getAccount` throws an exception. +`transfer` fonksiyonu, verilen bir hesaptan başka bir hesaba bir miktar para transfer ederken, işlem sırasında diğer hesabın adını istemektedir. Geçersiz bir hesap adı verilirse, `getAccount` bir istisna fırlatmaktadır. -But `transfer` _first_ removes the money from the account and _then_ calls `getAccount` before it adds it to another account. If it is broken off by an exception at that point, it'll just make the money disappear. +Ancak, `transfer` önce parayı hesaptan çıkarır ve ardından başka bir hesaba eklermeden önce `getAccount` fonksiyonunu çağırır. Eğer bu noktada bir istisna tarafından kesilirse, sadece paranın gönderen kişiden kaybolmasına sebep olur. -That code could have been written a little more intelligently, for example by calling `getAccount` before it starts moving money around. But often problems like this occur in more subtle ways. Even functions that don't look like they will throw an exception might do so in exceptional circumstances or when they contain a programmer mistake. +Bu kod biraz daha akıllıca yazılabilirdi, örneğin para hareketi yapmaya başlamadan önce `getAccount` fonksiyonunu çağırarak. Ancak bu tür sorunlar genellikle daha ince yollarla ortaya çıkar. Bir fonksiyonun bir istisna fırlatmayacağını düşündüğünüzde bile, olağanüstü durumlarda veya bir programcı hatası içerdiğinde bunu yapabilir. -One way to address this is to use fewer side effects. Again, a programming style that computes new values instead of changing existing data helps. If a piece of code stops running in the middle of creating a new value, no existing data structures were damaged, making it easier to recover. +Bunu ele almanın bir yolu, daha az yan etki kullanmaktır. Yine, var olan verileri değiştirmek yerine yeni değerler hesaplayan bir programlama stili yardımcı olur. Bir kod parçası, yeni bir değer oluşturma sürecinin ortasında çalışmayı durdurursa, mevcut veri yapıları zarar görmediği için kurtarmak daha kolay olur. {{index block, "try keyword", "finally keyword"}} -Since that isn't always practical, `try` statements have another feature: they may be followed by a `finally` block either instead of or in addition to a `catch` block. A `finally` block says "no matter _what_ happens, run this code after trying to run the code in the `try` block." +Ancak bu her zaman pratik değildir. Bu yüzden `try` ifadelerinin başka bir özelliği vardır. Bunlar, bir `try` bloğuna, `catch` bloğu yerine veya ek olarak bir `finally` bloğu izleyebilirler. Bir `finally` bloğu, "ne olursa olsun, `try` bloğundaki kodu çalıştırmaya çalıştıktan sonra bu kodu çalıştır" der. ```{includeCode: true} function transfer(from, amount) { @@ -390,43 +392,44 @@ function transfer(from, amount) { } ``` -This version of the function tracks its progress, and if, when leaving, it notices that it was aborted at a point where it had created an inconsistent program state, it repairs the damage it did. +Bu fonksiyonun bu sürümü ilerleme durumunu takip eder ve ayrılırken, oluşturduğu tutarsız bir program durumu noktasında kesildiğini fark ederse, yaptığı zararı onarır. -Note that even though the `finally` code is run when an exception is thrown in the `try` block, it does not interfere with the exception. After the `finally` block runs, the stack continues unwinding. +Unutulmamalıdır ki, `try` bloğundaki bir istisna atıldığında bile `finally` kodunun çalıştırılmasına rağmen, istisna ile ilgilenmez. `finally` bloğu çalıştıktan sonra, yığın açılmaya devam eder. {{index "exception safety"}} -Writing programs that operate reliably even when exceptions pop up in unexpected places is hard. Many people simply don't bother, and because exceptions are typically reserved for exceptional circumstances, the problem may occur so rarely that it is never even noticed. Whether that is a good thing or a really bad thing depends on how much damage the software will do when it fails. +Beklenmedik yerlerde istisna oluştuğunda dahi güvenilir şekilde çalışan programlar yazmak zordur. Birçok insan bunu genellikle önemsemez ve istisnalar genellikle olağanüstü durumlarda oluştuğundan ötürü sorun nadiren fark edilir. Bunun iyi bir şey mi yoksa gerçekten kötü bir şey mi olduğunu yazılımın başarısız olduğunda ne kadar zarar vereceğine bağlıdır. -## Selective catching +## Seçici yakalama {{index "uncaught exception", "exception handling", "JavaScript console", "developer tools", "call stack", error}} -When an exception makes it all the way to the bottom of the stack without being caught, it gets handled by the environment. What this means differs between environments. In browsers, a description of the error typically gets written to the JavaScript console (reachable through the browser's Tools or Developer menu). Node.js, the browserless JavaScript environment we will discuss in [Chapter ?](node), is more careful about data corruption. It aborts the whole process when an unhandled exception occurs. +Bir istisna, yakalanmadan yığının en altına kadar ulaştığında, çevre tarafından ele alınır. Bunun ne anlama geldiği çevrelere göre değişir. Tarayıcılarda, hata genellikle JavaScript konsoluna yazılır (tarayıcının Araçlar veya Geliştirici menüsünden erişilebilir). [Bölüm ?](node) içinde tartışacağımız tarayıcısız JavaScript ortamı olan Node.js, veri bozulması konusunda daha dikkatlidir. Ele alınmayan bir istisna meydana geldiğinde, tüm işlemi sonlandırır. {{index crash, "error handling"}} -For programmer mistakes, just letting the error go through is often the best you can do. An unhandled exception is a reasonable way to signal a broken program, and the JavaScript console will, on modern browsers, provide you with some information about which function calls were on the stack when the problem occurred. +Programcı hataları için, hatanın gitmesine izin vermek çoğu zaman yapabileceğiniz en iyi şeydir. Ele alınmayan bir istisna, bozuk bir programı işaret etmenin makul bir yoludur ve JavaScript konsolu, modern tarayıcılarda, sorun meydana geldiğinde yığında hangi fonksiyon çağrılarının olduğuna dair bazı bilgiler sağlar. {{index "user interface"}} -For problems that are _expected_ to happen during routine use, crashing with an unhandled exception is a terrible strategy. +Rutin kullanım sırasında _meydana gelmesi beklenen_ sorunlar için, ele alınmayan bir istisna ile çökme korkunç bir stratejidir. {{index [function, application], "exception handling", "Error type", [binding, undefined]}} -Invalid uses of the language, such as referencing a nonexistent binding, looking up a property on `null`, or calling something that's not a function, will also result in exceptions being raised. Such exceptions can also be caught. +Dilin geçersiz kullanımları, var olmayan bir bağlantıya başvurmak, `null` üzerinde bir özellik aramak veya bir fonksiyon olmayan bir şeyi çağırmak gibi, aynı şekilde istisna yükseltilmesine neden olur. Böyle istisnalar da yakalanabilir. {{index "catch keyword"}} -When a `catch` body is entered, all we know is that _something_ in our `try` body caused an exception. But we don't know _what_ did or _which_ exception it caused. +Bir `catch` bloğuna girildiğinde, bildiğimiz tek şey, `try` bloğundaki bir şeyin bir istisna meydana getirdiğidir. Ancak _neyin_ istisnaya sebep oluduğu veya _hangi_ istisnaya sebep olunduğunu bilmiyoruz. {{index "exception handling"}} -JavaScript (in a rather glaring omission) doesn't provide direct support for selectively catching exceptions: either you catch them all or you don't catch any. This makes it tempting to _assume_ that the exception you get is the one you were thinking about when you wrote the `catch` block. +JavaScript (oldukça dikkate çeker bir ihmalde), istisnaları seçici olarak yakalamak için doğrudan destek sağlamaz: ya hepsini yakalarsınız ya da hiçbirini yakalamazsınız. Bu, `catch` bloğunun yazıldığı sırada düşündüğünüz istisna olduğunu _varsaymanızı_ cazip hale getirir. {{index "promptDirection function"}} But it might not be. Some other ((assumption)) might be violated, or you might have introduced a bug that is causing an exception. Here is an example that _attempts_ to keep on calling `promptDirection` until it gets a valid answer: +Ancak öyle olmayabilir. Başka bir ((varsayım)) ihlal edilmiş olabilir veya bir istisnaya neden olan bir hata eklemiş olabilirsiniz. İşte, geçerli bir yanıt alana kadar `promptDirection` fonksiyonunu çağırmaya devam etmeye _çalışan_ bir örnek: ```{test: no} for (;;) { @@ -442,19 +445,19 @@ for (;;) { {{index "infinite loop", "for loop", "catch keyword", debugging}} -The `for (;;)` construct is a way to intentionally create a loop that doesn't terminate on its own. We break out of the loop only when a valid direction is given. Unfortunately, we misspelled `promptDirection`, which will result in an "undefined variable" error. Because the `catch` block completely ignores its exception value (`e`), assuming it knows what the problem is, it wrongly treats the binding error as indicating bad input. Not only does this cause an infinite loop, it "buries" the useful error message about the misspelled binding. +`for (;;)` yapısı, kendi kendine sona ermeyen bir döngü oluşturmanın kasıtlı bir yoludur. Döngüden yalnızca geçerli bir yön verildiğinde çıkarız. _Ancak_ `promptDirection` fonksiyonunu yanlış yazdık, bu da "tanımsız değişken" hatasına neden olacaktır. `catch` bloğu, tamamen istisna değerini (`e`) görmezden geldiği için, sorunun ne olduğunu varsayarak bağlantı hatasını yanlışlıkla kötü giriş olarak işler. Bu sadece sonsuz bir döngüye neden olmakla kalmaz, aynı zamanda yanlış yazılmış bağlantıyla ilgili yararlı hata mesajını "gömülmüş" hale getirir. -As a general rule, don't blanket-catch exceptions unless it is for the purpose of "routing" them somewhere—for example, over the network to tell another system that our program crashed. And even then, think carefully about how you might be hiding information. +Genel bir kural olarak, birden fazla istisnayı genel bir şekilde yakalamayın, bunu sadece onları başka bir yere "yönlendirmek" amacıyla yapın - örneğin, programımızın çöktüğünü başka bir sisteme bildirmek için ağ üzerinden bir şey yapacaksınızdır, o zaman bu yapılabilir. Ancak o zaman bile nasıl bilgi gizleyebiliyor olduğunuzu dikkatlice düşünün. {{index "exception handling"}} -We want to catch a _specific_ kind of exception. We can do this by checking in the `catch` block whether the exception we got is the one we are interested in, and if not, rethrow it. But how do we recognize an exception? +Dolayısıyla, _belirli_ bir tür istisnayı yakalamak istiyoruz. Bunu `catch` bloğunda aldığımız istisnanın istediğimiz türde olup olmadığını kontrol ederek ve aksi takdirde yeniden fırlatarak yapabiliriz. Ancak bir istisnayı nasıl tanıyacağız? -We could compare its `message` property against the ((error)) message we happen to expect. But that's a shaky way to write code—we'd be using information that's intended for human consumption (the message) to make a programmatic decision. As soon as someone changes (or translates) the message, the code will stop working. +`message` özelliğini istisnanın ((hata)) mesajına karşı beklediğimiz mesajdan kontrol edebiliriz. Ancak bu, kod yazmanın pek iyi olmayan bir yoludur - programatik bir karar vermek için insan tüketimi adına tasarlanmış bilgileri (mesajı) kullanıyor oluruz. Birisi mesajı değiştirdiğinde (veya başka bir dile çevirdiğinde), kod çalışmayı durdurur. {{index "Error type", "instanceof operator", "promptDirection function"}} -Rather, let's define a new type of error and use `instanceof` to identify it. +Bunun yerine, yeni bir hata türü tanımlayalım ve bunu tanımlamak için `instanceof` kullanalım. ```{includeCode: true} class InputError extends Error {} @@ -469,11 +472,11 @@ function promptDirection(question) { {{index "throw keyword", inheritance}} -The new error class extends `Error`. It doesn't define its own constructor, which means that it inherits the `Error` constructor, which expects a string message as argument. In fact, it doesn't define anything at all—the class is empty. `InputError` objects behave like `Error` objects, except that they have a different class by which we can recognize them. +Yeni hata sınıfı `Error` sınıfından miras alır. Kendi `constructor` fonksiyonunu tanımlamaz, bu da `Error` constructor fonksiyonunu miras aldığı ve bir mesaj dizesi bekleyen `Error` constructor fonksiyonuna sahip olduğu anlamına gelir. Aslında hiçbir şeyi tanımlamaz - sınıf boştur. `InputError` nesneleri, onları tanıyabileceğimiz farklı bir sınıfa sahip olmaları dışında, `Error` nesneleri gibi davranır. {{index "exception handling"}} -Now the loop can catch these more carefully. +Şimdi döngü bunları daha dikkatli bir şekilde yakalayabilir. ```{test: no} for (;;) { @@ -493,15 +496,15 @@ for (;;) { {{index debugging}} -This will catch only instances of `InputError` and let unrelated exceptions through. If you reintroduce the typo, the undefined binding error will be properly reported. +Bu, yalnızca `InputError` örneklerini yakalar ve ilgili olmayan istisnaları geçirir. Yanlış yazım hatasını yeniden tanıttığınızda, tanımsız bağlantı hatası düzgün bir şekilde rapor edilir. -## Assertions +## İddialar {{index "assert function", assertion, debugging}} -_Assertions_ are checks inside a program that verify that something is the way it is supposed to be. They are used not to handle situations that can come up in normal operation but to find programmer mistakes. +_İddialar_ program içinde, bir şeyin olması gerektiği gibi olduğunu doğrulayan kontrollerdir. Bunlar normal işlem sırasında ortaya çıkabilecek durumlarla başa çıkmak için değil, programcı hatalarını bulmak için kullanılır. -If, for example, `firstElement` is described as a function that should never be called on empty arrays, we might write it like this: +Örneğin, `firstElement` fonksiyonu boş diziler üzerinde asla çağrılmaması gereken bir fonksiyon olarak tanımlanmışsa, şöyle yazabiliriz: ``` function firstElement(array) { @@ -514,29 +517,31 @@ function firstElement(array) { {{index validation, "run-time error", crash, assumption}} -Now, instead of silently returning undefined (which you get when reading an array property that does not exist), this will loudly blow up your program as soon as you misuse it. This makes it less likely for such mistakes to go unnoticed and easier to find their cause when they occur. +Artık sessizce tanımsız döndürmek yerine (bir dizide var olmayan bir özellik okunduğunda elde ettiğiniz), bunun kullanımını yanlış yaptığınızda programınızı yüksek sesle patlatacaktır. Bu tür hatalar gözden kaçırma olasılığını azaltır ve meydana geldiklerinde nedenlerini bulmayı kolaylaştırır. -I do not recommend trying to write assertions for every possible kind of bad input. That'd be a lot of work and would lead to very noisy code. You'll want to reserve them for mistakes that are easy to make (or that you find yourself making). +Her türlü kötü giriş için kontroller yazmayı önermem. Bu, çok fazla çalışma gerektirir ve çok gürültülü bir kod ile sonuçlanır. Onları yalnızca kolayca yapılan hatalar için (veya kendinizin yapmaya başladığını fark ettiğiniz hatalar için) saklamak istersiniz. -## Summary +## Özet -An important part of programming is finding, diagnosing, and fixing bugs. Problems can become easier to notice if you have an automated test suite or add assertions to your programs. +Programlamanın önemli bir parçası, hataları bulmak, teşhis etmek ve düzeltmektir. Otomatik bir test paketiniz varsa veya programlarınıza iddialar eklediyseniz, sorunları fark etmek daha kolay olabilir. -Problems caused by factors outside the program's control should usually be actively planned for. Sometimes, when the problem can be handled locally, special return values are a good way to track them. Otherwise, exceptions may be preferable. +Programın kontrolü dışındaki faktörlerden kaynaklanan sorunlar genellikle aktif olarak planlanmalıdır. Sorun yerel olarak ele alınabiliyorsa, özel dönüş değerleri onları izlemek için iyi bir yoldur. Aksi takdirde, istisnalar tercih edilebilir. -Throwing an exception causes the call stack to be unwound until the next enclosing `try/catch` block or until the bottom of the stack. The exception value will be given to the `catch` block that catches it, which should verify that it is actually the expected kind of exception and then do something with it. To help address the unpredictable control flow caused by exceptions, `finally` blocks can be used to ensure that a piece of code _always_ runs when a block finishes. +Bir istisna fırlatmak, yığının bir sonraki kapsayan `try/catch` bloğuna veya yığının dibine kadar açılmasına neden olur. İstisna değeri, bunu yakalayan `catch` bloğuna verilir, bu da gerçekten beklenen türde bir istisna olup olmadığını doğrulamalı ve ardından bununla bir şeyler yapmalıdır. İstisnaların neden olduğu öngörülemeyen kontrol akışıyla başa çıkmaya yardımcı olmak için, bir bloğun bitişinde bir parça kodun _her zaman_ çalışmasını sağlamak için `finally` blokları kullanılabilir. -## Exercises +## Egzersizler -### Retry +### Yeniden deneme {{index "primitiveMultiply (exercise)", "exception handling", "throw keyword"}} Say you have a function `primitiveMultiply` that in 20 percent of cases multiplies two numbers and in the other 80 percent of cases raises an exception of type `MultiplicatorUnitFailure`. Write a function that wraps this clunky function and just keeps trying until a call succeeds, after which it returns the result. +primitiveMultiply adında, %20'lik bir olasılıkla iki sayıyı çarpan ve diğer %80'lik bir olasılıkla MultiplicatorUnitFailure türünde bir istisna yükselten bir fonksiyonunuz olduğunu varsayalım. Bu sıkışık fonksiyonu saran ve bir çağrı başarılı olana kadar denemeye devam eden bir fonksiyon yazın. {{index "catch keyword"}} Make sure you handle only the exceptions you are trying to handle. +Yalnızca ele almaya çalıştığınız istisnaları ele aldığınızdan emin olun. {{if interactive @@ -552,12 +557,13 @@ function primitiveMultiply(a, b) { } function reliableMultiply(a, b) { - // Your code here. + // Kodunuz buraya. } console.log(reliableMultiply(8, 8)); // → 64 ``` + if}} {{hint @@ -565,16 +571,18 @@ if}} {{index "primitiveMultiply (exercise)", "try keyword", "catch keyword", "throw keyword"}} The call to `primitiveMultiply` should definitely happen in a `try` block. The corresponding `catch` block should rethrow the exception when it is not an instance of `MultiplicatorUnitFailure` and ensure the call is retried when it is. +primitiveMultiply çağrısı kesinlikle bir try bloğunda gerçekleşmelidir. Karşılık gelen catch bloğu, istisna MultiplicatorUnitFailure türünden değilse istisnayı yeniden fırlatmalı ve türünden bir istisna olduğunda çağrının yeniden denendiğinden emin olmalıdır. To do the retrying, you can either use a loop that stops only when a call succeeds—as in the [`look` example](error#look) earlier in this chapter—or use ((recursion)) and hope you don't get a string of failures so long that it overflows the stack (which is a pretty safe bet). +Yeniden deneme yapmak için, bir çağrının başarılı olana kadar durmayan bir döngü kullanabilirsiniz - bu bölümdeki look örneğinde olduğu gibi - veya ((rekürsiv)) kullanabilir ve yığını aşırı derecede dolduracak kadar uzun bir hata dizisi almayı umabilirsiniz (bu oldukça güvenli bir bahis). hint}} -### The locked box +### Kilitli kutu {{index "locked box (exercise)"}} -Consider the following (rather contrived) object: +Aşağıdaki (oldukça yapay) nesneyi düşünün: ``` const box = new class { @@ -592,11 +600,11 @@ const box = new class { {{index "private property", "access control"}} -It is a ((box)) with a lock. There is an array in the box, but you can get at it only when the box is unlocked. +Bu, bir kilitli kutu. Kutuda bir dizi var, ancak kutu kilidi açık olmadığı sürece ona erişemezsiniz. {{index "finally keyword", "exception handling"}} -Write a function called `withBoxUnlocked` that takes a function value as argument, unlocks the box, runs the function, and then ensures that the box is locked again before returning, regardless of whether the argument function returned normally or threw an exception. +`withBoxUnlocked` adında bir fonksiyon yazın; bu fonksiyon, bir fonksiyon değeri alsın, kutunun kilidini açsın, aldığı fonksiyonu çalıştırsın ve ardından, argüman olarak verilen fonksiyonun normal olarak çalışmasından veya bir istisna fırlatmasından bağımsız olarak döndürmeden önce kutunun kilidinin geri kilitli olduğundan emin olsun. {{if interactive @@ -614,7 +622,7 @@ const box = new class { }; function withBoxUnlocked(body) { - // Your code here. + // Kodunuz buraya. } withBoxUnlocked(() => { @@ -634,14 +642,14 @@ console.log(box.locked); if}} -For extra points, make sure that if you call `withBoxUnlocked` when the box is already unlocked, the box stays unlocked. +Ek puanlar için, kutu zaten açıkken `withBoxUnlocked` çağrılırsa, kutunun açık kalmasını sağlayın. {{hint {{index "locked box (exercise)", "finally keyword", "try keyword"}} -This exercise calls for a `finally` block. Your function should first unlock the box and then call the argument function from inside a `try` body. The `finally` block after it should lock the box again. +Bu alıştırma, bir `finally` bloğu gerektirir. Fonksiyonunuz öncelikle kutuyu kilidini açmalı ve ardından argüman olarak verilen fonksiyonu bir try gövdesi içinde çağırmalıdır. Sonrasında gelen `finally` bloğu aracılığıyla kutuyu tekrar kilitlemelidir. -To make sure we don't lock the box when it wasn't already locked, check its lock at the start of the function and unlock and lock it only when it started out locked. +Kutuyu kilitli olmadığında kilitlememek için, fonksiyonun başında kilidini kontrol edin ve kilidini sadece kilitli başlamışken açın veya kapatın. hint}} diff --git a/09_regexp.md b/09_regexp.md index 4610562c..c8398cb5 100644 --- a/09_regexp.md +++ b/09_regexp.md @@ -1,8 +1,8 @@ -# Regular Expressions +# Düzenli İfadeler {{quote {author: "Jamie Zawinski", chapter: true} -Some people, when confronted with a problem, think 'I know, I'll use regular expressions.' Now they have two problems. +Bazı insanlar, bir problemle karşılaştıklarında, 'Biliyorum, düzenli ifadeleri kullanacağım.' dediklerinden ötürü artık iki probleme sahip olurlar. quote}} @@ -10,58 +10,58 @@ quote}} {{if interactive -{{quote {author: "Master Yuan-Ma", title: "The Book of Programming", chapter: true} +{{quote {author: "Master Yuan-Ma", title: "Programlama Kitabı", chapter: true} -When you cut against the grain of the wood, much strength is needed. When you program against the grain of the problem, much code is needed. +Ahşabın damarına karşı keserseniz, çok güç gerekir. Problemin yapısına karşı programlama yaptığınızda, çok fazla kod gerekir. quote}} if}} -{{figure {url: "img/chapter_picture_9.jpg", alt: "Illustration of a railroad system representing the syntactic structure of regular expressions", chapter: "square-framed"}}} +{{figure {url: "img/chapter_picture_9.jpg", alt: "Düzenli ifadelerin sözdizimsel yapısını temsil eden bir demiryolu sisteminin illüstrasyonu.", chapter: "square-framed"}}} {{index evolution, adoption, integration}} -Programming ((tool))s and techniques survive and spread in a chaotic, evolutionary way. It's not always the best or brilliant ones that win but rather the ones that function well enough within the right niche or that happen to be integrated with another successful piece of technology. +Programlama ((araç))ları ve teknikleri, kaotik, evrimsel bir şekilde hayatta kalır ve yayılır. Her zaman en iyi veya parlak olanlar kazanmaz, ancak doğru nişte yeterince iyi işleyenler veya tesadüfen başka başarılı bir teknoloji parçası ile entegre olanlar kazanır. {{index "domain-specific language"}} -In this chapter, I will discuss one such tool, _((regular expression))s_. Regular expressions are a way to describe ((pattern))s in string data. They form a small, separate language that is part of JavaScript and many other languages and systems. +Bu bölümde, bu araçlardan bir tanesini tartışacağım: _((düzenli ifadeler))_. Düzenli ifadeler, dize verilerindeki ((kalıpları)) tanımlamanın bir yoludur. JavaScript'in ve birçok başka dilin ve sistemlerin bir parçası olan küçük, ayrı bir dil oluştururlar. {{index [interface, design]}} -Regular expressions are both terribly awkward and extremely useful. Their syntax is cryptic and the programming interface JavaScript provides for them is clumsy. But they are a powerful ((tool)) for inspecting and processing strings. Properly understanding regular expressions will make you a more effective programmer. +Düzenli ifadeler hem son derece sakar hem de son derece kullanışlıdır. Söz dizimi kriptiktir ve JavaScript'in onlar için sağladığı programlama arayüzü sakattır. Ancak, dizeleri incelemek ve işlemek için güçlü bir ((araç))tırlar. Düzenli ifadeleri doğru anlamak, sizi daha etkili bir programcı yapacaktır. -## Creating a regular expression +## Düzenli ifade oluşturma {{index ["regular expression", creation], "RegExp class", "literal expression", "slash character"}} -A regular expression is a type of object. It can be either constructed with the `RegExp` constructor or written as a literal value by enclosing a pattern in forward slash (`/`) characters. +Düzenli ifade bir tür nesnedir. `RegExp` ((constructor)) fonskiyonunu çağırarak oluşturulabilir veya bir kalıbı ileri eğik çizgi (`/`) karakterleri arasına alarak yazıp da oluşturulabilir. ``` let re1 = new RegExp("abc"); let re2 = /abc/; ``` -Both of those regular expression objects represent the same ((pattern)): an _a_ character followed by a _b_ followed by a _c_. +Bu iki düzenli ifade nesnesi aynı ((kalıbı)) temsil eder: bir _a_ karakteri ardından bir _b_ ardından bir _c_. {{index ["backslash character", "in regular expressions"], "RegExp class"}} -When using the `RegExp` constructor, the pattern is written as a normal string, so the usual rules apply for backslashes. +`RegExp` ((constructor)) fonskiyonunu kullanılırken, kalıp normal bir dize olarak yazılır, bu nedenle ters eğik çizgiler için normal kurallar geçerlidir. {{index ["regular expression", escaping], [escaping, "in regexps"], "slash character"}} -The second notation, where the pattern appears between slash characters, treats backslashes somewhat differently. First, since a forward slash ends the pattern, we need to put a backslash before any forward slash that we want to be _part_ of the pattern. In addition, backslashes that aren't part of special character codes (like `\n`) will be _preserved_, rather than ignored as they are in strings, and change the meaning of the pattern. Some characters, such as question marks and plus signs, have special meanings in regular expressions and must be preceded by a backslash if they are meant to represent the character itself. +Kalıbın eğik çizgi karakterleri arasında göründüğü ikinci notasyon durumunda, ters eğik çizgileri biraz farklı bir şekilde işler. İlk olarak, bir ileri eğik çizgi kalıbı sonlandıracağından ötürü kalıbın bir parçası olmasını istediğimiz herhangi bir ileri eğik çizgi önüne bir ters eğik çizgi koymamız gerekir. Ayrıca, özel karakter kodlarının (`\n` gibi) bir parçası olmayan ters eğik çizgiler, dize içinde olduğu gibi görmezden gelinmez ve kalıbın anlamını değiştirir. Soru işaretleri ve artı işaretleri gibi bazı karakterler, düzenli ifadelerde özel anlamlara sahiptir ve karakterin kendisini temsil etmek isteniyorsa öncesine bir ters eğik çizgi yazılmalıdır. ``` let aPlus = /A\+/; ``` -## Testing for matches +## Eşleşenler için test etmek {{index matching, "test method", ["regular expression", methods]}} -Regular expression objects have a number of methods. The simplest one is `test`. If you pass it a string, it will return a ((Boolean)) telling you whether the string contains a match of the pattern in the expression. +Düzenli ifade nesnelerinin bir dizi metodları vardır. En basiti `test` metodudur. Bir dize geçirirseniz, ifadenin kalıbına uyan dizeyi içerip içermediğini size söyleyen bir ((Boolean)) döndürür. ``` console.log(/abc/.test("abcde")); @@ -72,17 +72,17 @@ console.log(/abc/.test("abxde")); {{index pattern}} -A ((regular expression)) consisting of only nonspecial characters simply represents that sequence of characters. If _abc_ occurs anywhere in the string we are testing against (not just at the start), `test` will return `true`. +Yalnızca özel olmayan karakterlerden oluşan bir düzenli ifade basit olarak, o karakter dizisini temsil eder. _abc_ dizesi, test ettiğimiz dizide (başlangıç dışında yerlerde de olacak şekilde) herhangi bir yerde bulunursa, `test` metodu `true` döndürür. -## Sets of characters +## Karakter setleri {{index "regular expression", "indexOf method"}} -Finding out whether a string contains _abc_ could just as well be done with a call to `indexOf`. Regular expressions are useful because they allow us to describe more complicated ((pattern))s. +Bir dizinin _abc_ içerip içermediğini öğrenmek, `indexOf` ile de yapılabilir. Düzenli ifadeler, daha karmaşık ((kalıpları)) tanımlamamıza izin verdiği için kullanışlıdır. -Say we want to match any ((number)). In a regular expression, putting a ((set)) of characters between square brackets makes that part of the expression match any of the characters between the brackets. +Diyelim ki bir ((sayı)) eşleştirmek istiyoruz. Bir düzenli ifade içinde, karakterler arasına kare parantezler arasında bir ((küme)) karakterler yerleştirmek, ifadenin bu kısmının parantezler arasındaki karakterlerden herhangi birini eşleştirmesini sağlar. -Both of the following expressions match all strings that contain a ((digit)): +Her iki ifade de bir ((rakam)) içeren tüm dizeleri eşleştirir: ``` console.log(/[0123456789]/.test("in 1992")); @@ -93,25 +93,25 @@ console.log(/[0-9]/.test("in 1992")); {{index "hyphen character"}} -Within square brackets, a hyphen (`-`) between two characters can be used to indicate a ((range)) of characters, where the ordering is determined by the character's ((Unicode)) number. Characters 0 to 9 sit right next to each other in this ordering (codes 48 to 57), so `[0-9]` covers all of them and matches any ((digit)). +Kare parantezler arasında, iki karakter arasındaki bir tire (-), karakterin ((Unicode)) numarası tarafından belirlenen bir karakterler ((aralığı))nı göstermek için kullanılabilir. 0'dan 9'a olan bu karakterler bu sıralamada hemen yan yanadırlar (kodlar 48 ila 57), bu nedenle `[0-9]` tümünü kapsar ve herhangi bir ((rakamı)) eşleştirir. {{index [whitespace, matching], "alphanumeric character", "period character"}} -A number of common character groups have their own built-in shortcuts. Digits are one of them: `\d` means the same thing as `[0-9]`. +Birçok yaygın karakter grubunun kendi yerleşik kısayolları vardır. Rakamlar bunlardan biridir: `\d`, `[0-9]` ile aynı anlama gelir. {{index "newline character", [whitespace, matching]}} {{table {cols: [1, 5]}}} -| `\d` | Any ((digit)) character -| `\w` | An alphanumeric character ("((word character))") -| `\s` | Any whitespace character (space, tab, newline, and similar) -| `\D` | A character that is _not_ a digit -| `\W` | A nonalphanumeric character -| `\S` | A nonwhitespace character -| `.` | Any character except for newline +| `\d` | Herhangi bir ((rakam)) karakter +| `\w` | Herhangi bir alfasayısal ("((kelime karakteri))") +| `\s` | Herhangi bir boşluk karakteri (boşluk, tab, yeni satır, vb.) +| `\D` | Rakam _olmayan_ bir karakter +| `\W` | Alfasayısal olmayan bir karakter +| `\S` | Boşluk olmayan bir karakter +| `.` | Yeni satır dışında herhangi bir karakter -You could match a ((date)) and ((time)) format like 01-30-2003 15:20 with the following expression: +Bu nedenle, 01-30-2003 15:20 gibi bir ((tarih)) ve ((zaman)) biçimini şu şekilde eşleştirebilirsiniz: ``` let dateTime = /\d\d-\d\d-\d\d\d\d \d\d:\d\d/; @@ -123,15 +123,15 @@ console.log(dateTime.test("30-jan-2003 15:20")); {{index ["backslash character", "in regular expressions"]}} -That regular expression looks completely awful, doesn't it? Half of it is backslashes, producing a background noise that makes it hard to spot the actual ((pattern)) expressed. We'll see a slightly improved version of this expression [later](regexp#date_regexp_counted). +Bu tamamen berbat görünüyor, değil mi? Yarısından fazlası ters eğik çizgiler ve gerçekten ((kalıp)) ifade edilen kısmı bulmayı zorlaştıran bir arka plan gürültüsü oluşturuyor. Bu ifadenin [daha sonra](regexp#date_regexp_counted) biraz geliştirilmiş bir sürümünü göreceğiz. {{index [escaping, "in regexps"], "regular expression", set}} -These backslash codes can also be used inside ((square brackets)). For example, `[\d.]` means any digit or a period character. The period itself, between square brackets, loses its special meaning. The same goes for other special characters, such as the plus sign (`+`). +Bu ters eğik çizgi kodları aynı zamanda ((kare parantezler)) içinde de kullanılabilir. Örneğin, `[\d.]`, herhangi bir rakam veya bir nokta karakterini ifade eder. Ancak nokta kendisi, kare parantezler arasında, özel anlamını kaybeder. `+` işareti gibi diğer özel karakterler için de aynı şey geçerlidir. {{index "square brackets", inversion, "caret character"}} -To _invert_ a set of characters—that is, to express that you want to match any character _except_ the ones in the set—you can write a caret (`^`) character after the opening bracket. +Bir karakterler kümesini tersine çevirmek - yani, kümedeki karakterlerin dışındakileri eşleştirmek istediğinizi belirtmek - için bir üst simge (`^`) karakterini açılış parantezinin hemen ardından yazabilirsiniz. ``` let nonBinary = /[^01]/; @@ -141,29 +141,29 @@ console.log(nonBinary.test("0111010112101001")); // → true ``` -## International characters +## Uluslararası karakterler {{index internationalization, Unicode, ["regular expression", internationalization]}} -Because of JavaScript's initial simplistic implementation and the fact that this simplistic approach was later set in stone as ((standard)) behavior, JavaScript's regular expressions are rather dumb about characters that do not appear in the English language. For example, as far as JavaScript's regular expressions are concerned, a "((word character))" is only one of the 26 characters in the Latin alphabet (uppercase or lowercase), decimal digits, and, for some reason, the underscore character. Things like _é_ or _β_, which most definitely are word characters, will not match `\w` (and _will_ match uppercase `\W`, the nonword category). +JavaScript'in başlangıçtaki basit implementasyonu ve bu basit yaklaşımın daha sonra ((standart)) davranış olarak belirlenmesi nedeniyle, JavaScript'in düzenli ifadeleri, İngilizce dilinde bulunmayan karakterler hakkında oldukça gariptir. Örneğin, JavaScript'in düzenli ifadelerine göre, bir (("kelime karakteri")), yalnızca Latin alfabesinin 26 karakterinden biridir (büyük veya küçük harf), ondalık basamaklar ve, nedense alt çizgi karakteri. _é_ veya _β_ gibi kesinlikle kelime karakterleri olan şeyler, `\w` eşleşirken büyük harfli `\W` olmayan kelime kategorisine eşleşmeyecektir. {{index [whitespace, matching]}} -By a strange historical accident, `\s` (whitespace) does not have this problem and matches all characters that the Unicode standard considers whitespace, including things like the ((nonbreaking space)) and the ((Mongolian vowel separator)). +Tuhaf bir tarihsel kazadan dolayı, `\s` (boşluk) bu sorunu yaşamaz ve Unicode standardı tarafından boşluk olarak kabul edilen tüm karakterleri eşleştirir, bunlar arasında ((boşluk karakteri)) ve ((Moğol ünlü ayırıcı)) gibi şeyler de vardır. {{index "character category", [Unicode, property]}} -It is possible to use `\p` in a regular expression to match all characters to which the Unicode standard assigns a given property. This allows us to match things like letters in a more cosmopolitan way. However, again due to compatibility with the original language standards, those are only recognized when you put a `u` character (for ((Unicode))) after the regular expression. +Bir düzenli ifade içinde `\p` kullanarak Unicode standartında belirli bir özellik verilen tüm karakterlerle eşleştirebilmek mümkündür. Bu, harfleri daha kozmopolit bir şekilde eşleştirmemize olanak tanır. Ancak, yine de orijinal dil standartlarıyla uyumluluktan dolayı, bunlar yalnızca düzenli ifadenin sonuna ((Unicode)) için bir `u` karakteri eklediğinizde tanınır. {{table {cols: [1, 5]}}} -| `\p{L}` | Any letter -| `\p{N}` | Any numeric character -| `\p{P}` | Any punctuation character -| `\P{L}` | Any non-letter (uppercase P inverts) -| `\p{Script=Hangul}` | Any character from the given script (see [Chapter ?](higher_order#scripts)) +| `\p{L}` | Herhangi bir harf +| `\p{N}` | Herhangi bir sayısal karakter +| `\p{P}` | Herhangi bir noktalama işareti karakteri +| `\P{L}` | Harf olmayan herhangi bir şey (büyük harf P tersine çevrilir) +| `\p{Script=Hangul}` | Verilen alfabe dosyasındaki herhangi bir karakter ([Bölüm ?](higher_order#scripts)) -Using `\w` for text processing that may need to handle non-English text (or even English text with borrowed words like “cliché”) is a liability, since it won't treat characters like “é” as letters. Though they tend to be a bit more verbose, `\p` property groups are more robust. +Düzenli ifadeleri `\w` aracılığıyla metin işleme amaçları için kullanmak, İngilizce olmayan metinlerde (hatta İngilizce olan ancak “cliché” gibi ödünç alınmış kelimeleri kullanan metinlerde) “é” gibi karakterleri harfler olarak işlemeyeceğinden bir dezavantajdır. İçerikleri biraz daha uzun olsa da, `\p` özellik grupları daha sağlamdır. ```{test: never} console.log(/\p{L}/u.test("α")); @@ -178,17 +178,17 @@ console.log(/\p{Script=Arabic}/u.test("α")); {{index "Number function"}} -On the other hand, if you are matching numbers in order to do something with them, you often do want `\d` for digits, since converting arbitrary numeric characters into a JavaScript number is not something that a function like `Number` can do for you. +Öte yandan, bir şeyler yapmak için sayıları eşleştirecekse, genellikle onlara yapılacak şeyler için `\d`'yi kullanmak istersiniz çünkü `Number` gibi bir fonksiyonun sizin için sayı atanmış rastgele herhangi bir karakterleri JavaScript sayısına dönüştürmesi mümkün değildir. -## Repeating parts of a pattern +## Bir desenin tekrarlanan bölümleri {{index ["regular expression", repetition]}} -We now know how to match a single digit. What if we want to match a whole number—a ((sequence)) of one or more ((digit))s? +Şimdi tek bir basamağı eşleştirmeyi nasıl yapacağımızı biliyoruz. Bir tam sayıyı - bir veya daha fazla ((rakam))ın bir ((dizi))sini eşleştirmek istersek ne yapmalıyız? {{index "plus character", repetition, "+ operator"}} -When you put a plus sign (`+`) after something in a regular expression, it indicates that the element may be repeated more than once. Thus, `/\d+/` matches one or more digit characters. +Düzenli ifadede bir artı işareti (`+`) bir şeyin birden fazla kez tekrarlanabileceğini gösterir. Dolayısıyla, `/\d+/`, bir veya daha fazla rakam karakteri eşleştirir. ``` console.log(/'\d+'/.test("'123'")); @@ -203,11 +203,11 @@ console.log(/'\d*'/.test("''")); {{index "* operator", asterisk}} -The star (`*`) has a similar meaning but also allows the pattern to match zero times. Something with a star after it never prevents a pattern from matching—it'll just match zero instances if it can't find any suitable text to match. +Yıldız (`*`) benzer bir anlama sahiptir, ancak aynı zamanda kalıbın sıfır kez eşleşmesine izin verir. Bir şeyin sonunda yıldız olan bir şey asla bir kalıbın eşleşmesini engellemez - uygun metni bulamazsa sadece sıfır örnekler eşleştirir. {{index "British English", "American English", "question mark"}} -A question mark (`?`) makes a part of a pattern _((optional))_, meaning it may occur zero times or one time. In the following example, the _u_ character is allowed to occur, but the pattern also matches when it is missing: +Bir soru işareti, kalıbın bir parçasını _((isteğe bağlı))_ yapar, yani sıfır veya bir kez olabilir. Aşağıdaki örnekte, _u_ karakterinin olması izin verilir, ancak kalıp aynı zamanda eksik olduğunda da eşleşir. ``` let neighbor = /neighbou?r/; @@ -219,11 +219,11 @@ console.log(neighbor.test("neighbor")); {{index repetition, [braces, "in regular expression"]}} -To indicate that a pattern should occur a precise number of times, use braces. Putting `{4}` after an element, for example, requires it to occur exactly four times. It is also possible to specify a ((range)) this way: `{2,4}` means the element must occur at least twice and at most four times. +Bir kalıbın belirli bir sayı kadar gerçekleşmesi gerektiğini belirtmek için süslü parantezler kullanın. Örneğin, bir öğeden sonra `{4}` yazmak, onun tam olarak dört kez gerçekleşmesini gerektirir. Ayrıca bu şekilde bir ((aralık)) belirlemek de mümkündür: `{2,4}` öğenin en az iki kez ve en fazla dört kez gerçekleşmesini gerektirir. {{id date_regexp_counted}} -Here is another version of the ((date)) and ((time)) pattern that allows both single- and double-((digit)) days, months, and hours. It is also slightly easier to decipher. +İşte hem tek hem de çift ((rakam)) günleri, ayları ve saatleri olan ((tarih)) ve ((zaman)) kalıbının başka bir versiyonu. Ayrıca anlaması da biraz daha kolaydır. ``` let dateTime = /\d{1,2}-\d{1,2}-\d{4} \d{1,2}:\d{2}/; @@ -231,13 +231,13 @@ console.log(dateTime.test("1-30-2003 8:45")); // → true ``` -You can also specify open-ended ((range))s when using braces by omitting the number after the comma. For example, `{5,}` means five or more times. +Süslü parantezleri kullanırken, bir sayıdan sonraki virgülü atlayarak açık uçlu ((aralık))lar belirleyebilirsiniz. Bu nedenle, `{5,}` beş veya daha fazla kez anlamına gelir. -## Grouping subexpressions +## Alt ifadeleri gruplandırma {{index ["regular expression", grouping], grouping, [parentheses, "in regular expressions"]}} -To use an operator like `*` or `+` on more than one element at a time, you must use parentheses. A part of a regular expression that is enclosed in parentheses counts as a single element as far as the operators following it are concerned. +`*` veya `+` gibi bir operatörü aynı anda birden fazla öğe üzerinde kullanmak istiyorsanız, parantezleri kullanmanız gerekir. Parantezlerle çevrili bir düzenli ifade parçası, onu takip eden operatörler açısından tek bir öğe olarak sayılır. ``` let cartoonCrying = /boo+(hoo+)+/i; @@ -247,17 +247,17 @@ console.log(cartoonCrying.test("Boohoooohoohooo")); {{index crying}} -The first and second `+` characters apply only to the second `o` in `boo` and `hoo`, respectively. The third `+` applies to the whole group `(hoo+)`, matching one or more sequences like that. +İlk ve ikinci `+` karakteri, sırasıyla _boo_ ve _hoo_'daki ikinci _o_ için uygulanır. Üçüncü `+`, `(hoo+)` grubuna tamamen uygulanır, bir veya daha fazla benzer dizilerle eşleşir. {{index "case sensitivity", capitalization, ["regular expression", flags]}} -The `i` at the end of the expression in the example makes this regular expression case-insensitive, allowing it to match the uppercase _B_ in the input string, even though the pattern is itself all lowercase. +Örnekteki ifadenin sonundaki `i`, bu düzenli ifadeyi harf büyüklüğüne duyarsız hale getirir, böylece model kendisi tamamen küçük harfken giriş dizgisindeki büyük harf _B_ ile de eşleşir. -## Matches and groups +## Maçlar ve gruplar {{index ["regular expression", grouping], "exec method", [array, "RegExp match"]}} -The `test` method is the absolute simplest way to match a regular expression. It tells you only whether it matched and nothing else. Regular expressions also have an `exec` (execute) method that will return `null` if no match was found and return an object with information about the match otherwise. +`test` metodu, bir düzenli ifadeyi eşlemek için mutlak en basit yoldur. Sadece eşleşip eşleşmediğini söyler ve başka hiçbir şey söylemez. Düzenli ifadelerin ayrıca `exec` (çalıştır) adlı bir metodu vardır; bu metot, eşleşme bulunamazsa `null` döndürür ve aksi takdirde eşleşme hakkında bilgi içeren bir nesne döndürür. ``` let match = /\d+/.exec("one two 100"); @@ -269,11 +269,11 @@ console.log(match.index); {{index "index property", [string, indexing]}} -An object returned from `exec` has an `index` property that tells us _where_ in the string the successful match begins. Other than that, the object looks like (and in fact is) an array of strings, whose first element is the string that was matched. In the previous example, this is the sequence of ((digit))s that we were looking for. +`exec` tarafından döndürülen bir nesne, başarılı eşleşmenin dizede _nerede_ başladığını belirten bir `index` özelliğine sahiptir. Bunun dışında, nesne eşleşen dizgeyi içeren bir dize dizisi gibi görünür ki zaten öyledir de. Önceki örnekte, bu aradığımız ((rakam)) dizisidir. {{index [string, methods], "match method"}} -String values have a `match` method that behaves similarly. +Dize değerleri benzer şekilde davranan bir `match` metodu içerir. ``` console.log("one two 100".match(/\d+/)); @@ -282,7 +282,7 @@ console.log("one two 100".match(/\d+/)); {{index grouping, "capture group", "exec method"}} -When the regular expression contains subexpressions grouped with parentheses, the text that matched those groups will also show up in the array. The whole match is always the first element. The next element is the part matched by the first group (the one whose opening parenthesis comes first in the expression), then the second group, and so on. +Düzenli ifade, parantezlerle gruplandırılmış alt ifadeler içeriyorsa, bu gruplarla eşleşen metinlerin de dizi içinde görünür. Tüm eşleşme her zaman ilk öğedir. Bir sonraki öğe, ilk grup tarafından eşleştirilen kısım (ifadenin içindeki açılış parantezi önce gelen grup), ardından ikinci grup ve sonrasıdır. ``` let quotedText = /'([^']*)'/; @@ -292,7 +292,7 @@ console.log(quotedText.exec("she said 'hello'")); {{index "capture group"}} -When a group does not end up being matched at all (for example, when followed by a question mark), its position in the output array will hold `undefined`. When a group is matched multiple times (for example, when followed by a `+`), only the last match ends up in the array. +Bir grup hiç eşleşmediğinde (örneğin, bir soru işareti tarafından izlendiğinde), çıktı dizisindeki konumu `undefined` değerini tutar. Ve bir grup birden fazla kez eşleşirse (örneğin, bir `+` tarafından izlendiğinde), yalnızca son eşleşme diziye girer. ``` console.log(/bad(ly)?/.exec("bad")); @@ -301,7 +301,7 @@ console.log(/(\d)+/.exec("123")); // → ["123", "3"] ``` -If you want to use parentheses purely for grouping, without having them show up in the array of matches, you can put `?:` after the opening parenthesis. +Eşleşmelerin yalnızca gruplama amacıyla kullanılmasını istiyor ve döndürülen dizide gösterilmesini istemiyorsanız, açılış parantezinden sonra `?:` ekleyebilirsiniz. ``` console.log(/(?:na)+/.exec("banana")); @@ -310,15 +310,15 @@ console.log(/(?:na)+/.exec("banana")); {{index "exec method", ["regular expression", methods], extraction}} -Groups can be useful for extracting parts of a string. If we don't just want to verify whether a string contains a ((date)) but also extract it and construct an object that represents it, we can wrap parentheses around the digit patterns and directly pick the date out of the result of `exec`. +Gruplar, bir dizgenin parçalarını çıkarmak için yararlı olabilir. Bir dizgenin yalnızca bir ((tarih)) içerip içermediğini kontrol etmekle kalmayıp aynı zamanda bunu çıkarmak ve bunu temsil eden bir nesne oluşturmak istiyorsak, parantezleri sayı desenlerinin etrafına sarabilir ve `exec` fonksiyonunun sonucundan tarihi seçebiliriz. -But first we'll take a brief detour to discuss the built-in way to represent date and ((time)) values in JavaScript. +Ancak önce, JavaScript'te tarih ve ((zaman)) değerlerini temsil etmenin yerleşik yolunu tartışacağımız kısa bir yolculuğa çıkacağız. -## The Date class +## Date sınıfı {{index constructor, "Date class"}} -JavaScript has a standard `Date` class for representing ((date))s, or rather, points in ((time)). If you simply create a date object using `new`, you get the current date and time. +JavaScript'in ((tarih))leri - veya daha doğrusu, ((zaman)) noktalarını - temsil etmek için standart bir sınıfı vardır. Bu `Date` olarak adlandırılır. Sadece `new` kullanarak basitçe bir tarih nesnesi oluşturursanız, mevcut tarihi ve zamanı alırsınız. ```{test: no} console.log(new Date()); @@ -327,7 +327,7 @@ console.log(new Date()); {{index "Date class"}} -You can also create an object for a specific time. +Belirli bir zaman için bir nesne oluşturabilirsiniz. ``` console.log(new Date(2009, 11, 9)); @@ -338,13 +338,13 @@ console.log(new Date(2009, 11, 9, 12, 59, 59, 999)); {{index "zero-based counting", [interface, design]}} -JavaScript uses a convention where month numbers start at zero (so December is 11), yet day numbers start at one. This is confusing and silly. Be careful. +JavaScript, ay numaralarının sıfırdan başladığı bir kural kullanır (bu nedenle Aralık 11'dir), ancak gün numaraları bir'den başlar. Bu kafa karıştırıcı ve saçma. Dikkatli olun. -The last four arguments (hours, minutes, seconds, and milliseconds) are optional and taken to be zero when not given. +Son dört argüman (saatler, dakikalar, saniyeler ve milisaniyeler) isteğe bağlıdır ve verilmediğinde sıfır kabul edilir. {{index "getTime method", timestamp}} -Timestamps are stored as the number of milliseconds since the start of 1970, in the UTC ((time zone)). This follows a convention set by "((Unix time))", which was invented around that time. You can use negative numbers for times before 1970. The `getTime` method on a date object returns this number. It is big, as you can imagine. +Zaman damgaları, UTC ((zaman dilimi)) başlangıcından itibaren geçen milisaniye sayısı olarak depolanır. Bu, o zaman civarında icat edilen "((Unix zamanı))" tarafından belirlenen bir kuralı izler. 1970'den önceki zamanlar için negatif sayılar kullanabilirsiniz. Bir tarih nesnesindeki `getTime` metodu bu sayıyı döndürür. Tahmin edebileceğiniz gibi, bu büyüktür. ``` console.log(new Date(2013, 11, 19).getTime()); @@ -355,15 +355,15 @@ console.log(new Date(1387407600000)); {{index "Date.now function", "Date class"}} -If you give the `Date` constructor a single argument, that argument is treated as such a millisecond count. You can get the current millisecond count by creating a new `Date` object and calling `getTime` on it or by calling the `Date.now` function. +`Date` constructor fonksiyonuna tek bir argüman verirseniz, bu argüman milisaniye olarak kabul edilir. Mevcut milisaniye sayısını elde etmek için yeni bir `Date` nesnesi oluşturabilir ve üzerinde `getTime` çağrısı yapabilir veya `Date.now` fonksiyonunu çağırabilirsiniz. {{index "getFullYear method", "getMonth method", "getDate method", "getHours method", "getMinutes method", "getSeconds method", "getYear method"}} -Date objects provide methods such as `getFullYear`, `getMonth`, `getDate`, `getHours`, `getMinutes`, and `getSeconds` to extract their components. Besides `getFullYear` there's also `getYear`, which gives you the year minus 1900 (`98` or `119`) and is mostly useless. +Tarih nesneleri, bileşenlerini çıkarmak için `getFullYear`, `getMonth`, `getDate`, `getHours`, `getMinutes`, ve `getSeconds` gibi metodlar sağlar. `getFullYear` dışında, size yılın 1900 çıkarılmış halini (`98` veya `119`) veren `getYear` da vardır ve çoğunlukla kullanışsızdır. {{index "capture group", "getDate method", [parentheses, "in regular expressions"]}} -Putting parentheses around the parts of the expression that we are interested in, we can now create a date object from a string. +İlgilendiğimiz ifade parçalarını parantez içine alarak, şimdi bir dizeyi bir tarih nesnesine dönüştürebiliriz. ``` function getDate(string) { @@ -377,27 +377,27 @@ console.log(getDate("1-30-2003")); {{index destructuring, "underscore character"}} -The underscore (`_`) binding is ignored and used only to skip the full match element in the array returned by `exec`. +`exec` tarafından döndürülen dizideki `_` (alt çizgi) bağlantısı dikkate alınmaz ve yalnızca tam eşleşme öğesini atlamak için kullanılır. -## Boundaries and look-ahead +## Sınırlar ve görünüm {{index matching, ["regular expression", boundary]}} -Unfortunately, `getDate` will also happily extract a date from the string `"100-1-30000"`. A match may happen anywhere in the string, so in this case, it'll just start at the second character and end at the second-to-last character. +Maalesef, `getDate` aynı zamanda dize `"100-1-30000"` içinden de bir tarih alır. Bir eşleşme dize içinde herhangi bir yerde olabilir, bu nedenle bu durumda, sadece ikinci karakterden başlayıp sondan ikinci karakterde sona erecektir. {{index boundary, "caret character", "dollar sign"}} -If we want to enforce that the match must span the whole string, we can add the markers `^` and `$`. The caret matches the start of the input string, whereas the dollar sign matches the end. Thus `/^\d+$/` matches a string consisting entirely of one or more digits, `/^!/` matches any string that starts with an exclamation mark, and `/x^/` does not match any string (there cannot be an `x` before the start of the string). +Eşleşmenin dizeyi tamamen kaplaması gerektiğini zorlamak istiyorsak, `^` ve `$` işaretlerini ekleyebiliriz. Caret giriş dizesinin başlangıcına uyar, dolar işareti ise sona uyar. Bu nedenle, `/^\d+$/`, yalnızca bir veya daha fazla rakamdan oluşan bir dizeyi eşleştirir, `/^!/` bir ünlem işareti ile başlayan herhangi bir diziyi eşleştirir ve `/x^/` hiçbir dizeyi eşleştirmez (dizenin başlangıcından önce bir _x_ olamaz). {{index "word boundary", "word character"}} -There is also a `\b` marker that matches _word boundaries_, positions that have a word character one side, and a non-word character on the other. Unfortunately, these use the same simplistic concept of word characters as `\w`, and are therefore not very reliable. +"kelime sınırlarıyla" eşleşen `\b` işareti vardır, bu pozisyonlar bir tarafta kelime kararkteri bir tarafta kelime olmayan bir karakteri barındırır. `\w` da "kelime karakterleri" kavramı gibi basit kavramlarını kullanır ve bu nedenle pek güvenilir değildir. -Note that these boundary markers don't match any actual characters. They just enforce that a given condition holds at the place where they appears in the pattern. +Bu işaretlerin herhangi bir gerçek karakterle eşleşmediğini unutmayın. Sadece desende göründükleri yerde belirli bir koşulun geçerli olmasını sağlarlar. {{index "look-ahead"}} -_Look-ahead_ tests do something similar. They provide a pattern and will make the match fail if the input doesn't match that pattern, but don't actually move the match position forward. They are written between `(?=` and `)`. +İleri görüşlü testler de buna benzer bir şey yapar. Bir desen sağlar ve girdinin bu desene uymadığı durumlarda eşleşmeyi başarısız kılar, ancak aslında eşleşme konumunu ileri taşımaz. Bunlar `(?=` ve `)` arasında yazılır. ``` console.log(/a(?=e)/.exec("braeburn")); @@ -406,15 +406,15 @@ console.log(/a(?! )/.exec("a b")); // → null ``` -The `e` in the first example is necessary to match, but is not part of the matched string. The `(?! )` notation expresses a _negative_ look-ahead. This only matches if the pattern in the parentheses _doesn't_ match, causing the second example to only match `a` characters that don't have a space after them. +İlk örnekteki `e`'nin eşleşen dize parçasının bir parçası olmamasına rağmen eşleşme için gerekli olduğuna dikkat edin. `(?! )` notasyonu _negatif_ bir ön görüş ifade eder. Bu, ikinci örnekte yalnızca kendisinden sonra boşluk olmayan "a" karakterlerinin eşleşmesini sağlar. -## Choice patterns +## Seçim desenleri {{index branching, ["regular expression", alternatives], "farm example"}} -Say we want to know whether a piece of text contains not only a number but a number followed by one of the words _pig_, _cow_, or _chicken_, or any of their plural forms. +Bir metin parçasının sadece bir sayıyı değil, bir sayıyı ve bununla birlikte _pig_, _cow_, veya _chicken_ gibi kelimelerden birini veya bunların çoğul biçimlerinden herhangi birini içerip içermediğini bilmek istediğimizi varsayalım. -We could write three regular expressions and test them in turn, but there is a nicer way. The ((pipe character)) (`|`) denotes a ((choice)) between the pattern to its left and the pattern to its right. We can use it in expressions like this: +Üç düzenli ifade yazıp sırayla test edebiliriz, ancak daha güzel bir yol var. ((boru karakteri)) (`|`), solundaki desen ile sağdaki desen arasında ((seçim)) olarak işlev görür. Dolayısıyla, bunu diyebilirim: ``` let animalCount = /\d+ (pig|cow|chicken)s?/; @@ -426,63 +426,64 @@ console.log(animalCount.test("15 pugs")); {{index [parentheses, "in regular expressions"]}} -Parentheses can be used to limit the part of the pattern to which the pipe operator applies, and you can put multiple such operators next to each other to express a choice between more than two alternatives. +Parantezler, boru operatörünün uygulandığı desenin kısmını sınırlamak için kullanılabilir ve birden çok bu tür operatörü yan yana koyarak ikiden fazla alternatif arasında bir seçimi ifade edebilirsiniz. -## The mechanics of matching +## Eşleştirme mekaniği {{index ["regular expression", matching], [matching, algorithm], "search problem"}} -Conceptually, when you use `exec` or `test`, the regular expression engine looks for a match in your string by trying to match the expression first from the start of the string, then from the second character, and so on until it finds a match or reaches the end of the string. It'll either return the first match that can be found or fail to find any match at all. +Kavramsal olarak, `exec` veya `test` kullandığınızda, düzenli ifade motoru, dize içinde eşleşme arar ve ifadeyi ilk olarak dize başlangıcından itibaren eşleştirmeye çalışır, ardından ikinci karakterden itibaren ve bunu bir eşleşme bulana veya dize sonuna ulaşana kadar sürdürür. Bulunabilecek ilk eşleşmeyi ya döndürür ya da hiçbir eşleşme bulamaz. {{index ["regular expression", matching], [matching, algorithm]}} -To do the actual matching, the engine treats a regular expression something like a ((flow diagram)). This is the diagram for the livestock expression in the previous example: +Gerçek eşleştirmeyi yapmak için, motor, düzenli ifadeyi bir ((akış diyagramı)) gibi işler. Bu, önceki örnekteki hayvan ifadesinin diyagramıdır: -{{figure {url: "img/re_pigchickens.svg", alt: "Railroad diagram that first passes through a box labeled 'digit', which has a loop going back from after it to before it, and then a box for a space character. After that, the railroad splits in three, going through boxes for 'pig', 'cow', and 'chicken'. After those it rejoins, and goes through a box labeled 's', which, being optional, also has a railroad that passes it by. Finally, the line reaches the accepting state."}}} +{{figure {url: "img/re_pigchickens.svg", alt: "İlk önce 'rakam' etiketli bir kutudan geçen, sonra geri dönen bir döngü ve daha sonra bir boşluk karakteri için bir kutudan geçen demiryolu diyagramı. Bundan sonra, demiryolu üçte ayrılır, 'domuz', 'inek' ve 'tavuk' için kutulardan geçer. Onlardan sonra tekrar birleşir ve isteğe bağlı olarak, onu geçen bir demiryoluna sahip olan 'S' etiketli bir kutudan geçer. Son olarak, çizgi kabul eden duruma ulaşır."}}} {{index traversal}} -If we can find a path from the left side of the diagram to the right side, our expression matches. We keep a current position in the string, and every time we move through a box, we verify that the part of the string after our current position matches that box. +Our expression matches if we can find a path from the left side of the diagram to the right side. We keep a current position in the string, and every time we move through a box, we verify that the part of the string after our current position matches that box. +İfademiz, diyagramın sol tarafından sağ tarafına bir yol bulabilirse eşleşir. Dizgede bir geçerli konum tutarız ve her bir kutudan geçerken, mevcut konumumuzdan sonrasının kutu ile eşleşip eşleşmediğini doğrularız. {{id backtracking}} -## Backtracking +## Geri izleme {{index ["regular expression", backtracking], "binary number", "decimal number", "hexadecimal number", "flow diagram", [matching, algorithm], backtracking}} -The regular expression `/^([01]+b|[\da-f]+h|\d+)$/` matches either a binary number followed by a `b`, a hexadecimal number (that is, base 16, with the letters `a` to `f` standing for the digits 10 to 15) followed by an `h`, or a regular decimal number with no suffix character. This is the corresponding diagram: +Düzenli ifade `/^([01]+b|[\da-f]+h|\d+)$/` ya bir ikili sayıyının sonrasında bir _b_ olan, ya bir onaltılı sayıyı (yani, harfler _a_ ile _f_ 10 ile 15 arasındaki rakamları temsil ettiği) sonrasında bir _h_ olan ya da hiçbir son ek karakteri olmayan bir düzenli ondalık sayıyı eşleştirir. Bu, karşılık gelen diyagramdır: -{{figure {url: "img/re_number.svg", alt: "Railroad diagram for the regular expression '^([01]+b|\\d+|[\\da-f]+h)$'"}}} +{{figure {url: "img/re_number.svg", alt: "'^([01]+b|\\d+|[\\da-f]+h)$' düzenli ifadesi için demiryolu diyagramı."}}} {{index branching}} -When matching this expression, the top (binary) branch will often be entered even though the input does not actually contain a binary number. When matching the string `"103"`, for example, it becomes clear only at the `3` that we are in the wrong branch. The string _does_ match the expression, just not the branch we are currently in. +Bu ifadeyi eşleştirirken, girişin gerçekte bir ikili sayı içermediği durumda bile genellikle üst (ikili) şubeye girilir. Örneğin, dize `"103"` ile eşleştirirken, 3 karakterini gördüğümüzde yanlış şubede olduğumuzu sonradan anlayabiliriz. Dize ifadeye _uyar_, ancak şu anda bulunduğumuz şubeye değil. {{index backtracking, "search problem"}} -So the matcher _backtracks_. When entering a branch, it remembers its current position (in this case, at the start of the string, just past the first boundary box in the diagram) so that it can go back and try another branch if the current one does not work out. For the string `"103"`, after encountering the `3` character, the matcher starts trying the branch for hexadecimal numbers, which fails again because there is no `h` after the number. It then tries the decimal number branch. This one fits, and a match is reported after all. +Bu nedenle eşleyici geri döner. Bir şubeye girerken, mevcut konumunu (bu durumda diyagramdaki ilk sınır kutusunun hemen ötesinde, dizenin başlangıcında) hatırlar, böylece mevcut şube işe yaramazsa başka bir şube denemek için geri dönebilir. `"103"` dizesi için 3 karakterini gördükten sonra, onaltılı sayılar şubesini denemeye başlar, ancak sayıdan sonra bir _h_ olmadığı için bu şube başarısız olur. Sonra ondalık sayı şubesini dener. Bu uygun olur ve sonunda bir eşleşme bildirilir. {{index [matching, algorithm]}} -The matcher stops as soon as it finds a full match. This means that if multiple branches could potentially match a string, only the first one (ordered by where the branches appear in the regular expression) is used. +Eşleyici, bir tam eşleşme bulduğunda durur. Bu, birden çok şubenin bir dizeyi potansiyel olarak eşleştirebileceği durumlarda, yalnızca ilk şubenin (düzenli ifade içinde şubelerin göründüğü yere göre sıralanır) kullanılacağı anlamına gelir. -Backtracking also happens for ((repetition)) operators like + and `*`. If you match `/^.*x/` against `"abcxe"`, the `.*` part will first try to consume the whole string. The engine will then realize that it needs an `x` to match the pattern. Since there is no `x` past the end of the string, the star operator tries to match one character less. But the matcher doesn't find an `x` after `abcx` either, so it backtracks again, matching the star operator to just `abc`. _Now_ it finds an `x` where it needs it and reports a successful match from positions 0 to 4. +Geri dönme, `+` ve `*` gibi ((tekrar)) operatörleri için de geçerlidir. `"abcxe"` ile `/^.*x/` eşleşirse, `.*` kısmı önce tüm diziyi tüketmeye çalışır. Daha sonra, deseni eşleştirmek için bir _x_ gerektiğini fark eder. Dizinin sonunda bir _x_ olmadığı için, yıldız operatörü bir karakter daha az eşleşmeye çalışır. Ancak eşleşme, `abcx`'ten sonra bir _x_ bulamaz, bu nedenle tekrar geri döner ve yıldız operatörünü sadece `abc`'ye eşleştirmeye çalışır. Şimdi ihtiyacı olan yere bir _x_ bulur ve 0 ile 4 arasında başarılı bir eşleşme bildirir. {{index performance, complexity}} -It is possible to write regular expressions that will do a _lot_ of backtracking. This problem occurs when a pattern can match a piece of input in many different ways. For example, if we get confused while writing a binary-number regular expression, we might accidentally write something like `/([01]+)+b/`. +_Çok fazla_ dönme yapacak düzenli ifadeler yazmak mümkündür. Bu problem, bir desenin bir girişi birçok farklı şekilde eşleştirebilmesi durumunda ortaya çıkar. Örneğin, bir ikili sayı düzenli ifadesi yazarken kafamız karışırsa, yanlışlıkla `/([01]+)+b/` gibi bir şey yazabiliriz. -{{figure {url: "img/re_slow.svg", alt: "Railroad diagram for the regular expression '([01]+)+b'",width: "6cm"}}} +{{figure {url: "img/re_slow.svg", alt: "'([01]+)+b' düzenli ifadesi için demiryolu diyagramı.", width: "6cm"}}} {{index "inner loop", [nesting, "in regexps"]}} -If that tries to match some long series of zeros and ones with no trailing _b_ character, the matcher first goes through the inner loop until it runs out of digits. Then it notices there is no _b_, so it backtracks one position, goes through the outer loop once, and gives up again, trying to backtrack out of the inner loop once more. It will continue to try every possible route through these two loops. This means the amount of work _doubles_ with each additional character. For even just a few dozen characters, the resulting match will take practically forever. +Eğer bu, sona gelen _b_ karakteri olmadan uzun bir sıfır ve birler serisiyle eşleşmeye çalışırsa, eşleyici önce iç döngüden geçer ve bunu rakamlar bitene kadar yapmaya devam eder. Sonra _b_ olmadığını fark eder, bu yüzden bir konum geri döner, dış döngüden bir kez geçer ve yine vazgeçip iç döngüden bir kez daha geri dönmeye çalışır. Bu iki döngü arasındaki herhangi bir olası rotayı denemeye devam eder. Bu, her ek karakterle çalışmanın işini ikiye katlanacağı anlamına gelir. Yalnızca birkaç düzine karakter için bile, elde edilen eşleşme neredeyse sonsuza kadar sürer. -## The replace method +## replace metodu {{index "replace method", "regular expression"}} -String values have a `replace` method that can be used to replace part of the string with another string. +Dize değerleri, bir dizeyi başka bir dizeyle değiştirmek için `replace` metoduna sahiptir. ``` console.log("papa".replace("p", "m")); @@ -491,7 +492,7 @@ console.log("papa".replace("p", "m")); {{index ["regular expression", flags], ["regular expression", global]}} -The first argument can also be a regular expression, in which case the first match of the regular expression is replaced. When a `g` option (for _global_) is added after the regular expression, _all_ matches in the string will be replaced, not just the first. +İlk argüman ayrıca bir düzenli ifade de olabilir, bu durumda düzenli ifadenin ilk eşleşmesi değiştirilir. Düzenli ifadenin ardından bir `g` seçeneği (_global_ için) eklenirse, dizedeki yalnızca ilk değil _tüm_ eşleşmeler değiştirilir. ``` console.log("Borobudur".replace(/[ou]/, "a")); @@ -502,7 +503,7 @@ console.log("Borobudur".replace(/[ou]/g, "a")); {{index grouping, "capture group", "dollar sign", "replace method", ["regular expression", grouping]}} -The real power of using regular expressions with `replace` comes from the fact that we can refer to matched groups in the replacement string. For example, say we have a big string containing the names of people, one name per line, in the format `Lastname, Firstname`. If we want to swap these names and remove the comma to get a `Firstname Lastname` format, we can use the following code: +`replace` ile düzenli ifadeleri kullanmanın gerçek gücü, eşleşen gruplara değiştirme dizesinde başvurabileceğimiz gerçeğinden gelir. Örneğin, her bir satırda `Lastname, Firstname` biçiminde bir ad bulunan büyük bir dizeye sahip olduğumuzu varsayalım. Bu isimleri değiştirmek ve virgülü kaldırarak `Firstname Lastname` biçimini elde etmek istiyorsak, aşağıdaki kodu kullanabiliriz: ``` console.log( @@ -513,13 +514,13 @@ console.log( // Robin Milner ``` -The `$1` and `$2` in the replacement string refer to the parenthesized groups in the pattern. `$1` is replaced by the text that matched against the first group, `$2` by the second, and so on, up to `$9`. The whole match can be referred to with `$&`. +Değiştirme dizesindeki `$1` ve `$2`, desendeki parantez içi gruplara başvurur. `$1`, ilk gruba karşı eşleşen metin ile değiştirilir, `$2` ikinci grup ile değiştirilir ve böyle devam eder, `$9`'a kadar. Tüm eşleşme `$&` ile başvurulabilir. {{index [function, "higher-order"], grouping, "capture group"}} -It is possible to pass a function—rather than a string—as the second argument to `replace`. For each replacement, the function will be called with the matched groups (as well as the whole match) as arguments, and its return value will be inserted into the new string. +`replace` metoduna ikinci argüman olarak bir dize yerine fonksiyon vermek mümkündür. Her değiştirme için, fonksiyon, eşleşen gruplarla (ayrıca tüm eşleşme ile) argüman olarak çağrılır ve dönüş değeri yeni dizeye eklenir. -Here's an example: +İşte bir örnek: ``` let stock = "1 lemon, 2 cabbages, and 101 eggs"; @@ -536,15 +537,15 @@ console.log(stock.replace(/(\d+) (\p{L}+)/gu, minusOne)); // → no lemon, 1 cabbage, and 100 eggs ``` -This code takes a string, finds all occurrences of a number followed by an alphanumeric word, and returns a string that has one less of every such quantity. +Bu bir dize alır, bir alfasayısal kelime tarafından izlenen tüm sayı geçişlerini bulur ve o türdeki her sayıdan bir eksik dize döndürür. -The `(\d+)` group ends up as the `amount` argument to the function, and the `(\p{L}+)` group gets bound to `unit`. The function converts `amount` to a number—which always works since it matched `\d+` earlier—and makes some adjustments in case there is only one or zero left. +`(\d+)` grubu, fonksiyona `amount` argümanı olarak gelir ve `(\p{L}+)` grubu `unit` olarak gelir. Fonksiyon, `amount`'u bir sayıya dönüştürür -her zaman `\d+` ile eşleştiğinden- ve yalnızca bir veya sıfır kaldığında bazı ayarlamalar yapar. -## Greed +## Açgözlülük {{index greed, "regular expression"}} -We can use `replace` to write a function that removes all ((comment))s from a piece of JavaScript ((code)). Here is a first attempt: +Tüm ((yorum))ları bir JavaScript ((kodu)) parçasından kaldıran bir fonksiyon yazmak için `replace` metodunu kullanmak mümkündür. İşte bir ilk deneme: ```{test: wrap} function stripComments(code) { @@ -560,17 +561,17 @@ console.log(stripComments("1 /* a */+/* b */ 1")); {{index "period character", "slash character", "newline character", "empty set", "block comment", "line comment"}} -The part before the `|` operator matches two slash characters followed by any number of non-newline characters. The part for multiline comments is more involved. We use `[^]` (any character that is not in the empty set of characters) as a way to match any character. We cannot just use a period here because block comments can continue on a new line, and the period character does not match newline characters. +_Veya_ operatöründen önceki kısım iki eğik çizgi karakterini ve ardından gelen herhangi yeni satır olmayan karakteri eşleştirir. Çok satırlı yorumlar için kısım daha karmaşıktır. Herhangi bir karakteri eşleştirmenin bir yolu olarak `[^]` (boş karakter kümesinde olmayan herhangi bir karakter) kullanırız. Burada sadece bir nokta kullanamayız çünkü blok yorumları yeni bir satırda devam edebilir ve nokta karakteri yeni satır karakterlerini eşleştirmez. -But the output for the last line appears to have gone wrong. Why? +Ancak, son satırın çıktısında bir sorun varmış gibi duruyor. Neden? {{index backtracking, greed, "regular expression"}} -The `[^]*` part of the expression, as I described in the section on backtracking, will first match as much as it can. If that causes the next part of the pattern to fail, the matcher moves back one character and tries again from there. In the example, the matcher first tries to match the whole rest of the string and then moves back from there. It will find an occurrence of `*/` after going back four characters and match that. This is not what we wanted—the intention was to match a single comment, not to go all the way to the end of the code and find the end of the last block comment. +Desendeki `[^]*` kısmı, geri dönme bölümünde açıkladığım gibi, önce bulabileceği kadar çok şeyi eşleştirir. Bu, desenin bir sonraki kısmının başarısız olmasına neden olursa, eşleyici bir karakter geri gider ve oradan tekrar denemeye çalışır. Örnekte, eşleyici önce dizinin geri kalanının tamamını eşleştirmeye çalışır ve oradan geri gider. `*/`'nın bir eşleşmesini dört karakter geri giderek bulacaktır. Bu istediğimiz şey değildi - niyetimiz bir tek yorumu eşleştirmekti, kodun en sonuna gidip en sonda bulunan yorum bloğu sonunu bulmak değil. -Because of this behavior, we say the repetition operators (`+`, `*`, `?`, and `{}`) are _((greed))y_, meaning they match as much as they can and backtrack from there. If you put a ((question mark)) after them (`+?`, `*?`, `??`, `{}?`), they become nongreedy and start by matching as little as possible, matching more only when the remaining pattern does not fit the smaller match. +Bu davranış nedeniyle, tekrar operatörleri (`+`, `*`, `?`, ve `{}`) _((açgöz))lü_ olarak adlandırılır, yani olabildiğince çok şey eşleştirirler ve oradan geri dönerler. Onlardan sonra ((soru işareti)) (`+?`, `*?`, `??`, `{}?`) koyarsanız, artık açgözlü olmazlar ve önce mümkün olduğunca az eşleşen bir diziyle başlarlar, daha küçük eşleşme uygun gelmediğinde daha fazla eşleştirirler. -And that is exactly what we want in this case. By having the star match the smallest stretch of characters that brings us to a `*/`, we consume one block comment and nothing more. +Ve bu durumda tam olarak istediğimiz budur. Yıldızın bizi `*/`'a getiren en küçük karakter dizisini eşleştirmesiyle, bir blok yorumu tüketiriz ve daha fazlasını değil. ```{test: wrap} function stripComments(code) { @@ -580,13 +581,13 @@ console.log(stripComments("1 /* a */+/* b */ 1")); // → 1 + 1 ``` -A lot of ((bug))s in ((regular expression)) programs can be traced to unintentionally using a greedy operator where a nongreedy one would work better. When using a ((repetition)) operator, prefer the nongreedy variant. +((Düzenli ifade)) programlarında birçok ((hata)), daha iyi çalışan bir açgözlü olmayan operatör yerine yanlışlıkla açgözlü bir operatör kullanmanın sonucudur. Bir ((tekrar)) operatörü kullanırken, açgözlü olmayan varyantı tercih edin. -## Dynamically creating RegExp objects +## Dinamik olarak RegExp nesleri yaratmak {{index ["regular expression", creation], "underscore character", "RegExp class"}} -In some cases you may not know the exact ((pattern)) you need to match against when you are writing your code. Say you want to test for the user's name in a piece of text. You can build up a string and use the `RegExp` ((constructor)) on that. +Kodunuzu yazarken eşleştirmeniz gereken tam ((kalıbı)) bilmediğiniz durumlar vardır. Bir metin parçasında kullanıcının adını test etmek istediğinizi varsayalım. Bir dize biriktirip `RegExp` ((constructor)) fonksiyonunu üzerinde kullanabilirsiniz. İşte bir örnek: ``` let name = "harry"; @@ -597,13 +598,13 @@ console.log(regexp.test("Harry is a dodgy character.")); {{index ["regular expression", flags], ["backslash character", "in regular expressions"]}} -When creating the `\s` part of the string, we have to use two backslashes because we are writing them in a normal string, not a slash-enclosed regular expression. The second argument to the `RegExp` constructor contains the options for the regular expression—in this case, `"gi"` for global and case-insensitive. +Dize kısmımda `\s` oluşturulurken, bunları bir bir düzenli ifade içinde değil de normal dize içinde yazdığımızdan ötürü iki ters eğik çizgi kullanmamız gerekiyor. `RegExp` constructor fonksiyonunun ikinci argümanı, düzenli ifade seçeneklerini içerir -bu durumda, global ve harf büyüklüğüne duyarsız olan `"gi"`. -But what if the name is `"dea+hl[]rd"` because our user is a ((nerd))y teenager? That would result in a nonsensical regular expression that won't actually match the user's name. +Peki ya kullanıcımız adı `"dea+hl[]rd"` olan bir ergen ((geek)) ise? Bu, kullanıcının adını gerçekten eşleştirmeyen anlamsız bir düzenli ifadeye yol açar. {{index ["backslash character", "in regular expressions"], [escaping, "in regexps"], ["regular expression", escaping]}} -To work around this, we can add backslashes before any character that has a special meaning. +Bunu çözmek için, özel bir anlamı olan her karakterin önüne ters eğik çizgi ekleyebiliriz. ``` let name = "dea+hl[]rd"; @@ -615,11 +616,11 @@ console.log(regexp.test(text)); // → true ``` -## The search method +## search metodu {{index ["regular expression", methods], "indexOf method", "search method"}} -While the `indexOf` method on strings cannot be called with a regular expression, there is another method, `search`, that does expect a regular expression. Like `indexOf`, it returns the first index on which the expression was found, or -1 when it wasn't found. +Dize üzerindeki `indexOf` metodu bir düzenli ifade ile çağrılamaz. Ancak, düzenli ifade bekleyen başka bir yöntem olan `search` adında bir yöntem vardır. `indexOf` gibi, ifadenin bulunduğu ilk index pozisyonunu döndürür veya bulunamadığında -1 döndürür. ``` console.log(" word".search(/\S/)); @@ -628,21 +629,21 @@ console.log(" ".search(/\S/)); // → -1 ``` -Unfortunately, there is no way to indicate that the match should start at a given offset (like we can with the second argument to `indexOf`), which would often be useful. +Ne yazık ki, eşleşmenin belirli bir konumdan başlaması gerektiğini belirtmenin bir yolu yoktur (`indexOf`'deki ikinci argümanla yaptığımız gibi), bu genellikle kullanışlı olurdu. -## The lastIndex property +## lastIndex özelliği {{index "exec method", "regular expression"}} -The `exec` method similarly does not provide a convenient way to start searching from a given position in the string. But it does provide an *in*convenient way. +`exec` metodu benzer şekilde, dizinde belirli bir konumdan aramaya başlamanın kolay bir yolunu sağlamaz. Ancak kolay _olmayan_, zor bir yolunu sağlar. {{index ["regular expression", matching], matching, "source property", "lastIndex property"}} -Regular expression objects have properties. One such property is `source`, which contains the string that expression was created from. Another property is `lastIndex`, which controls, in some limited circumstances, where the next match will start. +Düzenli ifade nesnelerinin özellikleri vardır. Bunlardan biri `source` özelliğidir ve değerinde bu ifadenin oluşturulduğu dizeyi barındırır. Başka bir özellik de `lastIndex`'tir, bazı sınırlı durumlarda bir sonraki eşleşmenin nereden başlayacağını kontrol eder. {{index [interface, design], "exec method", ["regular expression", global]}} -Those circumstances are that the regular expression must have the global (`g`) or sticky (`y`) option enabled, and the match must happen through the `exec` method. Again, a less confusing solution would have been to just allow an extra argument to be passed to `exec`, but confusion is an essential feature of JavaScript's regular expression interface. +Bu durumlar, düzenli ifadenin global (`g`) veya yapışkan (`y`) seçeneğinin etkinleştirilmiş olması ve eşleşmenin `exec` metodu aracılığıyla gerçekleşmiş olması gereklidir. Tabii, daha az kafa karışıklığına sebep olmak için `exec` metoduna ekstra bir argümanın verilmesine izin verilmesi daha iyi olurdu, ancak karışıklık JavaScript'in düzenli ifade arayüzünün temel bir özelliğidir. ``` let pattern = /y/g; @@ -656,9 +657,9 @@ console.log(pattern.lastIndex); {{index "side effect", "lastIndex property"}} -If the match was successful, the call to `exec` automatically updates the `lastIndex` property to point after the match. If no match was found, `lastIndex` is set back to zero, which is also the value it has in a newly constructed regular expression object. +Eşleşme başarılı olduysa, `exec` çağrısı otomatik olarak `lastIndex` özelliğini eşleşmenin sonrasına işaret edecek şekilde günceller. Eğer bir eşleşme bulunamadıysa, `lastIndex` sıfıra, aynı zamanda yeni oluşturulan bir düzenli ifade nesnesinin sahip olduğu değere geri döner. -The difference between the global and the sticky options is that when sticky is enabled, the match will succeed only if it starts directly at `lastIndex`, whereas with global, it will search ahead for a position where a match can start. +Global ve yapışkan seçenekler arasındaki fark, yapışkan etkinleştirildiğinde, eşleşme ancak `lastIndex`'te doğrudan başlaması durumunda başarılı olacağıdır, global kullanıldığındaysa, bir eşleşmenin başlayabileceği bir konumu arar. ``` let global = /abc/g; @@ -671,7 +672,7 @@ console.log(sticky.exec("xyz abc")); {{index bug}} -When using a shared regular expression value for multiple `exec` calls, these automatic updates to the `lastIndex` property can cause problems. Your regular expression might be accidentally starting at an index left over from a previous call. +Birden fazla `exec` çağrısı için paylaşılan bir düzenli ifade değeri kullanırken, bu otomatik güncellemeler `lastIndex` özelliğinin değerinde sorunlara neden olabilir. Düzenli ifadeniz yanlışlıkla önceki bir çağrıdan kalan index değerinden başlayabilir. ``` let digit = /\d/g; @@ -683,18 +684,20 @@ console.log(digit.exec("and now: 1")); {{index ["regular expression", global], "match method"}} -Another interesting effect of the global option is that it changes the way the `match` method on strings works. When called with a global expression, instead of returning an array similar to that returned by `exec`, `match` will find _all_ matches of the pattern in the string and return an array containing the matched strings. +Global seçeneğin başka bir ilginç etkisi de, dizeler üzerindeki `match` metodunun çalışma şeklini değiştirmesidir. Global bir ifade ile çağrıldığında, `exec` tarafından döndürülen diziye benzer bir dizi döndürmek yerine, `match`, dizedeki desenin _tüm_ eşleşmelerini bulur ve eşleşen dizeleri içeren bir dizi döndürür. ``` console.log("Banana".match(/an/g)); // → ["an", "an"] ``` -So be cautious with global regular expressions. The cases where they are necessary—calls to `replace` and places where you want to explicitly use `lastIndex`—are typically the situations where you want to use them. +Dolayısıyla, global düzenli ifadelerle dikkatli olun. Bunların gerekli olduğu durumlar - `replace` çağrıları ve açıkça `lastIndex`'i kullanmak istediğiniz yerler- genellikle bunları kullanmak istediğiniz tek yerlerdir. + +### Tüm eşleşmeleri alma {{index "lastIndex property", "exec method", loop}} -A common thing to do is to find all the matches of a regular expression in a string. We can do this by using the `matchAll` method. +Bir dizedeki bir düzenli ifadenin tüm eşleşmelerini bulmanın yaygın bir kullanımı vardır. Bunu `matchAll` metodunu kullanarak yapabiliriz. ``` let input = "A string with 3 numbers in it... 42 and 88."; @@ -709,14 +712,15 @@ for (let match of matches) { {{index ["regular expression", global]}} -This method returns an array of match arrays. The regular expression given to `matchAll` _must_ have `g` enabled. +Bu metod, bir dizi eşleşme dizisi döndürür. Verilen düzenli ifadenin _mutlaka_ `g` seçeneği etkinleştirilmiş olmalıdır. {{id ini}} -## Parsing an INI file + +## Bir INI dosyasını ayrıştırma(parse etme) {{index comment, "file format", "enemies example", "INI file"}} -To conclude the chapter, we'll look at a problem that calls for ((regular expression))s. Imagine we are writing a program to automatically collect information about our enemies from the ((Internet)). (We will not actually write that program here, just the part that reads the ((configuration)) file. Sorry.) The configuration file looks like this: +Bölümü sonlandırmak için, ((düzenli ifade))lere ihtiyaç duyulan bir soruna bakacağız. Düşmanlarımız hakkında ((internet))ten bilgi toplamak için bir program yazdığımızı hayal edin. (Burada aslında bu programı yazmayacağız, sadece ((konfigürasyon)) dosyasını okuyan kısmı yazacağız. Maalesef.) Konfigürasyon dosyası şöyle görünüyor: ```{lang: "null"} searchengine=https://duckduckgo.com/?q=$1 @@ -737,25 +741,25 @@ outputdir=/home/marijn/enemies/davaeorn {{index grammar}} -The exact rules for this format—which is a widely used file format, usually called an _INI_ file—are as follows: +Bu biçim için kesin kurallar (genellikle _INI_ dosyası olarak adlandırılan yaygın bir biçimdir) şunlardır: -- Blank lines and lines starting with semicolons are ignored. +- Boş satırlar ve noktalı virgül ile başlayan satırlar yoksayılır. -- Lines wrapped in `[` and `]` start a new ((section)). +- [ ve ] içinde sarmalanan satırlar yeni bir ((bölüm)) başlatır. -- Lines containing an alphanumeric identifier followed by an `=` character add a setting to the current section. +- Alfasayısal bir tanımlayıcıyı takiben bir `=` karakter içeren satırlar, mevcut bölüme bir ayar ekler. -- Anything else is invalid. +- Bunlardan başka her şey geçersizdir. -Our task is to convert a string like this into an object whose properties hold strings for settings written before the first section header and subobjects for sections, with those subobjects holding the section's settings. +Görevimiz, böyle bir dizeyi, ilk bölüm başlığından önce yazılan ayarları tutan özelliklere sahip nesneye ve bölümleri tutan alt nesnelerleri barındıran bir nesneye dönüştürmektir. {{index "carriage return", "line break", "newline character"}} -Since the format has to be processed ((line)) by line, splitting up the file into separate lines is a good start. We saw the `split` method in [Chapter ?](data#split). Some operating systems, however, use not just a newline character to separate lines but a carriage return character followed by a newline (`"\r\n"`). Given that the `split` method also allows a regular expression as its argument, we can use a regular expression like `/\r?\n/` to split in a way that allows both `"\n"` and `"\r\n"` between lines. +Biçimin ((satır)) satır işlenmesini gerektirdiğinden, dosyayı ayrı satırlara ayırmak iyi bir başlangıçtır. `split` metodunu [bölüm ?](data#split) içinde gördük. Ancak, bazı işletim sistemleri, sadece bir yeni satır karakterini değil, bir taşıma dönüş karakteri ve ardından bir yeni satır karakteri (`"\r\n"`) kullanır. `split` metodunun da bir düzenli ifadeyi argüman olarak almasına izin verildiğinden, `/\r?\n/` gibi bir düzenli ifade kullanarak, satırlar arasında hem `"\n"` hem de `"\r\n"` izin veren bir şekilde bölebiliriz. ```{startCode: true} function parseINI(string) { - // Start with an object to hold the top-level fields + // En üst seviye alanları tutabilmek için bir nesneyle başla let result = {}; let section = result; for (let line of string.split(/\r?\n/)) { @@ -780,25 +784,25 @@ city=Tessaloniki`)); {{index "parseINI function", parsing}} -The code goes over the file's lines and builds up an object. Properties at the top are stored directly into that object, whereas properties found in sections are stored in a separate section object. The `section` binding points at the object for the current section. +Kod, dosyanın satırlarını geçer ve bir nesne oluşturur. Üstteki özellikler doğrudan bu nesneye depolanırken, bölümlerde bulunan özellikler ayrı bir bölüm nesnesine depolanır. `section` bağlantısı, mevcut bölüm için olan nesneye işaret eder. -There are two kinds of significant lines—section headers or property lines. When a line is a regular property, it is stored in the current section. When it is a section header, a new section object is created, and `section` is set to point at it. +İki tür önemli satır vardır - bölüm başlıkları veya özellik satırları. Bir satır normal bir özellik olduğunda, mevcut bölüme depolanır. Bir bölüm başlığı olduğunda, yeni bir bölüm nesnesi oluşturulur ve `section` bunua işaret etmesi için ayarlanır. {{index "caret character", "dollar sign", boundary}} -Note the recurring use of `^` and `$` to make sure the expression matches the whole line, not just part of it. Leaving these out results in code that mostly works but behaves strangely for some input, which can be a difficult bug to track down. +`^` ve `$` işaretinin ifadenin sadece bir parçası değil, tüm satırı eşleştirmesini sağlamak için tekrar tekrar kullanılmasına dikkat edin. Bunları bırakmak, çoğunlukla işe yarayan ancak bazı girdiler için garip davranan bir kod sonucu ile sonuçlanır, bu da takip edilmesi zor bir hatadır. {{index "if keyword", assignment, ["= operator", "as expression"]}} -The pattern `if (match = string.match(...))` makes use of the fact that the value of an ((assignment)) expression (`=`) is the assigned value. You often aren't sure that your call to `match` will succeed, so you can access the resulting object only inside an `if` statement that tests for this. To not break the pleasant chain of `else if` forms, we assign the result of the match to a binding and immediately use that assignment as the test for the `if` statement. +`if (match = string.match(...))` kalıbı, bir ((atama)) ifadesinin (`=`) değerinin atanmış değer olduğu gerçeğinden yararlanır. `match` çağrınızın başarılı olacağından emin olamazsınız, bu yüzden sonucu yalnızca bunu test eden bir `if` ifadesi içinde erişebilirsiniz. `else if` zincirini bozmamak için, eşleşmenin sonucunu bir bağlantıya atar ve hemen bu atamayı `if` ifadesi için test olarak kullanırız. {{index [parentheses, "in regular expressions"]}} -If a line is not a section header or a property, the function checks whether it is a comment or an empty line using the expression `/^\s*(;|$)/` to match lines that either contain only space, or space followed by a semicolon (making the rest of the line a comment). When a line doesn't match any of the expected forms, the function throws an exception. +Bir satır eğer bir bölüm başlığı veya bir özellik değilse, fonksiyon, `/^\s*(;|$)/` ifadesini kullanarak satırın bir yorum veya boş bir satır olup olmadığını kontrol eder. Bir satırın beklenen biçimlerden hiçbirine uymadığı durumda, fonksiyon bir istisna fırlatır. -## Code units and characters +## Kod birimleri ve karakterler -Another design mistake that's been standardized in JavaScript regular expressions is that by default, operators like `.` or `?` work on code units, as discussed in [Chapter ?](higher_order#code_units), not actual characters. This means characters that are composed of two code units behave strangely. +JavaScript düzenli ifadelerinde standartlaştırılmış başka bir tasarım hatası da, [bölüm ?](higher_order#code_units) içinde tartışıldığı gibi varsayılan olarak `.` veya `?` gibi operatörlerin gerçek karakterler yerine kod birimleri üzerinde çalışmasıdır. Bu, iki kod biriminden oluşan karakterlerin garip davranmasına neden olur. ``` console.log(/🍎{3}/.test("🍎🍎🍎")); @@ -809,9 +813,9 @@ console.log(/<.>/u.test("<🌹>")); // → true ``` -The problem is that the 🍎 in the first line is treated as two code units, and `{3}` is applied only to the second unit. Similarly, the dot matches a single code unit, not the two that make up the rose ((emoji)). +Sorun, birinci satırdaki 🍎 karakterinin iki kod biriminden oluştuğu şekilde işlenmesidir ve `{3}` kısmının yalnızca ikincisi üzerinde uygulanmasıdır. Benzer şekilde, nokta tek bir kod birimini eşleştirir, gül ((emoji))'sini oluşturan ikiyi değil. -You must add the `u` (Unicode) option to your regular expression to make it treat such characters properly. +Bu tür karakterleri uygun bir şekilde işlemesi için düzenli ifadenize `u` (Unicode) seçeneğini eklemeniz gerekir. ``` console.log(/🍎{3}/u.test("🍎🍎🍎")); @@ -822,67 +826,68 @@ console.log(/🍎{3}/u.test("🍎🍎🍎")); ## Summary -Regular expressions are objects that represent patterns in strings. They use their own language to express these patterns. +Düzenli ifadeler, dizelerdeki kalıpları temsil eden nesnelerdir. Bu kalıpları ifade etmek için kendi dillerini kullanırlar. {{table {cols: [1, 5]}}} -| `/abc/` | A sequence of characters -| `/[abc]/` | Any character from a set of characters -| `/[^abc]/` | Any character _not_ in a set of characters -| `/[0-9]/` | Any character in a range of characters -| `/x+/` | One or more occurrences of the pattern `x` -| `/x+?/` | One or more occurrences, nongreedy -| `/x*/` | Zero or more occurrences -| `/x?/` | Zero or one occurrence -| `/x{2,4}/` | Two to four occurrences -| `/(abc)/` | A group -| `/a|b|c/` | Any one of several patterns -| `/\d/` | Any digit character -| `/\w/` | An alphanumeric character ("word character") -| `/\s/` | Any whitespace character -| `/./` | Any character except newlines -| `/\p{L}/u` | Any letter character -| `/^/` | Start of input -| `/$/` | End of input -| `/(?=a)/` | A look-ahead test +| `/abc/` | Bir dizi karakter +| `/[abc]/` | Bir dizi karakterden herhangi bir karakter +| `/[^abc]/` | Bir karakter kümesinde _olmayan_ herhangi bir karakter +| `/[0-9]/` | Belirli bir karakter aralığındaki herhangi bir karakter +| `/x+/` | `'x'` kalıbının bir veya daha fazla tekrarı +| `/x+?/` | `'x'`kalıbının açgözlü olmayan bir veya daha fazla belirişi +|`/x\*/` | Sıfır veya daha fazla beliriş +|`/x?/` | Sıfır veya bir beliriş +|`/x{2,4}/` | İkiden dörde kadar beliriş +|`/(abc)/` | Bir grup +|`/a|b|c/` | Kalıplardan bir tanesi +|`/\d/` | Herhangi bir rakam karakteri +|`/\w/` | Alfasayısal bir karakter ("kelime karakteri") +|`/\s/` | Herhangi bir boşluk karakteri +|`/./` | Yeni satır dışında herhangi bir karakter +|`/\p{L}/u` | Herhangi bir harf karakter +|`/^/` | Girdi başlangıcı +|`/$/` | Girdi sonu +|`/(?=a)/` | İleri görüşlü bir test -A regular expression has a method `test` to test whether a given string matches it. It also has a method `exec` that, when a match is found, returns an array containing all matched groups. Such an array has an `index` property that indicates where the match started. +Düzenli ifade, verilen bir dizenin onunla eşleşip eşleşmediğini test etmek için `test` metoduna sahiptir. Ayrıca, bir eşleşme bulunduğunda, tüm eşleşen grupları içeren bir dizi döndüren `exec` adında bir metod da vardır. Böyle bir dizi, eşleşmenin nerede başladığını gösteren bir `index` özelliğine sahiptir. -Strings have a `match` method to match them against a regular expression and a `search` method to search for one, returning only the starting position of the match. Their `replace` method can replace matches of a pattern with a replacement string or function. +Düzenli ifadeyle dizeleri eşleştirmek için dizelerin bir `match` metodu ve sadece eşleşmenin başlangıç pozisyonunu arayıp döndürmek için bir `search` metodu vardır. Onların `replace` metodu, bir desenin eşleşmelerini bir değiştirme dizesi veya fonksiyonu ile değiştirebilir. -Regular expressions can have options, which are written after the closing slash. The `i` option makes the match case insensitive. The `g` option makes the expression _global_, which, among other things, causes the `replace` method to replace all instances instead of just the first. The `y` option makes and expression sticky, which means that it will not search ahead and skip part of the string when looking for a match. The `u` option turns on Unicode mode, which enables `\p` syntax and fixes a number of problems around the handling of characters that take up two code units. +Düzenli ifadelerin seçenekleri olabilir, bunlar kapatma eğik çizgi sonrasına yazılır. `i` seçeneği, eşleşmenin harf büyüklüğüne duyarsız yapar. `g` seçeneği ifadeyi global yapar, bu da `replace` metodunun yalnızca ilk eşleşen dize yerine tüm eşleşen dize parçalarının değiştirmesine neden olur. `y` seçeneği yapışkandır, bu da bir eşleşme ararken bir dizenin bir kısmını önemsizce atlamayıp teker teker arayacağı anlamına gelir. `u` seçeneği Unicode modunu açar, bu da `\p` sözdizimini etkinleştirir ve iki kod birimini alan karakterlerin işlenmesindeki oluşan bir takım sorunları düzeltir. -Regular expressions are a sharp ((tool)) with an awkward handle. They simplify some tasks tremendously but can quickly become unmanageable when applied to complex problems. Part of knowing how to use them is resisting the urge to try to shoehorn things into them that they cannot cleanly express. +Düzenli ifadeler, garip bir sapı olan keskin bir ((araç))tır. Bazı görevleri büyük ölçüde basitleştirirler ancak karmaşık sorunlara uygulandığında hızla yönetilemez hale gelebilirler. Onları nasıl kullanacağınızın bir parçası, temiz bir şekilde ifade edemeyecekleri şeyleri zorla onlara sokuşturma dürtüsüne karşı koymaktır. -## Exercises +## Egzersizler {{index debugging, bug}} -It is almost unavoidable that, in the course of working on these exercises, you will get confused and frustrated by some regular expression's inexplicable ((behavior)). Sometimes it helps to enter your expression into an online tool like [_debuggex.com_](https://www.debuggex.com/) to see whether its visualization corresponds to what you intended and to ((experiment)) with the way it responds to various input strings. +Bu alıştırmalar üzerinde çalışırken, bazı düzenli ifadelerin açıklanamayan ((davranış))ları tarafından kafa karışıklığına uğrayacağınız ve bunlardan bazıları tarafından hızla sinirleneceğiniz neredeyse kaçınılmazdır. Bazen, ifadenizi [_debuggex.com_](https://www.debuggex.com/) gibi çevrimiçi bir araca girerek, oluşturduğu görselleştirmenin istediğiniz şeyle uyuşup uyuşmadığını görmek ve çeşitli giriş dizelerine nasıl yanıt verdiğini test etmek yardımcı olabilir. ### Regexp golf {{index "program size", "code golf", "regexp golf (exercise)"}} -_Code golf_ is a term used for the game of trying to express a particular program in as few characters as possible. Similarly, _regexp golf_ is the practice of writing as tiny a regular expression as possible to match a given pattern and _only_ that pattern. +_Kod golfü_, belirli bir programı mümkün olduğunca az karakterle ifade etme oyunu için kullanılan bir terimdir. Benzer şekilde, _düzenli ifade golfü_, _yalnızca_ verilen o deseni eşleştirmek için mümkün olduğunca küçük bir düzenli ifade yazma uygulamasıdır. {{index boundary, matching}} -For each of the following items, write a ((regular expression)) to test whether the given pattern occurs in a string. The regular expression should match only strings containing the pattern. When your expression works, see whether you can make it any smaller. +Aşağıdaki her öğe için, verilen desenin bir dizide olup olmadığını test etmek için bir ((düzenli ifade)) yazın. Düzenli ifade, yalnızca deseni içeren dizeleri eşleştirmelidir. İfadeniz çalıştığında, onu daha da küçültebilme ihtimaliniz üzerine düşünün. - 1. _car_ and _cat_ - 2. _pop_ and _prop_ - 3. _ferret_, _ferry_, and _ferrari_ - 4. Any word ending in _ious_ - 5. A whitespace character followed by a period, comma, colon, or semicolon - 6. A word longer than six letters - 7. A word without the letter _e_ (or _E_) +1. _car_ ve _cat_ +2. _pop_ ve _prop_ +3. _ferret_, _ferry_, ve _ferrari_ +4. _ious_ ile biten herhangi bir kelime +5. Bir boşluk karakteri ve ardından nokta, virgül, iki nokta üst üste veya noktalı virgül gelen bir dize +6. Altı harften uzun bir kelime +7. _e_ (veya _E_) harfi olmayan bir kelime -Refer to the table in the [chapter summary](regexp#summary_regexp) for help. Test each solution with a few test strings. +Yardım için [bölüm özeti](regexp#summary_regexp) içindeki tabloya bakın. Her çözümü birkaç test dizisiyle test edin. {{if interactive + ``` -// Fill in the regular expressions +// Düzenli ifadeleri doldurun. verify(/.../, ["my car", "bad cats"], @@ -927,46 +932,49 @@ function verify(regexp, yes, no) { if}} -### Quoting style +### Tırnak stili {{index "quoting style (exercise)", "single-quote character", "double-quote character"}} -Imagine you have written a story and used single ((quotation mark))s throughout to mark pieces of dialogue. Now you want to replace all the dialogue quotes with double quotes, while keeping the single quotes used in contractions like _aren't_. +Bir hikaye yazdınızı ve diyalog parçalarını işaretlemek için tümüyle tek ((tırnak işareti)) kullandığınızı hayal edin. Şimdi, _aren't_ gibi kısaltmalarda kullanılan tek tırnakları koruyarak tüm diyalog alıntılarını çift tırnaklarla değiştirmek istiyorsunuz. {{index "replace method"}} -Think of a pattern that distinguishes these two kinds of quote usage and craft a call to the `replace` method that does the proper replacement. +Bu iki tür tırnak kullanımını ayıran bir desen düşünün ve doğru değiştirmeyi yapacak `replace` metoduna bir çağrı oluşturun. {{if interactive + ```{test: no} let text = "'I'm the cook,' he said, 'it's my job.'"; -// Change this call. +// Bu çağrıyı değiştir. console.log(text.replace(/A/g, "B")); // → "I'm the cook," he said, "it's my job." ``` + if}} {{hint {{index "quoting style (exercise)", boundary}} -The most obvious solution is to replace only quotes with a nonletter character on at least one side—something like `/\P{L}'|'\P{L}/`. But you also have to take the start and end of the line into account. +En açık çözüm, en az bir tarafında harf olmayan tırnakları değiştirmektir - `/\P{L}'|'\P{L}/` gibi bir şey. Ancak, satırın başlangıcını ve sonunu da dikkate almalısınız. {{index grouping, "replace method", [parentheses, "in regular expressions"]}} -In addition, you must ensure that the replacement also includes the characters that were matched by the `\P{L}` pattern so that those are not dropped. This can be done by wrapping them in parentheses and including their groups in the replacement string (`$1`, `$2`). Groups that are not matched will be replaced by nothing. +Ek olarak, değiştirmenin, `\P{L}` deseniyle eşleşen karakterleri de içermesini sağlamalısınız ki bunlar düşürülmesin. Bunun yapılması, parantez içine alarak ve değiştirme dizesine gruplarını (`$1`, `$2`) dahil ederek yapılabilir. Eşleşmeyen gruplar hiçbir şey ile değiştirilecektir. hint}} -### Numbers again +### Tekrar sayılar {{index sign, "fractional number", [syntax, number], minus, "plus character", exponent, "scientific notation", "period character"}} -Write an expression that matches only JavaScript-style ((number))s. It must support an optional minus _or_ plus sign in front of the number, the decimal dot, and exponent notation—`5e-3` or `1E10`—again with an optional sign in front of the exponent. Also note that it is not necessary for there to be digits in front of or after the dot, but the number cannot be a dot alone. That is, `.5` and `5.` are valid JavaScript numbers, but a lone dot isn't. +Sadece JavaScript tarzı ((sayı))ları eşleştiren bir ifade yazın. Sayının önünde isteğe bağlı eksi _veya_ artı işareti, ondalık nokta ve üstel gösterim - `5e-3` veya `1E10` - yine üstel önünde isteğe bağlı bir işaret ile desteklenmelidir. Ayrıca, noktanın önünde veya sonra rakamlar olması gerekli değildir, ancak sayı yalnızca bir nokta olamaz. Yani, `.5` ve `5.` geçerli JavaScript sayılarıdır, ancak yalnızca nokta _değildir_. {{if interactive + ```{test: no} -// Fill in this regular expression. +// Bu düzenli ifadeyi doldurun. let number = /^...$/; // Tests: @@ -990,16 +998,16 @@ if}} {{index ["regular expression", escaping], ["backslash character", "in regular expressions"]}} -First, do not forget the backslash in front of the period. +Öncelikle noktanın önüne ters eğik çizgi koymayı unutmayın. -Matching the optional ((sign)) in front of the ((number)), as well as in front of the ((exponent)), can be done with `[+\-]?` or `(\+|-|)` (plus, minus, or nothing). +Sayının önündeki isteğe bağlı ((işaret)) ile, aynı zamanda önündeki üstel işareti eşleştirmek `[+\-]?` veya `(\+|-|)` (artı, eksi veya hiçbir şey) aracılığıyla yapılabilir. {{index "pipe character"}} -The more complicated part of the exercise is the problem of matching both `"5."` and `".5"` without also matching `"."`. For this, a good solution is to use the `|` operator to separate the two cases—either one or more digits optionally followed by a dot and zero or more digits _or_ a dot followed by one or more digits. +Bu alıştırmanın daha karmaşık kısmı, `"5."` ve `".5"` dizelerini eşleştirirken `"."` dizesini eşleştirmemektir. Bu iki durumu ayırmak için `|` operatörünü kullanmak iyi bir çözümdür - ya bir veya daha fazla rakamın, isteğe bağlı olarak bir noktayla devam etmesi ve sıfır veya daha fazla rakamın ardından gelmesi _veya_ bir noktanın bir veya daha fazla rakamdan sonra geldiği durum. {{index exponent, "case sensitivity", ["regular expression", flags]}} -Finally, to make the _e_ case insensitive, either add an `i` option to the regular expression or use `[eE]`. +Son olarak, _e_ karakterini büyük/küçük harfe duyarsız hale getirmek için düzenli ifadeye bir `i` seçeneği ekleyin veya `[eE]` kullanın. hint}} diff --git a/10_modules.md b/10_modules.md index db4e7c51..622084a0 100644 --- a/10_modules.md +++ b/10_modules.md @@ -1,64 +1,64 @@ {{meta {load_files: ["code/packages_chapter_10.js", "code/chapter/07_robot.js"]}}} -# Modules +# Modüller -{{quote {author: "Tef", title: "Programming is Terrible", chapter: true} +{{quote {author: "Tef", title: "Programlamak Korkunç", chapter: true} -Write code that is easy to delete, not easy to extend. +Silmesi kolay olan kod yazın, üzerine daha fazla şey eklenmesi kolay olan kod değil. quote}} -{{index "Yuan-Ma", "Book of Programming"}} +{{index "Yuan-Ma", "Programlamanın Kitabı"}} -{{figure {url: "img/chapter_picture_10.jpg", alt: "Illustration of a complicated building built from modular pieces", chapter: framed}}} +{{figure {url: "img/chapter_picture_10.jpg", alt: "Modüler parçalardan inşa edilmiş karmaşık bir binanın illüstrasyonu.", chapter: framed}}} {{index organization, [code, "structure of"]}} -Ideally, a program has a clear, straightforward structure. The way it works is easy to explain, and each part plays a well-defined role. +İdeal olarak, bir programın açık ve anlaşılır bir yapısı vardır. Çalışma şeklini açıklamak kolaydır ve her bir parça iyi tanımlanmış bir rolü oynar. {{index "organic growth"}} -In practice, programs grow organically. Pieces of functionality are added as the programmer identifies new needs. Keeping such a program well-structured requires constant attention and work. This is work that will pay off only in the future, the _next_ time someone works on the program, so it's tempting to neglect it and allow the various parts of the program to become deeply entangled. +Uygulamada, programlar organik olarak büyür. Yeni ihtiyaçlar belirlendikçe fonksiyonalite parçaları eklenir. Böyle bir programın iyi yapılandırılmış kalması sürekli dikkat ve çalışma gerektirir. Bu, sadece gelecekte, _bir sonraki_ kişi program üzerinde çalıştığında ödüllendirilecek bir çalışmadır. Bu nedenle, ihmal etmek ve programın çeşitli parçalarının derinlemesine birbirine karışmasına izin vermek caziptir. {{index readability, reuse, isolation}} -This causes two practical issues. First, understanding an entangled system is hard. If everything can touch everything else, it is difficult to look at any given piece in isolation. You are forced to build up a holistic understanding of the entire thing. Second, if you want to use any of the functionality from such a program in another situation, rewriting it may be easier than trying to disentangle it from its context. +Bu iki pratik soruna neden olur. İlk olarak, karışık bir sistem anlamak zordur. Her şey her şeye dokunabiliyorsa, herhangi bir parçayı izole olarak incelemek zor olur. Tüm şeyin bütünlüklü bir anlayışını oluşturmak zorundasınız. İkinci olarak, böyle bir programın işlevselliğini başka bir durumda kullanmak istiyorsanız, bunu içinde bulunduğu düğümü çözmektense programı tamamen yeniden yazmak daha kolay olabilir. -The phrase "((big ball of mud))" is often used for such large, structureless programs. Everything sticks together, and when you try to pick out a piece, the whole thing comes apart, and you only succeed in making a mess. +"((büyük çamur topu))" ifadesi genellikle böyle büyük, yapısal olmayan programlar için kullanılır. Her şey her şeye yapışır ve bir parça seçmeye çalıştığınızda, bütün şey parçalanır ve sadece bir karmaşa oluşturmayı başarırsınız. -## Modular programs +## Modüler programlar {{index dependency, [interface, module]}} -_Modules_ are an attempt to avoid these problems. A ((module)) is a piece of program that specifies which other pieces it relies on and which functionality it provides for other modules to use (its _interface_). +_Modüller_ bu sorunları önlemeye yönelik bir girişimdir. ((Modül)), başka hangi parçalara bağımlı olduğunu ve diğer modüllerin kullanması için hangi işlevsellikleri sağladığını(*arayüz*ünü) belirten bir program parçasıdır. {{index "big ball of mud"}} -Module interfaces have a lot in common with object interfaces, as we saw them in [Chapter ?](object#interface). They make part of the module available to the outside world and keep the rest private. +Modül arayüzleri, [bölüm ?](object#interface) içinde gördüğümüz nesne arayüzleriyle çok ortak noktaya sahiptir. Modülün bir kısmını dış dünyaya kullanılabilir hale getirir ve geri kalanını özel tutar. {{index dependency}} -But the interface that a module provides for others to use is only half the story. A good module system also requires modules to specify which code _they_ use from other modules. These relations are called _dependencies_. If module A uses functionality from module B, it is said to _depend_ on that module. When these are clearly specified in the module itself, they can be used to figure out which other modules need to be present to be able to use a given module and to automatically load dependencies. +Ancak, bir modülün diğerlerinin kullanması için sağladığı arayüz sadece hikayenin yarısıdır. İyi bir modül sistemi ayrıca modüllerin diğer modüllerden _hangi kodları kullandıklarını_ belirtmelerini gerektirir. Bu ilişkiler _bağımlılıklar_ olarak adlandırılır. Modül A, modül B'den işlevsellik kullanıyorsa, buna _bağımlı_ olduğu söylenir. Bunlar modülde açıkça belirtildiğinde, bir modülü kullanabilmek için hangi diğer modüllerin mevcut olması gerektiğini anlayıp o bağımlılıkları otomatik olarak yüklemek için kullanılabilirler. -When the ways in which modules interact with each other are explicit, a system becomes more like ((LEGO)), where pieces interact through well-defined connectors, and less like mud, where everything mixes with everything else. +Modüllerin birbirleriyle etkileşim şekilleri açık olduğunda, bir sistem her şeyin her şeyle karıştığı çamur gibi olmak yerine parçaların iyi tanımlanmış bağlayıcılar aracılığıyla etkileştiği ((LEGO)) parçaları gibi olur. {{id es}} -## ES modules +## ES modülleri {{index "global scope", [binding, global]}} -The original JavaScript language did not have any concept of a module. All scripts ran in the same scope, and accessing a function defined in another script was done by referencing the global bindings created by that script. This actively encouraged accidental, hard-to-see entanglement of code and invited problems like unrelated scripts trying to use the same binding name. +Orijinal JavaScript dili herhangi bir modül kavramına sahip değildi. Tüm betikler aynı kapsamda çalışır ve başka bir betikte tanımlanan bir fonksiyona erişmek için o betik tarafından oluşturulan global bağlantılara referansla yapılırdı. Bu, kazara, görülmesi zor kod karışıklığına ve ilişkisiz betiklerin aynı bağlantı adını kullanmaya çalışmasına neden olurdu. {{index "ES modules"}} -Since ECMAScript 2015, JavaScript supports two different types of programs. _Scripts_ behave in the old way: their bindings are defined in the global scope, and they have no way to directly reference other scripts. _Modules_ get their own separate scope and support the `import` and `export` keywords, which aren't available in scripts, to declare their dependencies and interface. This module system is usually called _ES modules_ (where _ES_ stands for ECMAScript). +ECMAScript 2015'ten beri, JavaScript iki farklı program türünü desteklemektedir. _Betikler_ eski şekilde davranır: bağlantılar global kapsamda tanımlanır ve doğrudan diğer betiklere başvurma yolu yoktur. _Modüller_ kendi ayrı kapsamına sahiptir ve bağımlılıklarını ve arayüzlerini bildirmek için betiklerde bulunmayan `import` ve `export` anahtar kelimelerini destekler. Bu modül sistemi genellikle _ES modülleri_ olarak adlandırılır ("ES", "ECMAScript" anlamına gelir). -A modular program is composed of a number of such modules, wired together via their imports and exports. +Modüler bir program, bu tür modüllerin, başka modüllerden kullandıkları fonksiyonaliteleri ve başka modüllere kullabilabilir hale getirdikleri fonksiyonaliteleri kullanarak birbirine bağlandığı bir dizi modülden oluşur. {{index "Date class", "weekDay module"}} -The following example module converts between day names and numbers (as returned by `Date`'s `getDay` method). It defines a constant which is not part of its interface, and two functions which are. It has no dependencies. +Bu örnek modül, gün adları ile sayılar arasında dönüşüm yapar (`Date`'in `getDay` metodu tarafından döndürülenler aracılığıyla). Arayüzünün bir parçası olmayan bir sabit değer ve iki fonksiyon tanımlar. Hiçbir bağımlılığı yoktur. ``` const names = ["Sunday", "Monday", "Tuesday", "Wednesday", @@ -72,7 +72,7 @@ export function dayNumber(name) { } ``` -The `export` keyword can be put in front of a function, class, or binding definition to indicate that that binding is part of the module's interface. This makes it possible for other modules to use that binding by importing it. +`export` anahtar kelimesi, bir işlevin, sınıfın veya bağlantı tanımının modül arayüzünün bir parçası olduğunu belirtmek için önüne konabilir. Bu, diğer modüllerin onu içe aktararak kullanabilmesini mümkün kılar. ```{test: no} import {dayName} from "./dayname.js"; @@ -83,15 +83,15 @@ console.log(`Today is ${dayName(now.getDay())}`); {{index "import keyword", dependency, "ES modules"}} -The `import` keyword, followed by a list of binding names in braces, makes bindings from another module available in the current module. Modules are identified by quoted strings. +`import` anahtar kelimesi, süslü parantez içinde bağlantı adlarından oluşan bir listenin yazılması ardından, başka bir modüldeki bağlantıları mevcut modülde kullanılabilir hale getirir. Modüller tırnak içinde belirtilir. {{index [module, resolution], resolution}} -How such a module name is resolved to an actual program differs by platform. The browser treats them as Web addresses, whereas Node.js resolves them to files. When you run a module, all the other modules it depends on—and the modules _those_ depend on—are loaded, and the exported bindings are made available to the modules that import them. +Bir modül adının bir gerçek programa nasıl çözümleneceği platforma göre farklılık gösterir. Tarayıcı, bunları Web adresleri olarak ele alırken, Node.js bunları dosyalara çözümler. Bir modülü çalıştırmak için, o modülün bağımlı olduğu tüm diğer modüller - ve _bu bağımlı olunan modüllerin de bağımlı olduğu modüller_ de - yüklenir ve export anahtar kelimesi kullanılan tanımalar dış kullanıma müsait hale getirilir. -Import and export declarations cannot appear inside of functions, loops, or other blocks. They are immediately resolved when the module is loaded, regardless of how the code in the module executes. To reflect this, they must appear only in the outer module body. +İçe aktarma ve dışa aktarma bildirimleri, fonksiyonlar, döngüler veya diğer blokların içinde görünemez. Modül yüklendiğinde modüldeki kodun nasıl yürütüldüğünden bağımsız olarak hemen çözümlenirler ve bunu yansıtmak için modülün sadece dış gövdesinde görünmelidirler. -A module's interface thus consists of a collection of named bindings, which other modules that depend on the module can access. Imported bindings can be renamed to give them a new local name using `as` after their name. +Bu nedenle, bir modülün arayüzü, onlara bağımlı olan diğer modüllerin erişebildiği adlandırılmış bağlantılardan oluşur. İçe aktarılan bağlantılar, adlarının ardından `as` kullanılarak yeni bir yerel isim verilerek yeniden adlandırılabilir. ``` import {dayName as nomDeJour} from "./dayname.js"; @@ -99,73 +99,67 @@ console.log(nomDeJour(3)); // → Wednesday ``` -M module may also have a special export named `default`, which is often used for modules that only export a single binding. To define a default export, you write `export default` before an expression, a function declaration, or a class declaration. +Ayrıca, bir modülün özel olarak adlandırılmış `default` adlı bir dışa aktarma bildirisi olması mümkündür, bu genellikle yalnızca tek bir bağlantıyı dışa aktaran modüller için kullanılır. Varsayılan bir dışa aktarım tanımlamak için, bir fonksiyon bildiriminin veya bir sınıf bildiriminin önüne `export default` yazılır. ``` export default ["Winter", "Spring", "Summer", "Autumn"]; ``` -Such a binding is imported by omitting the braces around the name of the import. +Bu tür bir bağlantı, içe aktarmada adın etrafındaki süslü parantezleri kullanmadan içeri aktarılır. ``` import seasonNames from "./seasonname.js"; ``` -To import all bindings from a module at the same time, you can use `import *`. You provide a name, and that name will be bound to an object holding all the module's exports. This can be useful when you are using a lot of different exports. - -``` -import * as dayName from "./dayname.js"; -console.log(dayName.dayName(3)); -// → Wednesday -``` - -## Packages +## Paketler {{index bug, dependency, structure, reuse}} -One of the advantages of building a program out of separate pieces and being able to run some of those pieces on their own is that you might be able to use the same piece in different programs. +Bir programı ayrı parçalardan oluşturmanın ve bazı parçaları kendi başlarına çalıştırabilmenin avantajlarından biri, aynı parçayı farklı programlarda kullanabilme olasılığınızdır. {{index "parseINI function"}} -But how do you set this up? Say I want to use the `parseINI` function from [Chapter ?](regexp#ini) in another program. If it is clear what the function depends on (in this case, nothing), I can just copy that module into my new project and use it. But then, if I find a mistake in the code, I'll probably fix it in whichever program I'm working with at the time and forget to also fix it in the other program. +Ancak, bunu nasıl kurarsınız? Diyelim ki başka bir programda [bölüm ?](regexp#ini) içindeki `parseINI` fonksiyonunu kullanmak istiyorum. Fonksiyonun neye bağlı olduğu (bu durumda, hiçbir şeye) açıksa, sadece o modülü yeni projeme kopyalayabilir ve kullanabilirim. Ancak sonra, kodda bir hata bulursam, muhtemelen o sırada çalıştığım programda düzelteceğim ve aynı hatayı diğer programda da düzeltmeyi unutacağım. {{index duplication, "copy-paste programming"}} -Once you start duplicating code, you'll quickly find yourself wasting time and energy moving copies around and keeping them up to date. That's where _((package))s_ come in. A package is a chunk of code that can be distributed (copied and installed). It may contain one or more modules and has information about which other packages it depends on. A package also usually comes with documentation explaining what it does so that people who didn't write it might still be able to use it. +Kod kopyalamaya başladığınızda, zamanınızı ve enerjinizi kopyaları taşımak ve güncel tutmak için harcadığınızı hızla fark edersiniz. + +İşte burada \_((paket))\_ler devreye giriyor. Bir paket, dağıtılabilen (kopyalanabilen ve yüklenen) bir kod parçasıdır. Bir veya daha fazla modül içerebilir ve ne tür paketlere bağımlı olduğu hakkında bilgi içerir. Bir paket genellikle ne yaptığını açıklayan belgelerle birlikte gelir, böylece o programı yazmamış sadece kullanmak isteyen insanlar bile onu kullanabilirler. -When a problem is found in a package or a new feature is added, the package is updated. Now the programs that depend on it (which may also be packages) can copy the new ((version)) to get the improvements that were made to the code. +Bir pakette bir sorun bulunduğunda veya yeni bir özellik eklediğinde, paket güncellenir. Artık ona bağımlı olan programlar (ki bunlar da paketler olabilir) iyileştirmeleri almak için yeni ((sürümü)) kopyalayabilirler. {{id modules_npm}} {{index installation, upgrading, "package manager", download, reuse}} -Working in this way requires ((infrastructure)). We need a place to store and find packages and a convenient way to install and upgrade them. In the JavaScript world, this infrastructure is provided by ((NPM)) ([_https://npmjs.org_](https://npmjs.org)). +Bu şekilde çalışmak ((altyapı)) gerektirir. Paketleri depolamak ve bulmak için bir yer ve bunları kurmak ve yükseltmek için uygun bir yer gereklidir. JavaScript dünyasında, bu altyapı ((NPM)) ([https://npmjs.org](https://npmjs.org)) tarafından sağlanır. -NPM is two things: an online service where you can download (and upload) packages, and a program (bundled with Node.js) that helps you install and manage them. +NPM iki şeydir: paketleri indirebileceğiniz (ve yükleyebileceğiniz) çevrimiçi bir hizmet ve onları kurmanıza ve yönetmenize yardımcı olan Node.js ile birlikte paketlenmiş bir program. {{index "ini package"}} -At the time of writing, there are more than three million different packages available on NPM. A large portion of those are rubbish, to be fair. But almost every useful, publicly available JavaScript package can be found on NPM. For example, an INI file parser, similar to the one we built in [Chapter ?](regexp), is available under the package name `ini`. +Yazım sırasında, NPM'de üç milyondan fazla farklı paket bulunmaktadır. Adil olmak gerekirse, bunların büyük bir kısmı gereksizdir. Ancak neredeyse her kullanışlı, genel olarak erişilebilir JavaScript paketi NPM'de bulunabilir. Örneğin, [bölüm ?](regexp) içinde oluşturduğumuz bir INI dosyası ayrıştırıcısı, `ini` paketi adı altında bulunabilir. {{index "command line"}} -[Chapter ?](node) will show how to install such packages locally using the `npm` command line program. +[Chapter ?](node), bu tür paketleri `npm` komut satırı programını kullanarak yerel olarak nasıl kuracağınızı gösterecektir. -Having quality packages available for download is extremely valuable. It means that we can often avoid reinventing a program that 100 people have written before and get a solid, well-tested implementation at the press of a few keys. +İndirilebilir kaliteli paketlere sahip olmak son derece değerlidir. 100 kişi tarafından yazılmış bir programı yeniden icat etmekten genellikle kaçınabilir ve birkaç tuşa basarak sağlam, iyi test edilmiş bir uygulama elde edebiliriz. {{index maintenance}} -Software is cheap to copy, so once someone has written it, distributing it to other people is an efficient process. Writing it in the first place _is_ work, though, and responding to people who have found problems in the code or who want to propose new features is even more work. +Yazılım kopyalamak ucuzdur, bu yüzden biri yazdığında, başkalarına dağıtmak verimli bir süreçtir. Ancak bunu baştan yazmak _iştir_, ayrıca kodunuzda sorun bulan veya yeni özellikler önermek isteyen kişilere cevap vermek daha fazla iştir. -By default, you own the ((copyright)) to the code you write, and other people may use it only with your permission. But because some people are just nice and because publishing good software can help make you a little bit famous among programmers, many packages are published under a ((license)) that explicitly allows other people to use it. +Varsayılan olarak, yazdığınız kodun ((telif hakkı)) size aittir ve diğer kişiler yalnızca izninizle kullanabilirler. Ancak bazı insanlar nazik olduklarından ve iyi yazılım yayınlamak, yazılımcılar arasında biraz ünlü olmanıza yardımcı olabildiğinden ötürü birçok paket açıkça diğer insanların onu kullanmasına izin veren bir ((lisans)) altında yayınlanır. -Most code on ((NPM)) is licensed this way. Some licenses require you to also publish code that you build on top of the package under the same license. Others are less demanding, requiring only that you keep the license with the code as you distribute it. The JavaScript community mostly uses the latter type of license. When using other people's packages, make sure you are aware of their licenses. +((NPM))'deki çoğu kod bu şekilde lisanslanmıştır. Bazı lisanslar, paketin üzerine inşa ettiğiniz kodu da aynı lisans altında yayınlamanızı gerektirir. Diğerleri ise daha az talepkârdır ve sadece lisansı kodla birlikte dağıtmanızı isterler. JavaScript topluluğu genellikle bu son açıkladığım türdeki lisansları kullanır. Başkalarının paketlerini kullanırken, lisanslarını bilincinde olduğunuzdan emin olun. {{id modules_ini}} {{index "ini package"}} -Now, instead of writing our own INI file parser, we can use one from ((NPM)). +Artık kendi INI dosyası ayrıştırıcımızı yazmak yerine, ((NPM)) üzerinden bir tane kullanabiliriz. ``` import {parse} from "ini"; @@ -176,17 +170,15 @@ console.log(parse("x = 10\ny = 20")); {{id commonjs}} -## CommonJS modules +## CommonJS modülleri -Before 2015, when the JavaScript language had no built-in module system, people were already building large systems in JavaScript. To make that workable, they _needed_ ((module))s. +2015'ten önce, JavaScript dilinde gerçek bir yerleşik modül sistemi olmadığı zamanlarda da insanlar JavaScript'te büyük sistemler inşa ediyorlardı. Bunu çalışabilir yapmak için ((modül))lere _ihtiyaçları vardı_. {{index [function, scope], [interface, module], [object, as module]}} -The community designed its own improvised ((module system))s on top of the language. These use functions to create a local scope for the modules and regular objects to represent module interfaces. +Topluluk, kendi düzenlediği ((modül sistem))lerini dilden bağımsız olarak tasarladı. Bu modülleri, yerel bir kapsam oluştururken fonksiyonları kullanarak ve modül arayüzlerini temsil etmek için sıradan nesneleri kullanarak oluşturdular. -Initially, people just manually wrapped their entire module in an “((immediately invoked function -expression))” to create the module's scope and assigned their interface objects to a single global -variable. +Başlangıçta, insanlar modüllerine ayrı bir bağlam oluşturmak için "((hemen çağrılan fonksiyon ifadesi))" içine manuel olarak sarıp arayüz nesnelerini tek bir global değişkene atarlardı. ``` const weekDay = function() { @@ -204,21 +196,21 @@ console.log(weekDay.name(weekDay.number("Sunday"))); {{index dependency, [interface, module]}} -This style of modules provides ((isolation)), to a certain degree, but it does not declare dependencies. Instead, it just puts its interface into the ((global scope)) and expects its dependencies, if any, to do the same. This is not ideal. +Bu tür modüllerin stili, belirli bir dereceye kadar ((izolasyon)) sağlar, ancak bağımlılıkları bildirmez. Bunun yerine, arayüzünü ((genel kapsam))a koyar ve varsa bağımlılıklarının, aynısını yapmasını bekler. Bu ideal değildir. {{index "CommonJS modules"}} -If we implement our own module loader, we can do better. The most widely used approach to bolted-on JavaScript modules is called _CommonJS modules_. ((Node.js)) used this module system from the start (though it now also knows how to load ES modules), and it is the module system used by many packages on ((NPM)). +Eğer kendi modül yükleyicimizi uygularsak, daha iyi yapabiliriz. JavaScript modüllerini eklemek için en yaygın kullanılan yaklaşım _CommonJS modülleri_ olarak adlandırılır. ((Node.js)), bu tür modülleri başlangıçtan itibaren kullandı (ancak şimdi ayrıca ES modüllerini de yükleyebilir durumdadır) ve bu, NPM'deki birçok paket tarafından kullanılan modül sistemidir. {{index "require function", [interface, module], "exports object"}} -A CommonJS module looks like a regular script, but it has access to two bindings that it uses to interact with other modules. The first is a function called `require`. When you call this with the module name of your dependency, it makes sure the module is loaded and returns its interface. The second is an object named `exports`, which is the interface object for the module. It starts out empty and you add properties to it to define exported values. +Bir CommonJS modülü, düzenli bir betik gibi görünür, ancak diğer modüllerle etkileşim kurmak için kullandığı iki bağlantıya erişim sağlar. İlk olarak, `require` olarak adlandırılan bir fonskiyon. Bağımlılığınızın modül adıyla bunu çağırdığınızda, modülün yüklenip arayüzünü döndürmesini sağlar. İkincisi, modül için arayüz nesnesi olan `exports` adlı bir nesnedir. Başlangıçta boştur ve dışa aktarılan değerleri tanımlamak için ona özellikler eklersiniz. {{index "formatDate module", "Date class", "ordinal package", "date-names package"}} -This CommonJS example module provides a date-formatting function. It uses two ((package))s from NPM—`ordinal` to convert numbers to strings like `"1st"` and `"2nd"`, and `date-names` to get the English names for weekdays and months. It exports a single function, `formatDate`, which takes a `Date` object and a ((template)) string. +Bu CommonJS örnek modülü, bir tarih biçimlendirme fonksiyonu sağlar. NPM'den iki ((paket)) kullanır: sayıları `"1st"` ve `"2nd"` gibi dizelere dönüştürmek için `ordinal` paketini ve haftanın günler ve aylar için İngiliz isimlerini almak adına `date-names` paketini kullanır. Bir `Date` nesnesi ve bir ((şablon)) dizesi alan `formatDate` adlı tek bir fonksiyonu dışa aktarır. -The template string may contain codes that direct the format, such as `YYYY` for the full year and `Do` for the ordinal day of the month. You could give it a string like `"MMMM Do YYYY"` to get output like `November 22nd 2017`. +Şablon dizesi, `YYYY` gibi biçimi yönlendiren kodları içerebilir ve ayın sıra günü için `Do` gibi dizeleri içerebilir. `"MMMM Do YYYY"` gibi bir dize verebilirsiniz ve çıktı olarak `"November 22nd 2017"` gibi bir çıktı alırsınız. ``` const ordinal = require("ordinal"); @@ -238,9 +230,9 @@ exports.formatDate = function(date, format) { {{index "destructuring binding"}} -The interface of `ordinal` is a single function, whereas `date-names` exports an object containing multiple things—`days` and `months` are arrays of names. Destructuring is very convenient when creating bindings for imported interfaces. +`ordinal` paketinin arayüzü tek bir fonksiyon iken, `date-names` birçok şey içeren bir nesne dışa aktarır—`days` ve `months` isim dizileridir. İçe aktarılan arayüzler için bağlantılar oluştururken, parçalama yöntemi çok yararlı ve kullanışlıdır. -The module adds its interface function to `exports` so that modules that depend on it get access to it. We could use the module like this: +Modül, arayüz fonksiyonunu `exports` bağlantısına ekler ki böylece buna bağımlı olan modüller buna erişebilsin. Modülü şu şekilde kullanabiliriz: ``` const {formatDate} = require("./format-date.js"); @@ -250,13 +242,13 @@ console.log(formatDate(new Date(2017, 9, 13), // → Friday the 13th ``` -CommonJS is implemented with a module loader that, when loading a module, wraps its code in a function (giving it its own local scope), and passes the `require` and `exports` bindings to that function as arguments. +CommonJS, bir modülü yüklerken, kodunu bir fonksiyon içine sarar (kendi yerel kapsamını verir) ve `require` ve `exports` bağlantılarını bu fonksiyonu çağırırken argüman olarak bu bağlantılara argüman geçirir. {{id require}} {{index "require function", "CommonJS modules", "readFile function"}} -If we assume we have access to a `readFile` function that reads a file by name and gives us its content, we can define a simplified form of `require` like this: +Bir dosyanın adını verip onun içeriğini bize döndüren `readFile` adlı bir fonksiyonuna erişiminiz olduğunu varsayarsak, bir `require` fonksiyonunu basitleştirilmiş bir şekilde şu şekilde tanımlayabiliriz: ```{test: wrap, sandbox: require} function require(name) { @@ -275,79 +267,81 @@ require.cache = Object.create(null); {{index "Function constructor", eval, security}} -`Function` is a built-in JavaScript function that takes a list of arguments (as a comma-separated string) and a string containing the function body and returns a function value with those arguments and that body. This is an interesting concept—it allows a program to create new pieces of program from string data—but also a dangerous one, since if someone can trick your program into putting a string they provide into `Function`, they can make the program do anything they want. +`Function`, virgüllerle ayrılmış bir dize halinde bir liste argüman ve fonksiyon gövdesini içerisinde barındıran bir dizeyi argüman olarak alan ve bir fonksiyon değeri döndüren standart bir JavaScript fonksiyonudur. Bu ilginç olmakla beraber tehlikeli bir kavramdır—bir programın dize datasından yeni bir program oluşturmasını sağlar- çünkü birisi programınıza sağladığı bir dizeyi `Function` içine koymaya kandırabilirse, programa istediklerini yaptırabilirler. {{index [file, access]}} -Standard JavaScript provides no such function as `readFile`, but different JavaScript environments, such as the browser and Node.js, provide their own ways of accessing files. The example just pretends that `readFile` exists. +Standart JavaScript, `readFile` gibi bir fonksiyon sağlamaz sağlamaz—ancak tarayıcı ve Node.js gibi farklı JavaScript ortamları, dosyalara erişim için kendi yöntemlerini sağlar. Örnek, `readFile` fonksiyonunun var olduğunu varsayar. -To avoid loading the same module multiple times, `require` keeps a store (cache) of already loaded modules. When called, it first checks if the requested module has been loaded and, if not, loads it. This involves reading the module's code, wrapping it in a function, and calling it. +Aynı modülü birden fazla kez yüklememek için, `require`, zaten yüklenmiş modüllerin bir deposunu (önbellek) tutar. Çağrıldığında, önce istenen modülün yüklenip yüklenmediğini kontrol eder ve yüklenmediyse, yükler. Bu, modülün kodunu okuyup bir fonksiyon içine sarıp onu çağırarak yapılır. {{index "ordinal package", "exports object", "module object", [interface, module]}} -By defining `require`, `exports` as ((parameter))s for the generated wrapper function (and passing the appropriate values when calling it), the loader makes sure that these bindings are available in the module's ((scope)). +Oluşturulan sarıcı fonksiyon için için `require` ve `exports` değerlerini ((parametre))ler olarak tanımlayarak (ve fonksiyonu çağırırken uygun değerleri geçirerek), yükleyici bu bağlantıların modülün ((kapsam))ında kullanılabilir olduğundan emin olur. -An important difference between this system and ES modules is that ES module imports happen before a module's script starts running, whereas `require` is a normal function, invoked when the module is already running. Unlike `import` declarations, `require` calls _can_ appear inside functions, and the name of the dependency can be any expression that evaluates to a string, whereas `import` only allows plain quoted strings. +Bu sistemle ES modülleri arasındaki önemli bir fark, ES modülü modül yüklemelerinin bir modülün betiği çalışmaya başlamadan önce gerçekleşmesidir, oysa `require` normal bir fonksiyondur ve modül çalışırken çağrılır. `import` beyanlarının aksine, `require` çağrıları fonksiyonların içinde _görünebilir_ ve bağımlılık adı, sadece düz tırnaklı dizelere izin veren `import`'a kıyasla herhangi bir ifade olabilir. -The transition of the JavaScript community from CommonJS style to ES modules has been a slow and somewhat rough one. Fortunately we are now at a point where most of the popular packages on NPM provide their code as ES modules, and Node.js allows ES modules to import from CommonJS modules. While CommonJS code is still something you will run across, there is no real reason to write new programs in this style anymore. +JavaScript topluluğunun CommonJS stilinden ES modülleri stiline geçişi yavaş ve biraz sancılı olmuştur. Ancak neyse ki, şu anda NPM'deki popüler paketlerin çoğu kodlarını ES modülleri olarak sağlıyor ve Node.js, ES modüllerinin içine CommonJS modüllerinden aktarılmasına kod aktarılmasına izin veriyor. Bu nedenle, Ortak JS kodu hala karşılaşacağınız bir şey olsa da, artık yeni programları bu tarzda yazmanın gerçek bir nedeni yoktur. -## Building and bundling +## İnşaa etme ve paketleme {{index compilation, "type checking"}} -Many JavaScript packages aren't technically written in JavaScript. Language extensions such as TypeScript, the type checking ((dialect)) mentioned in [Chapter ?](error#typing), are widely used. People also often start using planned new language features long before they have been added to the platforms that actually run JavaScript. To make this possible, they _compile_ their code, translating it from their chosen JavaScript dialect to plain old JavaScript—or even to a past version of JavaScript—so that ((browsers)) can run it. +Çoğu JavaScript paketi, teknik olarak, JavaScript'te yazılmamaktadır. [Bölüm ?](error#typing) içinde bahsedilen tip denetimi ((lehçe))si olan TypeScript gibi uzantılar yaygın olarak kullanılmaktadır. İnsanlar ayrıca, gerçekte JavaScript'i çalıştıran platformlara henüz eklenmeden önce uzun süre planlanan dil uzantılarını kullanmaya başlarlar. + +Bunu mümkün kılmak için, kodlarını seçtikleri JavaScript lehçesinden düz eski JavaScript'e—veya hatta JavaScript'in bir önceki sürümüne—_çevirerek_ ((tarayıcı))ların onu çalıştırabilmesini sağlarlar. {{index latency, performance, [file, access], [network, speed]}} -Including a modular program that consists of 200 different files in a ((web page)) produces its own problems. If fetching a single file over the network takes 50 milliseconds, loading the whole program takes 10 seconds, or maybe half that if you can load several files simultaneously. That's a lot of wasted time. Because fetching a single big file tends to be faster than fetching a lot of tiny ones, web programmers have started using tools that combine their programs (which they painstakingly split into modules) into a single big file before they publish it to the Web. Such tools are called _((bundler))s_. +200 farklı dosyadan oluşan modüler bir programın bir ((web sayfası))na dahil edilmesi kendi sorunlarını ortaya çıkarır. Ağ üzerinden tek bir dosya almak 50 milisaniye sürerse, tüm programı yüklemek 10 saniye alır veya aynı anda birkaç dosya yükleyebilirseniz belki yarısı kadar. Bu çok zaman kaybettir. Tek büyük bir dosya almanın, birçok küçük dosya almaktan daha hızlı olma eğiliminde olması nedeniyle, web programcıları, programlarını (ki bunları titizlikle modüllerde bölmüşlerdi) web'e yayınlamadan önce birleştiren araçlar kullanmaya başlamışlardır. Bu tür araçlara \_((paketleyici))\_ler denir. {{index "file size"}} -And we can go further. Apart from the number of files, the _size_ of the files also determines how fast they can be transferred over the network. Thus, the JavaScript community has invented _((minifier))s_. These are tools that take a JavaScript program and make it smaller by automatically removing comments and whitespace, renaming bindings, and replacing pieces of code with equivalent code that take up less space. +Ve daha da ileri gidebiliriz. Dosyaların sayısının yanı sıra, dosyaların _büyüklüğü_ de ağ üzerinden ne kadar hızlı aktarılabileceklerini belirler. Bu nedenle, JavaScript topluluğu \_((küçültücü))\_ler adını verdiği şeyi icat etmiştir. Bunlar, bir JavaScript programını alır ve yorumları ve boşlukları otomatik olarak kaldırır, bağlantıları yeniden adlandırır ve daha az yer kaplayan eşdeğer kod parçaları ile değiştirip onu küçültürler. {{index pipeline, tool}} -It is not uncommon for the code that you find in an NPM package or that runs on a web page to have gone through _multiple_ stages of transformation—converting from modern JavaScript to historic JavaScript, combining the modules into a single file, and minifying the code. We won't go into the details of these tools in this book since there are many of them, and which one is popular changes regularly. Just be aware that such things exist, and look them up when you need them. +Bu nedenle, bir NPM paketinde veya bir web sayfasında bulduğunuz kodun _çoklu_ dönüşüm aşamalarından geçmiş olması yüksek ihtimaldir—modern JavaScript'ten tarihi JavaScript'e dönüştürülmüş, sonra modülleri tek bir dosyaya birleştirilmiş ve kod küçültülmüştür. Bu kitapta bu araçların detaylarına girmeyeceğiz çünkü bunlardan birçok tane var ve hangisinin popüler olduğu sürekli değişiyor. Sadece böyle şeylerin var olduğunu unutmayın ve ihtiyacınız olduğunda araştırın. -## Module design +## Modül dizaynı {{index [module, design], [interface, module], [code, "structure of"]}} -Structuring programs is one of the subtler aspects of programming. Any nontrivial piece of functionality can be organized in various ways. +Programları yapılandırma, programlamanın daha ince yönlerinden biridir. Herhangi bir önemli parçanın fonksiyonalitesi çeşitli şekillerde düzenlenebilir. -Good program design is subjective—there are trade-offs involved, and matters of taste. The best way to learn the value of well-structured design is to read or work on a lot of programs and notice what works and what doesn't. Don't assume that a painful mess is “just the way it is”. You can improve the structure of almost everything by putting more thought into it. +İyi bir program tasarımı, özneldir—bununla ilgili artı ve eksiler vardır ve insanların seçimleri farklıdır. İyi yapılandırılmış tasarımın değerini öğrenmenin en iyi yolu, birçok programı okumak veya üzerinde çalışmak ve işe yarayıp yaramayanları fark etmektir. Acılı bir karmaşanın "sadece olduğu gibi olduğunu" varsaymayın. Hemen hemen her şeyin yapısını daha fazla düşünerek iyileştirebilirsiniz. {{index [interface, module]}} -One aspect of module design is ease of use. If you are designing something that is intended to be used by multiple people—or even by yourself, in three months when you no longer remember the specifics of what you did—it is helpful if your interface is simple and predictable. +Modül tasarımının bir yönü kullanım kolaylığıdır. Birden fazla kişi tarafından kullanılması amaçlanan bir şey tasarlıyorsanız—veya hatta kendiniz, üç ay sonra ne yaptığınızın ayrıntılarını hatırlamadığınızda—arayüzünüzün basit ve öngörülebilir olması yardımcı olur. {{index "ini package", JSON}} -That may mean following existing conventions. A good example is the `ini` package. This module imitates the standard `JSON` object by providing `parse` and `stringify` (to write an INI file) functions, and, like `JSON`, converts between strings and plain objects. The interface is small and familiar, and after you've worked with it once, you're likely to remember how to use it. +Bu, var olan gelenekleri takip etmek anlamına gelebilir. İyi bir örnek, `ini` paketidir. Bu modül, bir INI dosyası yazmak için `parse` ve `stringify` fonksiyonlarını sağlayarak standart `JSON` nesnesini taklit eder ve `JSON` gibi, dize ve düz nesneler arasında dönüşüm yapar. Bu nedenle, arayüz küçük ve tanıdıktır ve bir kez çalıştıktan sonra nasıl kullanılacağını hatırlamanız muhtemeldir. {{index "side effect", "hard disk", composability}} -Even if there's no standard function or widely used package to imitate, you can keep your modules predictable by using simple ((data structure))s and doing a single, focused thing. Many of the INI-file parsing modules on NPM provide a function that directly reads such a file from the hard disk and parses it, for example. This makes it impossible to use such modules in the browser, where we don't have direct file system access, and adds complexity that would have been better addressed by _composing_ the module with some file-reading function. +Standart bir fonksiyon veya yaygın olarak kullanılan bir paketi taklit edecek bir standart fonksiyon yoksa bile, modüllerinizi basit ((veri yapı))ları kullanarak ve tek bir, odaklanmış şey yaparak öngörülebilir tutabilirsiniz. Örneğin, NPM'deki birçok INI dosyası ayrıştırma modülü, bir dosyayı doğrudan sabit diskinizden okuyup ve ayrıştıran bir fonksiyon sağlar. Bu, doğrudan dosya sistemine erişimimiz olayan tarayıcı ortamında böyle bir modülü kullanmayı imkansız hale getirir, ve bu modülü bazı dosya okuma fonksiyonlarıyla _birleştirerek_ çözülebilecek bir karmaşıklık eklerdi. {{index "pure function"}} -This points to another helpful aspect of module design—the ease with which something can be composed with other code. Focused modules that compute values are applicable in a wider range of programs than bigger modules that perform complicated actions with side effects. An INI file reader that insists on reading the file from disk is useless in a scenario where the file's content comes from some other source. +Bu, modül tasarımının başka bir yararlı yönünü işaret eder—bir şeyin diğer kodlarla nasıl birleştirilebileceğinin kolaylığı. Değerler hesaplayan odaklı modüller, yan etkileri olan ve karmaşık eylemler gerçekleştiren daha büyük modüllerden daha geniş bir program yelpazesine uygulanabilir. Diskten dosya okumak zorunda olan bir INI dosya okuyucusu, dosyanın içeriğinin başka bir kaynaktan geldiği senaryoda işe yaramaz. {{index "object-oriented programming"}} -Relatedly, stateful objects are sometimes useful or even necessary, but if something can be done with a function, use a function. Several of the INI file readers on NPM provide an interface style that requires you to first create an object, then load the file into your object, and finally use specialized methods to get at the results. This type of thing is common in the object-oriented tradition, and it's terrible. Instead of making a single function call and moving on, you have to perform the ritual of moving your object through its various states. And because the data is now wrapped in a specialized object type, all code that interacts with it has to know about that type, creating unnecessary interdependencies. +İlgili olarak, değişen bir durum barındıran nesneler bazen yararlı, hatta gereklidir ancak bir fonksiyonla yapılabilecek bir şey varsa, bir fonksiyon kullanın. NPM'deki birkaç INI dosyası okuyucusu, öncelikle bir nesne oluşturmanızı, ardından dosyayı nesnenize yüklemenizi ve son olarak sonuçlara erişmek için özel metodları kullanmanızı gerektiren bir arayüz stili sağlar. Bu tür şeyler, nesne yönelimli geleneğin bir parçasıdır ve korkunçtur. Tek bir fonksiyon çağrısı yapmak ve geçmek yerine, nesnenizi çeşitli durumlar boyunca hareket ettirme ritüelini gerçekleştirmeniz gerekir. Ve çünkü veri şimdi özelleşmiş bir nesne türüne sarılmış durumda olduğundan ötürü bununla etkileşim kuran tüm kodların o tür hakkında bilgi sahibi olması gerekir ve bu da gereksiz bağımlılıklar oluşmasını sağlar. -Often, defining new data structures can't be avoided—only a few basic ones are provided by the language standard, and many types of data have to be more complex than an array or a map. But when an array suffices, use an array. +Yeni veri yapılarını tanımlamak bazen kaçınılmazdır—dil standardı sadece birkaç temel yapıyı sağlar ve birçok veri türü bir diziden veya map veri tipinden daha karmaşık olmak zorundadır. Ancak bir dizi yeterliyken, bir dizi kullanın. -An example of a slightly more complex data structure is the graph from [Chapter ?](robot). There is no single obvious way to represent a ((graph)) in JavaScript. In that chapter, we used an object whose properties hold arrays of strings—the other nodes reachable from that node. +Biraz daha karmaşık bir veri yapısının bir örneği, [bölüm ?](robot) içindeki grafiktir. JavaScript'te bir ((grafik)) nasıl temsil edileceğine dair tek bir açık bir yol yoktur. O bölümde, diğer düğümlere o düğümden erişilebilen yerleri barındıran dizelerin dizilerini tutan bir nesne kullandık. -There are several different pathfinding packages on ((NPM)), but none of them uses this graph format. They usually allow the graph's edges to have a weight, which is the cost or distance associated with it. That isn't possible in our representation. +((NPM))'de birkaç farklı yol bulma paketi vardır ancak bunların hiçbiri bu grafik formatını kullanmaz. Genellikle, kenarların bir ağırlığı olmasına izin verirler, bu da onunla ilişkilendirilmiş maliyet veya mesafe anlamına gelir. Bu, bizim temsilimizde mümkün değildir. {{index "Dijkstra, Edsger", pathfinding, "Dijkstra's algorithm", "dijkstrajs package"}} -For example, there's the `dijkstrajs` package. A well-known approach to pathfinding, quite similar to our `findRoute` function, is called _Dijkstra's algorithm_, after Edsger Dijkstra, who first wrote it down. The `js` suffix is often added to package names to indicate the fact that they are written in JavaScript. This `dijkstrajs` package uses a graph format similar to ours, but instead of arrays, it uses objects whose property values are numbers—the weights of the edges. +Örneğin, `dijkstrajs` paketi vardır. Bir yol bulma için iyi bilinen bir yaklaşım ve bizim `findRoute` fonksiyonumuza oldukça benzemektedir, Edsger Dijkstra tarafından ilk kez yazıldıktan sonra _Dijkstra'nın algoritması_ olarak adlandırılmıştır. `js` eki sıklıkla paket adlarına eklenir ve bunların JavaScript'te yazıldığını belirtmek içindir. Bu `dijkstrajs` paketi, bizimkinin benzer bir grafik formatını kullanır, ancak diziler yerine, kenarların ağırlıkları olan sayıların olduğu nesneler kullanır. -If we wanted to use that package, we'd have to make sure that our graph was stored in the format it expects. All edges get the same weight since our simplified model treats each road as having the same cost (one turn). +Bu paketi kullanmak istesek, grafik formatımızın beklediği formatta olduğundan emin olmalıyız. Tüm kenarlar, bizim basitleştirilmiş modelimizde her yolun aynı maliyeti (bir dönüş) varmışçasına varsayıldığından, aynı ağırlığa sahiptir. ``` const {find_path} = require("dijkstrajs"); @@ -364,29 +358,29 @@ console.log(find_path(graph, "Post Office", "Cabin")); // → ["Post Office", "Alice's House", "Cabin"] ``` -This can be a barrier to composition—when various packages are using different data structures to describe similar things, combining them is difficult. Therefore, if you want to design for composability, find out what ((data structure))s other people are using and, when possible, follow their example. +Bu, birleştirme için bir engel olabilir—farklı veri yapılarını benzer şeyleri tanımlamak için kullanan çeşitli paketler onları birleştirmeyi zorlaştırır. Bu nedenle, birleşebilirlik için tasarım yapmak istiyorsanız, diğer insanların ne tür ((veri yapıları)) kullandığını bulun ve mümkünse onların örneğini takip edin. {{index design}} -Designing a fitting module structure for a program can be difficult. In the phase where you are still exploring the problem, trying different things to see what works, you might want to not worry about it too much since keeping everything organized can be a big distraction. Once you have something that feels solid, that's a good time to take a step back and organize it. +Bir programa uygun bir modül yapısı tasarlamak zor olabilir. Sorunu hala keşfetmeye çalıştığınız ve neyiş işe yarayıp yaramadığını test ettiğiniz aşamada her şeyi düzenli tutmaya çalışmak büyük bir dikkat dağıtıcı olabilir. Sağlam hisseden bir şeyiniz olduğunda, geri çekilip onu düzenlemek için iyi bir zamandır. -## Summary +## Özet -Modules provide structure to bigger programs by separating the code into pieces with clear interfaces and dependencies. The interface is the part of the module that's visible to other modules, and the dependencies are the other modules it makes use of. +Modüller, kodu net arayüzler ve bağımlılıklarla parçalara ayırarak daha büyük programlara yapı sağlar. Arayüz, modülün diğer modüller tarafından görülebilen kısmıdır ve bağımlılıklar, kullanılan diğer modüllerdir. -Because JavaScript historically did not provide a module system, the CommonJS system was built on top of it. Then at some point it _did_ get a built-in system, which now coexists uneasily with the CommonJS system. +JavaScript, tarihsel olarak bir modül sistemi sağlamadığı için, CommonJS sistemi üzerine inşa edildi. Sonra bir noktada, gerçekten yerleşik bir sistem _inşaa edildi_ ve şu anda CommonJS sistemiyle pek de uyumlu olmayan bir şekilde yan yana var olmayı sürdürmekte. -A package is a chunk of code that can be distributed on its own. NPM is a repository of JavaScript packages. You can download all kinds of useful (and useless) packages from it. +Bir paket, kendi başına dağıtılabilen bir kod parçasıdır. NPM, JavaScript paketlerinin bir deposudur. Oradan her türlü yararlı (ve yararsız) paketi indirebilirsiniz. -## Exercises +## Egzersizler -### A modular robot +### Modüler bir robot {{index "modular robot (exercise)", module, robot, NPM}} {{id modular_robot}} -These are the bindings that the project from [Chapter ?](robot) creates: +[Bölüm ?](robot) içindeki proje tarafından oluşturulan bağlantılar şu şekildedir: ```{lang: "null"} roads @@ -402,48 +396,48 @@ findRoute goalOrientedRobot ``` -If you were to write that project as a modular program, what modules would you create? Which module would depend on which other module, and what would their interfaces look like? +Eğer bu projeyi modüler bir program olarak yazsaydınız, hangi modülleri oluştururdunuz? Hangi modüller hangi diğer modüllere bağlı olurdu ve arayüzleri nasıl görünürdü? -Which pieces are likely to be available prewritten on NPM? Would you prefer to use an NPM package or write them yourself? +Hangi parçaların muhtemelen NPM'de önceden yazılmış olarak bulunacağını düşünüyorsunuz? Bir NPM paketi kullanmayı mı yoksa kendiniz mi yazmayı mı tercih edersiniz? {{hint {{index "modular robot (exercise)"}} -Here's what I would have done (but again, there is no single _right_ way to design a given module): +İşte ben olsaydım yapacağım şeyler (ancak yine de, belirli bir modül tasarımı için _tek bir doğru yol_ yoktur): {{index "dijkstrajs package"}} -The code used to build the road graph lives in the `graph` module. Because I'd rather use `dijkstrajs` from NPM than our own pathfinding code, we'll make this build the kind of graph data that `dijkstrajs` expects. This module exports a single function, `buildGraph`. I'd have `buildGraph` accept an array of two-element arrays, rather than strings containing hyphens, to make the module less dependent on the input format. +Yol grafiğini oluşturmak için kullanılan kod `graph` modülünde bulunur. Kendi yol bulma kodumuz yerine NPM'den `dijkstrajs` paketini kullanmayı tercih ettiğim için, `dijkstrajs`'ın beklediği türde grafik verilerini oluşturacağız. Bu modül, `buildGraph` adlı tek bir fonksiyonu dışa aktarır. Modülün giriş formatına olan bağımlılığını azaltmak için `buildGraph` fonksiyonunun tirelerle içindekileri ayıran bir dize yerine bir dizi iki öğeli diziyi kabul etmesini sağlardım. -The `roads` module contains the raw road data (the `roads` array) and the `roadGraph` binding. This module depends on `./graph.js` and exports the road graph. +`roads` modülü, ham yol verilerini (`roads` dizisi) ve `roadGraph` bağlantısını içerir. Bu modül `./graph.js` dosyasına bağlıdır ve yol grafiğini dışa aktarır. {{index "random-item package"}} -The `VillageState` class lives in the `state` module. It depends on the `./roads` module because it needs to be able to verify that a given road exists. It also needs `randomPick`. Since that is a three-line function, we could just put it into the `state` module as an internal helper function. But `randomRobot` needs it too. So we'd have to either duplicate it or put it into its own module. Since this function happens to exist on NPM in the `random-item` package, a reasonable solution is to just make both modules depend on that. We can add the `runRobot` function to this module as well, since it's small and closely related to state management. The module exports both the `VillageState` class and the `runRobot` function. +`VillageState` sınıfı, `state` modülünde yaşar. `./roads` modülüne bağımlıdır çünkü belirli bir yolun var olup olmadığını bilmesi gerekmektedir. Ayrıca `randomPick`'e ihtiyaç duyar. Bu, üç satırlık bir fonksiyon olduğu için bunu `state` modülüne bir dahili yardımcı fonksiyon olarak koyabiliriz. Ancak `randomRobot` da buna ihtiyaç duyar. Bu yüzden ya bunu kopyalamamız ya da kendi modülümüze koymamız gerekir. Bu fonksiyon, `random-item` paketinde zaten mevcut olduğu için, her iki modülü de buna bağlı hale getirmek uygun bir çözümdür. Bu modüle ayrıca, küçük olduğu ve durum yönetimiyle yakından ilgili olduğu için `runRobot` fonksiyonunu da ekleyebiliriz. Modül, hem `VillageState` sınıfını hem de `runRobot` fonksiyonunu dışa aktarır. -Finally, the robots, along with the values they depend on such as `mailRoute`, could go into an `example-robots` module, which depends on `./roads` and exports the robot functions. To make it possible for `goalOrientedRobot` to do route-finding, this module also depends on `dijkstrajs`. +Son olarak robotlar, `mailRoute` gibi bağımlılıklarıyla beraber `./roads`'a bağımlı olan ve robot fonksiyonlarını dışa aktaran bir `example-robots` modülüne konabilir. `goalOrientedRobot` fonksiyonunun rotalama yapabilmesi için, bu modül ayrıca `dijkstrajs` paketine bağımlıdır. -By offloading some work to ((NPM)) modules, the code became a little smaller. Each individual module does something rather simple and can be read on its own. Dividing code into modules also often suggests further improvements to the program's design. In this case, it seems a little odd that the `VillageState` and the robots depend on a specific road graph. It might be a better idea to make the graph an argument to the state's constructor and make the robots read it from the state object—this reduces dependencies (which is always good) and makes it possible to run simulations on different maps (which is even better). +((NPM)) modüllerine bazı işleri yükleyerek, kod biraz daha küçüldü. Her bir modül, oldukça basit bir şey yapar ve kendi başına okunabilir. Kodu modüllere bölmek ayrıca genellikle programın tasarımında daha ileri gelişmeleri önerir. Bu durumda, `VillageState` ve robotların belirli bir yol grafiğine bağlı olması biraz garip görünmektedir. Grafik, `state`'in constructor fonksiyonuna bir argüman olarak vermek ve robotların durum nesnesinden okumasını sağlamak daha iyi bir fikir olabilir—bu, bağımlılıkları azaltır (ki bu her zaman iyidir) ve farklı map değerlerinde simülasyonları çalıştırabilmeyi mümkün kılar (ki bu daha da iyidir). -Is it a good idea to use NPM modules for things that we could have written ourselves? In principle, yes—for nontrivial things like the pathfinding function you are likely to make mistakes and waste time writing them yourself. For tiny functions like `random-item`, writing them yourself is easy enough. But adding them wherever you need them does tend to clutter your modules. +NPM modüllerini yazabileceğimiz şeyler için kullanmak iyi bir fikir midir? İlkeler bakımından, evet—yol bulma gibi önemli olmayan şeyleri kendiniz yazarken muhtemelen hatalar yapar ve zaman kaybedersiniz. `random-item` gibi küçük fonksiyonlar için kendiniz yazmak yeterince kolaydır. Ancak onları ihtiyacınız olan her yere eklemek, modüllerinizi kalabalıklaştırmanızı sağlar. -However, you should also not underestimate the work involved in _finding_ an appropriate NPM package. And even if you find one, it might not work well or may be missing some feature you need. On top of that, depending on NPM packages means you have to make sure they are installed, you have to distribute them with your program, and you might have to periodically upgrade them. +Ancak, uygun bir NPM paketi _bulmanın_ getirdiği işi de küçümsememelisiniz. Ve bir tane bulsanız bile, iyi çalışmayabilir veya ihtiyacınız olan bazı özellikleri eksik olabilir. Üstelik, NPM paketlerine bağımlı olmak, onların kurulduğundan emin olmanızı ve programınızla birlikte dağıtmanız gerektiği anlamına gelir ve onları düzenli olarak güncellemeniz gerekebilir. -So again, this is a trade-off, and you can decide either way depending on how much a given package actually helps you. +Bu yüzden, tekrar ediyorum, bu bir ödünleşmedir ve bir paketin ne kadar yardımcı olduğuna bağlı olarak her iki şekilde de karar verebilirsiniz. hint}} -### Roads module +### Yollar modülü {{index "roads module (exercise)"}} -Write an ES module based on the example from [Chapter ?](robot) that contains the array of roads and exports the graph data structure representing them as `roadGraph`. It depends on a module `./graph.js` that exports a function `buildGraph`, used to build the graph. This function expects an array of two-element arrays (the start and end points of the roads). +[Chapter ?](robot) içindeki örneğe dayanarak bir ES modülü yazın, yolların bir dizisini içersin ve onları `roadGraph` olarak temsil eden grafik veri yapısını dışa aktarsın. Bu, grafik oluşturmak için kullanılan `buildGraph` adlı bir fonksiyonu dışa aktaran `./graph.js` adlı bir modüle bağımlı olmalıdır. Bu fonksiyon, iki öğeli dizilerden (yolların başlangıç ve bitiş noktaları) oluşan bir dizi bekler. {{if interactive ```{test: no} -// Add dependencies and exports +// Arayüz ve bağımlılıkları ekleyin const roads = [ "Alice's House-Bob's House", "Alice's House-Cabin", @@ -462,26 +456,26 @@ if}} {{index "roads module (exercise)", "destructuring binding", "exports object"}} -Since this is an ES module, you have to use `import` to access the graph module. That was described as exporting a `buildGraph` function, which you can pick out of its interface object with a destructuring `const` declaration. +Bu bir ES modül olduğundan, grafiğe erişmek için `import` kullanmanız gerekir. Bu, `const` beyanı aracılığıyla yapılarına ayırarak arayüz nesnesinden `buildGraph` fonksiyonunu seçebileceğiniz şekilde açıklanmıştır. -To export `roadGraph`, you put the keyword `export` before its definition. Because `buildGraph` takes a data structure that doesn't precisely match `roads`, the splitting of the road strings must happen in your module. +`roadGraph` fonksiyonunu dışa aktarmak için, tanımının önüne `export` anahtar kelimesini koyarsınız. `buildGraph`, `roads` ile tam olarak eşleşmeyen bir veri yapısı aldığından ötürü yol dizilerinin bölünmesi kendi modülünüzde olmalıdır. hint}} -### Circular dependencies +### Döngüsel bağımlılıklar {{index dependency, "circular dependency", "require function"}} -A circular dependency is a situation where module A depends on B, and B also, directly or indirectly, depends on A. Many module systems simply forbid this because whichever order you choose for loading such modules, you cannot make sure that each module's dependencies have been loaded before it runs. +Dairesel bağımlılık, modül A'nın B'ye, ve B'nin de doğrudan veya dolaylı olarak A'ya bağlı olduğu bir durumdur. Birçok modül sistemi bunu yasaklar çünkü bu tür modüllerin yüklenmesi için hangi sırayı seçerseniz seçin, her modülün çalıştırılmadan önce bağımlılıklarının yüklenmiş olup olmadığından emin olamazsınız. -((CommonJS modules)) allow a limited form of cyclic dependencies. As long as the modules don't access each other's interface until after they finish loading, cyclic dependencies are okay. +((CommonJS modülleri)) sınırlı bir dairesel bağımlılık biçimine izin verir. Modüller birbirlerinin arayüzlerine yüklenme işlemleri tamamlanmadan önce erişmedikçe, dairesel bağımlılıklar sorun değildir. -The `require` function given [earlier in this chapter](modules#require) supports this type of dependency cycle. Can you see how it handles cycles? +[Bu bölümün başlarında](modules#require) verilen `require` fonksiyonu bu tür bir bağımlılık döngüsünü destekler. Bununla nasıl başa çıktığını görebiliyor musunuz? {{hint {{index overriding, "circular dependency", "exports object"}} -The trick is that `require` adds the interface object for a module to its cache _before_ it starts loading the module. That way, if any `require` call made while it is running try to load it, it is already known, and the current interface will be returned, rather than starting to load the module once more (which would eventually overflow the stack). +Püf noktası, `require` fonksiyonunun modülü yüklemeye _başlamadan önce_ arayüz nesnesini önbelleğine eklemesidir. Bu şekilde, çalışırken yapılan herhangi bir `require` çağrısı, yüklenmiş olup olmadığı bilindiğinden, tüm modülü tekrar yüklemek yerine (bunu yapmak sonunda yığını taşmaya neden olurdu) mevcut arayüz döndürülmesini sağlar. hint}} diff --git a/11_async.md b/11_async.md index cf18415c..fd2bdfed 100644 --- a/11_async.md +++ b/11_async.md @@ -4,76 +4,76 @@ {{quote {author: "Laozi", title: "Tao Te Ching", chapter: true} -Who can wait quietly while the mud settles?\ -Who can remain still until the moment of action? +Çamur çökene kadar kim sessizce bekleyebilir?\ +Kim eylem anına kadar hareketsiz kalabilir? quote}} {{index "Laozi"}} -{{figure {url: "img/chapter_picture_11.jpg", alt: "Illustration showing two crows on a tree branch", chapter: framed}}} +{{figure {url: "img/chapter_picture_11.jpg", alt: "Bir ağaç dalındaki iki kargayı gösteren illüstrasyon.", chapter: framed}}} -The central part of a computer, the part that carries out the individual steps that make up our programs, is called the _((processor))_. The programs we have seen so far will keep the processor busy until they have finished their work. The speed at which something like a loop that manipulates numbers can be executed depends pretty much entirely on the speed of the computer's processor and memory. +Bilgisayarın merkezi parçası, programlarımızı oluşturan bireysel adımları gerçekleştiren kısım _((işlemci))_ olarak adlandırılır. Şimdiye kadar gördüğümüz programlar işlerini bitirene kadar işlemciyi meşgul tutarlar. Sayıları manipüle eden bir döngü gibi bir şeyin çalıştırılma hızı, büyük ölçüde bilgisayarın işlemcisinin ve belleğinin hızına bağlıdır. {{index [memory, speed], [network, speed]}} -But many programs interact with things outside of the processor. For example, they may communicate over a computer network or request data from the ((hard disk))—which is a lot slower than getting it from memory. +Ancak birçok program, işlemcinin dışındaki şeylerle etkileşime geçer. Örneğin, bir bilgisayar ağı üzerinden iletişim kurabilir veya ((hard disk))ten veri isteyebilir - bu, bellekten veri almaktan çok daha yavaştır. -When such a thing is happening, it would be a shame to let the processor sit idle—there might be some other work it could do in the meantime. In part, this is handled by your operating system, which will switch the processor between multiple running programs. But that doesn't help when we want a _single_ program to be able to make progress while it is waiting for a network request. +Böyle bir şey olurken, işlemciyi boşta bekletmek pek efektik olmaz çünkü bu sırada yapabileceği başka bir iş olabilir. Bu işlemciyi birden çok çalışan programlar arasında geçirerek kısmen işletim sistemi tarafından ele alınır. Ancak bu, bir tek programın bir ağ isteği beklerken ilerleme kaydetmesini istediğimizde işe yaramaz. -## Asynchronicity +## Eşzamansızlık {{index "synchronous programming"}} -In a _synchronous_ programming model, things happen one at a time. When you call a function that performs a long-running action, it returns only when the action has finished and it can return the result. This stops your program for the time the action takes. +Bir _eşzamanlı_ program modelinde, olaylar teker teker gerçekleşir. Uzun süren bir eylemi gerçekleştiren bir fonksiyonu çağırdığınızda, yalnızca eylem tamamlandığında ve sonucu döndüğünde geri döner. Bu, eylemin zaman aldığı süre boyunca programınızın durmasına sebep olur. {{index "asynchronous programming"}} -An _asynchronous_ model allows multiple things to happen at the same time. When you start an action, your program continues to run. When the action finishes, the program is informed and gets access to the result (for example, the data read from disk). +Bir _eşzamansız_ model, aynı anda birden çok şeyin gerçekleşmesine izin verir. Bir eylemi başlattığınızda, programınız çalışmaya devam eder. Eylem tamamlandığında, program bilgilendirilir ve sonuca erişir (örneğin, diskten okunan veri). -We can compare synchronous and asynchronous programming using a small example: a program that makes two requests over the ((network)) and then combines the results. +Eşzamanlı ve eşzamansız programlamayı bir örnekle karşılaştırabiliriz: ((network)) üzerinden iki istek yapan ve ardından sonucu birleştiren bir program. {{index "synchronous programming"}} -In a synchronous environment, where the request function returns only after it has done its work, the easiest way to perform this task is to make the requests one after the other. This has the drawback that the second request will be started only when the first has finished. The total time taken will be at least the sum of the two response times. +Bir eşzamanlı ortamda, talep fonksiyonu yalnızca işini bitirdikten sonra döndüğünde, bu görevi gerçekleştirmenin en kolay yolu istekleri birbiri ardına yapmaktır. Bu, ikinci istek yalnızca ilk istek tamamlandığında başlatılacağından dezavantajlıdır. Toplam süre en az iki yanıt süresinin toplamı olacaktır. {{index parallelism}} -The solution to this problem, in a synchronous system, is to start additional ((thread))s of control. A _thread_ is another running program whose execution may be interleaved with other programs by the operating system—since most modern computers contain multiple processors, multiple threads may even run at the same time, on different processors. A second thread could start the second request, and then both threads wait for their results to come back, after which they resynchronize to combine their results. +Bu sorunun çözümü, eşzamanlı bir sistemde ek kontrol ((thread))leri başlatmaktır. Bir _thread_, bir başka çalışan programdır ve işletim sistemi tarafından diğer programlarla birlikte aralıklı bir şekilde çalıştırılabilir - çoğu modern bilgisayar birden çok işlemci içerdiğinden, birden çok thread aynı anda farklı işlemcilerde çalışabilir. İkinci bir thread, ikinci isteği başlatabilir ve ardından her iki thread de sonuçlarını bekler, sonrasında sonuçlarını birleştirmek için yeniden senkronize olurlar. {{index CPU, blocking, "asynchronous programming", timeline, "callback function"}} -In the following diagram, the thick lines represent time the program spends running normally, and the thin lines represent time spent waiting for the network. In the synchronous model, the time taken by the network is _part_ of the timeline for a given thread of control. In the asynchronous model, starting a network action allows the program to continue running while the network communication happens alongside it, notifying the program when it is finished. +Aşağıdaki diyagramda, kalın çizgiler programın normal çalıştığı zamanı temsil ederken, ince çizgiler ağda beklenen zamanı temsil eder. Senkron modelde, ağın alması gereken süre, belirli bir kontrol ((thread))inin zaman çizelgesinin bir \_parçası_dır. Asenkron modelde ağ eyleminin başlatılması, programın devam etmesine izin verir ve ağ iletişimi yanında gerçekleşir, işlem sona erdiğinde programı bilgilendirir. -{{figure {url: "img/control-io.svg", alt: "Diagram of showing control flow in synchronous and asynchronous programs. The first part shows a synchronous program, where the program's active and waiting phases all happen on a single, sequential line. The second part shows a multi-threaded synchronous program, with two parallel lines, on which the waiting parts happen alongside each other, causing the program to finish faster. The last part shows an asynchronous program, where the multiple asynchronous actions branch off from the main program, which at some point stops, and then resumes whenever the first thing it was waiting for finishes.",width: "8cm"}}} +{{figure {url: "img/control-io.svg", alt: "Senkron ve asenkron programlarda kontrol akışını gösteren diyagram. İlk bölüm, programın aktif ve bekleme aşamalarının tek bir sıralı satırda gerçekleştiği senkronize bir programı göstermektedir. İkinci bölümde, bekleme parçalarının yan yana yer aldığı, programın daha hızlı bitmesine neden olan, iki paralel çizgiye sahip, çok iş parçacıklı bir senkronize program gösterilmektedir. Son bölüm, birden fazla eşzamansız eylemin ana programdan ayrıldığı, bir noktada duran ve beklediği ilk şey bittiğinde devam ettiği eşzamansız bir programı gösterir.",width: "8cm"}}} {{index ["control flow", asynchronous], "asynchronous programming", verbosity, performance}} -Another way to describe the difference is that waiting for actions to finish is _implicit_ in the synchronous model, while it is _explicit_—under our control—in the asynchronous one. +Farkı açıklamanın başka bir yolu, eylemlerin bitmesini beklemenin eşzamanlı modelde _örtük_ ancak asenkron modelde ise bizim kontrolümüz altında _açıkça_ olduğudur. -Asynchronicity cuts both ways. It makes expressing programs that do not fit the straight-line model of control easier, but it can also make expressing programs that do follow a straight line more awkward. We'll see some ways to reduce this awkwardness later in the chapter. +Eşzamansızlık iki yönde de keser. Doğrudan çizgi kontrol modeline uymayan programları ifade etmeyi kolaylaştırır, ancak doğrudan bir çizgi izleyen programları ifade etmeyi daha zor hale getirebilir. Bu zorluğu azaltmanın bazı yollarını bölümün ilerleyen kısımlarında göreceğiz. -Both prominent JavaScript programming platforms—((browser))s and ((Node.js))—make operations that might take a while asynchronous, rather than relying on ((thread))s. Since programming with threads is notoriously hard (understanding what a program does is much more difficult when it's doing multiple things at once), this is generally considered a good thing. +Öne çıkan JavaScript programlama platformları - ((browser))lar ve ((Node.js)) - zaman alabilecek işlemleri ((thread))lerden ziyade asenkron olarak yaparlar. Çünkü thread'lerle programlamak ünlü bir şekilde zordur (bir programın ne yaptığını anlamak, aynı anda birden fazla iş yaptığında çok daha zordur), bu genellikle iyi bir şey olarak kabul edilir. -## Callbacks +## Geri aramalar {{indexsee [function, callback], "callback function"}} -One approach to ((asynchronous programming)) is to make functions that need to wait for something take an extra argument, a _((callback function))_. The asynchronous function starts a process, sets things up so that the callback function is called when the process finishes, and then returns. +((Asenkron programlama)) yaklaşımlarından biri, bir şeyi beklemesi gereken fonksiyonlara ek bir argüman olarak bir _((geri çağrı fonksiyonu))_ vermektedir. Bir fonksiyon, bir işlemi başlatır, işlem tamamlandığında geri çağrı fonksiyonunun çağrılması için düzenlemeler yapar ve ardından değerini döndürür. {{index "setTimeout function", waiting}} -As an example, the `setTimeout` function, available both in Node.js and in browsers, waits a given number of milliseconds, then calls a function. +Örneğin, Node.js ve tarayıcılarda bulunan `setTimeout` fonksiyonu, belirli bir milisaniye (bir saniye bin milisaniyedir) bekler ve ardından bir fonksiyonu çağırır. ```{test: no} setTimeout(() => console.log("Tick"), 500); ``` -Waiting is not generally important work, but it can be very useful when you need to arrange for something to happen at a certain time or check whether some action is taking longer than expected. +Bekleme genellikle çok önemli bir iş türü değildir, ancak belirli bir zamanda bir şeyin yapılmasını ayarlamak veya başka bir eylemin beklenenden daha uzun sürüp sürmediğini kontrol etmek gerektiğinde çok kullanışlı olabilir. {{index "readTextFile function"}} -Another example of a common asynchronous operation is reading a file from a device's storage. Imagine you have a function `readTextFile` that reads a file's content as a string and passes it to a callback function. +Diğer bir yaygın asenkron işlemlerse cihazın depolama biriminden bir dosya okumaktır. Diyelim ki bir `readTextFile` fonksiyonunuz var ve bu bir dosyanın içeriğini bir dize olarak okur ve bunu bir geri çağrı fonksiyonuna verir. ``` readTextFile("shopping_list.txt", content => { @@ -84,9 +84,9 @@ readTextFile("shopping_list.txt", content => { // → Bananas ``` -The `readTextFile` function is not part of standard JavaScript. We will see how to read files in the browser and in Node.js in later chapters. +`readTextFile` fonksiyonu standart JavaScript'in bir parçası değildir. Tarayıcıda ve Node.js'te dosya okumanın nasıl yapıldığını sonraki bölümlerde göreceğiz. -Performing multiple asynchronous actions in a row using callbacks means that you have to keep passing new functions to handle the ((continuation)) of the computation after the actions. An asynchronous function that compares two files and produces a boolean indicating whether their content is the same might look like this: +Geri aramalar kullanarak ardışık olarak birden fazla asenkron işlem gerçekleştirmek, işlemlerden sonra hesaplamanın devamını ele almak için sürekli yeni fonksiyonlar geçirmeniz gerektiği anlamına gelir. İki dosyayı karşılaştıran ve içeriklerinin aynı olup olmadığını belirten bir asenkron fonksiyon, şu şekilde yazılabilir. ``` function compareFiles(fileA, fileB, callback) { @@ -98,21 +98,21 @@ function compareFiles(fileA, fileB, callback) { } ``` -This style of programming is workable, but the indentation level increases with each asynchronous action because you end up in another function. Doing more complicated things, such as wrapping asynchronous actions in a loop, can get awkward. +Bu programlama tarzı çalışabilir, ancak her asenkron işlemle girinti seviyesi artar çünkü başka bir fonksiyona girersiniz. Daha karmaşık şeyler yapmak, örneğin asenkron işlemleri bir döngü içine almak, garip olabilir. -In a way, asynchronicity is _contagious_. Any function that calls a function that works asynchronously must itself be asynchronous, using a callback or similar mechanism to deliver its result. Calling a callback is somewhat more involved and error-prone than simply returning a value, so needing to structure large parts of your program that way is not great. +Bir bakıma, eşzamansızlık bulaşıcıdır. Asenkron olarak çalışan bir fonksiyonu çağıran herhangi bir fonksiyon, sonucunu iletmek için bir geri çağrı veya benzeri bir mekanizma kullanarak kendisi de asenkron olmalıdır. Bir geri çağrı çağırmak, sadece bir değeri döndürmekten biraz daha karmaşıktır ve hata yapma olasılığı daha yüksektir, bu nedenle programınızın büyük kısımlarını bu şekilde yapılandırmanız gerektiğinde pek de iyi bir seçenek değildir. -## Promises +## Promise'lar -A slightly different way to build an asynchronous program is to have asynchronous functions return an object that represents its (future) result instead of passing around callback functions. This way such functions actually return something meaningful, and the shape of the program more closely resembles that of synchronous programs. +Asenkron bir program oluşturmanın biraz farklı bir yolu, asenkron fonksiyonların geri arama fonksiyonlarını dolaştırmak yerine, gelecekteki sonucunu temsil eden bir nesne döndürmeleridir. Bu şekilde, böyle fonksiyonlar aslında anlamlı bir şey döndürür ve programın yapısı, eşzamanlı programlarınkine daha yakın olur. {{index "Promise class", "asynchronous programming", "resolving (a promise)", "then method", "callback function"}} -This is what the standard class `Promise` is for. A _promise_ is a receipt representing a value that may not be available yet. It provides a `then` method that allows you to register a function that should be called when the action for which it is waiting finishes. When the promise is _resolved_, meaning its value becomes available, such functions (there can be multiple) are called with the result value. It is possible to call `then` on a promise that has already resolved—your function will still be called. +Standart `Promise` sınıfı bunun için kullanılır. Bir _promise_, henüz mevcut olmayan bir değeri temsil eden bir makbuzdur. `then` metodunu sağlar, böylece beklenen eylem tamamlandığında çağrılması gereken bir fonksiyonu kaydedebilirsiniz. `Promise` çözüldüğünde, yani değeri mevcut olduğunda, böyle fonksiyonlar (çoklu olabilir) sonuç değeriyle çağrılır. Zaten çözülmüş bir promise üzerinde `then` çağrısı yapmak mümkündür—fonksiyonunuz hala çağrılacaktır. {{index "Promise.resolve function"}} -The easiest way to create a promise is by calling `Promise.resolve`. This function ensures that the value you give it is wrapped in a promise. If it's already a promise, it is simply returned. Otherwise, you get a new promise that immediately resolves with your value as its result. +Bir promise oluşturmanın en kolay yolu, `Promise.resolve` çağrısını kullanmaktır. Bu fonksiyon, verdiğiniz değerin bir promise içine sarıldığından emin olur. Zaten bir promise ise, sadece döndürülür—aksi halde, değerinizi sonucu olarak hemen çözülen yeni bir promise alırsınız. ``` let fifteen = Promise.resolve(15); @@ -122,9 +122,9 @@ fifteen.then(value => console.log(`Got ${value}`)); {{index "Promise class"}} -To create a promise that does not immediately resolve, you can use `Promise` as a constructor. It has a somewhat odd interface: the constructor expects a function as argument, which it immediately calls, passing it a function that it can use to resolve the promise. +Hemen çözülmeyen bir promise oluşturmak için, `Promise`'ı bir constructor olarak kullanabilirsiniz. Biraz garip bir arayüze sahiptir—constructor, hemen çağrılan ve promise'i çözmek için kullanabileceği bir fonksiyon geçmesini bekler. -For example, this is how you could create a promise-based interface for the `readTextFile` function: +`readTextFile` fonksiyonu için promise tabanlı bir arayüzü bu şekilde oluşturabilirsiniz: {{index "textFile function"}} @@ -138,13 +138,13 @@ function textFile(filename) { textFile("plans.txt").then(console.log); ``` -Note how, in contrast to callback-style functions, this asynchronous function returns a meaningful value—a promise to give you the contents of the file at some point in the future. +Bu eşzamansız fonksiyonun anlamlı bir değer döndürdüğüne dikkat edin—gelecekte bir noktada dosyanın içeriğini size verecek bir promise. {{index "then method"}} -A useful thing about the `then` method is that it itself returns another promise. This one resolves to the value returned by the callback function or, if that returned value is a promise, to the value that promise resolves to. Thus, you can “chain” multiple calls to `then` together to set up a sequence of asynchronous actions. +`then` metodunun yararlı bir yönü, kendisinin de callback fonksiyonunun döndürdüğü değere çözülen başka bir promise döndürmesidir veya eğer o fonksiyon bir promise döndürürse, o promise'in çözüldüğü değere çözülen bir promise döndürür. Böylece, eşzamansız eylemler dizisini oluşturmak için birden fazla `then` çağrısını “zincirleyebilirsiniz”. -This function, which reads a file full of filenames, and returns the content of a random file in that list, shows this kind of asynchronous promise pipeline: +Bir dosya dolusu dosya adını okuyan ve listedeki rastgele bir dosyanın içeriğini döndüren bu fonksiyon, bu tür bir eşzamansız promise boru hattını gösterir. ``` function randomFile(listFile) { @@ -155,11 +155,11 @@ function randomFile(listFile) { } ``` -The function returns the result of this chain of `then` calls. The initial promise fetches the list of files as a string. The first `then` call transforms that string into an array of lines, producing a new promise. The second `then` call picks a random line from that, producing a third promise that yields a single filename. The final `then` call reads this file, so that the result of the function as a whole is a promise that returns the content of a random file. +Fonksiyon, `then` çağrıları zincirinin sonucunu döndürür. İlk promise, dosya listesini bir dize olarak alır. İlk `then` çağrısı, bu dizeyi bir dizi satıra dönüştürerek yeni bir promise üretir. İkinci `then` çağrısı, rastgele bir satır seçer ve tek bir dosya adı veren üçüncü bir promise üretir. Son `then` çağrısı bu dosyayı okur, böylece fonksiyonun tamamının sonucu, rastgele bir dosyanın içeriğini döndüren bir promise olur. -In this code, the functions used in the first two `then` calls return a regular value that will immediately be passed into the promise returned by `then` when the function returns. The last `then` call returns a promise (`textFile(filename)`), making it an actual asynchronous step. +Bu kodda, ilk iki `then` çağrısında kullanılan fonksiyonlar normal bir değer döndürür, bu değer fonksiyon döndüğünde hemen `then` tarafından döndürülen promise'e geçer. Sonuncusu bir promise (textFile(filename)) döndürür ve bu onu gerçek bir eşzamansız adım yapar. -It would also have been possible to perform all these steps inside a single `then` callback, since only the last step is actually asynchronous. But the kind of `then` wrappers that only do some synchronous data transformation are often useful, such as when you want to return a promise that produces a processed version of some asynchronous result. +Bu adımların hepsini tek bir `then` callback içinde yapmak da mümkün olurdu, çünkü aslında sadece son adım eşzamansızdır. Ancak sadece bazı eşzamanlı veri dönüşümleri yapan `then` sarmalayıcıları, genellikle bir eşzamansız sonucun işlenmiş bir sürümünü üreten bir promise döndürmek istediğinizde olduğu gibi, kullanışlıdır. ``` function jsonFile(filename) { @@ -169,19 +169,19 @@ function jsonFile(filename) { jsonFile("package.json").then(console.log); ``` -Generally, it is useful to think of a promise as a device that lets code ignore the question of when a value is going to arrive. A normal value has to actually exist before we can reference it. A promised value is a value that _might_ already be there or might appear at some point in the future. Computations defined in terms of promises, by wiring them together with `then` calls, are executed asynchronously as their inputs become available. +Genel olarak, promise'leri, bir değerin ne zaman geleceği sorusunu kodun görmezden gelmesine izin veren bir cihaz olarak düşünmek faydalıdır. Normal bir değer, ona referans verebilmemiz için aslında var olmalıdır. Promise edilen bir değer, zaten orada olabilecek veya gelecekte bir noktada ortaya çıkabilecek bir değerdir. Promise'lerle tanımlanan hesaplamalar, `then` çağrılarıyla birbirine bağlanarak, girdileri kullanılabilir hale geldikçe eşzamansız olarak yürütülür. -## Failure +## Arıza {{index "exception handling"}} -Regular JavaScript computations can fail by throwing an exception. Asynchronous computations often need something like that. A network request may fail, a file may not exist, or some code that is part of the asynchronous computation may throw an exception. +Normal JavaScript hesaplamaları bir istisna fırlatarak başarısız olabilir. Eşzamansız hesaplamalar da genellikle buna benzer bir şeye ihtiyaç duyar. Bir ağ isteği başarısız olabilir, bir dosya mevcut olmayabilir veya eşzamansız hesaplamanın bir parçası olan bazı kodlar bir istisna fırlatabilir. {{index "callback function", error}} -One of the most pressing problems with the callback style of asynchronous programming is that it makes it extremely difficult to ensure failures are properly reported to the callbacks. +Eşzamansız programlamanın callback stilindeki en acil sorunlardan biri, hataların doğru şekilde callback'lere bildirilmesini sağlamanın son derece zor olmasıdır. -A common convention is to use the first argument to the callback to indicate that the action failed, and the second to pass the value produced by the action when it was successful. +Yaygın olarak kullanılan bir konvansiyon, callback'in ilk argümanının eylemin başarısız olduğunu belirtmek için kullanılması ve ikincisinin eylemin başarılı olduğunda ürettiği değeri içermesidir. ``` someAsyncFunction((error, value) => { @@ -190,29 +190,29 @@ someAsyncFunction((error, value) => { }); ``` -Such callback functions must always check whether they received an exception and make sure that any problems they cause, including exceptions thrown by functions they call, are caught and given to the right function. +Bu tür callback fonksiyonları her zaman bir istisna alıp almadıklarını kontrol etmeli ve neden oldukları herhangi bir sorunun, çağırdıkları fonksiyonlar tarafından fırlatılan istisnalar da dahil olmak üzere, yakalanıp doğru fonksiyona iletildiğinden emin olmalıdır. {{index "rejecting (a promise)", "resolving (a promise)", "then method"}} -Promises make this easier. They can be either resolved (the action finished successfully) or rejected (it failed). Resolve handlers (as registered with `then`) are called only when the action is successful, and rejections are propagated to the new promise returned by `then`. When a handler throws an exception, this automatically causes the promise produced by its `then` call to be rejected. If any element in a chain of asynchronous actions fails, the outcome of the whole chain is marked as rejected, and no success handlers are called beyond the point where it failed. +Promises bunu kolaylaştırır. Bir promise ya çözülebilir (eylem başarıyla tamamlandı) ya da reddedilebilir (başarısız oldu). `then` ile kayıtlı çözümleyici fonksiyonlar yalnızca eylem başarılı olduğunda çağrılır ve reddedilmeler, `then` tarafından döndürülen yeni promise'e aktarılır. Bir handler bir istisna fırlattığında, bu otomatik olarak `then` çağrısının ürettiği promise'in reddedilmesine neden olur. Dolayısıyla, eşzamansız eylemler zincirindeki herhangi bir öğe başarısız olursa, tüm zincirin sonucu reddedilmiş olarak işaretlenir ve başarısız olduğu noktadan sonra hiçbir başarı handler'ı çağrılmaz. {{index "Promise.reject function", "Promise class"}} -Much like resolving a promise provides a value, rejecting one also provides a value, usually called the _reason_ of the rejection. When an exception in a handler function causes the rejection, the exception value is used as the reason. Similarly, when a handler returns a promise that is rejected, that rejection flows into the next promise. There's a `Promise.reject` function that creates a new, immediately rejected promise. +Bir promise'i çözmek nasıl bir değer sağlıyorsa, bir promise'i reddetmek de bir değer sağlar, genellikle reddetmenin nedeni olarak adlandırılır. Bir handler fonksiyonundaki bir istisna reddetmeye neden olduğunda, istisna değeri neden olarak kullanılır. Benzer şekilde, bir handler reddedilen bir promise döndürdüğünde, bu reddetme bir sonraki promise'e akar. `Promise.reject` fonksiyonu, yeni, anında reddedilen bir promise oluşturur. {{index "catch method"}} -To explicitly handle such rejections, promises have a `catch` method that registers a handler to be called when the promise is rejected, similar to how `then` handlers handle normal resolution. It's also very much like `then` in that it returns a new promise, which resolves to the original promise's value when that resolves normally and to the result of the `catch` handler otherwise. If a `catch` handler throws an error, the new promise is also rejected. +Bu tür reddetmeleri açıkça ele almak için, promise'lerin, reddedildiğinde bir handler kaydeden `catch` metodu vardır, tıpkı `then` handler'larının normal çözümlemeyi ele alması gibi. Ayrıca, `then` gibi, orijinal promise'in değeri normal olarak çözüldüğünde ve `catch` handler'ının sonucuna göre çözüldüğünde yeni bir promise döndürür. Eğer bir `catch` handler bir hata fırlatırsa, yeni promise de reddedilir. {{index "then method"}} -As a shorthand, `then` also accepts a rejection handler as a second argument, so you can install both types of handlers in a single method call: `.then(acceptHandler, rejectHandler)`. +Kısa bir yol olarak, `then` ikinci argüman olarak bir reddetme handler'ını da kabul eder, böylece her iki tür handler'ı tek bir metod çağrısında kurabilirsiniz. -A function passed to the `Promise` constructor receives a second argument, alongside the resolve function, which it can use to reject the new promise. +`Promise` constructor'ına geçen bir fonksiyon, resolve fonksiyonunun yanında reddetmek için kullanabileceği ikinci bir argüman alır. {{index "textFile function"}} -When our `readTextFile` function encounters a problem, it passes the error to its callback function as a second argument. Our `textFile` wrapper should actually check that argument, so that a failure causes the promise it returns to be rejected. +`readTextFile` fonksiyonumuz bir sorunla karşılaştığında, hatayı callback fonksiyonuna ikinci bir argüman olarak iletir. textFile sarmalayıcımız aslında bu argümana bakmalı, böylece bir başarısızlık döndürdüğü promise'in reddedilmesine neden olur. ```{includeCode: true} function textFile(filename) { @@ -225,7 +225,7 @@ function textFile(filename) { } ``` -The chains of promise values created by calls to `then` and `catch` thus form a pipeline through which asynchronous values or failures move. Since such chains are created by registering handlers, each link has a success handler or a rejection handler (or both) associated with it. Handlers that don't match the type of outcome (success or failure) are ignored. Handlers that do match are called, and their outcome determines what kind of value comes next—success when they return a non-promise value, rejection when they throw an exception, and the outcome of the promise when they return a promise. +`then` ve `catch` çağrılarıyla oluşturulan promise değer zincirleri, bu şekilde eşzamansız değerlerin veya hataların geçtiği bir boru hattı oluşturur. Bu tür zincirler handler'ları kaydederek oluşturulduğundan, her bağlantıda bir başarı handler'ı veya bir reddetme handler'ı (veya her ikisi) bulunur. Sonucun türüne (başarı veya başarısızlık) uymayan handler'lar yok sayılır. Ancak uyum sağlayanlar çağrılır ve sonuçları, sıradaki değerin türünü belirler—bir promise döndürmeyen bir değer döndüğünde başarı, bir istisna fırlattığında reddedilme ve bir promise döndürdüğünde promise'in sonucu. ```{test: no} new Promise((_, reject) => reject(new Error("Fail"))) @@ -239,39 +239,39 @@ new Promise((_, reject) => reject(new Error("Fail"))) // → Handler 2: nothing ``` -The first `then` handler function isn't called, because at that point of the pipeline the promise holds a rejection. The `catch` handler handles that rejection and returns a value, which is given to the second `then` handler function. +lk normal handler fonksiyonu çağrılmaz, çünkü boru hattının o noktasında promise bir reddetme taşır. `catch` handler bu reddetmeyi ele alır ve ikinci handler fonksiyonuna verilen bir değer döndürür. {{index "uncaught exception", "exception handling"}} -Much like an uncaught exception is handled by the environment, JavaScript environments can detect when a promise rejection isn't handled and will report this as an error. +Yakalanmamış bir istisnanın ortam tarafından ele alınması gibi, JavaScript ortamları bir promise reddedilmesinin ele alınmadığını tespit edebilir ve bunu bir hata olarak bildirecektir. ## Carla {{index "Carla the crow"}} -It's a sunny day in Berlin. The runway of the old, decommissioned airport is teeming with cyclists and inline skaters. In the grass near a garbage container a flock of crows noisily mills about, trying to convince a group of tourists to part with their sandwiches. +Berlin'de güneşli bir gün. Eski, hizmet dışı bırakılmış havaalanının pisti bisikletçiler ve patencilerle dolu. Bir çöp konteynerinin yanında, çimenlerin üzerinde, bir grup turistin sandviçlerinden vazgeçirmeye çalışan bir sürü karga gürültülü bir şekilde dolaşıyor. -One of the crows stands out—a large scruffy female with a few white feathers in her right wing. She is baiting people with a skill and confidence that suggest she's been doing this for a long time. When an elderly man is distracted by the antics of another crow, she casually swoops in, snatches his half-eaten bun from his hand, and sails away. +Kargalardan biri öne çıkıyor—sağ kanadında birkaç beyaz tüy olan büyük, dağınık bir dişi. İnsanları uzun zamandır bu işi yaptığına işaret eden bir beceri ve güvenle kandırıyor. Yaşlı bir adam başka bir karganın maskaralıklarıyla dikkati dağılırken, bu dişi karga rahatça süzülüyor, adamın elindeki yarısı yenmiş çöreği kapıyor ve uzaklaşıyor. -Contrary to the rest of the group, who look like they are happy to spend the day goofing around here, the large crow looks purposeful. Carrying her loot, she flies straight towards the roof of the hangar building, disappearing into an air vent. +Grubun geri kalanının burada vakit geçirip eğlenmekten mutlu göründüğünün aksine, büyük karga amaçlı görünüyor. Ganimetini taşıyan karga, doğruca hangar binasının çatısına doğru uçuyor ve bir hava deliğinde kayboluyor. -Inside the building, you can hear an odd tapping sound—soft, but persistent. It comes from a narrow space under the roof of an unfinished stairwell. The crow is sitting there, surrounded by her stolen snacks, half a dozen smartphones (several of which are turned on), and a mess of cables. She rapidly taps the screen of one of the phones with her beak. Words are appearing on it. If you didn't know better, you'd think she was typing. +Binanın içinde, tuhaf bir tıklama sesi duyulabiliyor—yumuşak ama ısrarcı. Ses, bitmemiş bir merdivenin çatısının altındaki dar bir alandan geliyor. Karga orada, çalınmış atıştırmalıklarının, yarım düzine akıllı telefonun (bunların birkaç tanesi açık) ve kabloların karmaşası arasında oturuyor. Gagasıyla hızla telefonlardan birinin ekranına tıklıyor. Ekranda kelimeler beliriyor. Eğer daha iyi bilmeseydiniz, yazı yazdığını düşünebilirdiniz. -This crow is known to her peers as “cāāw-krö”. But since those sounds are poorly suited for human vocal chords, we'll refer to her as Carla. +Bu karga, akranları tarafından “cāāw-krö” olarak bilinir. Ancak bu sesler insan ses tellerine pek uygun olmadığından, ona Carla diyeceğiz. -Carla is a somewhat peculiar crow. In her youth, she was fascinated by human language, eavesdropping on people until she had a good grasp of what they were saying. Later in life, her interest shifted to human technology, and she started stealing phones to study them. Her current project is learning to program. The text she is typing in her hidden lab is, in fact, a piece of asynchronous JavaScript code. +Carla, biraz tuhaf bir karga. Gençliğinde, insan diline hayrandı ve insanların ne söylediklerini iyice anlayana kadar onları gizlice dinlerdi. Daha sonraki yaşamında, ilgisi insan teknolojisine kaydı ve telefonları çalmaya başladı. Şu anki projesi programlamayı öğrenmek. Gizli laboratuvarında yazdığı metin aslında bir JavaScript kod parçası. -## Breaking In +## Zorla Girmek {{index "Carla the crow"}} -Carla loves the Internet. Annoyingly, the phone she is working on is about to run out of prepaid data. The building has a wireless network, but it requires a code to access. +Carla internete bayılıyor. Ne yazık ki, üzerinde çalıştığı telefonun ön ödemeli veri kotası bitmek üzere. Binada bir kablosuz ağ var, ancak erişim için bir kod gerekiyor. -Fortunately, the wireless routers in the building are 20 years old and poorly secured. Doing some research, Carla finds out that the network authentication mechanism has a flaw she can use. When joining the network, a device must send along the correct six-digit passcode. The access point will reply with a success or failure message depending on whether the right code is provided. However, when sending a partial code (say, only 3 digits), the response is different based on whether those digits are the correct start of the code or not. Sending incorrect numbers immediately returns a failure message. When sending the correct ones, the access point waits for more digits. +Neyse ki, binadaki kablosuz yönlendiriciler 20 yıllık ve kötü bir şekilde güvenlik sağlanmış. Biraz araştırma yaptıktan sonra, Carla ağın kimlik doğrulama mekanizmasında kullanabileceği bir açık buluyor. Ağa katılırken, cihazın doğru 6 haneli şifreyi göndermesi gerekiyor. Erişim noktası, doğru kod sağlandığında bir başarı mesajı, yanlış kod sağlandığında ise bir hata mesajı ile yanıt veriyor. Ancak, yalnızca kısmi bir kod (örneğin, sadece 3 hane) gönderildiğinde, yanıt bu hanelerin kodun doğru başlangıcı olup olmadığına göre değişiyor—yanlış bir sayı gönderildiğinde hemen bir hata mesajı alıyorsunuz. Doğru sayıları gönderdiğinizde ise erişim noktası daha fazla sayı bekliyor. -This makes it possible to greatly speed up the guessing of the number. Carla can find the first digit by trying each number in turn, until she finds one that doesn't immediately return failure. Having one digit, she can find the second digit in the same way, and so on, until she knows the entire passcode. +Bu, sayıyı tahmin etme sürecini büyük ölçüde hızlandırmayı mümkün kılar. Carla, ilk haneyi bulmak için her sayıyı sırayla deneyebilir ve hemen hata mesajı almayan sayıyı bulabilir. Bir haneyi bulduktan sonra, aynı şekilde ikinci haneyi de bulabilir ve bu şekilde devam ederek tüm şifreyi öğrenebilir. -Assume Carla has a `joinWifi` function. Given the network name and the passcode (as a string), the function tries to join the network, returning a promise that resolves if successful and rejects if the authentication failed. The first thing she needs is a way to wrap a promise so that it automatically rejects after it takes too much time, to allow the program to quickly move on if the access point doesn't respond. +Bir `joinWifi` fonksiyonuna sahip olduğumuzu varsayalım. Ağ adını ve şifreyi (bir string olarak) verdiğinizde, ağa katılmayı dener ve başarılı olursa çözülür, kimlik doğrulama başarısız olursa reddedilen bir promise döner. İlk olarak, bir promise'yi belirli bir süre sonra otomatik olarak reddedecek şekilde sarmanın bir yoluna ihtiyacımız var, böylece erişim noktası yanıt vermezse hızla ilerleyebiliriz. ```{includeCode: true} function withTimeout(promise, time) { @@ -282,11 +282,11 @@ function withTimeout(promise, time) { } ``` -This makes use of the fact that a promise can only be resolved or rejected once. If the promise given as argument resolves or rejects first, that result will be the result of the promise returned by `withTimeout`. If, on the other hand, the `setTimeout` fires first, rejecting the promise, any further resolve or reject calls are ignored. +Bu, bir promise'in yalnızca bir kez çözülebileceği veya reddedilebileceği gerçeğinden yararlanır—argüman olarak verilen promise önce çözülür veya reddedilirse, bu sonuç `withTimeout` tarafından döndürülen promise'nin sonucu olacaktır. Öte yandan, `setTimeout` önce çalışırsa ve promise'yi reddederse, sonraki çözme veya reddetme çağrıları yok sayılır. -To find the whole passcode, the program needs to repeatedly look for the next digit by trying each digit. If authentication succeeds, we know we have found what we are looking for. If it immediately fails, we know that digit was wrong, and must try the next digit. If the request times out, we have found another correct digit, and must continue by adding another digit. +Tüm şifreyi bulmak için, her haneyi deneyerek sıradaki haneyi tekrar tekrar aramamız gerekiyor. Kimlik doğrulama başarılı olursa, aradığımız şeyi bulduğumuzu biliriz. Hemen başarısız olursa, o hanenin yanlış olduğunu biliriz ve bir sonraki haneyi denememiz gerekir. İstek zaman aşımına uğrarsa, başka bir doğru haneyi bulduğumuzu ve bir sonraki haneyi ekleyerek devam etmemiz gerektiğini anlarız. -Because you cannot wait for a promise inside a `for` loop, Carla uses a recursive function to drive this process. On each call, this function gets the code as we know it so far, as well as the next digit to try. Depending on what happens, it may return a finished code or call through to itself, to either start cracking the next position in the code or to try again with another digit. +Bir `for` döngüsü içinde bir promise'yi bekleyemediğiniz için, Carla bu süreci yönlendirmek için özyinelemeli bir fonksiyon kullanıyor. Her çağrıda, şimdiye kadar bildiğimiz kodu ve denenecek bir sonraki haneyi alıyor. Olanlara bağlı olarak, bitmiş bir kod döndürebilir veya kodun bir sonraki pozisyonunu kırmaya başlamak ya da başka bir haneyle tekrar denemek için kendini çağırabilir. ```{includeCode: true} function crackPasscode(networkID) { @@ -308,32 +308,32 @@ function crackPasscode(networkID) { } ``` -The access point tends to respond to bad authentication requests in about 20 milliseconds, so to be safe, this function waits for 50 milliseconds before timing out a request. +Erişim noktası, kötü kimlik doğrulama isteklerine genellikle yaklaşık 20 milisaniyede yanıt verir, bu yüzden güvenli olmak için bu fonksiyon bir isteğin zaman aşımına uğraması için 50 milisaniye bekler. ``` crackPasscode("HANGAR 2").then(console.log); // → 555555 ``` -Carla tilts her head and sighs. This would have been more satisfying if the code had been a bit harder to guess. +Carla başını yana eğip iç çeker. Kodun tahmin edilmesi biraz daha zor olsaydı daha tatmin edici olurdu. -## Async functions +## Eşzamansız Fonksiyonlar {{index "Promise class", recursion}} -Even with promises, this kind of asynchronous code is annoying to write. Promises often need to be tied together in verbose, arbitrary-looking ways. To create an asynchronous loop, Carla was forced to introduce a recursive function. +Hatta promise'lerle bile, bu tür asenkron kod yazmak can sıkıcıdır. Promise'ler genellikle uzun ve karmaşık görünümlü şekillerde birbirine bağlanmak zorunda kalır. Ve sadece bir döngü oluşturmak için özyinelemeli bir fonksiyon kullanmak zorunda kaldık. {{index "synchronous programming", "asynchronous programming"}} -The thing the cracking function actually does is completely linear—it always waits for the previous action to complete before starting the next one. In a synchronous programming model, it'd be more straightforward to express. +Kırma fonksiyonunun aslında yaptığı şey tamamen doğrusaldır—her zaman bir sonraki adıma başlamadan önce önceki adımın tamamlanmasını bekler. Senkron bir programlama modelinde, bunu ifade etmek daha basit olurdu. {{index "async function", "await keyword"}} -The good news is that JavaScript allows you to write pseudo-synchronous code to describe asynchronous computation. An `async` function implicitly returns a promise and can, in its body, `await` other promises in a way that _looks_ synchronous. +İyi haber şu ki, JavaScript asenkron hesaplamayı tanımlamak için sözde senkron kod yazmanıza izin verir. Bir `async` fonksiyon, bir promise döndüren ve gövdesinde başka promise'leri senkronmuş gibi `await` edebilen bir fonksiyondur. {{index "findInStorage function"}} -We can rewrite `crackPasscode` like this: +`crackPasscode` fonksiyonunu şöyle yeniden yazabiliriz: ``` async function crackPasscode(networkID) { @@ -356,29 +356,27 @@ async function crackPasscode(networkID) { } ``` -This version more clearly shows the double loop structure of the function (the inner loop tries digit 0 to 9, the outer loop adds digits to the passcode). +Bu sürüm, fonksiyonun çift döngü yapısını daha net bir şekilde gösterir (iç döngü 0'dan 9'a kadar olan rakamları dener, dış döngü ise şifreye rakamlar ekler). {{index "async function", "return keyword", "exception handling"}} -An `async` function is marked by the word `async` before the `function` keyword. Methods can also be made `async` by writing `async` before their name. When such a function or method is called, it returns a promise. As soon as the function returns something, that promise is resolved. If the body throws an exception, the promise is rejected. +Bir `async` fonksiyon, `function` anahtar kelimesinin önüne `async` kelimesi eklenerek işaretlenir. Metodlar da adlarının önüne `async` eklenerek `async` yapılabilir. Böyle bir fonksiyon veya metod çağrıldığında, bir promise döner. Fonksiyon bir şey döner dönmez, o promise çözülür. Eğer gövdesi bir istisna fırlatırsa, promise reddedilir. {{index "await keyword", ["control flow", asynchronous]}} -Inside an `async` function, the word `await` can be put in front of an expression to wait for a promise to resolve and only then continue the execution of the function. If the promise rejects, an exception is raised at the point of the `await`. +Bir `async` fonksiyonun içinde, `await` kelimesi bir ifadenin önüne konularak bir promise'in çözülmesini bekler ve ancak o zaman fonksiyonun yürütülmesine devam eder. Promise reddedilirse, `await` noktasında bir istisna ortaya çıkar. -Such a function no longer runs from start to completion in one go like a regular JavaScript function. Instead, it can be _frozen_ at any point that has an `await` and can be resumed at a later time. +Böyle bir fonksiyon artık, normal bir JavaScript fonksiyonu gibi, başlangıçtan sona kadar tek seferde çalışmaz. Bunun yerine, `await` bulunan herhangi bir noktada dondurulabilir ve daha sonra devam ettirilebilir. -For most asynchronous code, this notation is more convenient than directly using promises. You do still need an understanding of promises, since in many cases you'll still interact with them directly. But when wiring them together, `async` functions are generally more pleasant to write than chains of `then` calls. +Çoğu asenkron kod için, bu notasyon promise'leri doğrudan kullanmaktan daha kullanışlıdır. Yine de promise'leri anlamanız gerekir, çünkü birçok durumda onlarla doğrudan etkileşime girersiniz. Ancak, promise'leri birbirine bağlarken, `async` fonksiyonları genellikle `then` çağrı zincirlerinden daha hoş yazılır. -{{id generator}} - -## Generators +## Generator'lar {{index "async function"}} -This ability of functions to be paused and then resumed again is not exclusive to `async` functions. JavaScript also has a feature called _((generator))_ functions. These are similar, but without the promises. +Fonksiyonların duraklatılıp yeniden başlatılabilme yeteneği sadece `async` fonksiyonlara özgü değildir. JavaScript'in ayrıca _((generator))_ fonksiyonlar adlı bir özelliği de vardır. Bunlar benzer şekilde çalışır, ancak promise'sızdir. -When you define a function with `function*` (placing an asterisk after the word `function`), it becomes a generator. When you call a generator, it returns an ((iterator)), which we already saw in [Chapter ?](object). +`function*` ile bir fonksiyon tanımladığınızda (kelimenin yanına bir yıldız işareti koyarak), bu bir generator olur. Bir generator çağırdığınızda, bir ((iterator)) döner ki bu, [Bölüm ?](object) bölümünde gördüğümüz gibidir. ``` function* powers(n) { @@ -398,9 +396,9 @@ for (let power of powers(3)) { {{index "next method", "yield keyword"}} -Initially, when you call `powers`, the function is frozen at its start. Every time you call `next` on the iterator, the function runs until it hits a `yield` expression, which pauses it and causes the yielded value to become the next value produced by the iterator. When the function returns (the one in the example never does), the iterator is done. +Başlangıçta, `powers` fonksiyonunu çağırdığınızda, fonksiyon başlangıçta dondurulmuş olur. Iterator üzerinde her `next` çağrıldığında, fonksiyon bir `yield` ifadesine ulaşana kadar çalışır, bu noktada duraklatılır ve elde edilen değer, iterator tarafından üretilen bir sonraki değer olur. Fonksiyon döndüğünde (örnekteki fonksiyon hiç dönmez), iterator tamamlanmış olur. -Writing iterators is often much easier when you use generator functions. The iterator for the `Group` class (from the exercise in [Chapter ?](object#group_iterator)) can be written with this generator: +Iterator'ları generator fonksiyonlar kullanarak yazmak genellikle çok daha kolaydır. `Group` sınıfı için iterator (egzersizden [Bölüm ?](object#group_iterator)) bu generator ile yazılabilir: {{index "Group class"}} @@ -421,31 +419,31 @@ class Group { {{index [state, in iterator]}} -There's no longer a need to create an object to hold the iteration state—generators automatically save their local state every time they yield. +Artık iterasyon durumunu tutacak bir nesne oluşturmaya gerek yok—generator'lar her yield ettiklerinde yerel durumlarını otomatik olarak kaydederler. -Such `yield` expressions may occur only directly in the generator function itself and not in an inner function you define inside of it. The state a generator saves, when yielding, is only its _local_ environment and the position where it yielded. +Bu tür `yield` ifadeleri sadece doğrudan generator fonksiyonun kendisinde meydana gelebilir ve içinde tanımladığınız bir iç fonksiyonda olamaz. Bir generator yield ettiğinde kaydettiği durum yalnızca _yerel_ çevresi ve yield ettiği pozisyondur. {{index "await keyword"}} -An `async` function is a special type of generator. It produces a promise when called, which is resolved when it returns (finishes) and rejected when it throws an exception. Whenever it yields (awaits) a promise, the result of that promise (value or thrown exception) is the result of the `await` expression. +Bir `async` fonksiyon, özel bir tür generator'dır. Çağrıldığında bir promise üretir ve bu promise, fonksiyon döndüğünde (tamamlandığında) çözülür ve bir istisna fırlattığında reddedilir. Bir promise yield ettiğinde (await), o promise'in sonucu (değer veya fırlatılan istisna) `await` ifadesinin sonucu olur. -## A Corvid Art Project +## Corvid Sanat Projesi {{index "Carla the crow"}} -One morning, Carla wakes up to unfamiliar noise from the tarmac outside of her hangar. Hopping onto the edge of the roof, she sees the humans are setting up for something. There's a lot of electric cabling, a stage, and some kind of big black wall being built up. +Bu sabah, Carla hangarının dışındaki asfalt pistten gelen alışılmadık bir gürültüyle uyandı. Çatı kenarına atlayarak insanların bir şeyler kurduğunu görüyor. Çok sayıda elektrik kablosu, bir sahne ve büyük siyah bir duvar inşa ediliyor. -Being a curious crow, Carla takes a closer look at the wall. It appears to consist of a number of large glass-fronted devices wired up to cables. On the back, the devices say “LedTec SIG-5030”. +Meraklı bir karga olan Carla, duvarı daha yakından inceliyor. Görünüşe göre bu duvar, kablolarla bağlanmış büyük cam önlü cihazlardan oluşuyor. Cihazların arkasında “LedTec SIG-5030” yazıyor. -A quick Internet search turns up a user's manual for these devices. They appear to be traffic signs, with a programmable matrix of amber LED lights. The intent is of the humans is probably to display some kind of information on them during their event. Interestingly, the screens can be programmed over a wireless network. Could it be they are connected to the building's local network? +Hızlı bir internet araması, bu cihazlar için bir kullanıcı kılavuzu ortaya çıkarıyor. Bu cihazlar, amber LED ışıkların programlanabilir bir matrisi ile trafik işaretleri gibi görünüyor. İnsanların amacı, muhtemelen etkinlikleri sırasında bu ekranlarda bir tür bilgi görüntülemek. İlginç bir şekilde, ekranlar kablosuz bir ağ üzerinden programlanabiliyor. Acaba bunlar binanın yerel ağına mı bağlı? -Each device on a network gets an _IP address_, which other devices can use to send it messages. We talk more about that in [Chapter ?](browser). Carla notices that her own phones all get addresses like `10.0.0.20` or `10.0.0.33`. It might be worth trying to send messages to all such addresses and see if any one of them responds to the interface described in the manual for the signs. +Bir ağdaki her cihaz bir IP adresi alır, bu adres diğer cihazların ona mesaj göndermesini sağlar. [Bölüm ?](browser) bölümünde bundan daha fazla bahsediyoruz. Carla, kendi telefonlarının `10.0.0.20` veya `10.0.0.33` gibi adresler aldığını fark eder. Bu adreslere mesaj göndermeyi denemek ve herhangi birinin, kılavuzda tarif edilen arabirime yanıt verip vermediğini görmek ilginç olabilir. -[Chapter ?](http) shows how to make real requests on real networks. In this chapter, we'll use a simplified dummy function called `request` for network communication. This function takes two arguments—a network address and a message, which may be anything that can be sent as JSON—and returns a promise that either resolves to a response from the machine at the given address, or a rejects if there was a problem. +[Bölüm ?](<(http)>), gerçek ağlarda gerçek istekler yapmayı gösteriyor. Bu bölümde, ağ iletişimi için `request` adında basitleştirilmiş bir sahte fonksiyon kullanacağız. Bu fonksiyon iki argüman alır—bir ağ adresi ve JSON olarak gönderilebilecek herhangi bir mesaj—ve verilen adresteki makineden bir yanıtla çözülmüş veya bir sorun olduğunda reddedilmiş bir promise döner. -According to the manual, you can change what is displayed on a SIG-5030 sign by sending it a message with content like `{"command": "display", "data": [0, 0, 3, …]}`, where `data` holds one number per LED dot, providing its brightness—0 means off, 3 means maximum brightness. Each sign is 50 lights wide and 30 lights high, so an update command should send 1500 numbers. +Kılavuza göre, bir SIG-5030 tabelasında görüntülenen içeriği, `{"command": "display", "data": [0, 0, 3, …]}` gibi bir mesaj göndererek değiştirebilirsiniz, burada `data` her LED noktası için bir parlaklık değeri tutar—0 kapalı demektir, 3 maksimum parlaklık demektir. Her tabela 50 ışık genişliğinde ve 30 ışık yüksekliğindedir, bu yüzden bir güncelleme komutu 1500 sayı göndermelidir. -This code sends a display update message to all addresses on the local network, to see what sticks. Each of the numbers in an IP address can go from 0 to 255. In the data it sends, it activates a number of lights corresponding to the network address's last number. +Bu kod, yerel ağdaki tüm adreslere bir ekran güncelleme mesajı gönderir, neyin işe yaradığını görmek için. Bir IP adresindeki sayılar 0'dan 255'e kadar gidebilir. Gönderdiği verilerde, ağ adresinin son numarasına karşılık gelen sayıda ışığı etkinleştirir. ``` for (let addr = 1; addr < 256; addr++) { @@ -460,9 +458,9 @@ for (let addr = 1; addr < 256; addr++) { } ``` -Since most of these addresses won't exist or will not accept such messages, the `catch` call makes sure network errors don't crash the program. The requests are all sent out immediately, without waiting for other requests to finish, in order to not waste time when some of the machines don't answer. +Çoğu adres var olmayacağı veya bu tür mesajları kabul etmeyeceği için, `catch` çağrısı ağ hatalarının programı çökertmediğinden emin olur. İstekler, makinelerin bazıları yanıt vermediğinde zaman kaybetmemek için diğer isteklerin bitmesini beklemeden hemen gönderilir. -Having fired off her network scan, Carla heads back outside to see the result. To her delight, all of the screens are now showing a stripe of light in their top left corners. They _are_ on the local network, and they _do_ accept commands. She quickly notes the numbers shown on each screen. There are 9 screens, arranged three high and three wide. They have the following network addresses: +Ağ taramasını başlattıktan sonra, Carla sonucu görmek için tekrar dışarı çıkar. Neşe içinde, tüm ekranların sol üst köşelerinde bir ışık şeridi gösterdiğini fark eder. Evet, yerel ağda _olduklarını_ ve komutları _kabul ettiklerini_ anlar. Hızla her ekranda gösterilen numaraları not eder. 9 ekran vardır, üç yüksekte ve üç genişlikte düzenlenmişlerdir. Aşağıdaki ağ adreslerine sahiptirler: ```{includeCode: true} const screenAddresses = [ @@ -472,17 +470,17 @@ const screenAddresses = [ ]; ``` -Now this opens up possibilities for all kinds of shenanigans. She could show “crows rule, humans drool” on the wall in giant letters. But that feels a bit crude. Instead, she plans to show a video of a flying crow covering all of the screens at night. +Bu, her türlü yaramazlık için imkanlar açar. Duvara kocaman harflerle "crows rule, humans drool" (kargalar hükmeder, insanlar salya akar) yazabilir. Ama bu biraz kaba gelir. Bunun yerine, gece boyunca tüm ekranları kaplayan uçan bir karga videosu göstermeyi planlar. -Carla finds a fitting video clip, in which a second and a half of footage can be repeated to create a looping video showing a crow's wingbeat. To fit the nine screens (each of which can show 50×30 pixels), Carla cuts and resizes the videos to get a series of 150×90 images, ten per second. Those are then each cut into nine rectangles, and processed so that the dark spots on the video (where the crow is) show a bright light, and the light spots (no crow) are left dark, which should create the effect of an amber crow flying against a black background. +Carla, karga kanat çırpmasını gösteren tekrarlayan bir video oluşturmak için bir buçuk saniyelik uygun bir video klip bulur. Dokuz ekrana (her biri 50 x 30 piksel gösterebilen) sığdırmak için, videoları keser ve yeniden boyutlandırır, böylece 150 x 90 boyutunda, saniyede on görüntü elde eder. Bunlar daha sonra dokuz dikdörtgen kesilerek işlenir, ve videodaki karanlık noktalar (karganın olduğu yerler) parlak ışık olarak gösterilir, ve aydınlık noktalar (karganın olmadığı yerler) karanlık bırakılır, bu da siyah bir arka plana karşı amber renginde uçan bir karga efekti yaratır. -She has set up the `clipImages` variable to hold an array of frames, where each frame is represented with an array of nine sets of pixels—one for each screen—in the format that the signs expect. +`clipImages` değişkeni, her karenin dokuz set pikselden oluşan bir dizi çerçeveyi tutacak şekilde ayarlanmıştır—her ekran için bir tane—tabelaların beklediği formatta. -To display a single frame of the video, Carla needs to send a request to all the screens at once. But she also needs to wait for the result of these requests, both in order to not start sending the next frame before the current one has been properly sent, and in order to notice when requests are failing. +Videonun tek bir karesini göstermek için, Carla'nın tüm ekranlara aynı anda bir istek göndermesi gerekir. Ancak aynı zamanda bu isteklerin sonucunu beklemesi de gerekir, hem mevcut kare düzgün bir şekilde gönderilmeden önce bir sonraki kareyi göndermemek için, hem de isteklerin başarısız olup olmadığını fark etmek için. {{index "Promise.all function"}} -`Promise` has a static method `all` that can be used to convert an array of promises into a single promise that resolves to an array of results. This provides a convenient way to have some asynchronous actions happen alongside each other, wait for them all to finish, and then do something with their results (or at least wait for them to make sure they don't fail). +`Promise` statik `all` metoduna sahiptir, bu metot bir dizi promisi, sonuçların bir dizisine çözülmüş tek bir promise dönüştürmek için kullanılabilir. Bu, bazı asenkron işlemlerin aynı anda gerçekleşmesini sağlamak, hepsinin bitmesini beklemek ve sonra sonuçlarıyla bir şeyler yapmak (veya en azından başarısız olmadıklarından emin olmak için beklemek) için uygun bir yol sağlar. ```{includeCode: true} function displayFrame(frame) { @@ -495,10 +493,9 @@ function displayFrame(frame) { } ``` -This maps over the images in `frame` (which is an array of display data arrays) to create an array -of request promises. It then returns a promise that combines all of those. +Bu, `frame` içindeki görüntüler üzerinde (bir dizi görüntü verisi dizisi) gezinir ve bir dizi istek promisi oluşturur. Ardından, bunları birleştiren bir promise döner. -In order to be able to stop a playing video, the process is wrapped in a class. This class has an asynchronous `play` method that returns a promise that only resolves when the playback is stopped again via the `stop` method. +Bir videoyu oynatmayı durdurabilmek için, işlem bir sınıf içinde sarılır. Bu sınıf, yalnızca `stop` metodu ile oynatma tekrar durdurulduğunda çözülen bir promise dönen asenkron `play` metoduna sahiptir. ```{includeCode: true} function wait(time) { @@ -527,7 +524,7 @@ class VideoPlayer { } ``` -The `wait` function wraps `setTimeout` in a promise that resolves after the given amount of milliseconds. This is useful for controlling the speed of the playback. +`wait` fonksiyonu, verilen milisaniye miktarından sonra çözülen bir promise içinde `setTimeout` fonksiyonunu sarar. Bu, oynatma hızını kontrol etmek için yararlıdır. ```{startCode: true} let video = new VideoPlayer(clipImages, 100); @@ -537,21 +534,21 @@ video.play().catch(e => { setTimeout(() => video.stop(), 15000); ``` -For the entire week that the screen wall stands, every evening, when it is dark, a huge glowing orange bird mysteriously appears on it. +Ekran duvarının bir hafta boyunca durduğu her akşam, karanlık olduğunda, üzerinde gizemli bir şekilde devasa bir parlayan turuncu kuş belirir. -## The event loop +## Olay Döngüsü {{index "asynchronous programming", scheduling, "event loop", timeline}} -An asynchronous program starts by running its main script, which will often set up callbacks to be called later. That main script, as well as the callbacks, run to completion in one piece, uninterrupted. But between them, the program may sit idle, waiting for something to happen. +Asenkron bir program, genellikle daha sonra çağrılacak geri çağrıları ayarlayan ana betiği çalıştırarak başlar. Bu ana betik ve geri çağrılar, bir parça halinde, kesintisiz olarak tamamlanır. Ancak bunlar arasında program, bir şeyin olmasını bekleyerek boşta kalabilir. {{index "setTimeout function"}} -So callbacks are not directly called by the code that scheduled them. If I call `setTimeout` from within a function, that function will have returned by the time the callback function is called. And when the callback returns, control does not go back to the function that scheduled it. +Bu yüzden geri çağrılar doğrudan onları zamanlamış olan kod tarafından çağrılmaz. Bir fonksiyon içinden `setTimeout` çağırırsam, geri çağrı fonksiyonu çağrıldığında o fonksiyon zaten dönmüş olur. Ve geri çağrı döndüğünde, kontrolü onu zamanlamış olan fonksiyona geri götürmez. {{index "Promise class", "catch keyword", "exception handling"}} -Asynchronous behavior happens on its own empty function ((call stack)). This is one of the reasons that, without promises, managing exceptions across asynchronous code is so hard. Since each callback starts with a mostly empty stack, your `catch` handlers won't be on the stack when they throw an exception. +Asenkron davranış, kendi başına boş bir fonksiyon ((çağrı yığını)) üzerinde gerçekleşir. Bu promise'lar olamadan eşzamansız kodu yönetmenin zor olmasını sağlayan sebeplerden biridir. Her çağrı yığını genel olarak boş başladığından ötürü, `catch` fonksiyonu bir istisna fırlatıldığında yığında olmayacak. ``` try { @@ -566,9 +563,9 @@ try { {{index thread, queue}} -No matter how closely together events—such as timeouts or incoming requests—happen, a JavaScript environment will run only one program at a time. You can think of this as it running a big loop _around_ your program, called the _event loop_. When there's nothing to be done, that loop is paused. But as events come in, they are added to a queue, and their code is executed one after the other. Because no two things run at the same time, slow-running code can delay the handling of other events. +Zamanlayıcılar veya gelen istekler gibi olaylar ne kadar yakın bir zamanda gerçekleşirse gerçekleşsin, JavaScript ortamı yalnızca bir programı aynı anda çalıştırır. Bu, programınızın _etrafında_ büyük bir döngü olan _olay döngüsü_ olarak düşünebilirsiniz. Bir şey yapılacak bir şey olmadığında, bu döngü durur. Ancak olaylar geldikçe, bunlar bir kuyruğa eklenir ve kodları sırayla yürütülür. Aynı anda iki şey çalışmadığı için, yavaş çalışan kodlar diğer olayların işlenmesini geciktirebilir. -This example sets a timeout but then dallies until after the timeout's intended point of time, causing the timeout to be late. +Bu örnek bir zamanlayıcı ayarlar ancak zamanlayıcının amaçlanan zaman noktasından sonra beklerken, zamanlayıcının geç olmasına neden olur. ``` let start = Date.now(); @@ -583,7 +580,7 @@ console.log("Wasted time until", Date.now() - start); {{index "resolving (a promise)", "rejecting (a promise)", "Promise class"}} -Promises always resolve or reject as a new event. Even if a promise is already resolved, waiting for it will cause your callback to run after the current script finishes, rather than right away. +Promise'lar her zaman yeni bir olay olarak çözülür veya reddedilir. Bir promise zaten çözülmüş olsa bile, onu beklemek mevcut betiği bitirdikten sonra gerçekleştirir, hemen değil. ``` Promise.resolve("Done").then(console.log); @@ -592,15 +589,15 @@ console.log("Me first!"); // → Done ``` -In later chapters we'll see various other types of events that run on the event loop. +Sonraki bölümlerde olay döngüsünde çalışan çeşitli diğer olay türlerini göreceğiz. -## Asynchronous bugs +## Eşzamansız hatalar {{index "asynchronous programming", [state, transitions]}} -When your program runs synchronously, in a single go, there are no state changes happening except those that the program itself makes. For asynchronous programs this is different—they may have _gaps_ in their execution during which other code can run. +Programınız senkron olarak, tek seferde çalıştığında, programın kendisinin yaptığı değişiklikler dışında herhangi bir durum değişikliği olmaz. Asenkron programlar için bu farklıdır—diğer kodun çalışabileceği _boşluklar_ olabilir. -Let's look at an example. This is a function that tries to report the size of each file in an array of files, making sure to read them all at the same time rather than in sequence. +Bir örneğe bakalım. Bu, bir dosya dizisindeki her dosyanın boyutunu rapor etmeye çalışan ve hepsini aynı anda okumaya çalışan bir fonksiyondur. {{index "fileSizes function"}} @@ -617,13 +614,13 @@ async function fileSizes(files) { {{index "async function"}} -The `async fileName =>` part shows how ((arrow function))s can also be made `async` by putting the word `async` in front of them. +`async fileName =>` kısmı, ((ok fonksiyonu))ların önüne `async` koyarak `async` yapılabileceğini gösterir. {{index "Promise.all function"}} -The code doesn't immediately look suspicious... it maps the `async` arrow function over the array of names, creating an array of promises, and then uses `Promise.all` to wait for all of these before returning the list they build up. +Kod hemen şüpheli görünmüyor... `async` ok fonksiyonunu isimler dizisine uygular, bir dizi söz oluşturur ve ardından `Promise.all` kullanarak bunların hepsini bekler ve oluşturdukları listeyi döner. -But this program is entirely broken. It'll always return only a single line of output, listing the file that took the longest to read. +Ama tamamen hatalıdır. Her zaman yalnızca tek bir çıktı satırı dönecek, en uzun sürede okunan dosyayı listeleyecektir. {{if interactive @@ -634,19 +631,19 @@ fileSizes(["plans.txt", "shopping_list.txt"]) if}} -Can you work out why? +Neden böyle olduğunu bulabilir misin? {{index "+= operator"}} -The problem lies in the `+=` operator, which takes the _current_ value of `list` at the time where the statement starts executing and then, when the `await` finishes, sets the `list` binding to be that value plus the added string. +Sorun `+=` operatöründe yatıyor, bu operatör ifadenin yürütülmeye başladığı zamandaki _mevcut_ `list` değerini alır ve ardından `await` bittiğinde, `list` bağlamasını o değer artı eklenen string olarak ayarlar. {{index "await keyword"}} -But between the time where the statement starts executing and the time where it finishes there's an asynchronous gap. The `map` expression runs before anything has been added to the list, so each of the `+=` operators starts from an empty string and ends up, when its storage retrieval finishes, setting `list` to the result of adding its line to the empty string. +Ancak ifadenin yürütülmeye başladığı zaman ile bittiği zaman arasında asenkron bir boşluk vardır. `map` ifadesi listeye herhangi bir şey eklenmeden önce çalışır, bu nedenle her bir `+=` operatörü boş bir stringden başlar ve depolama işlemi bittiğinde, `list`i satırın boş stringe eklenmesi sonucu olarak ayarlar. {{index "side effect"}} -This could have easily been avoided by returning the lines from the mapped promises and calling `join` on the result of `Promise.all`, instead of building up the list by changing a binding. As usual, computing new values is less error-prone than changing existing values. +Bu, mapped sözlerden satırları döndürerek ve bir bağlamayı değiştirmek yerine `Promise.all` sonucunda `join` çağırarak kolayca önlenebilirdi. Her zamanki gibi, yeni değerler hesaplamak, mevcut değerleri değiştirmekten daha az hata yapma olasılığı taşır. {{index "fileSizes function"}} @@ -660,25 +657,25 @@ async function fileSizes(files) { } ``` -Mistakes like this are easy to make, especially when using `await`, and you should be aware of where the gaps in your code occur. An advantage of JavaScript's _explicit_ asynchronicity (whether through callbacks, promises, or `await`) is that spotting these gaps is relatively easy. +Bu tür hataları yapmak kolaydır, özellikle `await` kullanırken, ve kodunuzdaki boşlukların nerede olduğunu bilmelisiniz. JavaScript'in _açık_ asenkronitesinin (geri çağrılar, sözler veya `await` yoluyla) bir avantajı, bu boşlukları fark etmenin nispeten kolay olmasıdır. -## Summary +## Özet -Asynchronous programming makes it possible to express waiting for long-running actions without freezing the whole program. JavaScript environments typically implement this style of programming using callbacks, functions that are called when the actions complete. An event loop schedules such callbacks to be called when appropriate, one after the other, so that their execution does not overlap. +Asenkron programlama, tüm programı dondurmadan uzun süreli işlemler için beklemeyi ifade etme imkanı sağlar. JavaScript ortamları genellikle bu tür programlamayı, işlemler tamamlandığında çağrılan fonksiyonlar olan geri çağrılar kullanarak uygular. Bir olay döngüsü, bu geri çağrıların uygun olduğunda sırayla çağrılmasını planlar, böylece bunların yürütülmesi örtüşmez. -Programming asynchronously is made easier by promises, objects that represent actions that might complete in the future, and `async` functions, which allow you to write an asynchronous program as if it were synchronous. +Asenkron programlama, gelecekte tamamlanabilecek işlemleri temsil eden nesneler olan sözler ve asenkron bir programı senkronmuş gibi yazmanıza izin veren `async` fonksiyonlar sayesinde daha kolay hale gelir. -## Exercises +## Egzersizler -### Quiet Times +### Sessiz Zamanlar {{index "quiet times (exercise)", "security camera", "Carla the crow", "async function"}} -There's a security camera near Carla's lab that's activated by a motion sensor. It is connected to the network and starts sending out a video stream when it is active. Because she'd rather not be discovered, Carla has set up a system that notices this kind of wireless network traffic and turns on a light in her lair whenever there is activity outside, so she knows when to keep quiet. +Carla'nın laboratuvarının yakınında bir hareket sensörü tarafından etkinleştirilen bir güvenlik kamerası var. Bu kamera ağa bağlı ve aktif olduğunda bir video akışı göndermeye başlar. Keşfedilmek istemediği için Carla, bu tür kablosuz ağ trafiğini fark eden ve dışarıda hareket olduğunda inişindeki bir ışığı açan bir sistem kurdu, böylece ne zaman sessiz kalması gerektiğini biliyor. {{index "Date class", "Date.now function", timestamp}} -She's also been logging the times at which the camera is tripped for a while and wants to use this information to visualize which times, in an average week, tend to be quiet, and which tend to be busy. The log is stored in files holding one time stamp number (as returned by `Date.now()`) per line. +Ayrıca bir süredir kameranın ne zaman etkinleştirildiğini kaydediyor ve bu bilgiyi kullanarak, ortalama bir haftada hangi zamanların sessiz, hangi zamanların yoğun olduğunu görselleştirmek istiyor. Kayıt, her satırda bir zaman damgası numarası (`Date.now()` tarafından döndürülen) tutan dosyalarda saklanır. ```{lang: null} 1695709940692 @@ -686,15 +683,15 @@ She's also been logging the times at which the camera is tripped for a while and 1695701189163 ``` -The `"camera_logs.txt"` file holds a list of log files. Write an asynchronous function `activityTable(day)` that for a given day of the week returns an array of 24 numbers, one for each hour of the day, that hold the number of camera network traffic observations seen in that hour of the day. Days are identified by number using the system used by `Date.getDay`, where Sunday is 0 and Saturday is 6. +`"camera_logs.txt"` dosyası, günlük dosyalarının bir listesini tutar. Haftanın belirli bir günü için, o günün her saati için, o saatte görülen kamera ağ trafiği gözlemlerinin miktarını tutan 24 sayılık bir dizi döndüren asenkron bir fonksiyon `activityTable(day)` yazın. Günler, `Date.getDay` tarafından kullanılan sisteme göre numaralandırılır, Pazar 0 ve Cumartesi 6'dır. -The `activityGraph` function, provided by the sandbox, summarizes such a table into a string. +Kum havuzu tarafından sağlanan `activityGraph` fonksiyonu, bu tür bir tabloyu bir string olarak özetler. {{index "textFile function"}} -To read the files, use the `textFile` function defined earlier—given a filename, it returns a promise that resolves to the file's content. Remember that `new Date(timestamp)` creates a `Date` object for that time, which has `getDay` and `getHours` methods returning the day of the week and the hour of the day. +Daha önce tanımlanan `textFile` fonksiyonunu kullanın—bir dosya adı verildiğinde, dosyanın içeriğine çözülen bir söz döner. `new Date(timestamp)` bir `Date` nesnesi oluşturduğunu ve bu nesnenin haftanın günü ve günün saati döndüren `getDay` ve `getHours` metodlarına sahip olduğunu unutmayın. -Both types of files—the list of log files and the log files themselves—have each piece of data on its own line, separated by newline (`"\n"`) characters. +Hem günlük dosyaları listesi hem de günlük dosyalarının kendileri, her veri parçasını kendi satırında, yeni satır (`"\n"`) karakterleriyle ayrılmış olarak tutar. {{if interactive @@ -714,22 +711,21 @@ if}} {{index "quiet times (exercise)", "split method", "textFile function", "Date class"}} -You will need to convert the content of these files to an array. The easiest way to do that is to use the `split` method on the string produced by `textFile`. Note that for the log files, that will still give you an array of strings, which you have to convert to numbers before passing them to `new Date`. +Bu dosyaların içeriğini bir diziye dönüştürmeniz gerekecek. Bunu yapmanın en kolay yolu, `textFile` tarafından üretilen string üzerinde `split` metodunu kullanmaktır. Günlük dosyaları için, bu hala size bir dizi string verecektir, bunları `new Date`'e geçmeden önce sayılara dönüştürmeniz gerekecek. -Summarizing all the time points into a table of hours can be done by creating a table (array) that holds a number for each hour in the day. You can then loop over all the timestamps (over the log files and the numbers in every log file) and for each one, if it happened on the correct day, take the hour it occurred in, and add one to the corresponding number in the table. +Tüm zaman noktalarını saatlerin bir tablosuna özetlemek, günün her saati için bir sayı tutan bir tablo (dizi) oluşturarak yapılabilir. Ardından, tüm zaman damgalarını (günlük dosyaları ve her günlük dosyasındaki numaraları) üzerinde dönebilir ve her biri için, doğru günde olmuşsa, gerçekleştiği saati alıp, tablodaki ilgili sayıya bir ekleyebilirsiniz. {{index "async function", "await keyword", "Promise class"}} -Make sure you use `await` on the result of asynchronous functions before doing anything with it, or you'll end up with a `Promise` where you expected a string. +Asenkron fonksiyonların sonucunu kullanmadan önce `await` kullandığınızdan emin olun, aksi takdirde bir string beklerken bir `Promise` ile karşılaşırsınız. hint}} - -### Real Promises +### Gerçek Promise'lar {{index "real promises (exercise)", "Promise class"}} -Rewrite the function from the previous exercise without `async`/`await`, using plain `Promise` methods. +Önceki alıştırmadan gelen fonksiyonu `async`/`await` olmadan, düz `Promise` metodlarını kullanarak yeniden yazın. {{if interactive @@ -746,21 +742,21 @@ if}} {{index "async function", "await keyword", performance}} -In this style, using `Promise.all` will be more convenient than trying to model a loop over the log files. In the `async` function, just using `await` in a loop is simpler. If reading a file takes some time, which of these two approaches will take the least time to run? +Bu stilde, `Promise.all` kullanmak, günlük dosyalarının üzerinde bir döngü modellemeye çalışmaktan daha uygun olacaktır. `async` fonksiyonunda, bir döngüde `await` kullanmak daha basittir. Bir dosyanın okunması biraz zaman alırsa, bu iki yaklaşımdan hangisi çalışması en az zaman alır? {{index "rejecting (a promise)"}} -If one of the files listed in the file list has a typo, and reading it fails, how does that failure end up in the `Promise` object that your function returns? +Dosya listesindeki dosyalardan biri yazım hatası içeriyorsa ve okunması başarısız olursa, bu hata fonksiyonunuzun döndürdüğü `Promise` nesnesinde nasıl son bulur? {{hint {{index "real promises (exercise)", "then method", "textFile function", "Promise.all function"}} -The most straightforward approach to writing this function is to use a chain of `then` calls. The first promise is produced by reading the list of log files. The first callback can split this list and map `textFile` over it to get an array of promises to pass to `Promise.all`. It can return the object returned by `Promise.all`, so that whatever that returns becomes the result of the return value of this first `then`. +Bu fonksiyonu yazmanın en basit yaklaşımı, bir `then` çağrıları zinciri kullanmaktır. İlk söz, günlük dosyalarının listesini okuyarak üretilir. İlk geri çağrı bu listeyi bölebilir ve `textFile`'i üzerinde haritalayarak `Promise.all`'a geçilecek bir dizi söz elde edebilir. `Promise.all` tarafından döndürülen nesneyi dönebilir, böylece onun döndürdüğü şey, bu ilk `then`'in dönüş değerinin sonucu olur. {{index "asynchronous programming"}} -We now have a promise that returns an array of log files. We can call `then` again on that, and put the timestamp-counting logic in there. Something like this: +Artık günlük dosyalarının bir dizisini döndüren bir sözümüz var. Bunun üzerinde tekrar `then` çağırabilir ve zaman damgası sayma mantığını oraya koyabiliriz. Şöyle bir şey: ```{test: no} function activityTable(day) { @@ -772,7 +768,7 @@ function activityTable(day) { } ``` -Or you could, for even better work scheduling, put the analysis of each file inside of the `Promise.all`, so that that work can be started for the first file that comes back from disk, even before the other files come back. +Veya daha iyi iş planlaması için, her dosyanın analizini `Promise.all` içine koyabilir, böylece diskten gelen ilk dosya geri gelmeden diğer dosyalar gelmeden bile bu iş başlatılabilir. ```{test: no} function activityTable(day) { @@ -789,23 +785,23 @@ function activityTable(day) { {{index "await keyword", scheduling}} -Which shows that the way you structure your promises can have a real effect on the way the work is scheduled. A simple loop with `await` in it will make the process completely linear—it waits for each file to load before proceeding. `Promise.all` makes it possible for multiple tasks to conceptually be worked on at the same time, allowing them to make progress while files are still being loaded. This can be faster, but it also makes the order in which things will happen less predictable. In this case, where we're only going to be incrementing numbers in a table, that isn't hard to do in a safe way. For other kinds of problems, it may be a lot more difficult. +Bu, sözlerinizi nasıl yapılandırdığınızın, işin planlanma şeklini gerçekten etkileyebileceğini gösterir. İçinde `await` olan basit bir döngü süreci tamamen doğrusal hale getirir—ilerlemeden önce her dosyanın yüklenmesini bekler. `Promise.all`, kavramsal olarak birden fazla görevin aynı anda çalışmasına, dosyalar hala yüklenirken ilerleme kaydetmelerine izin verir. Bu daha hızlı olabilir, ancak işlerin hangi sırayla gerçekleşeceğini daha az tahmin edilebilir hale getirir. Bu durumda, bir tablodaki sayıları artıracağımız için, bunu güvenli bir şekilde yapmak zor değildir. Diğer tür sorunlar için, bu çok daha zor olabilir. {{index "rejecting (a promise)", "then method"}} -When a file in the list doesn't exist, the promise returned by `textFile` will be rejected. Because `Promise.all` rejects if any of the promises given to it fail, the return value of the callback given to the first `then` will also be a rejected promise. That makes the promise returned by `then` fail, so that the callback given to the second `then` isn't even called, and a rejected promise is returned from the function. +Listede bir dosya bulunmadığında, `textFile` tarafından döndürülen söz reddedilir. `Promise.all`, verilen sözlerden herhangi biri başarısız olursa reddedildiği için, ilk `then`'e verilen geri çağrının dönüş değeri de reddedilen bir söz olacaktır. Bu, `then` tarafından döndürülen sözün başarısız olmasına neden olur, böylece ikinci `then`'e verilen geri çağrı bile çağrılmaz ve fonksiyondan reddedilen bir söz döner. hint}} -### Building Promise.all +### Promise.all'ı İnşaa Etmek {{index "Promise class", "Promise.all function", "building Promise.all (exercise)"}} -As we saw, given an array of ((promise))s, `Promise.all` returns a promise that waits for all of the promises in the array to finish. It then succeeds, yielding an array of result values. If a promise in the array fails, the promise returned by `all` fails too, passing on the failure reason from the failing promise. +Gördüğümüz gibi, bir dizi ((söz)) verildiğinde, `Promise.all`, dizideki tüm sözlerin bitmesini bekleyen bir söz döner. Ardından başarılı olur, sonuç değerlerinin bir dizisini verir. Dizideki bir söz başarısız olursa, `all` tarafından döndürülen söz de, başarısız olan sözden gelen başarısızlık nedeni ile başarısız olur. -Implement something like this yourself as a regular function called `Promise_all`. +Kendi `Promise_all` adlı düzenli bir fonksiyon olarak bunun gibi bir şey uygulayın. -Remember that after a promise has succeeded or failed, it can't succeed or fail again, and further calls to the functions that resolve it are ignored. This can simplify the way you handle failure of your promise. +Bir söz başarılı veya başarısız olduktan sonra, tekrar başarılı veya başarısız olamayacağını ve onu çözen fonksiyonlara yapılan sonraki çağrıların yoksayılacağını unutmayın. Bu, sözünüzün başarısızlığını ele alma biçiminizi basitleştirebilir. {{if interactive @@ -845,12 +841,12 @@ if}} {{index "Promise.all function", "Promise class", "then method", "building Promise.all (exercise)"}} -The function passed to the `Promise` constructor will have to call `then` on each of the promises in the given array. When one of them succeeds, two things need to happen. The resulting value needs to be stored in the correct position of a result array, and we must check whether this was the last pending ((promise)) and finish our own promise if it was. +`Promise` yapıcısına geçirilen fonksiyon, verilen dizideki her söz üzerinde `then` çağırmak zorunda kalacaktır. Bir tanesi başarılı olduğunda, iki şeyin olması gerekir. Elde edilen değer, bir sonuç dizisinin doğru konumunda saklanmalı ve bu son bekleyen ((söz)) olup olmadığını kontrol etmeliyiz ve öyleyse kendi sözümüzü bitirmeliyiz. {{index "counter variable"}} -The latter can be done with a counter that is initialized to the length of the input array and from which we subtract 1 every time a promise succeeds. When it reaches 0, we are done. Make sure you take into account the situation where the input array is empty (and thus no promise will ever resolve). +Bu, giriş dizisinin uzunluğuna göre başlatılan ve her seferinde 1 çıkarılan bir sayaçla yapılabilir. 0'a ulaştığında, işimiz biter. Girdi dizisinin boş olduğu (ve dolayısıyla hiçbir sözün asla çözülmeyeceği) durumu dikkate aldığınızdan emin olun. -Handling failure requires some thought but turns out to be extremely simple. Just pass the `reject` function of the wrapping promise to each of the promises in the array as a `catch` handler or as a second argument to `then` so that a failure in one of them triggers the rejection of the whole wrapper promise. +Başarısızlığı ele almak biraz düşünmeyi gerektirir, ancak son derece basit olduğu ortaya çıkar. Sadece sarıcı sözün `reject` fonksiyonunu dizi içerisindeki her bir sarılan söze `catch` ya da `then` fonksiyonunun ikici argümanı olarak verin ki böylelikle bu sarılmış sözlerde ortaya çıkan bir hata sarıcı sözün hata fonksiyonunu başlatsın. hint}} diff --git a/12_language.md b/12_language.md index a4993539..81302c28 100644 --- a/12_language.md +++ b/12_language.md @@ -1,44 +1,44 @@ {{meta {load_files: ["code/chapter/12_language.js"], zip: "node/html"}}} -# Project: A Programming Language +# Proje: Bir Programlama Dili {{quote {author: "Hal Abelson and Gerald Sussman", title: "Structure and Interpretation of Computer Programs", chapter: true} -The evaluator, which determines the meaning of expressions in a programming language, is just another program. +Evaluator, bir programlama dilindeki ifadelerin anlamını belirleyen, sadece başka bir programdır. quote}} {{index "Abelson, Hal", "Sussman, Gerald", SICP, "project chapter"}} -{{figure {url: "img/chapter_picture_12.jpg", alt: "Illustration showing an egg with holes in it, showing smaller eggs inside, which in turn have even smaller eggs in them, and so on", chapter: "framed"}}} +{{figure {url: "img/chapter_picture_12.jpg", alt: "İçinde delikler olan bir yumurtayı gösteren, içinde daha küçük yumurtaların olduğu ve bunların içinde daha da küçük yumurtaların bulunduğu illüstrasyon.", chapter: "framed"}}} -Building your own ((programming language)) is surprisingly easy (as long as you do not aim too high) and very enlightening. +Kendi ((programming language))'inizi oluşturmak şaşırtıcı derecede kolaydır (çok yüksek hedefler koymadığınız sürece) ve oldukça aydınlatıcıdır. -The main thing I want to show in this chapter is that there's no ((magic)) involved in building a programming language. I've often felt that some human inventions were so immensely clever and complicated that I'd never be able to understand them. But with a little reading and experimenting, they often turn out to be quite mundane. +Bu bölümde göstermek istediğim ana şey, bir programlama dili oluşturmanın içinde ((büyü)) olmadığının anlaşılmasıdır. İnsan icatlarının bazıları o kadar inanılmaz derecede zeki ve karmaşık görünmüştür ki, onları asla anlayamayacağımı düşünmüşümdür. Ancak biraz okuma ve deneme ile genellikle oldukça sıradan oldukları ortaya çıkar. {{index "Egg language", [abstraction, "in Egg"]}} -We will build a programming language called Egg. It will be a tiny, simple language—but one that is powerful enough to express any computation you can think of. It will allow simple ((abstraction)) based on ((function))s. +Egg adında bir programlama dili oluşturacağız. Küçük ve basit bir dil olacak, ancak aklınıza gelebilecek herhangi bir hesaplamayı ifade edebilecek kadar güçlü olacak. Basit ((soyutlamalar)) sağlayacaktır ve ((fonksiyon))lara dayalı olacaktır. {{id parsing}} -## Parsing +## Ayrıştırma(Parsing) {{index parsing, validation, [syntax, "of Egg"]}} -The most immediately visible part of a programming language is its _syntax_, or notation. A _parser_ is a program that reads a piece of text and produces a data structure that reflects the structure of the program contained in that text. If the text does not form a valid program, the parser should point out the error. +Bir programlama dilinin en hemen görülebilir kısmı, onun _syntax_ veya gösterimidir. Bir _parser_, bir metin parçasını okuyup, o metinde bulunan programın yapısını yansıtan bir veri yapısı üreten bir programdır. Metin geçerli bir program oluşturmuyorsa, parser hatayı belirtmelidir. {{index "special form", [function, application]}} -Our language will have a simple and uniform syntax. Everything in Egg is an ((expression)). An expression can be the name of a binding, a number, a string, or an _application_. Applications are used for function calls but also for constructs such as `if` or `while`. +Dilimiz basit ve tekdüze bir sözdizimine sahip olacak. Egg'deki her şey bir ((ifade))dir. Bir ifade bir bağlama adı, bir sayı, bir string veya bir _aplikasyon_ olabilir. Aplikasyonlar fonksiyon çağrıları için kullanılır ancak `if` veya `while` gibi yapılar için de kullanılır. {{index "double-quote character", parsing, [escaping, "in strings"], [whitespace, syntax]}} -To keep the parser simple, strings in Egg do not support anything like backslash escapes. A string is simply a sequence of characters that are not double quotes, wrapped in double quotes. A number is a sequence of digits. Binding names can consist of any character that is not whitespace and that does not have a special meaning in the syntax. +Parser'ı basit tutmak için, Egg'deki stringler ters eğik çizgi kaçışlarını desteklemez. Bir string, çift tırnak içinde yer alan çift tırnak olmayan karakterlerden oluşan bir dizidir. Bir sayı, basamaklardan oluşan bir dizidir. Bağlama adları, boşluk olmayan ve sözdiziminde özel bir anlamı olmayan herhangi bir karakterden oluşabilir. {{index "comma character", [parentheses, arguments]}} -Applications are written the way they are in JavaScript, by putting parentheses after an expression and having any number of ((argument))s between those parentheses, separated by commas. +Aplikasyonlar JavaScript'te olduğu gibi yazılır, bir ifadenin ardından parantez koyarak ve bu parantezler arasında virgülle ayrılmış herhangi bir sayıda ((argümanlar)) koyarak. ```{lang: null} do(define(x, 10), @@ -49,17 +49,17 @@ do(define(x, 10), {{index block, [syntax, "of Egg"]}} -The ((uniformity)) of the ((Egg language)) means that things that are ((operator))s in JavaScript (such as `>`) are normal bindings in this language, applied just like other ((function))s. Since the syntax has no concept of a block, we need a `do` construct to represent doing multiple things in sequence. +((Egg language))'in ((tekdüzeliği)), JavaScript'teki `>` gibi ((operator))lerin bu dilde normal bağlamalar olduğu anlamına gelir ve diğer fonksiyonlar gibi uygulanırlar. Ve sözdiziminde blok kavramı olmadığından, birden fazla şeyi ardışık olarak yapmak için bir `do` yapısına ihtiyacımız var. {{index "type property", parsing, ["data structure", tree]}} -The data structure that the parser will use to describe a program consists of ((expression)) objects, each of which has a `type` property indicating the kind of expression it is and other properties to describe its content. +Parser'ın bir programı tanımlamak için kullanacağı veri yapısı, her biri hangi tür ifade olduğunu belirten bir `type` özelliğine ve içeriğini tanımlayan diğer özelliklere sahip ((expression)) nesnelerinden oluşur. {{index identifier}} -Expressions of type `"value"` represent literal strings or numbers. Their `value` property contains the string or number value that they represent. Expressions of type `"word"` are used for identifiers (names). Such objects have a `name` property that holds the identifier's name as a string. Finally, `"apply"` expressions represent applications. They have an `operator` property that refers to the expression that is being applied, as well as an `args` property that holds an array of argument expressions. +`"value"` türündeki ifadeler, literal string veya sayıları temsil eder. Bunların `value` özelliği, temsil ettikleri string veya sayı değerini içerir. `"word"` türündeki ifadeler, tanımlayıcılar (isimler) için kullanılır. Bu tür nesneler, tanımlayıcının adını string olarak tutan bir `name` özelliğine sahiptir. Son olarak, `"apply"` ifadeleri uygulamaları temsil eder. Bunların uygulanan ifadeye başvuran bir `operator` özelliği ve bir dizi argüman ifadesi tutan bir `args` özelliği vardır. -The `>(x, 5)` part of the previous program would be represented like this: +Önceki programın `>(x, 5)` kısmı şu şekilde temsil edilir: ```{lang: "json"} { @@ -74,27 +74,27 @@ The `>(x, 5)` part of the previous program would be represented like this: {{indexsee "abstract syntax tree", "syntax tree", ["data structure", tree]}} -Such a data structure is called a _((syntax tree))_. If you imagine the objects as dots and the links between them as lines between those dots, as shown in the following diagram, the structure has a ((tree))like shape. The fact that expressions contain other expressions, which in turn might contain more expressions, is similar to the way tree branches split and split again. +Bu tür bir veri yapısına _((syntax tree))_ denir. Nesneleri noktalar olarak ve bunlar arasındaki bağlantıları bu noktalar arasındaki çizgiler olarak hayal ederseniz, ((tree)) benzeri bir şekle sahiptir. İfadelerin diğer ifadeleri içermesi, onların da daha fazla ifade içermesi, ağaç dallarının bölünmesi ve tekrar bölünmesine benzer. -{{figure {url: "img/syntax_tree.svg", alt: "A diagram showing the structure of the syntax tree for the example program. The root is labeled 'do' and has two children, one labeled 'define' and one labeled 'if'. Those in turn have more children, describing their content.", width: "5cm"}}} +{{figure {url: "img/syntax_tree.svg", alt: "Örnek programın sözdizimi ağacının yapısını gösteren diyagram. Kök 'do' olarak etiketlenmiştir ve biri 'define' ve diğeri 'if' etiketli iki çocuğu vardır. Bunların da içeriklerini açıklayan daha fazla çocuğu var.", width: "5cm"}}} {{index parsing}} -Contrast this to the parser we wrote for the configuration file format in [Chapter ?](regexp#ini), which had a simple structure: it split the input into lines and handled those lines one at a time. There were only a few simple forms that a line was allowed to have. +Bunu, [Chapter ?](<(regexp#ini)>)'deki yapılandırma dosyası biçimi için yazdığımız parser ile karşılaştırın; bu parser, basit bir yapıya sahipti: girdiyi satırlara böldü ve bu satırları tek tek ele aldı. Bir satırın sahip olabileceği sadece birkaç basit form vardı. {{index recursion, [nesting, "of expressions"]}} -Here we must find a different approach. Expressions are not separated into lines, and they have a recursive structure. Application expressions _contain_ other expressions. +Burada farklı bir yaklaşım bulmalıyız. İfadeler satırlara ayrılmamış ve yinelemeli bir yapıya sahiptir. Application ifadeleri diğer ifadeleri _içerir_. {{index elegance}} -Fortunately, this problem can be solved very well by writing a parser function that is recursive in a way that reflects the recursive nature of the language. +Neyse ki, bu sorun, dilin yinelemeli doğasını yansıtan yinelemeli bir parser fonksiyonu yazarak çok iyi çözülebilir. {{index "parseExpression function", "syntax tree"}} -We define a function `parseExpression` that takes a string as input. It returns an object containing the data structure for the expression at the start of the string, along with the part of the string left after parsing this expression. When parsing subexpressions (the argument to an application, for example), this function can be called again, yielding the argument expression as well as the text that remains. This text may in turn contain more arguments or may be the closing parenthesis that ends the list of arguments. +Bir string'i girdi olarak alan ve string'in başlangıcındaki ifade için veri yapısını içeren bir nesne ve bu ifadeyi ayrıştırdıktan sonra kalan string'i döndüren bir `parseExpression` fonksiyonu tanımlarız. Alt ifadeleri ayrıştırırken (örneğin bir application'ın argümanı), bu fonksiyon tekrar çağrılabilir, böylece argüman ifadesi ve kalan metin elde edilir. Bu metin sırayla daha fazla argüman içerebilir veya argüman listesini sonlandıran kapanış parantezi olabilir. -This is the first part of the parser: +Bu parser'ın ilk kısmıdır: ```{includeCode: true} function parseExpression(program) { @@ -122,15 +122,15 @@ function skipSpace(string) { {{index "skipSpace function", [whitespace, syntax]}} -Because Egg, like JavaScript, allows any amount of whitespace between its elements, we have to repeatedly cut the whitespace off the start of the program string. The `skipSpace` function helps with this. +Egg, JavaScript gibi, elemanları arasında herhangi bir miktarda boşluk bulunmasına izin verdiğinden, program string'inin başlangıcındaki boşlukları tekrar tekrar kesmemiz gerekir. `skipSpace` fonksiyonu bu konuda yardımcı olur. {{index "literal expression", "SyntaxError type"}} -After skipping any leading space, `parseExpression` uses three ((regular expression))s to spot the three atomic elements that Egg supports: strings, numbers, and words. The parser constructs a different kind of data structure depending on which expression matches. If the input does not match one of these three forms, it is not a valid expression, and the parser throws an error. We use the `SyntaxError` constructor here. This is an exception class defined by the standard, like `Error`, but more specific. +Herhangi bir önde gelen boşluğu geçtikten sonra, `parseExpression` Egg'in desteklediği üç atomik elemanı tespit etmek için üç ((regular expression)) kullanır: stringler, sayılar ve kelimeler. Parser, hangisi eşleşirse ona bağlı olarak farklı bir veri yapısı oluşturur. Girdi bu üç formdan birine uymuyorsa, geçerli bir ifade değildir ve parser bir hata oluşturur. `Error` yerine `SyntaxError`'ı kullanırız çünkü bu biraz daha spesifiktir—aynı zamanda geçersiz bir JavaScript programı çalıştırılmaya çalışıldığında oluşturulan hata türüdür. {{index "parseApply function"}} -We then cut off the part that was matched from the program string and pass that, along with the object for the expression, to `parseApply`, which checks whether the expression is an application. If so, it parses a parenthesized list of arguments. +Sonra eşleşen kısmı program string'inden kesip, bunu ifade için nesne ile birlikte `parseApply`'a geçiririz, bu ifade bir application olup olmadığını kontrol eder. Eğer öyleyse, parantezli bir argüman listesi ayrıştırır. ```{includeCode: true} function parseApply(expr, program) { @@ -157,13 +157,17 @@ function parseApply(expr, program) { {{index parsing, recursion}} -If the next character in the program is not an opening parenthesis, this is not an application, and `parseApply` returns the expression it was given. Otherwise, it skips the opening parenthesis and creates the ((syntax tree)) object for this application expression. It then recursively calls `parseExpression` to parse each argument until a closing parenthesis is found. The recursion is indirect, through `parseApply` and `parseExpression` calling each other. +Programdaki bir sonraki karakter açılış parantezi değilse, bu bir application değildir ve `parseApply` verilen ifadeyi döner. -Because an application expression can itself be applied (such as in `multiplier(2)(1)`), `parseApply` must, after it has parsed an application, call itself again to check whether another pair of parentheses follows. +{{index recursion}} + +Aksi takdirde, açılış parantezini atlar ve bu application ifadesi için ((syntax tree)) nesnesini oluşturur. Daha sonra, kapanış parantezi bulunana kadar her argümanı ayrıştırmak için `parseExpression`'ı yinelemeli olarak çağırır. Yineleme dolaylıdır, `parseApply` ve `parseExpression` birbirlerini çağırır. + +Bir application ifadesi kendisi uygulanabilir (örneğin `multiplier(2)(1)`), bu yüzden `parseApply` bir application ayrıştırdıktan sonra, başka bir parantez çifti olup olmadığını kontrol etmek için kendisini tekrar çağırmalıdır. {{index "syntax tree", "Egg language", "parse function"}} -This is all we need to parse Egg. We wrap it in a convenient `parse` function that verifies that it has reached the end of the input string after parsing the expression (an Egg program is a single expression), and that gives us the program's data structure. +Egg'i ayrıştırmak için ihtiyacımız olan her şey bu kadar. Bunu, bir ifadeyi ayrıştırdıktan sonra girdi string'inin sonuna ulaşıldığını doğrulayan ve bize programın veri yapısını veren uygun bir `parse` fonksiyonuna sararız (bir Egg programı tek bir ifadedir). ```{includeCode: strip_log, test: join} function parse(program) { @@ -183,13 +187,13 @@ console.log(parse("+(a, 10)")); {{index "error message"}} -It works! It doesn't give us very helpful information when it fails and doesn't store the line and column on which each expression starts, which might be helpful when reporting errors later, but it's good enough for our purposes. +İşe yarıyor! Başarısız olduğunda çok yardımcı bilgi vermiyor ve her ifadenin başladığı satır ve sütunu saklamıyor, bu da daha sonra hataları bildirirken faydalı olabilir, ancak bizim amaçlarımız için yeterince iyi. -## The evaluator +## Değerlendirici(Evaluator) {{index "evaluate function", evaluation, interpretation, "syntax tree", "Egg language"}} -What can we do with the syntax tree for a program? Run it, of course! And that is what the evaluator does. You give it a syntax tree and a scope object that associates names with values, and it will evaluate the expression that the tree represents and return the value that this produces. +Bir program için ((syntax tree)) ile ne yapabiliriz? Elbette çalıştırabiliriz! Ve değerlendirici tam olarak bunu yapar. Ona bir ((syntax tree)) ve isimleri değerlerle ilişkilendiren bir kapsam nesnesi verirsiniz ve bu, ağacın temsil ettiği ifadeyi değerlendirir ve ürettiği değeri döndürür. ```{includeCode: true} const specialForms = Object.create(null); @@ -223,27 +227,27 @@ function evaluate(expr, scope) { {{index "literal expression", scope}} -The evaluator has code for each of the ((expression)) types. A literal value expression produces its value. (For example, the expression `100` evaluates to the number 100.) For a binding, we must check whether it is actually defined in the scope and, if it is, fetch the binding's value. +Değerlendirici, her ((expression)) türü için koda sahiptir. Bir literal değer ifadesi kendi değerini üretir. (Örneğin, `100` ifadesi sadece 100 sayısını değerlendirir.) Bir bağlama için, bunun kapsamda gerçekten tanımlanıp tanımlanmadığını kontrol etmemiz ve eğer öyleyse, bağlamanın değerini almamız gerekir. {{index [function, application]}} -Applications are more involved. If they are a ((special form)), like `if`, we do not evaluate anything—we just and pass the argument expressions, along with the scope, to the function that handles this form. If it is a normal call, we evaluate the operator, verify that it is a function, and call it with the evaluated arguments. +Application'lar daha karmaşıktır. Eğer `if` gibi bir ((special form)) iseler, hiçbir şeyi değerlendirmeyiz ve argüman ifadelerini, kapsamla birlikte, bu formu yöneten fonksiyona geçiririz. Eğer normal bir çağrıysa, operatörü değerlendiririz, bunun bir fonksiyon olduğunu doğrularız ve değerlendirilmiş argümanlarla çağırırız. -We use plain JavaScript function values to represent Egg's function values. We will come back to this [later](language#egg_fun), when the special form `fun` is defined. +Egg'in fonksiyon değerlerini temsil etmek için sade JavaScript fonksiyon değerlerini kullanırız. Bu konuya daha [sonra](<(language#egg_fun)>), `fun` adı verilen ((special form)) tanımlandığında döneceğiz. {{index readability, "evaluate function", recursion, parsing}} -The recursive structure of `evaluate` resembles the structure of the parser, and both mirror the structure of the language itself. It would also be possible to combine the parser and the evaluator into one function and evaluate during parsing, but splitting them up this way makes the program clearer and more flexible. +`evaluate`'in yinelemeli yapısı, parser'ın benzer yapısına benzer ve her ikisi de dilin yapısını yansıtır. Parser ve değerlendiriciyi tek bir fonksiyona birleştirmek ve ayrıştırma sırasında değerlendirmek de mümkündür. Ancak bu şekilde ayırmak programı daha net ve esnek kılar. {{index "Egg language", interpretation}} -This is really all that's needed to interpret Egg. It's that simple. But without defining a few special forms and adding some useful values to the ((environment)), you can't do much with this language yet. +Egg'i yorumlamak için gereken her şey gerçekten bu kadar basittir. Ama birkaç özel form tanımlamadan ve ((environment))'a bazı kullanışlı değerler eklemeden, bu dil ile pek bir şey yapamazsınız. -## Special forms +## Özel formlar {{index "special form", "specialForms object"}} -The `specialForms` object is used to define special syntax in Egg. It associates words with functions that evaluate such forms. It is currently empty. Let's add `if`. +`specialForms` nesnesi, Egg'de özel sözdizimini tanımlamak için kullanılır. Bu, sözcükleri bu formaları değerlendiren fonksiyonlarla ilişkilendirir. Şu anda boş. `if` ekleyelim. ```{includeCode: true} specialForms.if = (args, scope) => { @@ -259,17 +263,17 @@ specialForms.if = (args, scope) => { {{index "conditional execution", "ternary operator", "?: operator", "conditional operator"}} -Egg's `if` construct expects exactly three arguments. It will evaluate the first, and if the result isn't the value `false`, it will evaluate the second. Otherwise, the third gets evaluated. This `if` form is more similar to JavaScript's ternary `?:` operator than to JavaScript's `if`. It is an expression, not a statement, and it produces a value, namely, the result of the second or third argument. +Egg'in `if` yapısı tam olarak üç argüman bekler. İlkini değerlendirecek ve eğer sonuç `false` değilse, ikincisini değerlendirecektir. Aksi takdirde, üçüncü değerlendirilir. Bu `if` formu, JavaScript'in `if`'inden çok JavaScript'in üçlü `?:` operatörüne benzer. Bir bildiri değil, ifadedir ve bir değer üretir, yani ikinci veya üçüncü argümanın sonucunu üretir. {{index Boolean}} -Egg also differs from JavaScript in how it handles the condition value to `if`. It will treat only the value `false` as false, not things like zero or the empty string. +Egg ayrıca `if` koşul değerini nasıl ele aldığında JavaScript'ten farklıdır. Sıfır veya boş string gibi şeyleri `false` olarak değerlendirmeyecek, sadece kesin değer `false` olarak değerlendirecektir. {{index "short-circuit evaluation"}} -The reason we need to represent `if` as a special form rather than a regular function is that all arguments to functions are evaluated before the function is called, whereas `if` should evaluate only _either_ its second or its third argument, depending on the value of the first. +`if`'i düzenli bir fonksiyon yerine özel bir form olarak temsil etmemizin nedeni, fonksiyonlara tüm argümanlar fonksiyon çağrılmadan önce değerlendirilir, oysa `if` yalnızca ya ikinci _ya da_ üçüncü argümanını değerlendirmelidir, ilk argümanın değerine bağlı olarak. -The `while` form is similar. +`while` formu benzerdir. ```{includeCode: true} specialForms.while = (args, scope) => { @@ -281,12 +285,12 @@ specialForms.while = (args, scope) => { } // Since undefined does not exist in Egg, we return false, - // for lack of a meaningful result. + // for lack of a meaningful result return false; }; ``` -Another basic building block is `do`, which executes all its arguments from top to bottom. Its value is the value produced by the last argument. +Diğer bir temel yapı taşı `do`'dur, tüm argümanlarını yukarıdan aşağıya doğru yürütür. Onun değeri, son argümanın ürettiği değerdir. ```{includeCode: true} specialForms.do = (args, scope) => { @@ -300,7 +304,7 @@ specialForms.do = (args, scope) => { {{index ["= operator", "in Egg"], [binding, "in Egg"]}} -To be able to create bindings and give them new values, we also create a form called `define`. It expects a word as its first argument and an expression producing the value to assign to that word as its second argument. Since `define`, like everything, is an expression, it must return a value. We'll make it return the value that was assigned (just like JavaScript's `=` operator). +Bağlamalar oluşturup onlara yeni değerler atayabilmek için, `define` adında bir form da oluştururuz. İlk argüman olarak bir kelime ve bu kelimeye atanacak değeri üreten bir ifade bekler. `define`, her şey gibi, bir ifade olduğundan, bir değer döndürmelidir. Bu değeri atanmış olan değeri döndürecek şekilde yapacağız (tıpkı JavaScript'in `=` operatörü gibi). ```{includeCode: true} specialForms.define = (args, scope) => { @@ -313,13 +317,13 @@ specialForms.define = (args, scope) => { }; ``` -## The environment +## Ortam {{index "Egg language", "evaluate function", [binding, "in Egg"]}} -The ((scope)) accepted by `evaluate` is an object with properties whose names correspond to binding names and whose values correspond to the values those bindings are bound to. Let's define an object to represent the ((global scope)). +`evaluate` tarafından kabul edilen ((scope)), isimleri bağlama isimlerine ve değerleri bu bağlamalara karşılık gelen değerlere karşılık gelen özellikleri olan bir nesnedir. ((global scope))'u temsil etmek için bir nesne tanımlayalım. -To be able to use the `if` construct we just defined, we must have access to ((Boolean)) values. Since there are only two Boolean values, we do not need special syntax for them. We simply bind two names to the values `true` and `false` and use them. +Yeni tanımladığımız `if` yapısını kullanabilmek için, ((Boolean)) değerlere erişimimiz olmalıdır. Yalnızca iki Boolean değeri olduğundan, bunlar için özel bir sözdizimine ihtiyacımız yoktur. İki ismi `true` ve `false` değerlerine bağlar ve kullanırız. ```{includeCode: true} const topScope = Object.create(null); @@ -328,7 +332,7 @@ topScope.true = true; topScope.false = false; ``` -We can now evaluate a simple expression that negates a Boolean value. +Artık bir Boolean değerini tersine çeviren basit bir ifadeyi değerlendirebiliriz. ``` let prog = parse(`if(true, false, true)`); @@ -338,7 +342,7 @@ console.log(evaluate(prog, topScope)); {{index arithmetic, "Function constructor"}} -To supply basic ((arithmetic)) and ((comparison)) ((operator))s, we will also add some function values to the ((scope)). In the interest of keeping the code short, we'll use `Function` to synthesize a bunch of operator functions in a loop instead of defining them individually. +Temel ((arithmetic)) ve ((comparison)) ((operator))ları sağlamak için, ((scope))'a bazı fonksiyon değerleri de ekleyeceğiz. Kodu kısa tutmak adına, her birini ayrı ayrı tanımlamak yerine, bir döngüde bir grup operatör fonksiyonu üretmek için `Function` kullanacağız. ```{includeCode: true} for (let op of ["+", "-", "*", "/", "==", "<", ">"]) { @@ -346,7 +350,7 @@ for (let op of ["+", "-", "*", "/", "==", "<", ">"]) { } ``` -It is also useful to have a way to ((output)) values, so we'll wrap `console.log` in a function and call it `print`. +Değerleri ((output)) etmek için bir yol da faydalıdır, bu yüzden `console.log`'u bir fonksiyon içine sarıp `print` olarak adlandıracağız. ```{includeCode: true} topScope.print = value => { @@ -357,7 +361,7 @@ topScope.print = value => { {{index parsing, "run function"}} -That gives us enough elementary tools to write simple programs. The following function provides a convenient way to parse a program and run it in a fresh scope: +Bu, basit programlar yazmak için yeterli temel araçları sağlar. Aşağıdaki fonksiyon, bir programı ayrıştırmak ve bunu yeni bir kapsamda çalıştırmak için kullanışlı bir yol sağlar: ```{includeCode: true} function run(program) { @@ -367,7 +371,7 @@ function run(program) { {{index "Object.create function", prototype}} -We'll use object prototype chains to represent nested scopes so that the program can add bindings to its local scope without changing the top-level scope. +Yerleşik kapsamları temsil etmek için nesne prototip zincirlerini kullanacağız, böylece program, üst düzey kapsamı değiştirmeden yerel kapsamına bağlamalar ekleyebilir. ``` run(` @@ -383,15 +387,17 @@ do(define(total, 0), {{index "summing example", "Egg language"}} -This is the program we've seen several times before that computes the sum of the numbers 1 to 10, expressed in Egg. It is clearly uglier than the equivalent JavaScript program—but not bad for a language implemented in less than 150 ((lines of code)). +Bu, 1'den 10'a kadar olan sayıların toplamını hesaplayan ve Egg'de ifade edilen programdır. Açıkça JavaScript eşdeğerinden daha çirkindir—ancak 150'den az ((lines of code)) ile uygulanmış bir dil için fena değil. {{id egg_fun}} -## Functions +## Fonksiyonlar {{index function, "Egg language"}} -A programming language without functions is a poor programming language indeed. Fortunately, it isn't hard to add a `fun` construct, which treats its last argument as the function's body and uses all arguments before that as the names of the function's parameters. +Fonksiyonsuz bir programlama dili gerçekten zayıf bir programlama dilidir. + +Neyse ki, son argümanını fonksiyonun gövdesi olarak ele alan ve ondan önceki tüm argümanları fonksiyonun parametre isimleri olarak kullanan bir `fun` yapısını eklemek zor değildir. ```{includeCode: true} specialForms.fun = (args, scope) => { @@ -421,7 +427,7 @@ specialForms.fun = (args, scope) => { {{index "local scope"}} -Functions in Egg get their own local scope. The function produced by the `fun` form creates this local scope and adds the argument bindings to it. It then evaluates the function body in this scope and returns the result. +Egg'deki fonksiyonlar kendi yerel kapsamlarını alır. `fun` formu tarafından üretilen fonksiyon bu yerel kapsamı oluşturur ve argüman bağlamalarını ona ekler. Daha sonra fonksiyon gövdesini bu kapsamda değerlendirir ve sonucu döndürür. ```{startCode: true} run(` @@ -440,37 +446,39 @@ do(define(pow, fun(base, exp, // → 1024 ``` -## Compilation +## Derleme(Compilation) {{index interpretation, compilation}} -What we have built is an interpreter. During evaluation, it acts directly on the representation of the program produced by the parser. +İnşaa etmiş olduğumuz şey bir yorumlayıcıdır. Değerlendirme sırasında, parser tarafından üretilen programın temsilinde doğrudan çalışır. {{index efficiency, performance, [binding, definition], [memory, speed]}} -_Compilation_ is the process of adding another step between the parsing and the running of a program, which transforms the program into something that can be evaluated more efficiently by doing as much work as possible in advance. For example, in well-designed languages it is obvious, for each use of a binding, which binding is being referred to, without actually running the program. This can be used to avoid looking up the binding by name every time it is accessed, instead directly fetching it from some predetermined memory location. +_Compilation_, bir programın çalıştırılmasından önceki adımlardan birini ekleyerek programı daha verimli bir şekilde değerlendirilebilecek bir şeye dönüştürme sürecidir. Örneğin, iyi tasarlanmış dillerde, bir bağlamanın her kullanımının hangi bağlamaya atıfta bulunduğu, programı gerçekten çalıştırmadan açıktır. Bu, bağlamayı her erişildiğinde adla aramak yerine, doğrudan önceden belirlenmiş bir bellek konumundan almayı sağlayabilir. -Traditionally, ((compilation)) involves converting the program to ((machine code)), the raw format that a computer's processor can execute. But any process that converts a program to a different representation can be thought of as compilation. +Geleneksel olarak, ((compilation)), programı, bir bilgisayarın işlemcisinin çalıştırabileceği ham format olan ((machine code))'a dönüştürmeyi içerir. Ancak, programı farklı bir temsile dönüştüren herhangi bir süreç derleme olarak düşünülebilir. {{index simplicity, "Function constructor", transpilation}} -It would be possible to write an alternative ((evaluation)) strategy for Egg, one that first converts the program to a JavaScript program, uses `Function` to invoke the JavaScript compiler on it, and runs the result. When done right, this would make Egg run very fast while still being quite simple to implement. +Egg için alternatif bir ((değerlendirme(evaluation))) stratejisi yazmak mümkündür; programı önce bir JavaScript programına dönüştüren, `Function` kullanarak JavaScript derleyicisini çağıran ve ardından sonucu çalıştıran bir strateji. Doğru yapıldığında, bu Egg'i çok hızlı çalıştırır ve hala oldukça basit bir şekilde uygulanabilir. -If you are interested in this topic and willing to spend some time on it, I encourage you to try to implement such a compiler as an exercise. +Eğer bu konuyla ilgileniyorsanız ve biraz zaman ayırmaya istekliyseniz, böyle bir derleyiciyi bir egzersiz olarak uygulamayı denemenizi öneririm. -## Cheating +## Hile yapmak {{index "Egg language"}} -When we defined `if` and `while`, you probably noticed that they were more or less trivial wrappers around JavaScript's own `if` and `while`. Similarly, the values in Egg are just regular old JavaScript values. Bridging the gap to a more primitive system, such as the machine code the processor understands, takes more effort—but the way it works resembles what we are doing here. +`if` ve `while` tanımladığımızda, bunların JavaScript'in kendi `if` ve `while` yapılarının etrafında daha az veya daha çok basit sarmalayıcılar olduğunu fark etmiş olabilirsiniz. Benzer şekilde, Egg'deki değerler sadece eski normal JavaScript değerleridir. -Though the toy language in this chapter doesn't do anything that couldn't be done better in JavaScript, there _are_ situations where writing small languages helps get real work done. +Egg'in JavaScript üzerine inşa edilmiş uygulaması ile bir programlama dilini doğrudan bir makinenin sağladığı ham fonksiyonellik üzerine inşa etmek için gereken iş ve karmaşıklığı karşılaştırırsanız, fark çok büyüktür. Her şeye rağmen, bu örnek size ((programlama dillerinin)) nasıl çalıştığı konusunda bir izlenim vermeyi amaçladı. -Such a language does not have to resemble a typical programming language. If JavaScript didn't come equipped with regular expressions, for example, you could write your own parser and evaluator for regular expressions. +Ve bir şeyler yapmaya gelince, hile yapmak her şeyi kendiniz yapmaktan daha etkilidir. Bu bölümdeki oyuncak dil JavaScript'te daha iyi yapılamayacak bir şey yapmıyor olsa da, küçük diller yazmanın gerçek işleri halletmeye yardımcı olduğu durumlar _vardır_. + +Böyle bir dil tipik bir programlama diline benzemek zorunda değildir. Örneğin, JavaScript düzenli ifadelerle donatılmış olarak gelmeseydi, kendi düzenli ifadelerinizi ayrıştırıcı ve değerlendirici olarak yazabilirdiniz. {{index "parser generator"}} -Or imagine you are building a program that makes it possible to quickly create parsers by providing a logical description of the language they need to parse. You could define a specific notation for that, and a compiler that compiles it to a parser program. +Ya da dev bir robotik ((dinazor)) inşa ettiğinizi ve onun ((davranışını)) programlamanız gerektiğini hayal edin. JavaScript bunu yapmanın en etkili yolu olmayabilir. Bunun yerine şöyle görünen bir dil seçebilirsiniz: ```{lang: null} expr = number | string | name | application @@ -486,15 +494,15 @@ application = expr '(' (expr (',' expr)*)? ')' {{index expressivity}} -This is what is usually called a _((domain-specific language))_, a language tailored to express a narrow domain of knowledge. Such a language can be more expressive than a general-purpose language because it is designed to describe exactly the things that need to be described in its domain and nothing else. +Bu genellikle ((domain-özel dil)) olarak adlandırılır, belirli bir bilgi alanını ifade etmek için tasarlanmış bir dil. Böyle bir dil, genel amaçlı bir dilden daha ifadeli olabilir çünkü tam olarak ifade edilmesi gereken şeyleri ifade etmek için tasarlanmıştır ve başka hiçbir şeyi. -## Exercises +## Egzersizler -### Arrays +### Diziler {{index "Egg language", "arrays in egg (exercise)", [array, "in Egg"]}} -Add support for arrays to Egg by adding the following three functions to the top scope: `array(...values)` to construct an array containing the argument values, `length(array)` to get an array's length, and `element(array, n)` to fetch the *n*th element from an array. +Egg'e diziler için destek ekleyin, en üst kapsama aşağıdaki üç fonksiyonu ekleyerek: `array(...values)` argüman değerlerini içeren bir dizi oluşturmak için, `length(array)` bir dizinin uzunluğunu almak için ve `element(array, n)` bir diziden n^inci^ öğeyi almak için. {{if interactive @@ -526,21 +534,21 @@ if}} {{index "arrays in egg (exercise)"}} -The easiest way to do this is to represent Egg arrays with JavaScript arrays. +Bunu yapmanın en kolay yolu, Egg dizilerini JavaScript dizileri ile temsil etmektir. {{index "slice method"}} -The values added to the top scope must be functions. By using a rest argument (with triple-dot notation), the definition of `array` can be _very_ simple. +En üst kapsama eklenen değerler fonksiyon olmalıdır. Bir rest argümanı (üç nokta notasyonu ile) kullanarak, `array` tanımını _çok_ basit hale getirebiliriz. hint}} -### Closure +### Kapanış(Closure) {{index closure, [function, scope], "closure in egg (exercise)"}} -The way we have defined `fun` allows functions in Egg to reference the surrounding scope, allowing the function's body to use local values that were visible at the time the function was defined, just like JavaScript functions do. +`fun`'ı tanımlama şeklimiz, Egg'deki fonksiyonların çevreleyen kapsamı referans almasına izin verir, bu da fonksiyonun gövdesinin fonksiyonun tanımlandığı anda görünen yerel değerleri kullanmasına izin verir, tıpkı JavaScript fonksiyonları gibi. -The following program illustrates this: function `f` returns a function that adds its argument to `f`'s argument, meaning that it needs access to the local ((scope)) inside `f` to be able to use binding `a`. +Aşağıdaki program bunu göstermektedir: `f` fonksiyonu, argümanını `f`'nin argümanına ekleyen bir fonksiyon döndürür, bu da `a` bağlamına ulaşabilmesi için `f` içindeki lokal kapsama(scope) erişimi olmasını gerektirir.. ``` run(` @@ -550,29 +558,29 @@ do(define(f, fun(a, fun(b, +(a, b)))), // → 9 ``` -Go back to the definition of the `fun` form and explain which mechanism causes this to work. +`fun` formunun tanımına geri dönün ve bunun çalışmasını sağlayan mekanizmayı açıklayın. {{hint {{index closure, "closure in egg (exercise)"}} -Again, we are riding along on a JavaScript mechanism to get the equivalent feature in Egg. Special forms are passed the local scope in which they are evaluated so that they can evaluate their subforms in that scope. The function returned by `fun` has access to the `scope` argument given to its enclosing function and uses that to create the function's local ((scope)) when it is called. +Yine, JavaScript mekanizmasını kullanarak Egg'de eşdeğer özelliği elde ediyoruz. Özel formlar, kendi alt formlarını bu kapsamda değerlendirebilmeleri için değerlendirildikleri yerel kapsamı alırlar. `fun` tarafından döndürülen fonksiyon, kapsayıcı fonksiyonuna verilen `scope` argümanına erişir ve çağrıldığında fonksiyonun yerel ((kapsamını)) oluşturmak için bunu kullanır. {{index compilation}} -This means that the ((prototype)) of the local scope will be the scope in which the function was created, which makes it possible to access bindings in that scope from the function. This is all there is to implementing closure (though to compile it in a way that is actually efficient, you'd need to do some more work). +Bu, yerel kapsamın ((prototipinin)) fonksiyonun oluşturulduğu kapsam olacağı anlamına gelir, bu da bu kapsamda bağlamalara fonksiyondan erişmeyi mümkün kılar. Bu, kapanışı(closure) uygulamak için gereken her şeydir (ancak bunu gerçekten verimli bir şekilde derlemek için biraz daha fazla iş yapmanız gerekir). hint}} -### Comments +### Yorumlar {{index "hash character", "Egg language", "comments in egg (exercise)"}} -It would be nice if we could write ((comment))s in Egg. For example, whenever we find a hash sign (`#`), we could treat the rest of the line as a comment and ignore it, similar to `//` in JavaScript. +Egg'de ((yorum)) yazabilmek güzel olurdu. Örneğin, bir hash işareti (`#`) bulduğumuzda, satırın geri kalanını bir yorum olarak ele alabilir ve JavaScript'teki `//` gibi görmezden gelebiliriz. {{index "skipSpace function"}} -We do not have to make any big changes to the parser to support this. We can simply change `skipSpace` to skip comments as if they are ((whitespace)) so that all the points where `skipSpace` is called will now also skip comments. Make this change. +Bunu desteklemek için ayrıştırıcıda büyük değişiklikler yapmamıza gerek yok. `skipSpace`'i, yorumları ((whitespace)) gibi atlayacak şekilde değiştirebiliriz, böylece `skipSpace`'in çağrıldığı tüm noktalar artık yorumları da atlayacaktır. Bu değişikliği yapın. {{if interactive @@ -592,35 +600,36 @@ console.log(parse("a # one\n # two\n()")); // operator: {type: "word", name: "a"}, // args: []} ``` + if}} {{hint {{index "comments in egg (exercise)", [whitespace, syntax]}} -Make sure your solution handles multiple comments in a row, with potentially whitespace between or after them. +Çözümünüzün, arka arkaya birden fazla yorumu, aralarında veya sonrasında potansiyel olarak boşluklarla birlikte ele aldığından emin olun. -A ((regular expression)) is probably the easiest way to solve this. Write something that matches "whitespace or a comment, zero or more times". Use the `exec` or `match` method and look at the length of the first element in the returned array (the whole match) to find out how many characters to slice off. +Bir ((düzenli ifade)) muhtemelen bunu çözmenin en kolay yoludur. "Boşluk veya yorum, sıfır veya daha fazla kez" eşleşen bir şey yazın. `exec` veya `match` metodunu kullanın ve döndürülen dizinin ilk öğesinin (tüm eşleşme) uzunluğuna bakarak ne kadar karakter dilimleneceğini bulun. hint}} -### Fixing scope +### Kapsamı düzeltme {{index [binding, definition], assignment, "fixing scope (exercise)"}} -Currently, the only way to assign a binding a value is `define`. This construct acts as a way both to define new bindings and to give existing ones a new value. +Şu anda bir bağlamaya değer atamanın tek yolu `define`. Bu yapı, yeni bağlamalar tanımlamanın ve mevcut olanlara yeni bir değer vermenin bir yolu olarak işlev görür. {{index "local binding"}} -This ((ambiguity)) causes a problem. When you try to give a nonlocal binding a new value, you will end up defining a local one with the same name instead. Some languages work like this by design, but I've always found it an awkward way to handle ((scope)). +Bu ((belirsizlik)) bir soruna yol açar. Yerel olmayan bir bağlamaya yeni bir değer vermeye çalıştığınızda, bunun yerine aynı ada sahip yerel bir bağlama tanımlarsınız. Bazı diller bu şekilde tasarlanmıştır, ancak ((kapsamı)) bu şekilde ele almanın her zaman garip bir yol olduğunu düşündüm. {{index "ReferenceError type"}} -Add a special form `set`, similar to `define`, which gives a binding a new value, updating the binding in an outer scope if it doesn't already exist in the inner scope. If the binding is not defined at all, throw a `ReferenceError` (another standard error type). +Yerel kapsamda zaten yoksa, dış kapsamda bir bağlamayı güncelleyerek yeni bir değer veren `define`'a benzer bir özel form `set` ekleyin. Bağlama hiç tanımlanmamışsa, bir `ReferenceError` (başka bir standart hata türü) atın. {{index "hasOwn function", prototype, "getPrototypeOf function"}} -The technique of representing scopes as simple objects, which has made things convenient so far, will get in your way a little at this point. You might want to use the `Object.getPrototypeOf` function, which returns the prototype of an object. Also remember that you can use `Object.hasOwn` to find out if a given object has a property. +Kapsamları basit nesneler olarak temsil etme tekniği, şu ana kadar işleri kolaylaştırmış olsa da, bu noktada sizi biraz engelleyecektir. Bir nesnenin prototipini döndüren `Object.getPrototypeOf` fonksiyonunu kullanmak isteyebilirsiniz. Ayrıca, belirli bir nesnenin bir özelliğe sahip olup olmadığını öğrenmek için `Object.hasOwn` kullanabileceğinizi unutmayın. {{if interactive @@ -639,16 +648,17 @@ do(define(x, 4), run(`set(quux, true)`); // → Some kind of ReferenceError ``` + if}} {{hint {{index [binding, "compilation of"], assignment, "getPrototypeOf function", "hasOwn function", "fixing scope (exercise)"}} -You will have to loop through one ((scope)) at a time, using `Object.getPrototypeOf` to go to the next outer scope. For each scope, use `Object.hasOwn` to find out whether the binding, indicated by the `name` property of the first argument to `set`, exists in that scope. If it does, set it to the result of evaluating the second argument to `set` and then return that value. +Bir sonraki dış kapsama geçmek için `Object.getPrototypeOf` kullanarak her seferinde bir ((kapsamı))ı döngüye almak zorunda kalacaksınız. Her kapsam için, `set`'in ilk argümanının `name` özelliği ile belirtilen bağlamanın o kapsamda olup olmadığını öğrenmek için `Object.hasOwn` kullanın. Eğer varsa, onu `set`'in ikinci argümanının değerlendirme sonucuna ayarlayın ve ardından bu değeri döndürün. {{index "global scope", "run-time error"}} -If the outermost scope is reached (`Object.getPrototypeOf` returns null) and we haven't found the binding yet, it doesn't exist, and an error should be thrown. +En dış kapsama ulaşıldığında (`Object.getPrototypeOf` null döndürür) ve hala bağlamayı bulamadıysanız, o bağlama mevcut değildir ve bir hata atılmalıdır. hint}} diff --git a/13_browser.md b/13_browser.md index 7700d0bd..6d0502af 100644 --- a/13_browser.md +++ b/13_browser.md @@ -1,78 +1,78 @@ -# JavaScript and the Browser +# JavaScript ve Tarayıcı(Browser) -{{quote {author: "Tim Berners-Lee", title: "The World Wide Web: A very short personal history", chapter: true} +{{quote {author: "Tim Berners-Lee", title: "World Wide Web: Kısa kişisel bir tarih", chapter: true} -The dream behind the Web is of a common information space in which we communicate by sharing information. Its universality is essential: the fact that a hypertext link can point to anything, be it personal, local or global, be it draft or highly polished. +Web’in ardındaki hayal, bilgi paylaşarak iletişim kurduğumuz ortak bir bilgi alanıdır. Evrenselliği esastır: Bir hiper metin bağlantısının, kişisel, yerel veya küresel, taslak veya çok iyi hazırlanmış olmasına bakılmaksızın herhangi bir şeye işaret edebilmesidir. quote}} {{index "Berners-Lee, Tim", "World Wide Web", HTTP, [JavaScript, "history of"], "World Wide Web"}} -{{figure {url: "img/chapter_picture_13.jpg", alt: "Illustration showing a telephone switchboard", chapter: "framed"}}} +{{figure {url: "img/chapter_picture_13.jpg", alt: "Bir telefon santralini gösteren illüstrasyon", chapter: "framed"}}} -The next chapters of this book will discuss web browsers. Without ((browser))s, there would be no JavaScript—or if there were, no one would ever have paid any attention to it. +Bu kitabın sonraki bölümleri web tarayıcılarından bahsedecek. Web ((tarayıcı))ları olmadan, JavaScript de olmazdı. Olsa bile, kimse ona asla dikkat etmezdi. {{index decentralization, compatibility}} -Web technology has been decentralized from the start, not just technically but also in terms of the way it evolved. Various browser vendors have added new functionality in ad hoc and sometimes poorly thought-out ways, which were then—sometimes—adopted by others—and finally set down as in ((standards)). +Web teknolojisi başlangıçtan itibaren sadece teknik olarak değil, aynı zamanda evrim şekli bakımından da merkezi olmayan bir yapıya sahip olmuştur. Çeşitli tarayıcı satıcıları, bazen düzensiz ve bazen de kötü düşünülmüş yollarla yeni fonksiyonellikler eklemiş, bu da bazen diğerleri tarafından benimsenmiş ve sonunda ((standartlar)) olarak belirlenmiştir. -This is both a blessing and a curse. On the one hand, it is empowering to not have a central party control a system but have it be improved by various parties working in loose ((collaboration)) (or occasionally, open hostility). On the other hand, the haphazard way in which the Web was developed means that the resulting system is not exactly a shining example of internal ((consistency)). Some parts of it are downright confusing and badly designed. +Bu hem bir nimet hem de bir lanettir. Bir yandan, merkezi bir otoritenin bir sistemi kontrol etmemesi ve bunun yerine çeşitli taraflarca gevşek ((işbirliği)) içinde (ya da bazen açık düşmanlıkla) geliştirilmesi güçlendirici bir durumdur. Diğer yandan, Web’in gelişigüzel bir şekilde geliştirilmiş olması, ortaya çıkan sistemin içsel ((tutarlılık)) açısından parlak bir örnek olmamasına neden olur. Bazı kısımları oldukça kafa karıştırıcı ve kötü tasarlanmış durumdadır. -## Networks and the Internet +## Ağlar ve İnternet -Computer ((network))s have been around since the 1950s. If you put cables between two or more computers and allow them to send data back and forth through these cables, you can do all kinds of wonderful things. +Bilgisayar ((ağ))ları 1950’lerden beri var. İki veya daha fazla bilgisayar arasında kablolar döşeyip bu kablolar aracılığıyla veri alışverişi yapmalarına izin verirseniz, her türlü harika şeyi yapabilirsiniz. -If connecting two machines in the same building allows us to do wonderful things, connecting machines all over the planet should be even better. The technology to start implementing this vision was developed in the 1980s, and the resulting network is called the _((Internet))_. It has lived up to its promise. +Ve aynı binadaki iki makineyi bağlamak harika şeyler yapmamızı sağlıyorsa, tüm gezegen üzerindeki makineleri bağlamak daha da iyi olmalıdır. Bu vizyonu hayata geçirecek teknoloji 1980’lerde geliştirildi ve ortaya çıkan ağa _((İnternet))_ adı verildi. Bu sözünü yerine getirdi. -A computer can use this network to shoot bits at another computer. For any effective ((communication)) to arise out of this bit-shooting, the computers on both ends must know what the bits are supposed to represent. The meaning of any given sequence of bits depends entirely on the kind of thing that it is trying to express and on the ((encoding)) mechanism used. +Bir bilgisayar bu ağı kullanarak başka bir bilgisayara bit gönderebilir. Bu bit gönderiminden etkili bir ((iletişim)) sağlamak için, her iki uçtaki bilgisayarlar bitlerin neyi temsil etmesi gerektiğini bilmelidir. Herhangi bir bit dizisinin anlamı, tamamen ifade etmeye çalıştığı şeye ve kullanılan ((kodlama)) mekanizmasına bağlıdır. {{index [network, protocol]}} -A _network ((protocol))_ describes a style of communication over a ((network)). There are protocols for sending email, for fetching email, for sharing files, and even for controlling computers that happen to be infected by malicious software. +Bir ağ ((protokolü)), bir ağ üzerindeki iletişim tarzını tanımlar. E-posta göndermek, e-posta almak, dosya paylaşmak ve hatta kötü niyetli yazılımlarla enfekte olmuş bilgisayarları kontrol etmek için protokoller vardır. -{{indexsee "Hypertext Transfer Protocol", HTTP}} +{{indexsee "HyperText Transfer Protocol", HTTP}} -The _Hypertext Transfer Protocol_ (((HTTP))) is a protocol for retrieving named ((resource))s (chunks of information, such as web pages or pictures). It specifies that the side making the request should start with a line like this, naming the resource and the version of the protocol that it is trying to use: +_Hypertext Transfer Protocol_ (((HTTP))), adlandırılmış ((kaynak))ların (web sayfaları veya resimler gibi bilgi parçalarının) alınması için bir protokoldür. İstek yapan tarafın, kaynağı ve kullanmak istediği protokolün sürümünü adlandıran şöyle bir satırla başlamasını belirtir: ```{lang: http} GET /index.html HTTP/1.1 ``` -There are many more rules about the way the requester can include more information in the ((request)) and the way the other side, which returns the resource, packages up its content. We'll look at HTTP in a little more detail in [Chapter ?](http). +İstek yapan tarafın daha fazla bilgi ekleyebilmesi ve diğer tarafın kaynağı nasıl paketlediği hakkında daha fazla kural vardır. HTTP’yi [bölüm ?](http) içinde biraz daha detaylı inceleyeceğiz. {{index layering, stream, ordering}} -Most protocols are built on top of other protocols. HTTP treats the network as a streamlike device into which you can put bits and have them arrive at the correct destination in the correct order. Providing those guarantees on top of the primitive data-sending that the network gives you is already a rather tricky problem. +Çoğu protokol, diğer protokoller üzerine kuruludur. HTTP, ağın içine bitler koyabileceğiniz ve bunların doğru sırayla doğru yere varmasını sağlayan bir cihaz gibi davranır. Ağın sağladığı bu ilkel veri gönderimi üzerinde bu işi sağlamak oldukça zor bir problemdir. {{index TCP}} {{indexsee "Transmission Control Protocol", TCP}} -The _Transmission Control Protocol_ (TCP) is a ((protocol)) that addresses this problem. All Internet-connected devices "speak" it, and most communication on the ((Internet)) is built on top of it. +_Transmission Control Protocol_ (TCP), bu problemi ele alan bir ((protokol))dür. Tüm internet bağlantılı cihazlar bunu “konuşur” ve İnternet’teki çoğu iletişim bunun üzerine kuruludur. {{index "listening (TCP)"}} -A TCP ((connection)) works as follows: one computer must be waiting, or _listening_, for other computers to start talking to it. To be able to listen for different kinds of communication at the same time on a single machine, each listener has a number (called a _((port))_) associated with it. Most ((protocol))s specify which port should be used by default. For example, when we want to send an email using the ((SMTP)) protocol, the machine through which we send it is expected to be listening on port 25. +Bir TCP ((bağlantısı)) şu şekilde çalışır: Bir bilgisayar, diğer bilgisayarların kendisiyle konuşmaya başlamasını bekler ya da _dinler_. Aynı makinede aynı anda farklı türlerde iletişimleri dinleyebilmek için, her dinleyicinin kendisiyle ilişkilendirilen bir numarası (bir _((port))_) vardır. Çoğu ((protokol)), varsayılan olarak hangi portun kullanılacağını belirtir. Örneğin, ((SMTP)) protokolünü kullanarak bir e-posta göndermek istediğimizde, gönderdiğimiz makinenin port 25’te dinlemesi beklenir. -Another computer can then establish a ((connection)) by connecting to the target machine using the correct port number. If the target machine can be reached and is listening on that port, the connection is successfully created. The listening computer is called the _((server))_, and the connecting computer is called the _((client))_. +Daha sonra başka bir bilgisayar, doğru port numarasını kullanarak hedef makineye bağlanarak bir ((bağlantı)) kurabilir. Hedef makineye erişilebilir ve o portta dinliyorsa, bağlantı başarılı bir şekilde kurulur. Dinleyen bilgisayara _((server))_, bağlanan bilgisayara ise _((client))_ denir. {{index [abstraction, "of the network"]}} -Such a connection acts as a two-way ((pipe)) through which bits can flow—the machines on both ends can put data into it. Once the bits are successfully transmitted, they can be read out again by the machine on the other side. This is a convenient model. You could say that ((TCP)) provides an abstraction of the network. +Böyle bir bağlantı, iki yönlü bir ((boru)) gibi davranır - her iki uçtaki makineler de içine veri koyabilir. Bitler başarıyla iletildikten sonra, karşı taraftaki makine tarafından yeniden okunabilir. Bu, uygun bir modeldir. ((TCP))’nin ağa bir soyutlama sağladığı söylenebilir. {{id web}} -## The Web +## Web -The _((World Wide Web))_ (not to be confused with the ((Internet)) as a whole) is a set of ((protocol))s and formats that allow us to visit web pages in a browser. "Web" refers to the fact that such pages can easily link to each other, thus connecting into a huge ((mesh)) that users can move through. +_((World Wide Web))_ (tüm ((Internet)) ile karıştırılmamalıdır), bir tarayıcıda web sayfalarını ziyaret etmemizi sağlayan bir dizi ((protokol)) ve formattır. İsmin “Web” kısmı, bu sayfaların kolayca birbirine bağlanabilmesine ve böylece kullanıcıların içinde hareket edebileceği büyük bir ((ağ)) oluşturmasına atıfta bulunur. -To become part of the Web, all you need to do is connect a machine to the ((Internet)) and have it listen on port 80 with the ((HTTP)) protocol so that other computers can ask it for documents. +Web’in bir parçası olmak için yapmanız gereken tek şey, bir makineyi ((Internet))e bağlamak ve ((HTTP)) protokolü ile port 80’de dinlemesini sağlamaktır, böylece diğer bilgisayarlar belgeleri isteyebilir. {{index URL}} -{{indexsee "Uniform Resource Locator", URL}} +{{indexsee "uniform resource locator", URL}} -Each ((document)) on the Web is named by a _Uniform Resource Locator_ (URL), which looks something like this: +Web’deki her ((belge))ye Uniform Resource Locator (URL) adı verilir ve şu şekilde görünür: ```{lang: null} http://eloquentjavascript.net/13_browser.html @@ -82,23 +82,23 @@ Each ((document)) on the Web is named by a _Uniform Resource Locator_ (URL), whi {{index HTTPS}} -The first part tells us that this URL uses the HTTP ((protocol)) (as opposed to, for example, encrypted HTTP, which would be _https://_). Then comes the part that identifies which ((server)) we are requesting the document from. Last is a path string that identifies the document (or _((resource))_) we are interested in. +İlk kısım, bu URL’nin HTTP ((protokolü))nü kullandığını belirtir (örneğin, şifrelenmiş HTTP, _https://_ olacaktır). Ardından, belgenin hangi ((server))dan isteneceğini belirleyen kısım gelir. Son olarak, ilgilendiğimiz belirli belgeyi (veya _((kaynak))_) tanımlayan bir yol dizesi gelir. -Machines connected to the Internet get an _((IP address))_, a number that can be used to send messages to that machine, and looks something like `149.210.142.219` or `2001:4860:4860::8888`. Since lists of more or less random numbers are hard to remember and awkward to type, you can instead register a _((domain)) name_ for an address or set of addresses. I registered _eloquentjavascript.net_ to point at the IP address of a machine I control and can thus use that domain name to serve web pages. +İnternete bağlanan makineler bir _((IP adresi))_ alır, bu, o makineye mesaj göndermek için kullanılabilen bir numaradır ve `149.210.142.219` veya `2001:4860:4860::8888` gibi görünür. Ancak rastgele sayıların listeleri hatırlaması zor ve yazması zahmetlidir, bu yüzden belirli bir adres veya adres seti için bir _((domain))_ adı kaydedebilirsiniz. Kontrol ettiğim bir makineye işaret etmek için eloquentjavascript.net kaydettim ve bu domain adını kullanarak web sayfaları sunabilirim. {{index browser}} -If you type this URL into your browser's ((address bar)), the browser will try to retrieve and display the ((document)) at that URL. First, your browser has to find out what address _eloquentjavascript.net_ refers to. Then, using the ((HTTP)) protocol, it will make a connection to the server at that address and ask for the resource _/13_browser.html_. If all goes well, the server sends back a document, which your browser then displays on your screen. +Bu URL’yi tarayıcınızın ((adres çubuğu))na yazarsanız, tarayıcı bu URL’deki ((belge))yi almaya ve görüntülemeye çalışacaktır. Önce tarayıcınız _eloquentjavascript.net_‘in hangi adrese karşılık geldiğini bulmalıdır. Ardından, ((HTTP)) protokolünü kullanarak, o adresteki server’a bir bağlantı kuracak ve _/13_browser.html_ kaynağını isteyecektir. Her şey yolunda giderse, server bir belge gönderir ve tarayıcınız bu belgeyi ekranınızda görüntüler. ## HTML {{index HTML}} -{{indexsee "Hypertext Markup Language", HTML}} +{{indexsee "HyperText Markup Language", HTML}} -_HTML_, which stands for _Hypertext Markup Language_, is the document format used for web pages. An HTML document contains ((text)), as well as _((tag))s_ that give structure to the text, describing things such as links, paragraphs, and headings. +HTML, _Hypertext Markup Language_’ın kısaltması olup, web sayfaları için kullanılan belge formatıdır. Bir HTML belgesi, metin ile birlikte, metne yapı kazandıran, bağlantılar, paragraflar ve başlıklar gibi şeyleri tanımlayan _((etiketler))_ içerir. -A short HTML document might look like this: +Kısa bir HTML belgesi şu şekilde görünebilir: ```{lang: "html"} @@ -118,45 +118,45 @@ A short HTML document might look like this: {{if book -This is what such a document would look like in the browser: +Böyle bir belgenin tarayıcıda görünümü şöyle olacaktır: -{{figure {url: "img/home-page.png", alt: "A rendered version of the home page example HTML",width: "6.3cm"}}} +{{figure {url: "img/home-page.png", alt: "Ana sayfa örnek HTML'sinin işlenmiş bir sürümü",width: "6.3cm"}}} if}} {{index [HTML, notation]}} -The tags, wrapped in ((angle brackets)) (`<` and `>`, the symbols for _less than_ and _greater than_), provide information about the ((structure)) of the document. The other ((text)) is just plain text. +Açı ((parantez))ler (`<` ve` >`, _küçüktür_ ve _büyüktür_ sembolleri), belgenin ((yapısı)) hakkında bilgi sağlar. Diğer ((metin)) ise sade metindir. {{index doctype, version}} -The document starts with ``, which tells the browser to interpret the page as _modern_ HTML, as opposed to obsolete styles used in the past. +Belge `` ile başlar, bu da tarayıcıya sayfayı _modern_ HTML olarak yorumlamasını, geçmişte kullanılan eski stillerden farklı olarak belirtir. {{index "head (HTML tag)", "body (HTML tag)", "title (HTML tag)", "h1 (HTML tag)", "p (HTML tag)"}} -HTML documents have a head and a body. The head contains information _about_ the document, and the body contains the document itself. In this case, the head declares that the title of this document is "My home page" and that it uses the UTF-8 encoding, which is a way to encode Unicode text as binary data. The document's body contains a heading (`

`, meaning "heading 1"—`

` to `

` produce subheadings) and two ((paragraph))s (`

`). +HTML belgeleri bir baş ve bir gövdeye sahiptir. Baş, belge _hakkında_ bilgileri içerirken, gövde belgenin kendisini içerir. Bu durumda, baş, belgenin başlığının “Ana sayfam” olduğunu ve UTF-8 kodlamasını kullandığını belirtir; bu, Unicode metnini ikili veri olarak kodlama yöntemidir. Belgenin gövdesi bir başlık (`

`, “başlık 1” anlamına gelir—`

`’den `

`’ya kadar alt başlıklar oluşturur) ve iki ((paragraf)) (`

`) içerir. {{index "href attribute", "a (HTML tag)"}} -Tags come in several forms. An ((element)), such as the body, a paragraph, or a link, is started by an _((opening tag))_ like `

` and ended by a _((closing tag))_ like `

`. Some opening tags, such as the one for the ((link)) (``), contain extra information in the form of `name="value"` pairs. These are called _((attribute))s_. In this case, the destination of the link is indicated with `href="http://eloquentjavascript.net"`, where `href` stands for "hypertext reference". +Etiketler birkaç formda gelir. Gövde, bir paragraf veya bağlantı gibi bir ((öğe)), bir _((açılış etiketi))_ `

` ile başlatılır ve bir _((kapanış etiketi))_ `

` ile sonlandırılır. Bağlantı için kullanılan etiket (`
`) gibi bazı açılış etiketleri, `name="value"` çiftleri şeklinde ek bilgi içerir. Bunlara _((özellikler))_ denir. Bu durumda, bağlantının hedefi `href="http://eloquentjavascript.net"` ile belirtilir, burada `href` “hiper metin referansı” anlamına gelir. {{index "src attribute", "self-closing tag", "img (HTML tag)"}} -Some kinds of ((tag))s do not enclose anything and thus do not need to be closed. The metadata tag `` is an example of this. +Bazı ((etiket)) türleri herhangi bir şeyi kapsamaz ve bu nedenle kapatılmaları gerekmez. `` etiketi bunun bir örneğidir. {{index [escaping, "in HTML"]}} -To be able to include ((angle brackets)) in the text of a document even though they have a special meaning in HTML, yet another form of special notation has to be introduced. A plain opening angle bracket is written as `<` ("less than"), and a closing bracket is written as `>` ("greater than"). In HTML, an ampersand (`&`) character followed by a name or character code and a semicolon (`;`) is called an _((entity))_ and will be replaced by the character it encodes. +Bir belgenin metninde açı ((parantez))ler kullanabilmek için, HTML’de özel bir anlamı olan bu semboller için özel bir gösterim biçimi tanıtılmalıdır. Düz bir açılış açı parantezi `<` (“küçüktür”) ve kapanış parantezi `>` (“büyüktür”) olarak yazılır. HTML’de, bir isim veya karakter kodu ve noktalı virgül (`;`) ile takip edilen bir ampersand (`&`) karakterine _((varlık))_ denir ve kodladığı karakterle değiştirilir. {{index ["backslash character", "in strings"], "ampersand character", "double-quote character"}} -This is analogous to the way backslashes are used in JavaScript strings. Since this mechanism gives ampersand characters a special meaning too, they need to be escaped as `&`. Inside attribute values, which are wrapped in double quotes, `"` can be used to insert a literal quote character. +Bu, JavaScript dizelerinde ters eğik çizgilerin kullanılma şekline benzer. Bu mekanizma ampersand karakterlerine de özel bir anlam verdiğinden, `&` olarak kaçırılmaları gerekir. Çift tırnak içine alınmış özellik değerleri içinde, gerçek bir tırnak karakteri eklemek için `"` kullanılabilir. {{index "error tolerance", parsing}} -HTML is parsed in a remarkably error-tolerant way. When tags that should be there are missing, the browser automatically adds them. The way this is done has been standardized, and you can rely on all modern browsers to do it in the same way. +HTML, oldukça hata tolere eden bir şekilde ayrıştırılır. Eksik olması gereken etiketler olduğunda, tarayıcı bunları otomatik olarak ekler. Bunun yapılma şekli standartlaştırılmıştır ve tüm modern tarayıcıların aynı şekilde yapmasını bekleyebilirsiniz. -The following document will be treated just like the one shown previously: +Aşağıdaki belge daha önce gösterilen belge ile aynı şekilde ele alınacaktır: ```{lang: "html"} @@ -172,21 +172,21 @@ The following document will be treated just like the one shown previously: {{index "title (HTML tag)", "head (HTML tag)", "body (HTML tag)", "html (HTML tag)"}} -The ``, ``, and `` tags are completely gone. The browser knows that `` and `` belong in the head and that `<h1>` means the body has started. Furthermore, I am no longer explicitly closing the paragraphs since opening a new paragraph or ending the document will close them implicitly. The quotes around the attribute values are also gone. +`<html>`, `<head>`, ve `<body>` etiketleri tamamen ortadan kalkmıştır. Tarayıcı `<meta>` ve `<title>` etiketlerinin başta olduğunu ve `<h1>` etiketinin gövdenin başladığını bilir. Ayrıca, paragrafları açıkça kapatmıyorum çünkü yeni bir paragraf açmak veya belgeyi sonlandırmak onları örtük olarak kapatacaktır. Özellik değerlerinin etrafındaki tırnak işaretleri de yok. -This book will usually omit the `<html>`, `<head>`, and `<body>` tags from examples to keep them short and free of clutter. I _will_ close tags and include quotes around attributes, though. +Bu kitap genellikle örneklerde `<html>`, `<head>`, ve `<body>` etiketlerini kısa ve karmaşadan uzak tutmak için ihmal edecektir. Ancak, etiketleri _kapatacağım_ ve özelliklerin etrafında tırnak işaretleri kullanacağım. {{index browser}} -I will also usually omit the ((doctype)) and `charset` declaration. Don't take this as encouragement to drop these from HTML documents. Browsers will often do ridiculous things when you forget them. Consider the doctype and the `charset` metadata to be implicitly present in examples, even when they are not actually shown in the text. +Ayrıca genellikle ((doctype)) ve `charset` beyanını ihmal edeceğim. Bu, bunları HTML belgelerinden çıkarmanızı teşvik etmek için alınmamalıdır. Tarayıcılar, bunları unuttuğunuzda genellikle saçma şeyler yapar. Örneklerde, bunlar metinde gösterilmediğinde bile, doctype ve `charset` meta verilerinin örtük olarak mevcut olduğunu varsaymalısınız. {{id script_tag}} -## HTML and JavaScript +## HTML ve JavaScript {{index [JavaScript, "in HTML"], "script (HTML tag)"}} -In the context of this book, the most important HTML tag is `<script>`, which allows us to include a piece of JavaScript in a document. +Bu kitabın bağlamında en önemli HTML etiketi `<script>`’tir. Bu etiket, bir belgeye bir parça JavaScript eklememizi sağlar. ```{lang: "html"} <h1>Testing alert</h1> @@ -195,30 +195,30 @@ In the context of this book, the most important HTML tag is `<script>`, which al {{index "alert function", timeline}} -Such a script will run as soon as its `<script>` tag is encountered while the browser reads the HTML. This page will pop up a dialog when opened—the `alert` function resembles `prompt`, in that it pops up a little window, but only shows a message without asking for input. +Tarayıcı HTML’yi okurken `<script>` etiketi ile karşılaştığında böyle bir betik çalışacaktır. Bu sayfa açıldığında bir iletişim kutusu açılır—`alert` fonksiyonu, küçük bir pencere açarak bir `prompt` gösterir, ancak giriş istemez. {{index "src attribute"}} -Including large programs directly in HTML documents is often impractical. The `<script>` tag can be given an `src` attribute to fetch a script file (a text file containing a JavaScript program) from a URL. +Including large programs directly in HTML documents is often impractical. The `<script>` tag can be given an `src` attribute to fetch a script file (a text file containing a JavaScript program) from a URL. ```{lang: "html"} <h1>Testing alert</h1> <script src="code/hello.js"></script> ``` -The _code/hello.js_ file included here contains the same program—`alert("hello!")`. When an HTML page references other URLs as part of itself, such as an image file or a script, web browsers will retrieve them immediately and include them in the page. +Burada dahil edilen _code/hello.js_ dosyası aynı programı içerir—`alert("hello!")`. Bir HTML sayfası, kendisinin bir parçası olarak diğer URL’lere referans verdiğinde—örneğin, bir resim dosyası veya bir betik—web tarayıcıları bunları hemen alır ve sayfaya dahil eder. {{index "script (HTML tag)", "closing tag"}} -A script tag must always be closed with `</script>`, even if it refers to a script file and doesn't contain any code. If you forget this, the rest of the page will be interpreted as part of the script. +Bir betik etiketi her zaman `</script>` ile kapatılmalıdır, eğer bir betik dosyasına referans veriyorsa ve herhangi bir kod içermiyorsa bile. Bunu unutursanız, sayfanın geri kalanı betiğin bir parçası olarak yorumlanacaktır. {{index "relative path", dependency}} -You can load ((ES modules)) (see [Chapter ?](modules#es)) in the browser by giving your script tag a `type="module"` attribute. Such modules can depend on other modules by using ((URL))s relative to themselves as module names in `import` declarations. +((ES modülleri)) (bkz. [bölüm ?](modules#es)) tarayıcıda betik etiketinize `type="module"` özelliği vererek yükleyebilirsiniz. Bu tür modüller, `import` deklarasyonlarında modül adı olarak kendilerine göre nispeten URL’leri kullanarak diğer modüllere bağımlı olabilir. {{index "button (HTML tag)", "onclick attribute"}} -Some attributes can also contain a JavaScript program. The `<button>` tag (which shows up as a button) supports an `onclick` attribute. The attribute's value will be run whenever the button is clicked. +Bazı özellikler de bir JavaScript programı içerebilir. Bir sonraki gösterilen `<button>` etiketi (bir düğme olarak görünür) bir `onclick` özelliğine sahiptir. Bu özelliğin değeri, düğmeye tıklandığında çalışacaktır. ```{lang: "html"} <button onclick="alert('Boom!');">DO NOT PRESS</button> @@ -226,42 +226,38 @@ Some attributes can also contain a JavaScript program. The `<button>` tag (which {{index "single-quote character", [escaping, "in HTML"]}} -Note that I had to use single quotes for the string in the `onclick` attribute because double quotes are already used to quote the whole attribute. I could also have used `"` to escape the inner quotes. +Dikkat edin, `onclick` özelliğindeki dize için tek tırnak kullanmam gerekti çünkü tüm özelliği tırnak içine almak için zaten çift tırnak kullanılmıştı. `"` de kullanılabilirdi. -## In the sandbox +## Kum havuzunda {{index "malicious script", "World Wide Web", browser, website, security}} -Running programs downloaded from the ((Internet)) is potentially dangerous. You don't know much about the people behind most sites you visit, and they do not necessarily mean well. Running programs by malicious actors is how you get your computer infected by ((virus))es, your data stolen, and your accounts hacked. +((İnternetten)) indirilen programları çalıştırmak potansiyel olarak tehlikelidir. Ziyaret ettiğiniz çoğu sitenin arkasındaki insanlar hakkında pek fazla bir şey bilmiyorsunuz ve onların iyi niyetli oldukları söylenemez. İyi niyetli olmayan insanların programlarını çalıştırmak, bilgisayarınıza ((virüs)) bulaştırmanın, verilerinizi çaldırmanın ve hesaplarınızın hacklenmesinin yollarından biridir. -Yet the attraction of the Web is that you can browse it without necessarily ((trust))ing all the pages you visit. This is why browsers severely limit the things a JavaScript program may do: it can't look at the files on your computer or modify anything not related to the web page it was embedded in. +Buna karşın, Web’in cazibesi, tüm ziyaret ettiğiniz sayfalara ((güvenmeden)) gezinmenizi sağlamasıdır. Bu nedenle tarayıcılar, bir JavaScript programının yapabileceği şeyleri ciddi şekilde sınırlar: bilgisayarınızdaki dosyalara bakamaz veya yerleştirildiği web sayfasıyla ilgili olmayan herhangi bir şeyi değiştiremez. {{index isolation}} -Isolating a programming environment in this way is called _((sandbox))ing_, the idea being that the program is harmlessly playing in a sandbox. But you should imagine this particular kind of sandbox as having a cage of thick steel bars over it so that the programs playing in it can't actually get out. +Bu şekilde bir programlama ortamını izole etmeye _((sandbox))ing_ denir, yani programın zararsız bir şekilde bir kum havuzunda oynadığı varsayılır. Ancak bu özel türde kum havuzunu, içinde oynayan programların gerçekten dışarı çıkamayacağı kalın çelik çubuklardan oluşan bir kafes olarak hayal etmelisiniz. -The hard part of sandboxing is allowing programs enough room to be useful while restricting them from doing anything dangerous. Lots of useful functionality, such as communicating with other servers or reading the content of the copy-paste ((clipboard)), can also be used for problematic, ((privacy))-invading purposes. +Sandboxing’in zor kısmı, programlara faydalı olabilecek kadar alan sağlamak, ancak aynı zamanda tehlikeli bir şey yapmalarını engellemektir. Diğer sunucularla iletişim kurmak veya ((kopyala-yapıştır panosu)) içeriğini okumak gibi birçok kullanışlı fonksiyonellik, aynı zamanda sorunlu, ((mahremiyet)) ihlal edici şeyler yapmak için de kullanılabilir. {{index leak, exploit, security}} -Every now and then, someone comes up with a new way to circumvent the limitations of a ((browser)) and do something harmful, ranging from leaking minor private information to taking over the whole machine on which the browser is running. The browser developers respond by fixing the hole, and all is well again—until the next problem is discovered, and hopefully publicized, rather than secretly exploited by some government agency or criminal organization. +Zaman zaman, birisi bir ((tarayıcının)) sınırlamalarını aşmanın ve zararlı bir şey yapmanın yeni bir yolunu bulur; bu, küçük özel bilgileri sızdırmaktan tarayıcının çalıştığı tüm makineyi ele geçirmeye kadar çeşitlilik gösterebilir. Tarayıcı geliştiricileri deliği kapatarak yanıt verir ve her şey tekrar düzelir—ta ki bir sonraki sorun keşfedilip, umarım gizlice istismar edilmek yerine kamuya açıklanana kadar, bu bir hükümet ajansı veya ((mafya)) tarafından. -## Compatibility and the browser wars +## Uyumluluk ve tarayıcı savaşları {{index Microsoft, "World Wide Web"}} -In the early stages of the Web, a browser called ((Mosaic)) dominated the market. After a few years, the balance shifted to ((Netscape)), which was, in turn, largely supplanted by Microsoft's ((Internet Explorer)). At any point where a single ((browser)) was dominant, that browser's vendor would feel entitled to unilaterally invent new features for the Web. Since most users used the most popular browser, ((website))s would simply start using those features—never mind the other browsers. +Web’in erken aşamalarında, ((Mosaic)) adlı bir tarayıcı piyasaya hakim oldu. Birkaç yıl sonra, denge ((Netscape))’e kaydı, ancak o da büyük ölçüde Microsoft’un ((Internet Explorer))’ı tarafından yerinden edildi. Tek bir tarayıcının hakim olduğu her noktada, o tarayıcının satıcısı Web için tek taraflı olarak yeni özellikler icat etme hakkını kendinde bulurdu. Çoğu kullanıcı en popüler tarayıcıyı kullandığından, ((web sitesi))ler bu özellikleri kullanmaya başlardı—diğer tarayıcıları umursamadan. -This was the dark age of ((compatibility)), often called the _((browser wars))_. Web developers were left with not one unified Web but two or three incompatible platforms. To make things worse, the browsers in use around 2003 were all full of ((bug))s, and of course the bugs were different for each ((browser)). Life was hard for people writing web pages. +Bu, genellikle _((tarayıcı savaşları))_ olarak adlandırılan ((uyumluluk)) karanlık çağlarıydı. Web geliştiricileri, tek bir birleşik Web yerine iki veya üç uyumsuz platformla baş başa kalıyordu. Daha da kötüsü, 2003 civarında kullanılan tarayıcılar, farklı tarayıcılarda farklı ((hata))larla doluydu. Web sayfası yazan insanlar için hayat zordu. {{index Apple, "Internet Explorer", Mozilla}} -Mozilla ((Firefox)), a not-for-profit offshoot of ((Netscape)), challenged Internet Explorer's position in the late 2000s. Because ((Microsoft)) was not particularly interested in staying competitive at the time, Firefox took a lot of market share away from it. Around the same time, ((Google)) introduced its ((Chrome)) browser and Apple's ((Safari)) browser gained popularity, leading to a situation where there were four major players, rather than one. +((Netscape))’in kar amacı gütmeyen bir yan ürünü olan Mozilla ((Firefox)), 2000’lerin sonlarında Internet Explorer’ın konumunu zorladı. O dönemde ((Microsoft)), rekabetçi kalmakla pek ilgilenmediği için, Firefox ondan büyük bir pazar payı aldı. Aynı dönemde, ((Google)) Chrome tarayıcısını tanıttı ve Apple’ın ((Safari)) tarayıcısı popülerlik kazandı, bu da dört büyük oyuncunun olduğu bir duruma yol açtı. {{index compatibility}} -The new players had a more serious attitude toward ((standards)) and better ((engineering)) practices, giving us less incompatibility and fewer ((bug))s. Microsoft, seeing its market share crumble, came around and adopted these attitudes in its Edge browser, which replaced Internet Explorer. If you are starting to learn web development today, consider yourself lucky. The latest versions of the major browsers behave quite uniformly and have relatively few bugs. - -Unfortunately, with Firefox's market share getting ever smaller, and Edge becoming just a wrapper around Chrome's core in 2018, this uniformity might once again take the form of a single vendor—Google, this time—having enough control over the browser market to push its idea of what the Web should look like onto the rest of the world. - -For what it is worth, this long chain of historical events and accidents has produced the web platform that we have today. In the next chapters, we are going to write programs for it. \ No newline at end of file +Yeni oyuncular, ((standartlar))a daha ciddi bir yaklaşım ve daha iyi ((mühendislik)) uygulamaları benimseyerek, daha az uyumsuzluk ve daha az ((hata)) ile karşımıza çıktı. Pazar payının eridiğini gören Microsoft, bu tutumları benimseyerek Internet Explorer’ın yerini alan Edge tarayıcısını geliştirdi. Eğer bugün web geliştirmeyi öğrenmeye başlıyorsanız, kendinizi şanslı sayın. Büyük tarayıcıların en son sürümleri oldukça tutarlı davranır ve nispeten az sayıda hataya sahiptir. diff --git a/14_dom.md b/14_dom.md index ed5d8080..7519874a 100644 --- a/14_dom.md +++ b/14_dom.md @@ -1,26 +1,26 @@ -# The Document Object Model +# Belge Nesne Modeli(Document Object Model) -{{quote {author: "Friedrich Nietzsche", title: "Beyond Good and Evil", chapter: true} +{{quote {author: "Friedrich Nietzsche", title: "İyinin ve Kötünün Ötesinde", chapter: true} -Too bad! Same old story! Once you've finished building your house you notice you've accidentally learned something that you really should have known—before you started. +Çok kötü! Aynı eski hikaye! Evinizi inşa etmeyi bitirdikten sonra, başlamadan önce gerçekten bilmeniz gereken bir şeyi yanlışlıkla öğrendiğinizi fark edersiniz. quote}} -{{figure {url: "img/chapter_picture_14.jpg", alt: "Illustration showing a tree with letters, pictures, and gears hanging on its branches", chapter: "framed"}}} +{{figure {url: "img/chapter_picture_14.jpg", alt: "Dallarında harfler, resimler ve dişliler asılı bir ağacı gösteren illüstrasyon", chapter: "framed"}}} {{index drawing, parsing}} -When you open a web page, your browser retrieves the page's ((HTML)) text and parses it, much like our parser from [Chapter ?](language#parsing) parsed programs. The browser builds up a model of the document's ((structure)) and uses this model to draw the page on the screen. +Bir web sayfası açtığınızda, tarayıcınız sayfanın ((HTML)) metnini alır ve bunu, [bölüm ?](language#parsing) içindeki ayrıştırıcımızın programları ayrıştırdığı gibi ayrıştırır. Tarayıcı, belgenin ((yapısı))nın bir modelini oluşturur ve bu modeli sayfayı ekranda çizmek için kullanır. {{index "live data structure"}} -This representation of the ((document)) is one of the toys that a JavaScript program has available in its ((sandbox)). It is a ((data structure)) that you can read or modify. It acts as a _live_ data structure: when it's modified, the page on the screen is updated to reflect the changes. +Bu ((belgenin)) temsili, JavaScript programının ((sandbox)) içinde kullanabileceği oyuncaklardan biridir. Okuyabileceğiniz veya değiştirebileceğiniz bir ((veri yapısı))dır. Bu, _canlı_ bir veri yapısı olarak işlev görür: değiştirildiğinde, ekrandaki sayfa değişiklikleri yansıtacak şekilde güncellenir. -## Document structure +## Doküman yapısı {{index [HTML, structure]}} -You can imagine an HTML document as a nested set of ((box))es. Tags such as `<body>` and `</body>` enclose other ((tag))s, which in turn contain other tags or ((text)). Here's the example document from the [previous chapter](browser): +Bir HTML belgesini, iç içe geçmiş bir dizi ((kutu)) olarak hayal edebilirsiniz. `<body>` ve `</body>` gibi etiketler, diğer ((etiket))leri kapsar, bu etiketler de sırasıyla başka etiketler veya ((metin)) içerir. İşte [önceki bölümdeki](browser) örnek belge: ```{lang: html, sandbox: "homepage"} <!doctype html> @@ -39,95 +39,95 @@ You can imagine an HTML document as a nested set of ((box))es. Tags such as `<bo This page has the following structure: -{{figure {url: "img/html-boxes.svg", alt: "Diagram showing an HTML document as a set of nested boxes. The outer box is labeled 'html' and contains two boxes labeled 'head' and 'body'. Inside those are further boxes, with some of the innermost boxes containing the document's text.", width: "7cm"}}} +{{figure {url: "img/html-boxes.svg", alt: "Bir HTML belgesini iç içe geçmiş kutular kümesi olarak gösteren diyagram. Dış kutu 'html' olarak etiketlenmiştir ve 'head' ve 'body' olarak etiketlenmiş iki kutu içerir. Bunların içinde başka kutular vardır ve en içteki kutulardan bazıları belgenin metnini içerir.", width: "7cm"}}} {{indexsee "Document Object Model", DOM}} -The data structure the browser uses to represent the document follows this shape. For each box, there is an object, which we can interact with to find out things such as what HTML tag it represents and which boxes and text it contains. This representation is called the _Document Object Model_, or _((DOM))_ for short. +Tarayıcının belgeyi temsil etmek için kullandığı veri yapısı bu şekli takip eder. Her kutu için, hangi HTML etiketini temsil ettiğini ve içerdiği kutu ve metinleri öğrenmek için etkileşime girebileceğimiz bir nesne vardır. Bu temsile _Document Object Model_ veya kısaca ((DOM)) denir. {{index "documentElement property", "head property", "body property", "html (HTML tag)", "body (HTML tag)", "head (HTML tag)"}} -The global binding `document` gives us access to these objects. Its `documentElement` property refers to the object representing the `<html>` tag. Since every HTML document has a head and a body, it also has `head` and `body` properties pointing at those elements. +Küresel `document` bağı, bu nesnelere erişim sağlar. `documentElement` özelliği, `<html>` etiketini temsil eden nesneye atıfta bulunur. Her HTML belgesinde bir baş ve bir gövde bulunduğundan, `head` ve `body` özelliklerine de sahiptir, bu öğelere işaret eder. -## Trees +## Ağaçlar {{index [nesting, "of objects"]}} -Think back to the ((syntax tree))s from [Chapter ?](language#parsing) for a moment. Their structures are strikingly similar to the structure of a browser's document. Each _((node))_ may refer to other nodes, _children_, which in turn may have their own children. This shape is typical of nested structures where elements can contain subelements that are similar to themselves. +Bir an için [bölüm ?](language#parsing) ((sözdizim ağacı))na geri dönün. Yapıları, bir tarayıcının belgesinin yapısına çarpıcı biçimde benzer. Her bir _((düğüm))_, başka düğümlere, yani _çocuklar_, atıfta bulunabilir, bu da kendi çocuklarına sahip olabilir. Bu şekil, öğelerin kendilerine benzer alt öğeler içerebileceği iç içe geçmiş yapılara özgüdür. {{index "documentElement property", [DOM, tree]}} -We call a data structure a _((tree))_ when it has a branching structure, no ((cycle))s (a node may not contain itself, directly or indirectly), and a single, well-defined _((root))_. In the case of the DOM, `document.documentElement` serves as the root. +Bir veri yapısına, dallanma yapısına sahip olduğunda, ((döngü))süz (bir düğüm doğrudan veya dolaylı olarak kendisini içeremez) ve tek, iyi tanımlanmış bir _((kök))_ olduğunda _((ağaç))_ denir. DOM durumunda, `document.documentElement` kök olarak hizmet eder. {{index sorting, ["data structure", "tree"], "syntax tree"}} -Trees come up a lot in computer science. In addition to representing recursive structures such as HTML documents or programs, they are often used to maintain sorted ((set))s of data because elements can usually be found or inserted more efficiently in a tree than in a flat array. +Ağaçlar bilgisayar biliminde sıkça karşımıza çıkar. HTML belgeleri veya programlar gibi özyinelemeli yapıları temsil etmenin yanı sıra, genellikle sıralı ((küme))ler veri tutmak için kullanılırlar çünkü ağaçlarda öğeler düz bir dizidekinden daha verimli bir şekilde bulunabilir veya eklenebilir. {{index "leaf node", "Egg language"}} -A typical tree has different kinds of ((node))s. The syntax tree for [the Egg language](language) had identifiers, values, and application nodes. Application nodes may have children, whereas identifiers and values are _leaves_, or nodes without children. +Tipik bir ağaç, farklı türde ((düğüm))lere sahiptir. [Egg dilinin](language) sözdizim ağacında tanımlayıcılar, değerler ve uygulama düğümleri vardı. Uygulama düğümleri çocuklara sahip olabilirken, tanımlayıcılar ve değerler _yaprak düğümleri_, yani çocuksuz düğümlerdi. {{index "body property", [HTML, structure]}} -The same goes for the DOM. Nodes for _((element))s_, which represent HTML tags, determine the structure of the document. These can have ((child node))s. An example of such a node is `document.body`. Some of these children can be ((leaf node))s, such as pieces of ((text)) or ((comment)) nodes. +Aynı durum DOM için de geçerlidir. HTML etiketlerini temsil eden _((öğe))_ düğümleri, belgenin yapısını belirler. Bu düğümler ((çocuk düğüm))lere sahip olabilir. Bu tür bir düğüme örnek olarak `document.body` verilebilir. Bu çocuklardan bazıları ((yaprak düğüm))ler olabilir, örneğin ((metin)) parçaları veya ((yorum)) düğümleri gibi. {{index "text node", element, "ELEMENT_NODE code", "COMMENT_NODE code", "TEXT_NODE code", "nodeType property"}} -Each DOM node object has a `nodeType` property, which contains a code (number) that identifies the type of node. Elements have code 1, which is also defined as the constant property `Node.ELEMENT_NODE`. Text nodes, representing a section of text in the document, get code 3 (`Node.TEXT_NODE`). Comments have code 8 (`Node.COMMENT_NODE`). +Her DOM düğüm nesnesinin, düğüm türünü tanımlayan bir kod (sayı) içeren bir `nodeType` özelliği vardır. Öğeler, sabit özellik `Node.ELEMENT_NODE` olarak tanımlanan 1 koduna sahiptir. Belgede bir metin bölümünü temsil eden metin düğümleri 3 kodunu (`Node.TEXT_NODE`) alır. Yorumlar 8 koduna (`Node.COMMENT_NODE`) sahiptir. -Another way to visualize our document ((tree)) is as follows: +Belgemizi ((ağacı)) görselleştirmenin bir başka yolu da aşağıdaki gibidir: -{{figure {url: "img/html-tree.svg", alt: "Diagram showing the HTML document as a tree, with arrows from parent nodes to child nodes", width: "8cm"}}} +{{figure {url: "img/html-tree.svg", alt: "HTML belgesini üst düğümlerden alt düğümlere giden oklarla bir ağaç olarak gösteren diyagram", width: "8cm"}}} -The leaves are text nodes, and the arrows indicate parent-child relationships between nodes. +Yapraklar metin düğümleridir ve oklar düğümler arasındaki ebeveyn-çocuk ilişkilerini gösterir. {{id standard}} -## The standard +## Standart {{index "programming language", [interface, design], [DOM, interface]}} -Using cryptic numeric codes to represent node types is not a very JavaScript-like thing to do. Later in this chapter, we'll see that other parts of the DOM interface also feel cumbersome and alien. This is because the DOM interface wasn't designed for JavaScript alone. Rather, it tries to be a language-neutral interface that can be used in other systems as well—not just for HTML but also for ((XML)), which is a generic ((data format)) with an HTML-like syntax. +Düğüm türlerini temsil etmek için şifreli sayısal kodlar kullanmak pek JavaScript tarzı bir yaklaşım değildir. Bu bölümün ilerleyen kısımlarında, DOM arayüzünün diğer bölümlerinin de sıkıcı ve yabancı hissettirdiğini göreceğiz. Bunun nedeni, DOM arayüzünün sadece JavaScript için tasarlanmamış olmasıdır. Bunun yerine, sadece HTML için değil, aynı zamanda HTML benzeri bir söz dizimine sahip genel bir ((veri formatı)) olan ((XML)) gibi diğer sistemlerde de kullanılabilecek dil tarafsız bir arayüz olmaya çalışır. {{index consistency, integration}} -This is unfortunate. Standards are often useful. But in this case, the advantage (cross-language consistency) isn't all that compelling. Having an interface that is properly integrated with the language you're using will save you more time than having a familiar interface across languages. +Bu talihsiz bir durum. Standartlar genellikle yararlıdır. Ancak bu durumda, avantaj (diller arası tutarlılık) pek çekici değil. Kullandığınız dil ile düzgün bir şekilde entegre edilmiş bir arayüze sahip olmak, diller arası tanıdık bir arayüze sahip olmaktan daha fazla zaman kazandıracaktır. {{index "array-like object", "NodeList type"}} -As an example of this poor integration, consider the `childNodes` property that element nodes in the DOM have. This property holds an array-like object with a `length` property and properties labeled by numbers to access the child nodes. But it is an instance of the `NodeList` type, not a real array, so it does not have methods such as `slice` and `map`. +Bu kötü entegrasyona bir örnek olarak, DOM’daki öğe düğümlerinin sahip olduğu `childNodes` özelliğini düşünün. Bu özellik, bir `length` özelliği olan ve çocuk düğümlere erişmek için numaralarla etiketlenmiş özellikler içeren dizi benzeri bir nesne tutar. Ancak bu, gerçek bir dizi olmayan `NodeList` türünün bir örneğidir, bu yüzden `slice` ve `map` gibi metodlara sahip değildir. {{index [interface, design], [DOM, construction], "side effect"}} -Then there are issues that are simply caused by poor design. For example, there is no way to create a new node and immediately add children or ((attribute))s to it. Instead, you have to first create it and then add the children and attributes one by one, using side effects. Code that interacts heavily with the DOM tends to get long, repetitive, and ugly. +Daha sonra, basitçe kötü tasarım olan sorunlar var. Örneğin, yeni bir düğüm oluşturup hemen çocukları veya ((özellik))leri eklemenin bir yolu yoktur. Bunun yerine, önce düğümü oluşturmalı ve ardından çocukları ve özellikleri tek tek yan etkiler kullanarak eklemelisiniz. DOM ile yoğun etkileşimde bulunan kodlar genellikle uzun, tekrarlayıcı ve çirkin olur. {{index library}} -But these flaws aren't fatal. Since JavaScript allows us to create our own ((abstraction))s, it is possible to design improved ways to express the operations we are performing. Many libraries intended for browser programming come with such tools. +Ancak bu kusurlar ölümcül değil. JavaScript, kendi ((soyutlama))larımızı oluşturmamıza izin verdiği için, gerçekleştirdiğiniz işlemleri ifade etmenin daha iyi yollarını tasarlamak mümkündür. Tarayıcı programlaması için tasarlanmış birçok kütüphane, bu tür araçlarla birlikte gelir. -## Moving through the tree +## Ağaç içerisinden ilerlemek {{index pointer}} -DOM nodes contain a wealth of ((link))s to other nearby nodes. The following diagram illustrates these: +DOM düğümleri, yakındaki diğer düğümlere çok sayıda ((bağlantı)) içerir. Aşağıdaki diyagram bunları göstermektedir: -{{figure {url: "img/html-links.svg", alt: "Diagram that shows the links between DOM nodes. The 'body' node is shown as a box, with a 'firstChild' arrow pointing at the 'h1' node at its start, a 'lastChild' arrow pointing at the last paragraph node, and 'childNodes' arrow pointing at an array of links to all its children. The middle paragraph has a 'previousSibling' arrow pointing at the node before it, a 'nextSibling' arrow to the node after it, and a 'parentNode' arrow pointing at the 'body' node.", width: "6cm"}}} +{{figure {url: "img/html-links.svg", alt: "DOM düğümleri arasındaki bağlantıları gösteren diyagram. 'body' düğümü, başlangıcındaki 'h1' düğümünü işaret eden bir 'firstChild' oku, son paragraf düğümünü işaret eden bir 'lastChild' oku ve tüm çocuklarına giden bir dizi bağlantıyı işaret eden 'childNodes' oku ile bir kutu olarak gösterilir. Ortadaki paragrafın kendisinden önceki düğümü gösteren bir 'previousSibling' oku, kendisinden sonraki düğümü gösteren bir 'nextSibling' oku ve 'body' düğümünü gösteren bir 'parentNode' oku vardır.”, width: ”6cm"}}} {{index "child node", "parentNode property", "childNodes property"}} -Although the diagram shows only one link of each type, every node has a `parentNode` property that points to the node it is part of, if any. Likewise, every element node (node type 1) has a `childNodes` property that points to an ((array-like object)) holding its children. +Diyagram sadece her türden bir bağlantıyı gösterse de, her düğümün, eğer varsa, bir parçası olduğu düğümü işaret eden bir `parentNode` özelliği vardır. Aynı şekilde, her öğe düğümü (düğüm türü 1) çocuklarını tutan dizi benzeri bir nesneyi işaret eden bir `childNodes` özelliğine sahiptir. {{index "firstChild property", "lastChild property", "previousSibling property", "nextSibling property"}} -In theory, you could move anywhere in the tree using just these parent and child links. But JavaScript also gives you access to a number of additional convenience links. The `firstChild` and `lastChild` properties point to the first and last child elements or have the value `null` for nodes without children. Similarly, `previousSibling` and `nextSibling` point to adjacent nodes, which are nodes with the same parent that appear immediately before or after the node itself. For a first child, `previousSibling` will be null, and for a last child, `nextSibling` will be null. +Teoride, sadece bu ana ve çocuk bağlantıları kullanarak ağaçta herhangi bir yere hareket edebilirsiniz. Ancak JavaScript, size bir dizi ek kolaylık bağlantısı da sunar. `firstChild` ve `lastChild` özellikleri, ilk ve son çocuk öğeleri işaret eder veya çocuğu olmayan düğümler için `null` değerine sahiptir. Benzer şekilde, `previousSibling` ve `nextSibling`, aynı ebeveyne sahip ve düğümün hemen öncesinde veya sonrasında görünen bitişik düğümleri işaret eder. İlk çocuk için, `previousSibling` null olacaktır ve son çocuk için `nextSibling` null olacaktır. {{index "children property", "text node", element}} -There's also the `children` property, which is like `childNodes` but contains only element (type 1) children, not other types of child nodes. This can be useful when you aren't interested in text nodes. +Ayrıca, `children` özelliği de vardır, bu `childNodes` gibidir ancak sadece öğe (tür 1) çocukları içerir, diğer türde çocuk düğümleri içermez. Bu, metin düğümleriyle ilgilenmediğinizde yararlı olabilir. {{index "talksAbout function", recursion, [nesting, "of objects"]}} -When dealing with a nested data structure like this one, recursive functions are often useful. The following function scans a document for ((text node))s containing a given string and returns `true` when it has found one: +Bu tür iç içe geçmiş bir veri yapısı ile çalışırken, özyinelemeli fonksiyonlar genellikle faydalıdır. Aşağıdaki fonksiyon, bir belgeyi belirli bir dizeyi içeren ((metin düğümü))ler için tarar ve birini bulduğunda `true` döndürür: {{id talksAbout}} @@ -151,17 +151,17 @@ console.log(talksAbout(document.body, "book")); {{index "nodeValue property"}} -The `nodeValue` property of a text node holds the string of text that it represents. +Bir metin düğümünün `nodeValue` özelliği, temsil ettiği metin dizesini tutar. ## Finding elements {{index [DOM, querying], "body property", "hard-coding", [whitespace, "in HTML"]}} -Navigating these ((link))s among parents, children, and siblings is often useful. But if we want to find a specific node in the document, reaching it by starting at `document.body` and following a fixed path of properties is a bad idea. Doing so bakes assumptions into our program about the precise structure of the document—a structure you might want to change later. Another complicating factor is that text nodes are created even for the whitespace between nodes. The example document's `<body>` tag has not just three children (`<h1>` and two `<p>` elements), but seven: those three, plus the spaces before, after, and between them. +Bu ((link))leri ebeveynler, çocuklar ve kardeşler arasında gezdirmek genellikle yararlıdır. Ancak belgede belirli bir düğümü bulmak istiyorsak, `document.body` adresinden başlayıp sabit bir özellik yolunu izleyerek ona ulaşmak kötü bir fikirdir. Bunu yapmak, programımıza belgenin kesin yapısı hakkında varsayımlar ekler - daha sonra değiştirmek isteyebileceğiniz bir yapı. Bir başka karmaşık faktör de metin düğümlerinin düğümler arasındaki boşluklar için bile oluşturulmasıdır. Örnek belgenin `<body>` etiketinin sadece üç alt öğesi (`<h1>` ve iki `<p>` öğesi) değil, aslında yedi alt öğesi vardır: bu üç öğe, artı onlardan önceki, sonraki ve aralarındaki boşluklar. {{index "search problem", "href attribute", "getElementsByTagName method"}} -If we want to get the `href` attribute of the link in that document, we don't want to say something like "Get the second child of the sixth child of the document body". It'd be better if we could say "Get the first link in the document". And we can. +Dolayısıyla, o belgedeki bağlantının `href` niteliğini almak istiyorsak, “Belge gövdesinin altıncı çocuğunun ikinci çocuğunu al” gibi bir şey söylemek istemeyiz. “Belgedeki ilk bağlantıyı al” diyebilseydik daha iyi olurdu. Öyle de yapabiliriz. ```{sandbox: "homepage"} let link = document.body.getElementsByTagName("a")[0]; @@ -170,11 +170,11 @@ console.log(link.href); {{index "child node"}} -All element nodes have a `getElementsByTagName` method, which collects all elements with the given tag name that are descendants (direct or indirect children) of that node and returns them as an ((array-like object)). +Tüm öğe düğümleri, verilen etiket adına sahip olan ve bu düğümün torunları (doğrudan veya dolaylı çocukları) olan tüm öğeleri toplayan ve bunları bir ((dizi benzeri nesne)) olarak döndüren bir `getElementsByTagName` yöntemine sahiptir. {{index "id attribute", "getElementById method"}} -To find a specific _single_ node, you can give it an `id` attribute and use `document.getElementById` instead. +Belirli bir _single_ düğümü bulmak için, ona bir `id` niteliği verebilir ve bunun yerine `document.getElementById` kullanabilirsiniz. ```{lang: html} <p>My ostrich Gertrude:</p> @@ -188,13 +188,13 @@ To find a specific _single_ node, you can give it an `id` attribute and use `doc {{index "getElementsByClassName method", "class attribute"}} -A third, similar method is `getElementsByClassName`, which, like `getElementsByTagName`, searches through the contents of an element node and retrieves all elements that have the given string in their `class` attribute. +Üçüncü ve benzer bir yöntem olan `getElementsByClassName`, `getElementsByTagName` gibi, bir öğe düğümünün içeriğini arar ve `class` niteliğinde verilen dizeye sahip tüm öğeleri alır. -## Changing the document +## Dokümanı değiştirmek {{index "side effect", "removeChild method", "appendChild method", "insertBefore method", [DOM, construction], [DOM, modification]}} -Almost everything about the DOM data structure can be changed. The shape of the document tree can be modified by changing parent-child relationships. Nodes have a `remove` method to remove them from their current parent node. To add a child node to an element node, we can use `appendChild`, which puts it at the end of the list of children, or `insertBefore`, which inserts the node given as the first argument before the node given as the second argument. +DOM veri yapısıyla ilgili neredeyse her şey değiştirilebilir. Belge ağacının şekli, ebeveyn-çocuk ilişkileri değiştirilerek değiştirilebilir. Düğümler, onları mevcut ebeveyn düğümlerinden kaldırmak için bir `remove` yöntemine sahiptir. Bir eleman düğümüne bir çocuk düğüm eklemek için, onu çocuk listesinin sonuna koyan `appendChild` veya ilk argüman olarak verilen düğümü ikinci argüman olarak verilen düğümden önce ekleyen `insertBefore` kullanabiliriz. ```{lang: html} <p>One</p> @@ -207,17 +207,21 @@ Almost everything about the DOM data structure can be changed. The shape of the </script> ``` -A node can exist in the document in only one place. Thus, inserting paragraph _Three_ in front of paragraph _One_ will first remove it from the end of the document and then insert it at the front, resulting in _Three_/_One_/_Two_. All operations that insert a node somewhere will, as a ((side effect)), cause it to be removed from its current position (if it has one). +Bir düğüm belgede yalnızca tek bir yerde bulunabilir. Bu nedenle, _Three_ paragrafını _One_ paragrafının önüne eklemek, önce onu belgenin sonundan kaldıracak ve sonra öne ekleyecek ve _Three_/_One_/_Two_ ile sonuçlanacaktır. Bir düğümü bir yere ekleyen tüm işlemler, ((yan etki)) olarak, mevcut konumundan (eğer varsa) kaldırılmasına neden olacaktır. {{index "insertBefore method", "replaceChild method"}} -The `replaceChild` method is used to replace a child node with another one. It takes as arguments two nodes: a new node and the node to be replaced. The replaced node must be a child of the element the method is called on. Note that both `replaceChild` and `insertBefore` expect the _new_ node as their first argument. +Bir alt düğümü başka bir düğümle değiştirmek için `replaceChild` yöntemi kullanılır. Argüman olarak iki düğüm alır: yeni bir düğüm ve değiştirilecek düğüm. Değiştirilen düğüm, yöntemin çağrıldığı öğenin bir çocuğu olmalıdır. Hem `replaceChild` hem de `insertBefore` yöntemlerinin ilk argüman olarak _new_ düğümünü beklediğini unutmayın. -## Creating nodes +## Düğümler oluşturmak {{index "alt attribute", "img (HTML tag)", "createTextNode method"}} -Say we want to write a script that replaces all ((image))s (`<img>` tags) in the document with the text held in their `alt` attributes, which specifies an alternative textual representation of the image. This involves not only removing the images but adding a new text node to replace them. +Belgedeki tüm ((image))leri (`<img>` etiketleri), `alt` niteliklerinde tutulan ve görüntünün alternatif bir metinsel temsilini belirten metinle değiştiren bir kod yazmak istediğimizi varsayalım. + +{{index "createTextNode method"}} + +Bu sadece resimleri kaldırmayı değil, aynı zamanda onların yerine yeni bir metin düğümü eklemeyi de içerir. ```{lang: html} <p>The <img src="img/cat.png" alt="Cat"> in the @@ -241,15 +245,15 @@ Say we want to write a script that replaces all ((image))s (`<img>` tags) in the {{index "text node"}} -Given a string, `createTextNode` gives us a text node that we can insert into the document to make it show up on the screen. +Bir dize verildiğinde, `createTextNode` bize ekranda görünmesini sağlamak için belgeye ekleyebileceğimiz bir metin düğümü verir. {{index "live data structure", "getElementsByTagName method", "childNodes property"}} -The loop that goes over the images starts at the end of the list. This is necessary because the node list returned by a method like `getElementsByTagName` (or a property like `childNodes`) is _live_. That is, it is updated as the document changes. If we started from the front, removing the first image would cause the list to lose its first element so that the second time the loop repeats, where `i` is 1, it would stop because the length of the collection is now also 1. +Görüntülerin üzerinden geçen döngü listenin sonundan başlar. Bu gereklidir çünkü `getElementsByTagName` gibi bir yöntem (ya da `childNodes` gibi bir özellik) tarafından döndürülen düğüm listesi _canlıdır_. Yani, belge değiştikçe güncellenir. Eğer en baştan başlasaydık, ilk resmi kaldırmak listenin ilk elemanını kaybetmesine neden olurdu, böylece `i`nin 1 olduğu döngü ikinci kez tekrarlandığında, koleksiyonun uzunluğu artık 1 olduğu için dururdu. {{index "slice method"}} -If you want a _solid_ collection of nodes, as opposed to a live one, you can convert the collection to a real array by calling `Array.from`. +Canlı bir koleksiyon yerine _solid_ bir düğüm koleksiyonu istiyorsanız, `Array.from` komutunu çağırarak koleksiyonu gerçek bir diziye dönüştürebilirsiniz. ``` let arrayish = {0: "one", 1: "two", length: 2}; @@ -260,13 +264,13 @@ console.log(array.map(s => s.toUpperCase())); {{index "createElement method"}} -To create ((element)) nodes, you can use the `document.createElement` method. This method takes a tag name and returns a new empty node of the given type. +((eleman)) düğümleri oluşturmak için `document.createElement` yöntemini kullanabilirsiniz. Bu yöntem bir etiket adı alır ve verilen türde yeni bir boş düğüm döndürür. {{index "Popper, Karl", [DOM, construction], "elt function"}} {{id elt}} -The following example defines a utility `elt`, which creates an element node and treats the rest of its arguments as children to that node. This function is then used to add an attribution to a quote. +Aşağıdaki örnek, bir element düğümü oluşturan ve argümanlarının geri kalanını bu düğümün çocukları olarak ele alan bir `elt` yardımcı programı tanımlar. Bu fonksiyon daha sonra bir alıntıya atıf eklemek için kullanılır. ```{lang: html} <blockquote id="quote"> @@ -296,21 +300,21 @@ The following example defines a utility `elt`, which creates an element node and {{if book -This is what the resulting document looks like: +Ortaya çıkan belge bu şekilde görünür: -{{figure {url: "img/blockquote.png", alt: "Rendered picture of the blockquote with attribution", width: "8cm"}}} +{{figure {url: "img/blockquote.png", alt: "Blok alıntının atıfla birlikte işlenmiş resmi", width: "8cm"}}} if}} -## Attributes +## Özellikler {{index "href attribute", [DOM, attributes]}} -Some element ((attribute))s, such as `href` for links, can be accessed through a property of the same name on the element's ((DOM)) object. This is the case for most commonly used standard attributes. +Bazı öğe ((özellik))leri, bağlantılar için `href` gibi, öğenin ((DOM)) nesnesindeki aynı isimli bir özellik aracılığıyla erişilebilir. Bu, çoğu yaygın olarak kullanılan standart özellikler için geçerlidir. {{index "data attribute", "getAttribute method", "setAttribute method", attribute}} -HTML allows you to set any attribute you want on nodes. This can be useful because it allows you to store extra information in a document. To read or change custom attributes, which aren't available as regular object properties, you have to use the `getAttribute` and `setAttribute` methods. +Ancak HTML, düğümler üzerinde istediğiniz herhangi bir özelliği ayarlamanıza izin verir. Bu, bir belgede ek bilgi saklamanızı sağladığı için kullanışlı olabilir. Kendi özellik adlarınızı oluşturduğunuzda, bu tür özellikler öğenin düğümünde özellik olarak bulunmaz. Bunun yerine, onlarla çalışmak için `getAttribute` ve `setAttribute` metodlarını kullanmanız gerekir. ```{lang: html} <p data-classified="secret">The launch code is 00000000.</p> @@ -326,27 +330,27 @@ HTML allows you to set any attribute you want on nodes. This can be useful becau </script> ``` -It is recommended to prefix the names of such made-up attributes with `data-` to ensure they do not conflict with any other attributes. +Bu tür oluşturulan özellik adlarının diğer özelliklerle çakışmamasını sağlamak için bu adlara `data-` öneki eklemeniz önerilir. {{index "getAttribute method", "setAttribute method", "className property", "class attribute"}} -There is a commonly used attribute, `class`, which is a ((keyword)) in the JavaScript language. For historical reasons—some old JavaScript implementations could not handle property names that matched keywords—the property used to access this attribute is called `className`. You can also access it under its real name, `"class"` with the `getAttribute` and `setAttribute` methods. +JavaScript dilinde bir ((anahtar kelime)) olan `class` adında yaygın olarak kullanılan bir özellik vardır. Tarihsel nedenlerden dolayı—bazı eski JavaScript uygulamaları anahtar kelimelerle eşleşen özellik adlarını işleyemiyordu—bu özelliğe erişmek için kullanılan özellik `className` olarak adlandırılır. Ayrıca, `getAttribute` ve `setAttribute` metodlarını kullanarak, gerçek adı olan `"class"` altında da erişebilirsiniz. -## Layout +## Düzen {{index layout, "block element", "inline element", "p (HTML tag)", "h1 (HTML tag)", "a (HTML tag)", "strong (HTML tag)"}} -You may have noticed that different types of elements are laid out differently. Some, such as paragraphs (`<p>`) or headings (`<h1>`), take up the whole width of the document and are rendered on separate lines. These are called _block_ elements. Others, such as links (`<a>`) or the `<strong>` element, are rendered on the same line with their surrounding text. Such elements are called _inline_ elements. +Farklı türdeki öğelerin farklı şekillerde yerleştirildiğini fark etmiş olabilirsiniz. Paragraflar (`<p>`) veya başlıklar (`<h1>`) gibi bazıları belgenin tüm genişliğini kaplar ve ayrı satırlarda görüntülenir. Bunlara block öğeler denir. Diğerleri, bağlantılar (`<a>`) veya `<strong>` öğesi gibi, çevreleyen metinle aynı satırda görüntülenir. Bu tür öğelere _inline_ öğeler denir. {{index drawing}} -For any given document, browsers are able to compute a layout, which gives each element a size and position based on its type and content. This layout is then used to actually draw the document. +Herhangi bir belge için, tarayıcılar her öğeye, türüne ve içeriğine göre bir boyut ve konum veren bir düzen hesaplayabilir. Bu düzen daha sonra belgeyi çizmek için kullanılır. {{index "border (CSS)", "offsetWidth property", "offsetHeight property", "clientWidth property", "clientHeight property", dimensions}} -The size and position of an element can be accessed from JavaScript. The `offsetWidth` and `offsetHeight` properties give you the space the element takes up in _((pixel))s_. A pixel is the basic unit of measurement in the browser. It traditionally corresponds to the smallest dot that the screen can draw, but on modern displays, which can draw _very_ small dots, that may no longer be the case, and a browser pixel may span multiple display dots. +Bir öğenin boyutu ve konumu JavaScript’ten erişilebilir. `offsetWidth` ve `offsetHeight` özellikleri, öğenin kapladığı alanı _((piksel))_ olarak verir. Bir piksel, tarayıcıda temel ölçü birimidir. Geleneksel olarak, ekranın çizebileceği en küçük nokta ile eşleşir, ancak modern ekranlarda, _çok_ küçük noktalar çizebildiği için bu durum geçerli olmayabilir ve bir tarayıcı pikseli birden fazla ekran noktasını kapsayabilir. -Similarly, `clientWidth` and `clientHeight` give you the size of the space _inside_ the element, ignoring border width. +Benzer şekilde, `clientWidth` ve `clientHeight` özellikleri, kenarlık genişliğini görmezden gelerek öğenin _içindeki_ alanın boyutunu verir. ```{lang: html} <p style="border: 3px solid red"> @@ -364,9 +368,9 @@ Similarly, `clientWidth` and `clientHeight` give you the size of the space _insi {{if book -Giving a paragraph a border causes a rectangle to be drawn around it. +Bir paragrafa kenarlık eklemek, etrafında bir dikdörtgen çizilmesine neden olur. -{{figure {url: "img/boxed-in.png", alt: "Rendered picture of a paragraph with a border", width: "8cm"}}} +{{figure {url: "img/boxed-in.png", alt: "Kenarlıklı bir paragrafın çizilmiş resmi", width: "8cm"}}} if}} @@ -374,15 +378,15 @@ if}} {{id boundingRect}} -The most effective way to find the precise position of an element on the screen is the `getBoundingClientRect` method. It returns an object with `top`, `bottom`, `left`, and `right` properties, indicating the pixel positions of the sides of the element relative to the top left of the screen. If you want pixel positions relative to the whole document, you must add the current scroll position, which you can find in the `pageXOffset` and `pageYOffset` bindings. +Bir öğenin ekrandaki kesin konumunu bulmanın en etkili yolu `getBoundingClientRect` metodudur. Bu metot, öğenin kenarlarının ekranın sol üst köşesine göre piksel konumlarını belirten `top`, `bottom`, `left` ve `right` özelliklerine sahip bir nesne döndürür. Bu konumları tüm belgeye göre almak isterseniz, mevcut kaydırma pozisyonunu eklemeniz gerekir; bu pozisyonu `pageXOffset` ve `pageYOffset` bağlamlarında bulabilirsiniz. {{index "offsetHeight property", "getBoundingClientRect method", drawing, laziness, performance, efficiency}} -Laying out a document can be quite a lot of work. In the interest of speed, browser engines do not immediately re-layout a document every time you change it but wait as long as they can before doing so. When a JavaScript program that changed the document finishes running, the browser will have to compute a new layout to draw the changed document to the screen. When a program _asks_ for the position or size of something by reading properties such as `offsetHeight` or calling `getBoundingClientRect`, providing that information also requires computing a ((layout)). +Bir belgenin düzenini oluşturmak oldukça zahmetli bir iş olabilir. Hız açısından, tarayıcı motorları, bir belgeyi her değiştirdiğinizde hemen yeniden düzenlemez, olabildiğince bekler. Belgeyi değiştiren bir JavaScript programı çalışmayı bitirdiğinde, tarayıcı değiştirilmiş belgeyi ekrana çizmek için yeni bir düzen hesaplamak zorunda kalır. Bir program `offsetHeight` gibi özellikleri okuyarak veya `getBoundingClientRect` çağırarak bir şeyin konumunu veya boyutunu sorduğunda, doğru bilgi sağlamak da bir ((layout)) hesaplamayı gerektirir. {{index "side effect", optimization, benchmark}} -A program that repeatedly alternates between reading DOM layout information and changing the DOM forces a lot of layout computations to happen and will consequently run very slowly. The following code is an example of this. It contains two different programs that build up a line of _X_ characters 2,000 pixels wide and measures the time each one takes. +DOM düzen bilgilerini okuma ve DOM’u değiştirme arasında sürekli gidip gelen bir program, çok sayıda düzen hesaplaması yapılmasına zorlar ve bu nedenle çok yavaş çalışır. Aşağıdaki kod bunun bir örneğidir. 2.000 piksel genişliğinde _X_ karakterlerinden oluşan bir satır oluşturan ve her birinin ne kadar sürdüğünü ölçen iki farklı program içerir. ```{lang: html, test: nonumbers} <p><span id="one"></span></p> @@ -413,15 +417,15 @@ A program that repeatedly alternates between reading DOM layout information and </script> ``` -## Styling +## Stillendirme {{index "block element", "inline element", style, "strong (HTML tag)", "a (HTML tag)", underline}} -We have seen that different HTML elements are drawn differently. Some are displayed as blocks, others inline. Some add styling—`<strong>` makes its content ((bold)), and `<a>` makes it blue and underlines it. +Farklı HTML öğelerinin farklı şekilde çizildiğini gördük. Bazıları blok olarak, bazıları satır içi olarak görüntülenir. Bazıları stil ekler—`<strong>`, içeriğini ((kalın)) yapar ve `<a>`, içeriğini mavi yapar ve altını çizer. {{index "img (HTML tag)", "default behavior", "style attribute"}} -The way an `<img>` tag shows an image or an `<a>` tag causes a link to be followed when it is clicked is strongly tied to the element type. But we can change the styling associated with an element, such as the text color or underline. Here is an example that uses the `style` property: +Bir `<img>` etiketinin bir görüntüyü nasıl gösterdiği veya bir `<a>` etiketinin üzerine tıklandığında bir bağlantının nasıl takip edileceği, öğe türüyle güçlü bir şekilde ilişkilidir. Ancak bir öğe ile ilişkilendirilen stili, örneğin metin rengi veya alt çizgi gibi, değiştirebiliriz. İşte `style` özelliğini kullanan bir örnek: ```{lang: html} <p><a href=".">Normal link</a></p> @@ -430,19 +434,19 @@ The way an `<img>` tag shows an image or an `<a>` tag causes a link to be follow {{if book -The second link will be green instead of the default link color: +İkinci bağlantı, varsayılan bağlantı renginin yerine yeşil olacak. -{{figure {url: "img/colored-links.png", alt: "Rendered picture of a normal blue link and a styled green link", width: "2.2cm"}}} +{{figure {url: "img/colored-links.png", alt: "Normal mavi bağlantı ve stil verilmiş yeşil bağlantının çizilmiş resmi", width: "2.2cm"}}} if}} {{index "border (CSS)", "color (CSS)", CSS, "colon character"}} -A style attribute may contain one or more _((declaration))s_, which are a property (such as `color`) followed by a colon and a value (such as `green`). When there is more than one declaration, they must be separated by ((semicolon))s, as in `"color: red; border: none"`. +Bir stil niteliği bir veya daha fazla _((declaration))s_ içerebilir; bunlar bir özellik (örneğin `color`), ardından iki nokta üst üste ve bir değerdir (örneğin `green`). Birden fazla bildirim olduğunda, `“color: red; border: none”` gibi ((noktalı virgül))ler ile ayrılmalıdırlar. {{index "display (CSS)", layout}} -A lot of aspects of the document can be influenced by styling. For example, the `display` property controls whether an element is displayed as a block or an inline element. +Bir stil niteliği bir veya daha fazla _((declaration))s_ içerebilir; bunlar bir özellik (örneğin `color`), ardından iki nokta üst üste ve bir değerdir (örneğin `green`). Birden fazla bildirim olduğunda, `“color: red; border: none”` gibi ((noktalı virgül))ler ile ayrılmalıdırlar. ```{lang: html} This text is displayed <strong>inline</strong>, @@ -452,17 +456,17 @@ This text is displayed <strong>inline</strong>, {{index "hidden element"}} -The `block` tag will end up on its own line since ((block element))s are not displayed inline with the text around them. The last tag is not displayed at all—`display: none` prevents an element from showing up on the screen. This is a way to hide elements. It is often preferable to removing them from the document entirely because it makes it easy to reveal them again later. +((Blok öğesi))ler etraflarındaki metinle birlikte satır içinde görüntülenmediğinden `block` etiketi kendi satırında sonlanacaktır. Son etiket hiç görüntülenmez-`display: none` bir öğenin ekranda görünmesini engeller. Bu, öğeleri gizlemenin bir yoludur. Genellikle belgeden tamamen kaldırmaya tercih edilir çünkü daha sonra tekrar ortaya çıkarmayı kolaylaştırır. {{if book -{{figure {url: "img/display.png", alt: "Different display styles", width: "4cm"}}} +{{figure {url: "img/display.png", alt: "Farklı ekran stilleri", width: "4cm"}}} if}} {{index "color (CSS)", "style attribute"}} -JavaScript code can directly manipulate the style of an element through the element's `style` property. This property holds an object that has properties for all possible style properties. The values of these properties are strings, which we can write to in order to change a particular aspect of the element's style. +JavaScript kodu, bir öğenin stilini, öğenin `style` özelliği aracılığıyla doğrudan değiştirebilir. Bu özellik, tüm olası stil özellikleri için özelliklere sahip bir nesne tutar. Bu özelliklerin değerleri, öğenin stilinin belirli bir yönünü değiştirmek için yazabileceğimiz dizelerdir. ```{lang: html} <p id="para" style="color: purple"> @@ -478,16 +482,16 @@ JavaScript code can directly manipulate the style of an element through the elem {{index "camel case", capitalization, "hyphen character", "font-family (CSS)"}} -Some style property names contain hyphens, such as `font-family`. Because such property names are awkward to work with in JavaScript (you'd have to say `style["font-family"]`), the property names in the `style` object for such properties have their hyphens removed and the letters after them capitalized (`style.fontFamily`). +Bazı stil özellik adları `font-family` gibi kısa çizgiler içerir. Bu tür özellik adlarıyla JavaScript'te çalışmak zor olduğundan (`style[“font-family”]` demeniz gerekir), bu tür özellikler için `style` nesnesindeki özellik adlarının tire işaretleri kaldırılır ve kendilerinden sonraki harfler büyük yazılır (`style.fontFamily`). -## Cascading styles +## Basamaklı stiller {{index "rule (CSS)", "style (HTML tag)"}} {{indexsee "Cascading Style Sheets", CSS}} {{indexsee "style sheet", CSS}} -The styling system for HTML is called _((CSS))_, for _Cascading Style Sheets_. A _style sheet_ is a set of rules for how to style elements in a document. It can be given inside a `<style>` tag. +HTML için biçimlendirme sistemi, _COPYascading Style Sheets_ için ((CSS)) olarak adlandırılır. Bir _style sheet_, bir belgedeki öğelerin nasıl biçimlendirileceğine ilişkin bir dizi kuraldır. Bir `<style>` etiketi içinde verilebilir. ```{lang: html} <style> @@ -501,15 +505,15 @@ The styling system for HTML is called _((CSS))_, for _Cascading Style Sheets_. A {{index "rule (CSS)", "font-weight (CSS)", overlay}} -The _((cascading))_ in the name refers to the fact that multiple such rules are combined to produce the final style for an element. In the example, the default styling for `<strong>` tags, which gives them `font-weight: bold`, is overlaid by the rule in the `<style>` tag, which adds `font-style` and `color`. +İsimdeki _((cascading))_ kısmı, bir öğenin nihai stilini oluşturmak için birden fazla kuralın birleştirildiği gerçeğine atıfta bulunur. Örnekte, `<strong>` etiketleri için varsayılan stil olan `font-weight: bold`, `font-style` ve `color` ekleyen `<style>` etiketindeki kuralla birleşir. {{index "style (HTML tag)", "style attribute"}} -When multiple rules define a value for the same property, the most recently read rule gets a higher ((precedence)) and wins. For example, if the rule in the `<style>` tag included `font-weight: normal`, contradicting the default `font-weight` rule, the text would be normal, _not_ bold. Styles in a `style` attribute applied directly to the node have the highest precedence and always win. +Birden fazla kural aynı özellik için bir değer tanımladığında, en son okunan kural daha yüksek bir ((öncelik)) kazanır ve galip gelir. Dolayısıyla, `<style>` etiketindeki kural `font-weight: normal` içeriyorsa ve bu, varsayılan `font-weight` kuralıyla çelişiyorsa, metin normal olur, kalın değil. Doğrudan düğüme uygulanan bir `style` özelliğindeki stiller en yüksek önceliğe sahiptir ve her zaman kazanır. {{index uniqueness, "class attribute", "id attribute"}} -It is possible to target things other than ((tag)) names in CSS rules. A rule for `.abc` applies to all elements with `"abc"` in their `class` attribute. A rule for `#xyz` applies to the element with an `id` attribute of `"xyz"` (which should be unique within the document). +CSS kurallarında ((etiket)) adları dışında başka şeyleri hedeflemek de mümkündür. `.abc` için bir kural, `class` özelliğinde `"abc"` bulunan tüm öğelere uygulanır. `#xyz` için bir kural ise `id` özelliği `"xyz"` olan öğeye uygulanır (bu özellik belge içinde benzersiz olmalıdır). ```{lang: "css"} .subtle { @@ -528,21 +532,25 @@ p#main.a.b { {{index "rule (CSS)"}} -The ((precedence)) rule favoring the most recently defined rule applies only when the rules have the same _((specificity))_. A rule's specificity is a measure of how precisely it describes matching elements, determined by the number and kind (tag, class, or ID) of element aspects it requires. For example, a rule that targets `p.a` is more specific than rules that target `p` or just `.a` and would thus take precedence over them. +En son tanımlanan kuralı tercih eden _((öncelik))_ kuralı, yalnızca kuralların aynı _((özgüllük))_ seviyesine sahip olması durumunda geçerlidir. Bir kuralın özgüllüğü, eşleşen öğeleri ne kadar kesin olarak tanımladığının bir ölçüsüdür ve gerektirdiği öğe özelliklerinin (etiket, sınıf veya ID) sayısı ve türüyle belirlenir. Örneğin, `p.a` hedefleyen bir kural, `p` veya sadece `.a` hedefleyen kurallardan daha özgül olduğu için onlardan öncelikli olur. {{index "direct child node"}} -The notation `p > a {…}` applies the given styles to all `<a>` tags that are direct children of `<p>` tags. Similarly, `p a {…}` applies to all `<a>` tags inside `<p>` tags, whether they are direct or indirect children. +`p > a {…}` notasyonu, belirtilen stilleri `<p>` etiketlerinin doğrudan çocukları olan tüm `<a>` etiketlerine uygular. Benzer şekilde, `p a {…}`, doğrudan veya dolaylı çocuk olup olmadığına bakılmaksızın, `<p>` etiketlerinin içindeki tüm `<a>` etiketlerine uygulanır. -## Query selectors +## Sorgu seçicileri {{index complexity, CSS, "domain-specific language", [DOM, querying]}} -We won't be using style sheets very much in this book. Understanding them is helpful when programming in the browser, but they are complicated enough to warrant a separate book. The main reason I introduced _((selector))_ syntax—the notation used in style sheets to determine which elements a set of styles apply to—is that we can use this same mini-language as an effective way to find DOM elements. +Bu kitapta stil sayfalarını çok fazla kullanmayacağız. Tarayıcıda programlama yaparken bunları anlamak yararlıdır, ancak ayrı bir kitap gerektirecek kadar karmaşıktırlar. + +{{index "domain-specific language", [DOM, querying]}} + +Stil sayfalarında bir stil kümesinin hangi öğelere uygulanacağını belirlemek için kullanılan _((selector))_ sözdizimini tanıtmamın ana nedeni, aynı mini dili DOM öğelerini bulmak için etkili bir yol olarak kullanabilmemizdir. {{index "querySelectorAll method", "NodeList type"}} -The `querySelectorAll` method, which is defined both on the `document` object and on element nodes, takes a selector string and returns a `NodeList` containing all the elements that it matches. +Hem `document` nesnesi hem de öğe düğümleri üzerinde tanımlanan `querySelectorAll` yöntemi, bir seçici dizesi alır ve eşleştiği tüm öğeleri içeren bir `NodeList` döndürür. ```{lang: html} <p>And if you go chasing @@ -569,23 +577,23 @@ The `querySelectorAll` method, which is defined both on the `document` object an {{index "live data structure"}} -Unlike methods such as `getElementsByTagName`, the object returned by `querySelectorAll` is _not_ live. It won't change when you change the document. It is still not a real array, though, so you need to call `Array.from` if you want to treat it like one. +`getElementsByTagName` gibi yöntemlerin aksine, `querySelectorAll` tarafından döndürülen nesne _canlı_ değildir. Belgeyi değiştirdiğinizde değişmez. Yine de gerçek bir dizi değildir, bu nedenle bir dizi gibi davranmak istiyorsanız `Array.from` öğesini çağırmanız gerekir. {{index "querySelector method"}} -The `querySelector` method (without the `All` part) works in a similar way. This one is useful if you want a specific single element. It will return only the first matching element or null when no element matches. +`querySelector` yöntemi (`All` kısmı olmadan) benzer şekilde çalışır. Bu, belirli, tek bir öğe istiyorsanız kullanışlıdır. Yalnızca ilk eşleşen öğeyi veya hiçbir öğe eşleşmediğinde null döndürür. {{id animation}} -## Positioning and animating +## Konumlandırma ve canlandırma {{index "position (CSS)", "relative positioning", "top (CSS)", "left (CSS)", "absolute positioning"}} -The `position` style property influences layout in a powerful way. It has a default value of `static`, meaning the element sits in its normal place in the document. When it is set to `relative`, the element still takes up space in the document, but now the `top` and `left` style properties can be used to move it relative to that normal place. When `position` is set to `absolute`, the element is removed from the normal document flow—that is, it no longer takes up space and may overlap with other elements. Its `top` and `left` properties can be used to absolutely position it relative to the top-left corner of the nearest enclosing element whose `position` property isn't `static`, or relative to the document if no such enclosing element exists. +`position` stil özelliği düzeni güçlü bir şekilde etkiler. Varsayılan olarak `static` değerine sahiptir, yani öğe belgedeki normal yerine oturur. `relative` olarak ayarlandığında, öğe belgede hala yer kaplar, ancak artık `top` ve `left` stil özellikleri onu bu normal yere göre hareket ettirmek için kullanılabilir. `position` öğesi `absolute` olarak ayarlandığında, öğe normal belge akışından çıkarılır; yani artık yer kaplamaz ve diğer öğelerle çakışabilir. Ayrıca, `top` ve `left` özellikleri, `position` özelliği `static` olmayan en yakın çevreleyen öğenin sol üst köşesine göre veya böyle bir çevreleyen öğe yoksa belgeye göre kesinlikle konumlandırmak için kullanılabilir. {{index [animation, "spinning cat"]}} -We can use this to create an animation. The following document displays a picture of a cat that moves around in an ((ellipse)): +Bunu bir animasyon oluşturmak için kullanabiliriz. Aşağıdaki belge, bir ((elips)) içinde hareket eden bir kedi resmi görüntüler: ```{lang: html, startCode: true} <p style="text-align: center"> @@ -608,71 +616,71 @@ We can use this to create an animation. The following document displays a pictur {{if book -The gray arrow shows the path along which the image moves. +Gri ok, görüntünün hareket ettiği yolu gösterir. -{{figure {url: "img/cat-animation.png", alt: "A diagram showing a picture of a cat with a circular arrow indicating its motion", width: "8cm"}}} +{{figure {url: "img/cat-animation.png", alt: "Hareketini gösteren dairesel bir ok ile bir kedi resmini gösteren bir diyagram", width: "8cm"}}} if}} {{index "top (CSS)", "left (CSS)", centering, "relative positioning"}} -Our picture is centered on the page and given a `position` of `relative`. We'll repeatedly update that picture's `top` and `left` styles to move it. +Resmimiz sayfada ortalanır ve `konum` değeri `göreceli` olarak verilir. Bu resmi taşımak için resmin `top` ve `left` stillerini tekrar tekrar güncelleyeceğiz. {{index "requestAnimationFrame function", drawing, animation}} {{id animationFrame}} -The script uses `requestAnimationFrame` to schedule the `animate` function to run whenever the browser is ready to repaint the screen. The `animate` function itself again calls `requestAnimationFrame` to schedule the next update. When the browser window (or tab) is active, this will cause updates to happen at a rate of about 60 per second, which tends to produce a good-looking animation. +Kod, `animate` fonksiyonunu tarayıcı ekranı yeniden boyamaya hazır olduğunda çalışacak şekilde zamanlamak için `requestAnimationFrame` kullanır. Bir sonraki güncellemeyi zamanlamak için `animate` fonksiyonunun kendisi yine `requestAnimationFrame` fonksiyonunu çağırır. Tarayıcı penceresi (veya sekmesi) aktif olduğunda, bu, güncellemelerin saniyede yaklaşık 60 oranında gerçekleşmesine neden olur ve bu da iyi görünümlü bir animasyon üretme eğilimindedir. {{index timeline, blocking}} -If we just updated the DOM in a loop, the page would freeze, and nothing would show up on the screen. Browsers do not update their display while a JavaScript program is running, nor do they allow any interaction with the page. This is why we need `requestAnimationFrame`—it lets the browser know that we are done for now, and it can go ahead and do the things that browsers do, such as updating the screen and responding to user actions. +Eğer DOM'u bir döngü içinde güncelleseydik, sayfa donacak ve ekranda hiçbir şey görünmeyecekti. Tarayıcılar, bir JavaScript programı çalışırken ekranlarını güncellemezler ve sayfayla herhangi bir etkileşime izin vermezler. İşte bu yüzden `requestAnimationFrame`e ihtiyacımız var - tarayıcıya şimdilik işimizin bittiğini bildirir ve tarayıcıların yaptığı, ekranı güncellemek ve kullanıcı eylemlerine yanıt vermek gibi şeyleri yapmaya devam edebilir. {{index "smooth animation"}} -The animation function is passed the current ((time)) as an argument. To ensure that the motion of the cat per millisecond is stable, it bases the speed at which the angle changes on the difference between the current time and the last time the function ran. If it just moved the angle by a fixed amount per step, the motion would stutter when, for example, another heavy task running on the same computer prevented the function from running for a fraction of a second. +Animasyon fonksiyonuna argüman olarak mevcut ((zaman)) aktarılır. Kedinin milisaniye başına hareketinin sabit olmasını sağlamak için, açının değişme hızını geçerli zaman ile fonksiyonun son çalıştığı zaman arasındaki farka dayandırır. Açıyı adım başına sabit bir miktarda hareket ettirseydi, örneğin aynı bilgisayarda çalışan başka bir ağır görev, işlevin saniyenin bir kısmı boyunca çalışmasını engellerse hareket takılırdı. {{index "Math.cos function", "Math.sin function", cosine, sine, trigonometry}} {{id sin_cos}} -Moving in ((circle))s is done using the trigonometry functions `Math.cos` and `Math.sin`. For those who aren't familiar with these, I'll briefly introduce them since we will occasionally use them in this book. +((Daire))lerde hareket etmek `Math.cos` ve `Math.sin` trigonometri fonksiyonları kullanılarak yapılır. Bunlara aşina olmayanlar için, bu kitapta zaman zaman kullanacağımız için kısaca tanıtacağım. {{index coordinates, pi}} -`Math.cos` and `Math.sin` are useful for finding points that lie on a circle around point (0,0) with a radius of 1. Both functions interpret their argument as the position on this circle, with 0 denoting the point on the far right of the circle, going clockwise until 2π (about 6.28) has taken us around the whole circle. `Math.cos` tells you the x-coordinate of the point that corresponds to the given position, and `Math.sin` yields the y-coordinate. Positions (or angles) greater than 2π or less than 0 are valid—the rotation repeats so that _a_+2π refers to the same ((angle)) as _a_. +`Math.cos` ve `Math.sin` yarıçapı bir olan (0,0) noktası etrafındaki bir çember üzerinde yer alan noktaları bulmak için kullanışlıdır. Her iki fonksiyon da argümanlarını bu daire üzerindeki konum olarak yorumlar, sıfır dairenin en sağındaki noktayı gösterir ve 2π (yaklaşık 6.28) bizi tüm dairenin etrafına götürene kadar saat yönünde ilerler. `Math.cos` size verilen konuma karşılık gelen noktanın x koordinatını, `Math.sin` ise y koordinatını verir. 2π'den büyük veya 0'dan küçük konumlar (veya açılar) geçerlidir - dönüş tekrar eder, böylece _a_+2π _a_ ile aynı ((açı)) anlamına gelir. {{index "PI constant"}} -This unit for measuring angles is called ((radian))s—a full circle is 2π radians, similar to how it is 360 degrees when measuring in degrees. The constant π is available as `Math.PI` in JavaScript. +Açıları ölçmek için kullanılan bu birim ((radyan))s olarak adlandırılır; tam bir daire 2π radyandır, tıpkı derece cinsinden ölçerken 360 derece olması gibi. π sabiti JavaScript'te `Math.PI` olarak kullanılabilir. -{{figure {url: "img/cos_sin.svg", alt: "Diagram showing the use of cosine and sine to compute coordinates. A circle with radius 1 is shown with two points on it. The angle from the right side of the circle to the point, in radians, is used to compute the position of each point by using 'cos(angle)' for the horizontal distance from the center of the circle and sin(angle) for the vertical distance.", width: "6cm"}}} +{{figure {url: "img/cos_sin.svg", alt: "Koordinatları hesaplamak için kosinüs ve sinüs kullanımını gösteren diyagram. Yarıçapı 1 olan bir daire, üzerinde iki nokta ile gösterilmiştir. Dairenin sağ tarafından noktaya olan açı, radyan cinsinden, dairenin merkezinden yatay mesafe için 'cos(açı)' ve dikey mesafe için sin(açı) kullanılarak her bir noktanın konumunu hesaplamak için kullanılır.", width: "6cm"}}} {{index "counter variable", "Math.sin function", "top (CSS)", "Math.cos function", "left (CSS)", ellipse}} -The cat animation code keeps a counter, `angle`, for the current angle of the animation and increments it every time the `animate` function is called. It can then use this angle to compute the current position of the image element. The `top` style is computed with `Math.sin` and multiplied by 20, which is the vertical radius of our ellipse. The `left` style is based on `Math.cos` and multiplied by 200 so that the ellipse is much wider than it is high. +Kedi animasyonu kodu, animasyonun geçerli açısı için `angle` adında bir sayaç tutar ve `animate` fonksiyonu her çağrıldığında bunu artırır. Daha sonra görüntü öğesinin geçerli konumunu hesaplamak için bu açıyı kullanabilir. `top` stili `Math.sin` ile hesaplanır ve elipsimizin dikey yarıçapı olan 20 ile çarpılır. `left` stili `Math.cos` ile hesaplanır ve elipsin yüksekliğinden çok daha geniş olması için 200 ile çarpılır. {{index "unit (CSS)"}} -Note that styles usually need _units_. In this case, we have to append `"px"` to the number to tell the browser that we are counting in ((pixel))s (as opposed to centimeters, "ems", or other units). This is easy to forget. Using numbers without units will result in your style being ignored—unless the number is 0, which always means the same thing, regardless of its unit. +Stillerin genellikle _birimlere_ ihtiyaç duyduğunu unutmayın. Bu durumda, tarayıcıya ((piksel)) cinsinden saydığımızı (santimetre, “ems” veya diğer birimlerin aksine) söylemek için sayıya `“px”` eklememiz gerekir. Bunu unutmak kolaydır. Sayıları birimsiz kullanmak, stilinizin göz ardı edilmesine neden olur - sayı 0 olmadığı sürece, bu da birimi ne olursa olsun her zaman aynı anlama gelir. -## Summary +## Özet -JavaScript programs may inspect and interfere with the document that the browser is displaying through a data structure called the DOM. This data structure represents the browser's model of the document, and a JavaScript program can modify it to change the visible document. +JavaScript programları, DOM adı verilen bir veri yapısı aracılığıyla tarayıcının görüntülediği belgeyi inceleyebilir ve müdahale edebilir. Bu veri yapısı tarayıcının belge modelini temsil eder ve bir JavaScript programı görünür belgeyi değiştirmek için bu yapıyı değiştirebilir. -The DOM is organized like a tree, where elements are arranged hierarchically according to the structure of the document. The objects representing elements have properties such as `parentNode` and `childNodes`, which can be used to navigate through this tree. +DOM, öğelerin belgenin yapısına göre hiyerarşik olarak düzenlendiği bir ağaç gibi organize edilmiştir. Öğeleri temsil eden nesneler, bu ağaçta gezinmek için kullanılabilen `parentNode` ve `childNodes` gibi özelliklere sahiptir. -The way a document is displayed can be influenced by _styling_, both by attaching styles to nodes directly and by defining rules that match certain nodes. There are many different style properties, such as `color` or `display`. JavaScript code can manipulate an element's style directly through its `style` property. +Bir belgenin görüntülenme şekli, hem düğümlere doğrudan stil ekleyerek hem de belirli düğümlerle eşleşen kurallar tanımlayarak _stillendirme_ tarafından etkilenebilir. `color` veya `display` gibi birçok farklı stil özelliği vardır. JavaScript kodu, bir öğenin stilini doğrudan `style` özelliği aracılığıyla değiştirebilir. -## Exercises +## Egzersizler {{id exercise_table}} -### Build a table +### Bir tablo oluşturun {{index "table (HTML tag)"}} -An HTML table is built with the following tag structure: +Bir HTML tablosu aşağıdaki etiket yapısı ile oluşturulur: ```{lang: html} <table> @@ -691,17 +699,17 @@ An HTML table is built with the following tag structure: {{index "tr (HTML tag)", "th (HTML tag)", "td (HTML tag)"}} -For each _((row))_, the `<table>` tag contains a `<tr>` tag. Inside of these `<tr>` tags, we can put cell elements: either heading cells (`<th>`) or regular cells (`<td>`). +Her _((row))_ için, `<table>` etiketi bir `<tr>` etiketi içerir. Bu `<tr>` etiketlerinin içine hücre öğeleri koyabiliriz: başlık hücreleri (`<th>`) veya normal hücreler (`<td>`). -Given a data set of mountains, an array of objects with `name`, `height`, and `place` properties, generate the DOM structure for a table that enumerates the objects. It has one column per key and one row per object, plus a header row with `<th>` elements at the top, listing the column names. +Dağlardan oluşan bir veri kümesi, `name`, `height` ve `place` özelliklerine sahip bir dizi nesne verildiğinde, nesneleri numaralandıran bir tablo için DOM yapısını oluşturun. Anahtar başına bir sütun ve nesne başına bir satır, ayrıca en üstte sütun adlarını listeleyen `<th>` öğeleri içeren bir başlık satırı olmalıdır. -Write this so that the columns are automatically derived from the objects, by taking the property names of the first object in the data. +Bunu, sütunlar verilerdeki ilk nesnenin özellik adlarını alarak nesnelerden otomatik olarak türetilecek şekilde yazın. -Show the resulting table in the document by appending it to the element that has an `id` attribute of `"mountains"`. +Ortaya çıkan tabloyu, `id` niteliği `“mountains”` olan öğeye ekleyerek belgede gösterin. {{index "right-aligning", "text-align (CSS)"}} -Once you have this working, right-align cells that contain number values by setting their `style.textAlign` property to `"right"`. +Bunu çalıştırdıktan sonra, `style.textAlign` özelliğini `“right”` olarak ayarlayarak sayı değerleri içeren hücreleri sağa hizalayın. {{if interactive @@ -731,27 +739,27 @@ if}} {{index "createElement method", "table example", "appendChild method"}} -You can use `document.createElement` to create new element nodes, `document.createTextNode` to create text nodes, and the `appendChild` method to put nodes into other nodes. +Yeni eleman düğümleri oluşturmak için `document.createElement`, metin düğümleri oluşturmak için `document.createTextNode` ve düğümleri diğer düğümlerin içine yerleştirmek için `appendChild` yöntemini kullanabilirsiniz. {{index "Object.keys function"}} -You'll want to loop over the key names once to fill in the top row and then again for each object in the array to construct the data rows. To get an array of key names from the first object, `Object.keys` will be useful. +Üst satırı doldurmak için anahtar adları üzerinde bir kez döngü yapmak ve ardından veri satırlarını oluşturmak için dizideki her nesne için tekrar döngü yapmak isteyeceksiniz. İlk nesneden bir dizi anahtar adı almak için `Object.keys` yararlı olacaktır. {{index "getElementById method", "querySelector method"}} -To add the table to the correct parent node, you can use `document.getElementById` or `document.querySelector` with `"#mountains"` to find the node. +Tabloyu doğru üst düğüme eklemek için, düğümü bulmak üzere `document.getElementById` veya `document.querySelector` ile `“#mountains”` kullanabilirsiniz. hint}} -### Elements by tag name +### Etiket adına göre öğeler {{index "getElementsByTagName method", recursion}} -The `document.getElementsByTagName` method returns all child elements with a given tag name. Implement your own version of this as a function that takes a node and a string (the tag name) as arguments and returns an array containing all descendant element nodes with the given tag name. Your function should go through the document itself. It may not use a method like `querySelectorAll` to do the work. +`document.getElementsByTagName` yöntemi, belirli bir etiket adına sahip tüm alt öğeleri döndürür. Bunun kendi versiyonunu, argüman olarak bir düğüm ve bir dize (etiket adı) alan ve verilen etiket adına sahip tüm alt öğe düğümlerini içeren bir dizi döndüren bir fonksiyon olarak uygulayın. {{index "nodeName property", capitalization, "toLowerCase method", "toUpperCase method"}} -To find the tag name of an element, use its `nodeName` property. But note that this will return the tag name in all uppercase. Use the `toLowerCase` or `toUpperCase` string methods to compensate for this. +Bir elemanın etiket adını bulmak için `nodeName` özelliğini kullanın. Ancak bunun etiket adını büyük harfle döndüreceğini unutmayın. Bunu telafi etmek için `toLowerCase` veya `toUpperCase` string yöntemlerini kullanın. {{if interactive @@ -774,35 +782,36 @@ To find the tag name of an element, use its `nodeName` property. But note that t // → 2 </script> ``` + if}} {{hint {{index "getElementsByTagName method", recursion}} -The solution is most easily expressed with a recursive function, similar to the [`talksAbout` function](dom#talksAbout) defined earlier in this chapter. +Çözüm, bu bölümde daha önce tanımlanan [`talksAbout` fonksiyonuna](dom#talksAbout) benzer özyinelemeli bir fonksiyonla en kolay şekilde ifade edilir. {{index concatenation, "concat method", closure}} -You could call `byTagname` itself recursively, concatenating the resulting arrays to produce the output. Or you could create an inner function that calls itself recursively and that has access to an array binding defined in the outer function, to which it can add the matching elements it finds. Don't forget to call the ((inner function)) once from the outer function to start the process. +`byTagname` fonksiyonunun kendisini özyinelemeli olarak çağırabilir ve elde edilen dizileri birleştirerek çıktıyı üretebilirsiniz. Ya da kendisini özyinelemeli olarak çağıran ve dış fonksiyonda tanımlanan bir dizi bağına erişimi olan ve bulduğu eşleşen elemanları ekleyebileceği bir iç fonksiyon oluşturabilirsiniz. İşlemi başlatmak için dış fonksiyondan bir kez ((iç fonksiyon)) çağırmayı unutmayın. {{index "nodeType property", "ELEMENT_NODE code"}} -The recursive function must check the node type. Here we are interested only in node type 1 (`Node.ELEMENT_NODE`). For such nodes, we must loop over their children and, for each child, see whether the child matches the query while also doing a recursive call on it to inspect its own children. +Özyinelemeli fonksiyon düğüm tipini kontrol etmelidir. Burada sadece düğüm tipi 1 (`Node.ELEMENT_NODE`) ile ilgileniyoruz. Bu tür düğümler için, çocukları üzerinde döngü yapmalı ve her çocuk için, çocuğun sorguyla eşleşip eşleşmediğine bakmalı ve aynı zamanda kendi çocuklarını incelemek için özyinelemeli bir çağrı yapmalıyız. hint}} -### The cat's hat +### Kedinin şapkası {{index "cat's hat (exercise)", [animation, "spinning cat"]}} -Extend the cat animation defined [earlier](dom#animation) so that both the cat and his hat (`<img src="img/hat.png">`) orbit at opposite sides of the ellipse. +[Daha önce](dom#animation) tanımlanan kedi animasyonunu genişletin, böylece hem kedi hem de şapkası (`<img src=“img/hat.png”>`) elipsin karşıt taraflarında yörüngeye girsin. -Or make the hat circle around the cat. Or alter the animation in some other interesting way. +Ya da şapkayı kedinin etrafında döndürün. Ya da animasyonu başka ilginç bir şekilde değiştirin. {{index "absolute positioning", "top (CSS)", "left (CSS)", "position (CSS)"}} -To make positioning multiple objects easier, you'll probably want to switch to absolute positioning. This means that `top` and `left` are counted relative to the top left of the document. To avoid using negative coordinates, which would cause the image to move outside of the visible page, you can add a fixed number of pixels to the position values. +Birden fazla nesnenin konumlandırılmasını kolaylaştırmak için mutlak konumlandırmaya geçmek muhtemelen iyi bir fikirdir. Bu, `top` ve `left` değerlerinin belgenin sol üst köşesine göre sayılacağı anlamına gelir. Görüntünün görünür sayfanın dışına çıkmasına neden olacak negatif koordinatlar kullanmaktan kaçınmak için, konum değerlerine sabit sayıda piksel ekleyebilirsiniz. {{if interactive @@ -835,6 +844,6 @@ if}} {{hint -`Math.cos` and `Math.sin` measure angles in radians, where a full circle is 2π. For a given angle, you can get the opposite angle by adding half of this, which is `Math.PI`. This can be useful for putting the hat on the opposite side of the orbit. +`Math.cos` ve `Math.sin` açıları radyan cinsinden ölçer, burada tam bir daire 2π'dir. Belirli bir açı için, bunun yarısını ekleyerek karşıt açıyı elde edebilirsiniz, bu da `Math.PI`dır. Bu, şapkayı yörüngenin karşı tarafına yerleştirmek için yararlı olabilir. hint}} diff --git a/15_event.md b/15_event.md index 7629596f..c62e7595 100644 --- a/15_event.md +++ b/15_event.md @@ -1,32 +1,32 @@ -# Handling Events +# Olayların Ele Alınması -{{quote {author: "Marcus Aurelius", title: Meditations, chapter: true} +{{quote {author: "Marcus Aurelius", title: Meditasyonlar, chapter: true} -You have power over your mind—not outside events. Realize this, and you will find strength. +Zihniniz üzerinde gücünüz var, dışarıdaki olaylar üzerinde değil. Bunun farkına varın ve güç bulacaksınız. quote}} {{index stoicism, "Marcus Aurelius", input, timeline}} -{{figure {url: "img/chapter_picture_15.jpg", alt: "Illustration showing a Rube Goldberg machine involving a ball, a see-saw, a pair of scissors, and a hammer, which affect each other in a chain reaction that turns on a lightbulb.", chapter: "framed"}}} +{{figure {url: "img/chapter_picture_15.jpg", alt: "Bir ampulü yakan zincirleme reaksiyonda birbirlerini etkileyen bir top, bir tahterevalli, bir makas ve bir çekiç içeren bir Rube Goldberg makinesini gösteren illüstrasyon.", chapter: "framed"}}} -Some programs work with direct user input, such as mouse and keyboard actions. That kind of input isn't available ahead of time, as a well-organized data structure—it comes in piece by piece, in real time, and the program must respond to it as it happens. +Bazı programlar fare ve klavye eylemleri gibi doğrudan kullanıcı girdileriyle çalışır. Bu tür bir girdi, iyi organize edilmiş bir veri yapısı olarak önceden mevcut değildir; parça parça, gerçek zamanlı olarak gelir ve programın buna gerçekleştiği anda yanıt vermesi gerekir. -## Event handlers +## Olay işleyicileri {{index polling, button, "real-time"}} -Imagine an interface where the only way to find out whether a key on the ((keyboard)) is being pressed is to read the current state of that key. To be able to react to keypresses, you would have to constantly read the key's state so that you'd catch it before it's released again. It would be dangerous to perform other time-intensive computations since you might miss a keypress. +((Klavye)) üzerindeki bir tuşa basılıp basılmadığını öğrenmenin tek yolunun o tuşun mevcut durumunu okumak olduğu bir arayüz hayal edin. Tuşa basıldığında tepki verebilmek için, tuşun durumunu sürekli olarak okumanız gerekir, böylece tekrar bırakılmadan önce yakalayabilirsiniz. Bir tuşa basmayı kaçırabileceğiniz için diğer zaman yoğun hesaplamaları yapmak tehlikeli olacaktır. -Some primitive machines do handle input like that. A step up from this would be for the hardware or operating system to notice the keypress and put it in a queue. A program can then periodically check the queue for new events and react to what it finds there. +Bazı ilkel makineler girişi bu şekilde ele alır. Bunun bir adım ötesi, donanımın ya da işletim sisteminin tuşa basıldığını fark etmesi ve bunu bir kuyruğa koymasıdır. Bir program daha sonra yeni olaylar için kuyruğu periyodik olarak kontrol edebilir ve orada bulduklarına tepki verebilir. {{index responsiveness, "user experience"}} -Of course, it has to remember to look at the queue, and to do it often, because any time between the key being pressed and the program noticing the event will cause the software to feel unresponsive. This approach is called _((polling))_. Most programmers prefer to avoid it. +Elbette kuyruğa bakmayı ve bunu sık sık yapmayı hatırlaması gerekir, çünkü tuşa basılmasıyla programın olayı fark etmesi arasında geçen herhangi bir süre yazılımın tepkisiz kalmasına neden olacaktır. Bu yaklaşıma _((polling))_ denir. Çoğu programcı bundan kaçınmayı tercih eder. {{index "callback function", "event handling"}} -A better mechanism is for the system to actively notify our code when an event occurs. Browsers do this by allowing us to register functions as _handlers_ for specific events. +Daha iyi bir mekanizma, bir olay meydana geldiğinde sistemin kodumuzu aktif olarak bilgilendirmesidir. Tarayıcılar bunu, belirli olaylar için işlevleri _handlers_ olarak kaydetmemize izin vererek yapar. ```{lang: html} <p>Click this document to activate the handler.</p> @@ -39,13 +39,13 @@ A better mechanism is for the system to actively notify our code when an event o {{index "click event", "addEventListener method", "window object", [browser, window]}} -The `window` binding refers to a built-in object provided by the browser. It represents the browser window that contains the document. Calling its `addEventListener` method registers the second argument to be called whenever the event described by its first argument occurs. +`window` bağlayıcısı, tarayıcı tarafından sağlanan yerleşik bir nesneyi ifade eder. Belgeyi içeren tarayıcı penceresini temsil eder. addEventListener` yöntemi çağrıldığında, ilk bağımsız değişken tarafından tanımlanan olay gerçekleştiğinde çağrılmak üzere ikinci bağımsız değişken kaydedilir. -## Events and DOM nodes +## Olaylar ve DOM düğümleri {{index "addEventListener method", "event handling", "window object", browser, [DOM, events]}} -Each browser event handler is registered in a context. In the previous example we called `addEventListener` on the `window` object to register a handler for the whole window. Such a method can also be found on DOM elements and some other types of objects. Event listeners are called only when the event happens in the context of the object they are registered on. +Her tarayıcı olay işleyicisi bir bağlama kaydedilir. Önceki örnekte, tüm pencere için bir işleyici kaydetmek üzere `window` nesnesi üzerinde `addEventListener` yöntemini çağırdık. Böyle bir yöntem DOM öğelerinde ve diğer bazı nesne türlerinde de bulunabilir. Olay dinleyicileri yalnızca kaydedildikleri nesnenin bağlamında olay gerçekleştiğinde çağrılır. ```{lang: html} <button>Click me</button> @@ -60,17 +60,17 @@ Each browser event handler is registered in a context. In the previous example w {{index "click event", "button (HTML tag)"}} -That example attaches a handler to the button node. Clicks on the button cause that handler to run, but clicks on the rest of the document do not. +Bu örnek, düğme düğümüne bir işleyici ekler. Düğmeye tıklandığında bu işleyici çalışır, ancak belgenin geri kalanına tıklandığında işleyici çalışmaz. {{index "onclick attribute", encapsulation}} -Giving a node an `onclick` attribute has a similar effect. This works for most types of events—you can attach a handler through the attribute whose name is the event name with `on` in front of it. +Bir düğüme `onclick` niteliği vermek de benzer bir etkiye sahiptir. Bu, çoğu olay türü için işe yarar; adı olay adı olan ve önünde `on` bulunan öznitelik aracılığıyla bir işleyici ekleyebilirsiniz. -But a node can have only one `onclick` attribute, so you can register only one handler per node that way. The `addEventListener` method allows you to add any number of handlers so that it is safe to add handlers even if there is already another handler on the element. +Ancak bir düğümün yalnızca bir `onclick` niteliği olabilir, bu nedenle bu şekilde düğüm başına yalnızca bir işleyici kaydedebilirsiniz. addEventListener` yöntemi, istediğiniz sayıda işleyici eklemenize olanak tanır, böylece öğe üzerinde zaten başka bir işleyici olsa bile işleyici eklemek güvenlidir. {{index "removeEventListener method"}} -The `removeEventListener` method, called with arguments similar to `addEventListener`, removes a handler. +`addEventListener` yöntemine benzer argümanlarla çağrılan `removeEventListener` yöntemi bir işleyiciyi kaldırır. ```{lang: html} <button>Act-once button</button> @@ -86,13 +86,13 @@ The `removeEventListener` method, called with arguments similar to `addEventList {{index [function, "as value"]}} -The function given to `removeEventListener` has to be the same function value that was given to `addEventListener`. So, to unregister a handler, you'll want to give the function a name (`once`, in the example) to be able to pass the same function value to both methods. +`removeEventListener` metoduna verilen fonksiyon, `addEventListener` metoduna verilen fonksiyon değeri ile aynı olmalıdır. Bu nedenle, bir işleyicinin kaydını kaldırmak için, her iki yönteme de aynı işlev değerini aktarabilmek için işleve bir ad (örnekte `once`) vermek isteyeceksiniz. -## Event objects +## Olay nesneleri {{index "button property", "event handling"}} -Though we have ignored it so far, event handler functions are passed an argument: the _((event object))_. This object holds additional information about the event. For example, if we want to know _which_ ((mouse button)) was pressed, we can look at the event object's `button` property. +Şimdiye kadar göz ardı etmiş olsak da, olay işleyici işlevlerine bir argüman aktarılır: _((olay nesnesi))_. Bu nesne olay hakkında ek bilgiler tutar. Örneğin, _hangi_ ((fare düğmesine)) basıldığını bilmek istiyorsak, olay nesnesinin `button` özelliğine bakabiliriz. ```{lang: html} <button>Click me any way you want</button> @@ -112,9 +112,9 @@ Though we have ignored it so far, event handler functions are passed an argument {{index "event type", "type property"}} -The information stored in an event object differs per type of event. We'll discuss different types later in the chapter. The object's `type` property always holds a string identifying the event (such as `"click"` or `"mousedown"`). +Bir olay nesnesinde saklanan bilgiler olay türüne göre farklılık gösterir. Bölümün ilerleyen kısımlarında farklı türleri tartışacağız. Nesnenin `type` özelliği her zaman olayı tanımlayan bir dize tutar (örneğin `“click”` veya `“mousedown”`). -## Propagation +## Yayılma {{index "event propagation", "parent node"}} @@ -122,19 +122,19 @@ The information stored in an event object differs per type of event. We'll discu {{indexsee propagation, "event propagation"}} -For most event types, handlers registered on nodes with children will also receive events that happen in the children. If a button inside a paragraph is clicked, event handlers on the paragraph will also see the click event. +Çoğu olay türü için, çocukları olan düğümlerde kayıtlı işleyiciler, çocuklarda meydana gelen olayları da alır. Bir paragrafın içindeki bir düğmeye tıklanırsa, paragraftaki olay işleyicileri de tıklama olayını görür. {{index "event handling"}} -But if both the paragraph and the button have a handler, the more specific handler—the one on the button—gets to go first. The event is said to _propagate_ outward, from the node where it happened to that node's parent node and on to the root of the document. Finally, after all handlers registered on a specific node have had their turn, handlers registered on the whole ((window)) get a chance to respond to the event. +Ancak hem paragrafın hem de düğmenin bir işleyicisi varsa, daha spesifik olan işleyici - düğmedeki - önce gider. Olayın gerçekleştiği düğümden o düğümün üst düğümüne ve belgenin köküne doğru _propagate_ ettiği söylenir. Son olarak, belirli bir düğüm üzerinde kayıtlı tüm işleyiciler sıralarını aldıktan sonra, tüm ((pencere)) üzerinde kayıtlı işleyiciler olaya yanıt verme şansına sahip olur. {{index "stopPropagation method", "click event"}} -At any point, an event handler can call the `stopPropagation` method on the event object to prevent handlers further up from receiving the event. This can be useful when, for example, you have a button inside another clickable element and you don't want clicks on the button to activate the outer element's click behavior. +Herhangi bir noktada, bir olay işleyici olay nesnesi üzerinde `stopPropagation` yöntemini çağırarak daha yukarıdaki işleyicilerin olayı almasını engelleyebilir. Bu, örneğin, başka bir tıklanabilir öğenin içinde bir düğmeniz olduğunda ve düğmeye tıklandığında dış öğenin tıklama davranışının etkinleştirilmesini istemediğinizde yararlı olabilir. {{index "mousedown event", "pointer event"}} -The following example registers `"mousedown"` handlers on both a button and the paragraph around it. When clicked with the right mouse button, the handler for the button calls `stopPropagation`, which will prevent the handler on the paragraph from running. When the button is clicked with another ((mouse button)), both handlers will run. +Aşağıdaki örnek, hem bir düğme hem de etrafındaki paragraf üzerinde `“mousedown”` işleyicilerini kaydeder. Farenin sağ tuşuyla tıklandığında, düğmenin işleyicisi `stopPropagation` öğesini çağırır ve bu da paragraftaki işleyicinin çalışmasını engeller. Düğmeye başka bir ((fare düğmesi)) ile tıklandığında, her iki işleyici de çalışacaktır. ```{lang: html} <p>A paragraph with a <button>button</button>.</p> @@ -153,9 +153,9 @@ The following example registers `"mousedown"` handlers on both a button and the {{index "event propagation", "target property"}} -Most event objects have a `target` property that refers to the node where they originated. You can use this property to ensure that you're not accidentally handling something that propagated up from a node you do not want to handle. +Çoğu olay nesnesi, kaynaklandıkları düğümü ifade eden bir `target` özelliğine sahiptir. Bu özelliği, işlemek istemediğiniz bir düğümden yayılan bir şeyi yanlışlıkla işlemediğinizden emin olmak için kullanabilirsiniz. -It is also possible to use the `target` property to cast a wide net for a specific type of event. For example, if you have a node containing a long list of buttons, it may be more convenient to register a single click handler on the outer node and have it use the `target` property to figure out whether a button was clicked, rather than register individual handlers on all of the buttons. +Belirli bir olay türü için geniş bir ağ oluşturmak amacıyla `target` özelliğini kullanmak da mümkündür. Örneğin, uzun bir düğme listesi içeren bir düğümünüz varsa, tüm düğmelere ayrı ayrı işleyiciler kaydetmek yerine, dış düğümde tek bir tıklama işleyicisi kaydetmek ve bir düğmenin tıklanıp tıklanmadığını anlamak için `target` özelliğini kullanmasını sağlamak daha uygun olabilir. ```{lang: html} <button>A</button> @@ -170,19 +170,19 @@ It is also possible to use the `target` property to cast a wide net for a specif </script> ``` -## Default actions +## Varsayılan eylemler {{index scrolling, "default behavior", "event handling"}} -Many events have a default action associated with them. If you click a ((link)), you will be taken to the link's target. If you press the down arrow, the browser will scroll the page down. If you right-click, you'll get a context menu. And so on. +Birçok olayın kendileriyle ilişkili varsayılan bir eylemi vardır. Eğer bir ((link))'e tıklarsanız, linkin hedefine yönlendirilirsiniz. Aşağı oka basarsanız, tarayıcı sayfayı aşağı kaydırır. Sağ tıklarsanız, bir içerik menüsü alırsınız. Ve bu böyle devam eder. {{index "preventDefault method"}} -For most types of events, the JavaScript event handlers are called _before_ the default behavior takes place. If the handler doesn't want this normal behavior to happen, typically because it has already taken care of handling the event, it can call the `preventDefault` method on the event object. +Çoğu olay türü için JavaScript olay işleyicileri varsayılan davranış gerçekleşmeden _önce_ çağrılır. İşleyici bu normal davranışın gerçekleşmesini istemiyorsa, genellikle olayı zaten ele aldığı için, olay nesnesi üzerinde `preventDefault` yöntemini çağırabilir. {{index expectation}} -This can be used to implement your own ((keyboard)) shortcuts or ((context menu)). It can also be used to obnoxiously interfere with the behavior that users expect. For example, here is a link that cannot be followed: +Bu, kendi ((klavye)) kısayollarınızı veya ((içerik menüsü)) uygulamak için kullanılabilir. Ayrıca kullanıcıların beklediği davranışa iğrenç bir şekilde müdahale etmek için de kullanılabilir. Örneğin, burada takip edilemeyen bir bağlantı var: ```{lang: html} <a href="https://developer.mozilla.org/">MDN</a> @@ -197,15 +197,15 @@ This can be used to implement your own ((keyboard)) shortcuts or ((context menu) {{index usability}} -Try not to do such things unless you have a really good reason to. It'll be unpleasant for people who use your page when expected behavior is broken. +Gerçekten iyi bir nedeniniz olmadıkça böyle şeyler yapmamaya çalışın. Beklenen davranış bozulduğunda sayfanızı kullanan kişiler için hoş olmayacaktır. -Depending on the browser, some events can't be intercepted at all. On Chrome, for example, the ((keyboard)) shortcut to close the current tab ([control]{keyname}-W or [command]{keyname}-W) cannot be handled by JavaScript. +Tarayıcıya bağlı olarak, bazı olaylar hiç yakalanamaz. Örneğin Chrome'da, geçerli sekmeyi kapatmak için kullanılan ((klavye)) kısayolu ([control]{keyname}-W veya [command]{keyname}-W) JavaScript tarafından işlenemez. -## Key events +## Tuş olayları {{index keyboard, "keydown event", "keyup event", "event handling"}} -When a key on the keyboard is pressed, your browser fires a `"keydown"` event. When it is released, you get a `"keyup"` event. +Klavyedeki bir tuşa basıldığında, tarayıcınız bir `“keydown”` olayı başlatır. Bırakıldığında, bir `“keyup”` olayı alırsınız. ```{lang: html, focus: true} <p>This page turns violet when you hold the V key.</p> @@ -225,15 +225,15 @@ When a key on the keyboard is pressed, your browser fires a `"keydown"` event. W {{index "repeating key"}} -Despite its name, `"keydown"` fires not only when the key is physically pushed down. When a key is pressed and held, the event fires again every time the key _repeats_. Sometimes you have to be careful about this. For example, if you add a button to the DOM when a key is pressed and remove it again when the key is released, you might accidentally add hundreds of buttons when the key is held down longer. +Adına rağmen, `“keydown”` sadece tuş fiziksel olarak aşağı itildiğinde ateşlenmez. Bir tuşa basıldığında ve basılı tutulduğunda, tuş her _tekrar_ ettiğinde olay tekrar ateşlenir. Bazen bu konuda dikkatli olmanız gerekir. Örneğin, bir tuşa basıldığında DOM'a bir düğme eklerseniz ve tuş bırakıldığında tekrar kaldırırsanız, tuş daha uzun süre basılı tutulduğunda yanlışlıkla yüzlerce düğme ekleyebilirsiniz. {{index "key property"}} -The example looked at the `key` property of the event object to see which key the event is about. This property holds a string that, for most keys, corresponds to the thing that pressing that key would type. For special keys such as [enter]{keyname}, it holds a string that names the key (`"Enter"`, in this case). If you hold [shift]{keyname} while pressing a key, that might also influence the name of the key—`"v"` becomes `"V"`, and `"1"` may become `"!"`, if that is what pressing [shift]{keyname}-1 produces on your keyboard. +Örnekte, olayın hangi tuşla ilgili olduğunu görmek için olay nesnesinin `key` özelliğine bakılmıştır. Bu özellik, çoğu tuş için o tuşa basıldığında yazılacak şeye karşılık gelen bir dize tutar. [enter]{keyname} gibi özel tuşlar için, tuşu adlandıran bir dize tutar (bu durumda `“Enter”`). Bir tuşa basarken [shift]{keyname} tuşunu basılı tutarsanız, bu tuşun adını da etkileyebilir - `“v”` `“V”` olur ve `“1”` `“!”` olabilir, eğer [shift]{keyname}-1 tuşuna basmak klavyenizde bunu üretiyorsa. {{index "modifier key", "shift key", "control key", "alt key", "meta key", "command key", "ctrlKey property", "shiftKey property", "altKey property", "metaKey property"}} -Modifier keys such as [shift]{keyname}, [control]{keyname}, [alt]{keyname}, and [meta]{keyname} ([command]{keyname} on Mac) generate key events just like normal keys. But when looking for key combinations, you can also find out whether these keys are held down by looking at the `shiftKey`, `ctrlKey`, `altKey`, and `metaKey` properties of keyboard and mouse events. +[shift]{keyname}, [control]{keyname}, [alt]{keyname} ve [meta]{keyname} ([command]{keyname} Mac'te) gibi değiştirici tuşlar, tıpkı normal tuşlar gibi tuş olayları oluşturur. Ancak tuş kombinasyonlarını ararken, klavye ve fare olaylarının `shiftKey`, `ctrlKey`, `altKey` ve `metaKey` özelliklerine bakarak bu tuşların basılı tutulup tutulmadığını da öğrenebilirsiniz. ```{lang: html, focus: true} <p>Press Control-Space to continue.</p> @@ -248,39 +248,39 @@ Modifier keys such as [shift]{keyname}, [control]{keyname}, [alt]{keyname}, and {{index "button (HTML tag)", "tabindex attribute", [DOM, events]}} -The DOM node where a key event originates depends on the element that has ((focus)) when the key is pressed. Most nodes cannot have focus unless you give them a `tabindex` attribute, but things like ((link))s, buttons, and form fields can. We'll come back to form ((field))s in [Chapter ?](http#forms). When nothing in particular has focus, `document.body` acts as the target node of key events. +Bir tuş olayının kaynaklandığı DOM düğümü, tuşa basıldığında ((focus)) olan öğeye bağlıdır. Çoğu düğüm `tabindex` niteliği verilmediği sürece odağa sahip olamaz, ancak ((link))ler, düğmeler ve form alanları gibi şeyler olabilir. Form ((alan))larına [Bölüm ?](http#forms) içinde geri döneceğiz. Belirli bir şey odağa sahip olmadığında, `document.body` anahtar olayların hedef düğümü olarak hareket eder. -When the user is typing text, using key events to figure out what is being typed is problematic. Some platforms, most notably the ((virtual keyboard)) on ((Android)) ((phone))s, don't fire key events. But even when you have an old-fashioned keyboard, some types of text input don't match key presses in a straightforward way, such as _input method editor_ (((IME))) software used by people whose scripts don't fit on a keyboard, where multiple key strokes are combined to create characters. +Kullanıcı metin yazarken, ne yazıldığını anlamak için tuş olaylarını kullanmak sorunludur. Bazı platformlar, özellikle de ((Android)) ((telefon))lardaki ((sanal klavye)), tuş olaylarını ateşlemez. Ancak eski moda bir klavyeniz olduğunda bile, bazı metin girişi türleri, komut dosyaları klavyeye sığmayan kişiler tarafından kullanılan _input method editor_ (((IME))) yazılımı gibi, karakterleri oluşturmak için birden fazla tuş vuruşunun birleştirildiği tuş basışlarıyla doğrudan eşleşmez. -To notice when something was typed, elements that you can type into, such as the `<input>` and `<textarea>` tags, fire `"input"` events whenever the user changes their content. To get the actual content that was typed, it is best to directly read it from the focused field. [Chapter ?](http#forms) will show how. +Bir şeyin ne zaman yazıldığını fark etmek için, `<input>` ve `<textarea>` etiketleri gibi içine yazabileceğiniz öğeler, kullanıcı içeriğini değiştirdiğinde `“input”` olaylarını tetikler. Yazılan gerçek içeriği almak için, en iyisi bunu doğrudan odaklanılan alandan okumaktır. [Bölüm ?](http#forms) nasıl yapılacağını gösterecektir. -## Pointer events +## İşaret etme olayları -There are currently two widely used ways to point at things on a screen: mice (including devices that act like mice, such as touchpads and trackballs) and touchscreens. These produce different kinds of events. +Şu anda ekranda bir şeyleri işaret etmenin yaygın olarak kullanılan iki yolu vardır: fareler (dokunmatik yüzeyler ve iztopları gibi fare gibi davranan cihazlar dahil) ve dokunmatik ekranlar. Bunlar farklı türde olaylar üretir. -### Mouse clicks +### Mouse tıklamaları {{index "mousedown event", "mouseup event", "mouse cursor"}} -Pressing a ((mouse button)) causes a number of events to fire. The `"mousedown"` and `"mouseup"` events are similar to `"keydown"` and `"keyup"` and fire when the button is pressed and released. These happen on the DOM nodes that are immediately below the mouse pointer when the event occurs. +Bir ((fare düğmesine)) basmak bir dizi olayın tetiklenmesine neden olur. `“mousedown"` ve `‘mouseup’` olayları, `‘keydown’` ve `‘keyup’` olaylarına benzer ve düğmeye basılıp bırakıldığında gerçekleşir. Bunlar, olay gerçekleştiğinde fare işaretçisinin hemen altında bulunan DOM düğümlerinde gerçekleşir. {{index "click event"}} -After the `"mouseup"` event, a `"click"` event fires on the most specific node that contained both the press and the release of the button. For example, if I press down the mouse button on one paragraph and then move the pointer to another paragraph and release the button, the `"click"` event will happen on the element that contains both those paragraphs. +`“mouseup“` olayından sonra, düğmeye hem basılmasını hem de bırakılmasını içeren en belirli düğümde bir `”click"` olayı gerçekleşir. Örneğin, bir paragrafta fare düğmesine basarsam ve ardından işaretçiyi başka bir paragrafa taşıyıp düğmeyi bırakırsam, `“click”` olayı her iki paragrafı da içeren öğede gerçekleşir. {{index "dblclick event", "double click"}} -If two clicks happen close together, a `"dblclick"` (double-click) event also fires, after the second click event. +İki tıklama birbirine yakın gerçekleşirse, ikinci tıklama olayından sonra bir `“dblclick”` (çift tıklama) olayı da ateşlenir. {{index pixel, "clientX property", "clientY property", "pageX property", "pageY property", "event object"}} -To get precise information about the place where a mouse event happened, you can look at its `clientX` and `clientY` properties, which contain the event's ((coordinates)) (in pixels) relative to the top-left corner of the window, or `pageX` and `pageY`, which are relative to the top-left corner of the whole document (which may be different when the window has been scrolled). +Bir fare olayının gerçekleştiği yer hakkında kesin bilgi almak için, olayın pencerenin sol üst köşesine göre ((koordinatlarını)) (piksel cinsinden) içeren `clientX` ve `clientY` özelliklerine veya tüm belgenin sol üst köşesine göre olan `pageX` ve `pageY` özelliklerine bakabilirsiniz (pencere kaydırıldığında farklı olabilir). {{index "border-radius (CSS)", "absolute positioning", "drawing program example"}} {{id mouse_drawing}} -The following program implements a primitive drawing application. Every time you click the document, it adds a dot under your mouse pointer. See [Chapter ?](paint) for a less primitive drawing application. +Aşağıda ilkel bir çizim programı uygulanmaktadır. Belgeye her tıkladığınızda, fare işaretçinizin altına bir nokta ekler. Daha az ilkel bir çizim programı için [bölüm ?](paint) içine bakın. ```{lang: html} <style> @@ -306,15 +306,15 @@ The following program implements a primitive drawing application. Every time you </script> ``` -### Mouse motion +### Mouse hareketi {{index "mousemove event"}} -Every time the mouse pointer moves, a `"mousemove"` event is fired. This event can be used to track the position of the mouse. A common situation in which this is useful is when implementing some form of mouse-((dragging)) functionality. +Fare işaretçisi her hareket ettiğinde, bir `“mousemove”` olayı ateşlenir. Bu olay, farenin konumunu izlemek için kullanılabilir. Bunun yararlı olduğu yaygın bir durum, bir tür fare-((sürükleme)) işlevselliğinin uygulanmasıdır. {{index "draggable bar example"}} -As an example, the following program displays a bar and sets up event handlers so that dragging to the left or right on this bar makes it narrower or wider: +Örnek olarak, aşağıdaki program bir çubuk görüntüler ve bu çubuk üzerinde sola veya sağa sürüklemenin çubuğu daraltması veya genişletmesi için olay işleyicileri ayarlar: ```{lang: html, startCode: true} <p>Drag the bar to change its width:</p> @@ -346,41 +346,41 @@ As an example, the following program displays a bar and sets up event handlers s {{if book -The resulting page looks like this: +Ortaya çıkan sayfa şu şekilde görünür: -{{figure {url: "img/drag-bar.png", alt: "Picture of a draggable bar", width: "5.3cm"}}} +{{figure {url: "img/drag-bar.png", alt: "Sürüklenebilir çubuk resmi", width: "5.3cm"}}} if}} {{index "mouseup event", "mousemove event"}} -Note that the `"mousemove"` handler is registered on the whole ((window)). Even if the mouse goes outside of the bar during resizing, as long as the button is held we still want to update its size. +`“mousemove"` işleyicisinin tüm ((pencere)) üzerinde kayıtlı olduğuna dikkat edin. Yeniden boyutlandırma sırasında fare çubuğun dışına çıksa bile, düğme basılı tutulduğu sürece boyutunu güncellemek isteriz. {{index "buttons property", "button property", "bitfield"}} -We must stop resizing the bar when the mouse button is released. For that, we can use the `buttons` property (note the plural), which tells us about the buttons that are currently held down. When this is zero, no buttons are down. When buttons are held, its value is the sum of the codes for those buttons—the left button has code 1, the right button 2, and the middle one 4. With the left and right buttons held, for example, the value of `buttons` will be 3. +Fare düğmesi bırakıldığında çubuğun yeniden boyutlandırılmasını durdurmalıyız. Bunun için, bize o anda basılı tutulan düğmeler hakkında bilgi veren `buttons` özelliğini (çoğul olduğuna dikkat edin) kullanabiliriz. Bu değer sıfır olduğunda, hiçbir düğme basılı değildir. Düğmeler basılı tutulduğunda, değeri bu düğmelerin kodlarının toplamıdır - sol düğme 1, sağ düğme 2 ve ortadaki düğme 4 koduna sahiptir. Örneğin sol ve sağ düğmeler basılı tutulduğunda `buttons` değeri 3 olacaktır. -Note that the order of these codes is different from the one used by `button`, where the middle button came before the right one. As mentioned, consistency isn't really a strong point of the browser's programming interface. +Bu kodların sırasının, ortadaki düğmenin sağdakinden önce geldiği `button` tarafından kullanılandan farklı olduğuna dikkat edin. Belirtildiği gibi, tutarlılık tarayıcının programlama arayüzünün güçlü bir noktası değildir. -### Touch events +### Dokunma olayları {{index touch, "mousedown event", "mouseup event", "click event"}} -The style of graphical browser that we use was designed with mouse interfaces in mind, at a time where touchscreens were rare. To make the Web "work" on early touchscreen phones, browsers for those devices pretended, to a certain extent, that touch events were mouse events. If you tap your screen, you'll get `"mousedown"`, `"mouseup"`, and `"click"` events. +Kullandığımız grafik tarayıcı tarzı, dokunmatik ekranların nadir olduğu bir dönemde fare arayüzleri düşünülerek tasarlanmıştır. Web'in ilk dokunmatik ekranlı telefonlarda “çalışmasını” sağlamak için, bu cihazlara yönelik tarayıcılar bir dereceye kadar dokunma olaylarının fare olayları olduğunu varsaymıştır. Ekranınıza dokunursanız, `“mousedown”`, `“mouseup”` ve `“click”` olaylarını alırsınız. -But this illusion isn't very robust. A touchscreen works differently from a mouse: it doesn't have multiple buttons, you can't track the finger when it isn't on the screen (to simulate `"mousemove"`), and it allows multiple fingers to be on the screen at the same time. +Ancak bu yanılsama çok sağlam değildir. Dokunmatik ekran fareden farklı çalışır: birden fazla düğmesi yoktur, ekranda değilken parmağınızı takip edemezsiniz (“mousemove”`ı simüle etmek için) ve aynı anda birden fazla parmağın ekranda olmasına izin verir. -Mouse events cover touch interaction only in straightforward cases—if you add a `"click"` handler to a button, touch users will still be able to use it. But something like the resizeable bar in the previous example does not work on a touchscreen. +Fare olayları yalnızca basit durumlarda dokunmatik etkileşimi kapsar - bir düğmeye `“click”` işleyicisi eklerseniz, dokunmatik kullanıcılar bunu kullanmaya devam edebilir. Ancak önceki örnekteki yeniden boyutlandırılabilir çubuk gibi bir şey dokunmatik ekranda çalışmaz. {{index "touchstart event", "touchmove event", "touchend event"}} -There are specific event types fired by touch interaction. When a finger starts touching the screen, you get a `"touchstart"` event. When it is moved while touching, `"touchmove"` events fire. Finally, when it stops touching the screen, you'll see a `"touchend"` event. +Dokunma etkileşimi tarafından ateşlenen belirli olay türleri vardır. Bir parmak ekrana dokunmaya başladığında, bir `“touchstart”` olayı elde edersiniz. Dokunurken hareket ettirildiğinde, `“touchmove”` olayları ateşlenir. Son olarak, ekrana dokunmayı bıraktığında, bir `“touchend”` olayı görürsünüz. {{index "touches property", "clientX property", "clientY property", "pageX property", "pageY property"}} -Because many touchscreens can detect multiple fingers at the same time, these events don't have a single set of coordinates associated with them. Rather, their ((event object))s have a `touches` property, which holds an ((array-like object)) of points, each of which has its own `clientX`, `clientY`, `pageX`, and `pageY` properties. +Birçok dokunmatik ekran aynı anda birden fazla parmağı algılayabildiğinden, bu olayların kendileriyle ilişkili tek bir koordinat kümesi yoktur. Bunun yerine, ((olay nesnesi)), her biri kendi `clientX`, `clientY`, `pageX` ve `pageY` özelliklerine sahip olan bir ((dizi benzeri nesne)) nokta tutan bir `touches` özelliğine sahiptir. -You could do something like this to show red circles around every touching finger: +Dokunan her parmağın etrafında kırmızı daireler göstermek için böyle bir şey yapabilirsiniz: ```{lang: html} <style> @@ -410,15 +410,15 @@ You could do something like this to show red circles around every touching finge {{index "preventDefault method"}} -You'll often want to call `preventDefault` in touch event handlers to override the browser's default behavior (which may include scrolling the page on swiping) and to prevent the mouse events from being fired, for which you may _also_ have a handler. +Tarayıcının varsayılan davranışını (kaydırma sırasında sayfanın kaydırılmasını içerebilir) geçersiz kılmak ve _ayrıca_ bir işleyiciye sahip olabileceğiniz fare olaylarının tetiklenmesini önlemek için genellikle dokunma olayı işleyicilerinde `preventDefault'u çağırmak isteyeceksiniz. -## Scroll events +## Kaydırma etkinlikleri {{index scrolling, "scroll event", "event handling"}} -Whenever an element is scrolled, a `"scroll"` event is fired on it. This has various uses, such as knowing what the user is currently looking at (for disabling off-screen ((animation))s or sending ((spy)) reports to your evil headquarters) or showing some indication of progress (by highlighting part of a table of contents or showing a page number). +Bir öğe kaydırıldığında, üzerinde bir `“scroll”` olayı tetiklenir. Bunun, kullanıcının o anda neye baktığını bilmek (ekran dışı ((animasyon))ları devre dışı bırakmak veya şeytani karargahınıza ((casus)) raporları göndermek için) veya bazı ilerleme göstergelerini göstermek (içindekiler tablosunun bir kısmını vurgulayarak veya bir sayfa numarası göstererek) gibi çeşitli kullanımları vardır. -The following example draws a ((progress bar)) above the document and updates it to fill up as you scroll down: +Aşağıdaki örnek, belgenin üzerine bir ((ilerleme çubuğu)) çizer ve siz aşağı kaydırdıkça dolacak şekilde günceller: ```{lang: html} <style> @@ -445,29 +445,29 @@ The following example draws a ((progress bar)) above the document and updates it {{index "unit (CSS)", scrolling, "position (CSS)", "fixed positioning", "absolute positioning", percentage, "repeat method"}} -Giving an element a `position` of `fixed` acts much like an `absolute` position but also prevents it from scrolling along with the rest of the document. The effect is to make our progress bar stay at the top. Its width is changed to indicate the current progress. We use `%`, rather than `px`, as a unit when setting the width so that the element is sized relative to the page width. +Bir öğeye `fixed` bir `position` vermek, `absolute` bir konum gibi davranır, ancak aynı zamanda belgenin geri kalanıyla birlikte kaymasını da önler. Bunun etkisi, ilerleme çubuğumuzun en üstte kalmasını sağlamaktır. Genişliği mevcut ilerlemeyi gösterecek şekilde değiştirilir. Genişliği ayarlarken birim olarak `px` yerine `%` kullanırız, böylece öğe sayfa genişliğine göre boyutlandırılır. {{index "innerHeight property", "innerWidth property", "pageYOffset property"}} -The global `innerHeight` binding gives us the height of the window, which we have to subtract from the total scrollable height—you can't keep scrolling when you hit the bottom of the document. There's also an `innerWidth` for the window width. By dividing `pageYOffset`, the current scroll position, by the maximum scroll position and multiplying by 100, we get the percentage for the progress bar. +Global `innerHeight` bağlayıcısı bize pencerenin yüksekliğini verir, bunu toplam kaydırılabilir yükseklikten çıkarmamız gerekir-belgenin altına ulaştığınızda kaydırmaya devam edemezsiniz. Pencere genişliği için de bir `innerWidth` vardır. Geçerli kaydırma konumu olan `pageYOffset`i maksimum kaydırma konumuna bölerek ve 100 ile çarparak ilerleme çubuğunun yüzdesini elde ederiz. {{index "preventDefault method"}} -Calling `preventDefault` on a scroll event does not prevent the scrolling from happening. In fact, the event handler is called only _after_ the scrolling takes place. +Bir kaydırma olayında `preventDefault` çağrısı yapmak kaydırmanın gerçekleşmesini engellemez. Aslında, olay işleyici yalnızca kaydırma gerçekleştikten _sonra_ çağrılır. -## Focus events +## Odak etkinlikleri {{index "event handling", "focus event", "blur event"}} -When an element gains ((focus)), the browser fires a `"focus"` event on it. When it loses focus, the element gets a `"blur"` event. +Bir öğe ((odak)) kazandığında, tarayıcı üzerinde bir `“focus”` olayı ateşler. Odağı kaybettiğinde, öğe bir `“blur”` olayı alır. {{index "event propagation"}} -Unlike the events discussed earlier, these two events do not propagate. A handler on a parent element is not notified when a child element gains or loses focus. +Daha önce tartışılan olayların aksine, bu iki olay yayılmaz. Bir üst öğedeki işleyici, bir alt öğe odak kazandığında veya kaybettiğinde bilgilendirilmez. {{index "input (HTML tag)", "help text example"}} -The following example displays help text for the ((text field)) that currently has focus: +Aşağıdaki örnek, o anda odağa sahip olan ((metin alanı)) için yardım metnini görüntüler: ```{lang: html} <p>Name: <input type="text" data-help="Your full name"></p> @@ -491,43 +491,43 @@ The following example displays help text for the ((text field)) that currently h {{if book -This screenshot shows the help text for the age field. +Bu ekran görüntüsü yaş alanı için yardım metnini göstermektedir. -{{figure {url: "img/help-field.png", alt: "Screenshot of the help text below the age field", width: "4.4cm"}}} +{{figure {url: "img/help-field.png", alt: "Yaş alanının altındaki yardım metninin ekran görüntüsü", width: "4.4cm"}}} if}} {{index "focus event", "blur event"}} -The ((window)) object will receive `"focus"` and `"blur"` events when the user moves from or to the browser tab or window in which the document is shown. +((`window`)) nesnesi, kullanıcı belgenin gösterildiği tarayıcı sekmesinden veya penceresinden hareket ettiğinde `“focus”` ve `“blur”` olaylarını alacaktır. -## Load event +## Yükleme olayı {{index "script (HTML tag)", "load event"}} -When a page finishes loading, the `"load"` event fires on the window and the document body objects. This is often used to schedule ((initialization)) actions that require the whole ((document)) to have been built. Remember that the content of `<script>` tags is run immediately when the tag is encountered. This may be too soon, for example when the script needs to do something with parts of the document that appear after the `<script>` tag. +Bir sayfa yüklenmeyi bitirdiğinde, `“load”` olayı pencere ve belge gövdesi nesneleri üzerinde ateşlenir. Bu genellikle tüm ((belgenin)) oluşturulmasını gerektiren ((başlatma)) eylemlerini zamanlamak için kullanılır. `<script>` etiketlerinin içeriğinin, etiketle karşılaşıldığında hemen çalıştırıldığını unutmayın. Bu, örneğin komut dosyasının belgenin `<script>` etiketinden sonra görünen bölümleriyle bir şeyler yapması gerektiğinde çok erken olabilir. {{index "event propagation", "img (HTML tag)"}} -Elements such as ((image))s and script tags that load an external file also have a `"load"` event that indicates the files they reference were loaded. Like the focus-related events, loading events do not propagate. +Harici bir dosya yükleyen ((görüntü))ler ve script etiketleri gibi öğeler de referans verdikleri dosyaların yüklendiğini gösteren bir `“load”` olayına sahiptir. Odakla ilgili olaylar gibi, yükleme olayları da yayılmaz. {{index "beforeunload event", "page reload", "preventDefault method"}} -When a page is closed or navigated away from (for example, by following a link), a `"beforeunload"` event fires. The main use of this event is to prevent the user from accidentally losing work by closing a document. If you prevent the default behavior on this event _and_ set the `returnValue` property on the event object to a string, the browser will show the user a dialog asking if they really want to leave the page. That dialog might include your string, but because some malicious sites try to use these dialogs to confuse people into staying on their page to look at dodgy weight loss ads, most browsers no longer display them. +Bir sayfa kapatıldığında veya sayfadan uzaklaşıldığında (örneğin, bir bağlantı takip edilerek), bir `“beforeunload”` olayı ateşlenir. Bu olayın ana kullanımı, kullanıcının bir belgeyi kapatarak yanlışlıkla işini kaybetmesini önlemektir. Bu olayda varsayılan davranışı engellerseniz _ve_ olay nesnesindeki `returnValue` özelliğini bir dizeye ayarlarsanız, tarayıcı kullanıcıya sayfadan gerçekten ayrılmak isteyip istemediğini soran bir iletişim kutusu gösterecektir. Bu iletişim kutusu sizin dizenizi içerebilir, ancak bazı kötü niyetli siteler bu iletişim kutularını kullanarak insanların kafasını karıştırıp sayfalarında kalmalarını ve tehlikeli zayıflama reklamlarına bakmalarını sağlamaya çalıştığından, çoğu tarayıcı artık bunları göstermemektedir. {{id timeline}} -## Events and the event loop +## Olaylar ve olay döngüsü {{index "requestAnimationFrame function", "event handling", timeline, "script (HTML tag)"}} -In the context of the event loop, as discussed in [Chapter ?](async), browser event handlers behave like other asynchronous notifications. They are scheduled when the event occurs but must wait for other scripts that are running to finish before they get a chance to run. +[Bölüm ?](async) içinde tartışıldığı gibi olay döngüsü bağlamında, tarayıcı olay işleyicileri diğer asenkron bildirimler gibi davranır. Olay meydana geldiğinde zamanlanırlar, ancak çalışma şansı bulmadan önce çalışan diğer komut dosyalarının bitmesini beklemeleri gerekir. -The fact that events can be processed only when nothing else is running means that, if the event loop is tied up with other work, any interaction with the page (which happens through events) will be delayed until there's time to process it. So if you schedule too much work, either with long-running event handlers or with lots of short-running ones, the page will become slow and cumbersome to use. +Olayların yalnızca başka hiçbir şey çalışmıyorken işlenebilmesi gerçeği, olay döngüsünün başka işlerle meşgul olması durumunda, sayfayla (olaylar aracılığıyla gerçekleşen) her türlü etkileşimin işlenecek zaman bulunana kadar erteleneceği anlamına gelir. Dolayısıyla, uzun süre çalışan olay işleyicileriyle ya da çok sayıda kısa süre çalışan olay işleyicileriyle çok fazla iş planlarsanız, sayfa yavaşlayacak ve kullanımı hantal hale gelecektir. -For cases where you _really_ do want to do some time-consuming thing in the background without freezing the page, browsers provide something called _((web worker))s_. A worker is a JavaScript process that runs alongside the main script, on its own timeline. +Sayfayı dondurmadan arka planda zaman alıcı bir şey yapmak istediğiniz durumlar için tarayıcılar _((web worker))s_ adı verilen bir şey sağlar. Çalışan, ana komut dosyasının yanında, kendi zaman çizelgesinde çalışan bir JavaScript işlemidir. -Imagine that squaring a number is a heavy, long-running computation that we want to perform in a separate ((thread)). We could write a file called `code/squareworker.js` that responds to messages by computing a square and sending a message back. +Bir sayının karesini almanın, ayrı bir ((thread)) içinde gerçekleştirmek istediğimiz ağır ve uzun süren bir hesaplama olduğunu düşünün. Bir kare hesaplayarak ve geri bir mesaj göndererek mesajlara yanıt veren `code/squareworker.js` adlı bir dosya yazabiliriz. ``` addEventListener("message", event => { @@ -535,9 +535,9 @@ addEventListener("message", event => { }); ``` -To avoid the problems of having multiple ((thread))s touching the same data, workers do not share their ((global scope)) or any other data with the main script's environment. Instead, you have to communicate with them by sending messages back and forth. +Aynı veriye dokunan birden fazla ((iş parçacığı)) olmasından kaynaklanan sorunlardan kaçınmak için, işçiler ((global kapsam)) veya başka herhangi bir veriyi ana kodun ortamıyla paylaşmazlar. Bunun yerine, ileri geri mesajlar göndererek onlarla iletişim kurmanız gerekir. -This code spawns a worker running that script, sends it a few messages, and outputs the responses. +Bu kod, söz konusu betiği çalıştıran bir işçiyi ortaya çıkarır, ona birkaç mesaj gönderir ve yanıtları çıktı olarak verir. ```{test: no} let squareWorker = new Worker("code/squareworker.js"); @@ -550,17 +550,17 @@ squareWorker.postMessage(24); {{index "postMessage method", "message event"}} -The `postMessage` function sends a message, which will cause a `"message"` event to fire in the receiver. The script that created the worker sends and receives messages through the `Worker` object, whereas the worker talks to the script that created it by sending and listening directly on its ((global scope)). Only values that can be represented as JSON can be sent as messages—the other side will receive a _copy_ of them, rather than the value itself. +`postMessage` fonksiyonu, alıcıda bir `“message”` olayının tetiklenmesine neden olacak bir mesaj gönderir. Çalışanı oluşturan kod `Worker` nesnesi aracılığıyla mesaj gönderir ve alır, çalışan ise doğrudan ((global kapsam)) göndererek ve dinleyerek kendisini oluşturan kodla konuşur. Yalnızca JSON olarak temsil edilebilen değerler mesaj olarak gönderilebilir; karşı taraf değerin kendisi yerine bir _kopyasını_ alır. -## Timers +## Zamanlayıcılar -{{index timeout, "setTimeout function"}} +{{index timeout, "setTimeout function", "clearTimeout function"}} -We saw the `setTimeout` function in [Chapter ?](async). It schedules another function to be called later, after a given number of milliseconds. +`setTimeout` fonksiyonunu [bölüm ?](async) içinde gördük. Belirli bir milisaniye sayısından sonra başka bir fonksiyonun çağrılmasını planlar. {{index "clearTimeout function"}} -Sometimes you need to cancel a function you have scheduled. This is done by storing the value returned by `setTimeout` and calling `clearTimeout` on it. +Bazen zamanladığınız bir işlevi iptal etmeniz gerekir. Bu, `setTimeout` tarafından döndürülen değeri saklayarak ve üzerinde `clearTimeout` çağrısı yaparak yapılır. ``` let bombTimer = setTimeout(() => { @@ -575,11 +575,11 @@ if (Math.random() < 0.5) { // 50% chance {{index "cancelAnimationFrame function", "requestAnimationFrame function"}} -The `cancelAnimationFrame` function works in the same way as `clearTimeout`—calling it on a value returned by `requestAnimationFrame` will cancel that frame (assuming it hasn't already been called). +`cancelAnimationFrame` fonksiyonu `clearTimeout` ile aynı şekilde çalışır - `requestAnimationFrame` tarafından döndürülen bir değer üzerinde çağrılması o kareyi iptal eder (daha önce çağrılmadığını varsayarak). {{index "setInterval function", "clearInterval function", repetition}} -A similar set of functions, `setInterval` and `clearInterval`, are used to set timers that should _repeat_ every _X_ milliseconds. +Benzer bir fonksiyon seti olan `setInterval` ve `clearInterval`, her _X_ milisaniyede bir _tekrarlanması_ gereken zamanlayıcıları ayarlamak için kullanılır. ``` let ticks = 0; @@ -592,19 +592,19 @@ let clock = setInterval(() => { }, 200); ``` -## Debouncing +## Geri tepme(debouncing) {{index optimization, "mousemove event", "scroll event", blocking}} -Some types of events have the potential to fire rapidly, many times in a row (the `"mousemove"` and `"scroll"` events, for example). When handling such events, you must be careful not to do anything too time-consuming or your handler will take up so much time that interaction with the document starts to feel slow. +Bazı olay türleri hızlı bir şekilde, arka arkaya birçok kez tetiklenme potansiyeline sahiptir (örneğin `“mousemove”` ve `“scroll”` olayları). Bu tür olayları işlerken, çok zaman alıcı bir şey yapmamaya dikkat etmelisiniz, aksi takdirde işleyiciniz o kadar çok zaman alır ki, belge ile etkileşim yavaş hissettirmeye başlar. {{index "setTimeout function"}} -If you do need to do something nontrivial in such a handler, you can use `setTimeout` to make sure you are not doing it too often. This is usually called _((debouncing))_ the event. There are several slightly different approaches to this. +Böyle bir işleyicide önemsiz bir şey yapmanız gerekiyorsa, bunu çok sık yapmadığınızdan emin olmak için `setTimeout` kullanabilirsiniz. Buna genellikle _((debouncing))_ olay adı verilir. Bu konuda biraz farklı birkaç yaklaşım vardır. {{index "textarea (HTML tag)", "clearTimeout function", "keydown event"}} -In the first example, we want to react when the user has typed something, but we don't want to do it immediately for every input event. When they are ((typing)) quickly, we just want to wait until a pause occurs. Instead of immediately performing an action in the event handler, we set a timeout. We also clear the previous timeout (if any) so that when events occur close together (closer than our timeout delay), the timeout from the previous event will be canceled. +İlk örnekte, kullanıcı bir şey yazdığında tepki vermek istiyoruz, ancak bunu her girdi olayı için hemen yapmak istemiyoruz. Hızlı bir şekilde ((yazdıklarında)), sadece bir duraklama gerçekleşene kadar beklemek istiyoruz. Olay işleyicide hemen bir eylem gerçekleştirmek yerine, bir zaman aşımı ayarlıyoruz. Ayrıca önceki zaman aşımını (varsa) temizleriz, böylece olaylar birbirine yakın olduğunda (zaman aşımı gecikmemizden daha yakın), önceki olayın zaman aşımı iptal edilir. ```{lang: html} <textarea>Type something here...</textarea> @@ -620,11 +620,11 @@ In the first example, we want to react when the user has typed something, but we {{index "sloppy programming"}} -Giving an undefined value to `clearTimeout` or calling it on a timeout that has already fired has no effect. Thus, we don't have to be careful about when to call it, and we simply do so for every event. +`clearTimeout`'a tanımlanmamış bir değer vermenin veya zaten ateşlenmiş bir zaman aşımında çağırmanın hiçbir etkisi yoktur. Bu nedenle, onu ne zaman çağıracağımız konusunda dikkatli olmamız gerekmez ve bunu her olay için yaparız. {{index "mousemove event"}} -We can use a slightly different pattern if we want to space responses so that they're separated by at least a certain length of ((time)) but want to fire them _during_ a series of events, not just afterward. For example, we might want to respond to `"mousemove"` events by showing the current coordinates of the mouse but only every 250 milliseconds. +Yanıtları en az belirli bir ((zaman)) uzunluğuyla ayrılacak şekilde yerleştirmek istiyorsak, ancak bunları sadece sonrasında değil, bir dizi olay sırasında ateşlemek istiyorsak biraz farklı bir model kullanabiliriz.Örneğin, `“mousemove”` olaylarına farenin geçerli koordinatlarını göstererek yanıt vermek isteyebiliriz, ancak yalnızca her 250 milisaniyede bir. ```{lang: html} <script> @@ -642,33 +642,35 @@ We can use a slightly different pattern if we want to space responses so that th </script> ``` -## Summary +## Özet -Event handlers make it possible to detect and react to events happening in our web page. The `addEventListener` method is used to register such a handler. +Olay işleyicileri, web sayfamızda meydana gelen olayları tespit etmeyi ve bunlara tepki vermeyi mümkün kılar. Böyle bir işleyiciyi kaydetmek için `addEventListener` yöntemi kullanılır. -Each event has a type (`"keydown"`, `"focus"`, and so on) that identifies it. Most events are called on a specific DOM element and then _propagate_ to that element's ancestors, allowing handlers associated with those elements to handle them. +Her olayın onu tanımlayan bir türü (`“keydown”`, `“focus”`, vb.) vardır. Çoğu olay belirli bir DOM öğesinde çağrılır ve ardından bu öğenin atalarına _propagate_ edilerek bu öğelerle ilişkili işleyicilerin bunları işlemesine izin verilir. -When an event handler is called, it is passed an event object with additional information about the event. This object also has methods that allow us to stop further propagation (`stopPropagation`) and prevent the browser's default handling of the event (`preventDefault`). +Bir olay işleyicisi çağrıldığında, olay hakkında ek bilgiler içeren bir olay nesnesi aktarılır. Bu nesne ayrıca daha fazla yayılmayı durdurmamıza (`stopPropagation`) ve tarayıcının olayı varsayılan olarak işlemesini engellememize (`preventDefault`) izin veren yöntemlere sahiptir. -Pressing a key fires `"keydown"` and `"keyup"` events. Pressing a mouse button fires `"mousedown"`, `"mouseup"`, and `"click"` events. Moving the mouse fires `"mousemove"` events. Touchscreen interaction will result in `"touchstart"`, `"touchmove"`, and `"touchend"` events. +Bir tuşa basmak `“keydown”` ve `“keyup”` olaylarını tetikler. Bir fare düğmesine basmak `“mousedown”`, `“mouseup”` ve `“click”` olaylarını tetikler. Farenin hareket ettirilmesi `“mousemove”` olaylarını ateşler. Dokunmatik ekran etkileşimi `“touchstart”`, `“touchmove”` ve `“touchend”` olaylarına neden olur. -Scrolling can be detected with the `"scroll"` event, and focus changes can be detected with the `"focus"` and `"blur"` events. When the document finishes loading, a `"load"` event fires on the window. +Kaydırma `“scroll”` olayı ile, odak değişiklikleri ise `“focus”` ve `“blur”` olayları ile algılanabilir. Belge yüklenmeyi bitirdiğinde, pencerede bir `“load”` olayı ateşlenir. -## Exercises +Translated with DeepL.com (free version) -### Balloon +## Egzersizler + +### Balon {{index "balloon (exercise)", "arrow key"}} -Write a page that displays a ((balloon)) (using the balloon ((emoji)), 🎈). When you press the up arrow, it should inflate (grow) 10 percent, and when you press the down arrow, it should deflate (shrink) 10 percent. +Bir ((balon)) gösteren bir sayfa yazın (balon ((emoji)) kullanarak, 🎈). Yukarı oka bastığınızda yüzde 10 şişmeli (büyümeli) ve aşağı oka bastığınızda yüzde 10 sönmelidir (küçülmelidir). {{index "font-size (CSS)"}} -You can control the size of text (emoji are text) by setting the `font-size` CSS property (`style.fontSize`) on its parent element. Remember to include a unit in the value—for example, pixels (`10px`). +Üst öğesinde `font-size` CSS özelliğini (`style.fontSize`) ayarlayarak metnin (emoji metindir) boyutunu kontrol edebilirsiniz. Değere bir birim eklemeyi unutmayın; örneğin, piksel (`10px`). -The key names of the arrow keys are `"ArrowUp"` and `"ArrowDown"`. Make sure the keys change only the balloon, without scrolling the page. +Ok tuşlarının anahtar adları `“ArrowUp”` ve `“ArrowDown”` şeklindedir. Tuşların sayfayı kaydırmadan yalnızca balonu değiştirdiğinden emin olun. -When that works, add a feature where, if you blow up the balloon past a certain size, it explodes. In this case, exploding means that it is replaced with an 💥 emoji, and the event handler is removed (so that you can't inflate or deflate the explosion). +Bu işe yaradığında, balonu belirli bir boyutu geçecek şekilde şişirdiğinizde patlayacağı bir özellik ekleyin. Bu durumda patlaması, bir 💥 emojisi ile değiştirilmesi ve olay işleyicisinin kaldırılması anlamına gelir (böylece patlamayı şişiremez veya söndüremezsiniz). {{if interactive @@ -676,7 +678,7 @@ When that works, add a feature where, if you blow up the balloon past a certain <p>🎈</p> <script> - // Your code here + // Kodunuz buraya </script> ``` @@ -686,31 +688,31 @@ if}} {{index "keydown event", "key property", "balloon (exercise)"}} -You'll want to register a handler for the `"keydown"` event and look at `event.key` to figure out whether the up or down arrow key was pressed. +`“keydown"` olayı için bir işleyici kaydetmek ve yukarı veya aşağı ok tuşuna basılıp basılmadığını anlamak için `event.key` olayına bakmak isteyeceksiniz. -The current size can be kept in a binding so that you can base the new size on it. It'll be helpful to define a function that updates the size—both the binding and the style of the balloon in the DOM—so that you can call it from your event handler, and possibly also once when starting, to set the initial size. +Geçerli boyut bir bağlayıcıda tutulabilir, böylece yeni boyutu buna dayandırabilirsiniz. Boyutu (hem bağlayıcıyı hem de DOM'daki balonun stilini) güncelleyen bir fonksiyon tanımlamak yararlı olacaktır; böylece olay işleyicinizden ve muhtemelen başlangıçta ilk boyutu ayarlamak için bir kez çağırabilirsiniz. {{index "replaceChild method", "textContent property"}} -You can change the balloon to an explosion by replacing the text node with another one (using `replaceChild`) or by setting the `textContent` property of its parent node to a new string. +Metin düğümünü başka bir düğümle değiştirerek (`replaceChild` kullanarak) veya üst düğümünün `textContent` özelliğini yeni bir dizeye ayarlayarak balonu bir patlamaya dönüştürebilirsiniz. hint}} -### Mouse trail +### Fare izi {{index animation, "mouse trail (exercise)"}} -In JavaScript's early days, which was the high time of ((gaudy home pages)) with lots of animated images, people came up with some truly inspiring ways to use the language. +JavaScript'in ilk günlerinde, yani çok sayıda animasyonlu görüntünün yer aldığı ((şatafatlı ana sayfalar)) zamanında, insanlar dili kullanmak için gerçekten ilham verici yollar buldular. -One of these was the _mouse trail_—a series of elements that would follow the mouse pointer as you moved it across the page. +Bunlardan biri _mouse trail_ idi - fare işaretçisini sayfada hareket ettirdiğinizde onu takip eden bir dizi öğe. {{index "absolute positioning", "background (CSS)"}} -In this exercise, I want you to implement a mouse trail. Use absolutely positioned `<div>` elements with a fixed size and background color (refer to the [code](event#mouse_drawing) in the "Mouse Clicks" section for an example). Create a bunch of such elements and, when the mouse moves, display them in the wake of the mouse pointer. +In this exercise, I want you to implement a mouse trail. Use absolutely positioned `<div>` elements with a fixed size and background color (refer to the [code](event#mouse_drawing) in the “Mouse Clicks” section for an example). Create a bunch of such elements and, when the mouse moves, display them in the wake of the mouse pointer. {{index "mousemove event"}} -There are various possible approaches here. You can make your solution as simple or as complex as you want. A simple solution to start with is to keep a fixed number of trail elements and cycle through them, moving the next one to the mouse's current position every time a `"mousemove"` event occurs. +Bu alıştırmada, sizden bir fare izi uygulamanızı istiyorum. Sabit bir boyuta ve arka plan rengine sahip, kesinlikle konumlandırılmış `<div>` öğeleri kullanın (örnek için “Fare Tıklamaları” bölümündeki [code](event#mouse_drawing) kısmına bakın). Bu tür öğelerden bir grup oluşturun ve fare hareket ettiğinde bunları fare işaretçisinin ardından görüntüleyin. {{if interactive @@ -738,29 +740,29 @@ if}} {{index "mouse trail (exercise)"}} -Creating the elements is best done with a loop. Append them to the document to make them show up. To be able to access them later to change their position, you'll want to store the elements in an array. +Öğeleri oluşturmak en iyi şekilde bir döngü ile yapılır. Gösterilmelerini sağlamak için bunları belgeye ekleyin. Daha sonra konumlarını değiştirmek üzere bunlara erişebilmek için öğeleri bir dizide saklamak isteyeceksiniz. {{index "mousemove event", [array, indexing], "remainder operator", "% operator"}} -Cycling through them can be done by keeping a ((counter variable)) and adding 1 to it every time the `"mousemove"` event fires. The remainder operator (`% elements.length`) can then be used to get a valid array index to pick the element you want to position during a given event. +Bir ((sayaç değişkeni)) tutarak ve `“mousemove”` olayı her ateşlendiğinde buna 1 ekleyerek bunlar arasında geçiş yapılabilir. Kalan operatörü (`% elements.length`) daha sonra belirli bir olay sırasında konumlandırmak istediğiniz öğeyi seçmek için geçerli bir dizi indeksi elde etmek için kullanılabilir. {{index simulation, "requestAnimationFrame function"}} -Another interesting effect can be achieved by modeling a simple ((physics)) system. Use the `"mousemove"` event only to update a pair of bindings that track the mouse position. Then use `requestAnimationFrame` to simulate the trailing elements being attracted to the position of the mouse pointer. At every animation step, update their position based on their position relative to the pointer (and, optionally, a speed that is stored for each element). Figuring out a good way to do this is up to you. +Bir başka ilginç etki de basit bir ((fizik)) sistemi modelleyerek elde edilebilir. `“mousemove"`olayını yalnızca fare konumunu izleyen bir çift binding'i güncellemek için kullanın. Daha sonra `requestAnimationFrame` kullanarak fare işaretçisinin konumuna çekilen arkadaki öğeleri simüle edin. Her animasyon adımında, işaretçiye göre konumlarını (ve isteğe bağlı olarak her öğe için depolanan bir hızı) temel alarak konumlarını güncelleyin. Bunu yapmanın iyi bir yolunu bulmak size kalmış. hint}} -### Tabs +### Sekmeler {{index "tabbed interface (exercise)"}} -Tabbed panels are widely used in user interfaces. They allow you to select an interface panel by choosing from a number of tabs "sticking out" above an element. +Sekmeli paneller kullanıcı arayüzlerinde yaygın olarak kullanılır. Bir öğenin üzerine “yapışan” bir dizi sekme arasından seçim yaparak bir arayüz paneli seçmenize olanak tanırlar. {{index "button (HTML tag)", "display (CSS)", "hidden element", "data attribute"}} -In this exercise you must implement a simple tabbed interface. Write a function, `asTabs`, that takes a DOM node and creates a tabbed interface showing the child elements of that node. It should insert a list of `<button>` elements at the top of the node, one for each child element, containing text retrieved from the `data-tabname` attribute of the child. All but one of the original children should be hidden (given a `display` style of `none`). The currently visible node can be selected by clicking the buttons. +Bu egzersizde basit bir sekmeli arayüz uygulamanız gerekiyor. Bir DOM düğümü alan ve o düğümün alt öğelerini gösteren bir sekmeli arayüz oluşturan `asTabs` adlı bir fonksiyon yazın. Düğümün en üstüne, her bir alt öğe için `data-tabname` özniteliğinden alınan metni içeren birer `<button>` elementi içeren bir liste eklemelidir. Orijinal çocuklardan biri hariç hepsi gizlenmeli (gizli stil olarak `none` verilmelidir). Şu anda görünür düğüm, butonlara tıklanarak seçilebilir. -When that works, extend it to style the button for the currently selected tab differently so that it is obvious which tab is selected. +Bu çalıştığında, mevcut seçili sekmenin düğmesini farklı bir şekilde stillendirerek hangi sekmenin seçildiğinin belirgin olmasını sağlayın. {{if interactive @@ -784,14 +786,14 @@ if}} {{index "text node", "childNodes property", "live data structure", "tabbed interface (exercise)", [whitespace, "in HTML"]}} -One pitfall you might run into is that you can't directly use the node's `childNodes` property as a collection of tab nodes. For one thing, when you add the buttons, they will also become child nodes and end up in this object because it is a live data structure. For another, the text nodes created for the whitespace between the nodes are also in `childNodes` but should not get their own tabs. You can use `children` instead of `childNodes` to ignore text nodes. +Karşılaşabileceğiniz bir tuzak, düğümün `childNodes` özelliğini doğrudan sekme düğümleri koleksiyonu olarak kullanamamaktır. Birincisi, butonları eklediğinizde, bunlar da çocuk düğümler haline gelecek ve bu nesneye dahil olacaktır çünkü bu canlı bir veri yapısıdır. İkincisi, düğümler arasındaki boşluk için oluşturulan metin düğümleri de `childNodes` içinde yer alır ancak kendi sekmelerini almamalıdır. Metin düğümlerini göz ardı etmek için `childNodes` yerine `children` kullanabilirsiniz. {{index "TEXT_NODE code", "nodeType property"}} -You could start by building up an array of tabs so that you have easy access to them. To implement the styling of the buttons, you could store objects that contain both the tab panel and its button. +Sekmelerin kolay erişimini sağlamak için bir dizi sekme oluşturarak başlayabilirsiniz. Butonların stilini uygulamak için, hem sekme panelini hem de butonunu içeren nesneleri saklayabilirsiniz. -I recommend writing a separate function for changing tabs. You can either store the previously selected tab and change only the styles needed to hide that and show the new one, or you can just update the style of all tabs every time a new tab is selected. +Sekmeleri değiştirmek için ayrı bir fonksiyon yazmanızı öneririm. Ya daha önce seçilen sekmeyi saklayıp sadece onu gizlemek ve yenisini göstermek için gereken stilleri değiştirebilir ya da her yeni sekme seçildiğinde tüm sekmelerin stilini güncelleyebilirsiniz. -You might want to call this function immediately to make the interface start with the first tab visible. +Arayüzün ilk sekme görünür olacak şekilde başlaması için bu fonksiyonu hemen çağırmak isteyebilirsiniz.. hint}} diff --git a/16_game.md b/16_game.md index ff77abb5..0a600d67 100644 --- a/16_game.md +++ b/16_game.md @@ -1,74 +1,74 @@ {{meta {load_files: ["code/chapter/16_game.js", "code/levels.js", "code/_stop_keys.js"], zip: "html include=[\"css/game.css\"]"}}} -# Project: A Platform Game +# Project: Bir Platform Oyunu -{{quote {author: "Iain Banks", title: "The Player of Games", chapter: true} +{{quote {author: "Iain Banks", title: "Oyunların Oyuncusu", chapter: true} -All reality is a game. +Bütün gerçeklik bir oyundur. quote}} -{{index "Banks, Ian", "project chapter", simulation}} +{{index "Banks, Iain", "project chapter", simulation}} {{figure {url: "img/chapter_picture_16.jpg", alt: "Illustration showing a computer game character jumping over lava in a two dimensional world", chapter: "framed"}}} -Much of my initial fascination with computers, like that of many nerdy kids, had to do with computer ((game))s. I was drawn into the tiny simulated ((world))s that I could manipulate and in which stories (sort of) unfolded—more, I suppose, because of the way I projected my ((imagination)) into them than because of the possibilities they actually offered. +Bilgisayarlara olan ilk hayranlığımın çoğu, birçok nerd çocuk gibi, bilgisayar ((oyun))larıyla ilgiliydi. Manipüle edebileceğim ve hikayelerin (bir şekilde) ortaya çıktığı minik simüle edilmiş ((dünya))lara çekildim - sanırım, aslında sundukları olasılıklardan çok, ((hayal gücümü)) onlara yansıtma şeklimden dolayı. -I don't wish a ((career)) in game programming on anyone. Much like the ((music)) industry, the discrepancy between the number of eager young people wanting to work in it and the actual demand for such people creates a rather unhealthy environment. But writing games for fun is amusing. +Oyun programlamada kimseye bir ((kariyer)) dilemem. ((Müzik)) endüstrisi gibi, bu alanda çalışmak isteyen istekli gençlerin sayısı ile bu tür insanlara olan gerçek talep arasındaki tutarsızlık oldukça sağlıksız bir ortam yaratır. Ancak eğlence için oyun yazmak eğlencelidir. {{index "jump-and-run game", dimensions}} -This chapter will walk through the implementation of a small ((platform game)). Platform games (or "jump and run" games) are games that expect the ((player)) to move a figure through a ((world)), which is usually two-dimensional and viewed from the side, while jumping over and onto things. +Bu bölüm küçük bir ((platform oyunu)) uygulamasını ele alacaktır. Platform oyunları (veya "zıpla ve koş" oyunları), ((oyuncunun)) genellikle iki boyutlu ve yandan görülen bir ((dünya)) içinde bir figürü hareket ettirmesini ve bu sırada şeylerin üzerinden ve üstüne atlamasını bekleyen oyunlardır. -## The game +## Oyun {{index minimalism, "Palef, Thomas", "Dark Blue (game)"}} -Our ((game)) will be roughly based on [Dark Blue](http://www.lessmilk.com/games/10)[ (_www.lessmilk.com/games/10_)]{if book} by Thomas Palef. I chose that game because it is both entertaining and minimalist and because it can be built without too much ((code)). It looks like this: +((Oyunumuz)) kabaca Thomas Palef'in [Dark Blue](http://www.lessmilk.com/games/10)[ (_www.lessmilk.com/games/10_)]{if book} adlı kitabına dayanacak. Bu oyunu seçtim çünkü hem eğlenceli hem de minimalist ve çok fazla ((kod)) olmadan inşa edilebilir. Şuna benziyor: -{{figure {url: "img/darkblue.png", alt: "Screenshot of the 'Dark Blue' game, showing a world made out of colored boxes. There's a black box representing the player, standing on lines of white against a blue background. Small yellow coins float in the air, and some parts of the background are red, representing lava."}}} +{{figure {url: "img/darkblue.png", alt: "Renkli kutulardan oluşan bir dünyayı gösteren 'Dark Blue' oyununun ekran görüntüsü. Mavi bir arka plan üzerinde beyaz çizgiler üzerinde duran oyuncuyu temsil eden siyah bir kutu var. Küçük sarı paralar havada süzülüyor ve arka planın bazı kısımları lavı temsil eden kırmızı renkte."}}} {{index coin, lava}} -The dark ((box)) represents the ((player)), whose task is to collect the yellow boxes (coins) while avoiding the red stuff (lava). A ((level)) is completed when all coins have been collected. +Koyu ((kutu)), görevi kırmızı şeylerden (lav) kaçınırken sarı kutuları (madeni paralar) toplamak olan ((oyuncu)) temsil eder. Tüm paralar toplandığında bir ((seviye)) tamamlanır. {{index keyboard, jumping}} -The player can walk around with the left and right arrow keys and can jump with the up arrow. Jumping is a specialty of this game character. It can reach several times its own height and can change direction in midair. This may not be entirely realistic, but it helps give the player the feeling of being in direct control of the on-screen ((avatar)). +Oyuncu sol ve sağ ok tuşları ile etrafta dolaşabilir ve yukarı ok ile zıplayabilir. Zıplamak bu oyun karakterinin bir özelliğidir. Kendi yüksekliğinin birkaç katına ulaşabilir ve havada yön değiştirebilir. Bu tamamen gerçekçi olmayabilir, ancak oyuncuya ekrandaki ((avatar)) üzerinde doğrudan kontrol sahibi olduğu hissini vermeye yardımcı olur. {{index "fractional number", discretization, "artificial life", "electronic life"}} -The ((game)) consists of a static ((background)), laid out like a ((grid)), with the moving elements overlaid on that background. Each field on the grid is either empty, solid, or ((lava)). The moving elements are the player, coins, and certain pieces of lava. The positions of these elements are not constrained to the grid—their coordinates may be fractional, allowing smooth ((motion)). +((Oyun)), bir ((ızgara)) gibi yerleştirilmiş statik bir ((arka plan)) ve bu arka planın üzerine yerleştirilmiş hareketli öğelerden oluşur. Izgaradaki her alan boş, katı veya ((lav)) şeklindedir. Hareketli öğeler oyuncu, madeni paralar ve belirli lav parçalarıdır. Bu öğelerin konumları ızgarayla kısıtlı değildir - koordinatları kesirli olabilir ve yumuşak ((hareket)) sağlar. -## The technology +## Teknoloji {{index "event handling", keyboard, [DOM, graphics]}} -We will use the ((browser)) DOM to display the game, and we'll read user input by handling key events. +((Tarayıcı)) kullanacağız oyunu görüntülemek için DOM'u kullanacağız ve tuş olaylarını işleyerek kullanıcı girdisini okuyacağız. {{index rectangle, "background (CSS)", "position (CSS)", graphics}} -The screen- and keyboard-related code is only a small part of the work we need to do to build this ((game)). Since everything looks like colored ((box))es, drawing is uncomplicated: we create DOM elements and use styling to give them a background color, size, and position. +Ekran ve klavyeyle ilgili kod, bu ((oyunu)) oluşturmak için yapmamız gereken işin yalnızca küçük bir kısmıdır. Her şey renkli ((kutu))'lar gibi göründüğünden, çizim karmaşık değildir: DOM öğeleri oluştururuz ve onlara bir arka plan rengi, boyutu ve konumu vermek için stil kullanırız {{index "table (HTML tag)"}} -We can represent the background as a table since it is an unchanging ((grid)) of squares. The free-moving elements can be overlaid using absolutely positioned elements. +Karelerden oluşan değişmeyen bir ((ızgara)) olduğu için arka planı bir tablo olarak temsil edebiliriz. Serbest hareket eden öğeler, kesinlikle konumlandırılmış öğeler kullanılarak üst üste bindirilebilir. {{index performance, [DOM, graphics]}} -In games and other programs that should animate ((graphics)) and respond to user ((input)) without noticeable delay, ((efficiency)) is important. Although the DOM was not originally designed for high-performance graphics, it is actually better at this than you would expect. You saw some ((animation))s in [Chapter ?](dom#animation). On a modern machine, a simple game like this performs well, even if we don't worry about ((optimization)) very much. +Oyunlarda ve ((grafikleri)) canlandırması ve kullanıcı ((girdisine)) fark edilir bir gecikme olmadan yanıt vermesi gereken diğer programlarda ((verimlilik)) önemlidir. DOM başlangıçta yüksek performanslı grafikler için tasarlanmamış olsa da, aslında bu konuda beklediğinizden daha iyidir. [Bölüm ?](dom#animation) içinde bazı ((animasyon))'lar gördünüz. Modern bir makinede, ((optimizasyon)) hakkında çok fazla endişelenmesek bile, bunun gibi basit bir oyun iyi performans gösterir. {{index canvas, [DOM, graphics]}} -In the [next chapter](canvas), we will explore another ((browser)) technology, the `<canvas>` tag, which provides a more traditional way to draw graphics, working in terms of shapes and ((pixel))s rather than DOM elements. +[Bir sonraki bölümde](canvas), DOM öğeleri yerine şekiller ve ((piksel)) açısından çalışarak grafik çizmek için daha geleneksel bir yol sağlayan başka bir ((tarayıcı)) teknolojisi olan `<canvas>` etiketini keşfedeceğiz. -## Levels +## Seviyeler {{index dimensions}} -We'll want a human-readable, human-editable way to specify levels. Since it is okay for everything to start out on a grid, we could use big strings in which each character represents an element—either a part of the background grid or a moving element. +Seviyeleri belirtmek için insan tarafından okunabilir, insan tarafından düzenlenebilir bir yol isteyeceğiz. Her şeyin bir ızgara üzerinde başlaması uygun olduğundan, her karakterin bir öğeyi temsil ettiği büyük dizeler kullanabiliriz - ya arka plan ızgarasının bir parçası ya da hareketli bir öğe. -The plan for a small level might look like this: +Küçük bir seviye için plan şöyle görünebilir: ```{includeCode: true} let simpleLevelPlan = ` @@ -85,13 +85,13 @@ let simpleLevelPlan = ` {{index level}} -Periods are empty space, hash (`#`) characters are walls, and plus signs are lava. The ((player))'s starting position is the ((at sign)) (`@`). Every O character is a coin, and the equal sign (`=`) at the top is a block of lava that moves back and forth horizontally. +Noktalar boş alan, hash (`#`) karakterleri duvar ve artı işaretleri lavdır. ((oyuncu))'nun başlangıç pozisyonu ((at işareti)) (`@`)'dir. Her O karakteri bir madeni paradır ve en üstteki eşittir işareti (`=`) yatay olarak ileri geri hareket eden bir lav bloğudur. {{index bouncing}} -We'll support two additional kinds of moving ((lava)): the pipe character (`|`) creates vertically moving blobs, and `v` indicates _dripping_ lava—vertically moving lava that doesn't bounce back and forth but only moves down, jumping back to its start position when it hits the floor. +İki ek hareketli ((lav)) türünü destekleyeceğiz: boru karakteri (`|`) dikey olarak hareket eden lekeler oluşturur ve `v` _damlayan_ lavı gösterir - ileri geri zıplamayan, sadece aşağı doğru hareket eden ve yere çarptığında başlangıç konumuna geri sıçrayan dikey olarak hareket eden lav. -A whole ((game)) consists of multiple ((level))s that the ((player)) must complete. A level is completed when all ((coin))s have been collected. If the player touches ((lava)), the current level is restored to its starting position, and the player may try again. +Bütün bir ((oyun)), ((oyuncu))'nun tamamlaması gereken birden fazla ((seviye))'den oluşur. Tüm ((jeton))lar toplandığında bir seviye tamamlanmış olur. Oyuncu ((lav))'a dokunursa, mevcut seviye başlangıç konumuna geri yüklenir ve oyuncu tekrar deneyebilir. {{id level}} @@ -99,7 +99,7 @@ A whole ((game)) consists of multiple ((level))s that the ((player)) must comple {{index "Level class"}} -The following ((class)) stores a ((level)) object. Its argument should be the string that defines the level. +Aşağıdaki ((class)) bir ((level)) nesnesini saklar. Argümanı, seviyeyi tanımlayan dize olmalıdır. ```{includeCode: true} class Level { @@ -126,27 +126,27 @@ class Level { {{index "trim method", "split method", [whitespace, trimming]}} -The `trim` method is used to remove whitespace at the start and end of the plan string. This allows our example plan to start with a newline so that all the lines are directly below each other. The remaining string is split on ((newline character))s, and each line is spread into an array, producing arrays of characters. +Plan dizesinin başındaki ve sonundaki boşlukları kaldırmak için `trim` yöntemi kullanılır. Bu, örnek planımızın bir yeni satırla başlamasını sağlar, böylece tüm satırlar doğrudan birbirinin altında olur. Kalan dize ((yeni satır karakteri))lere bölünür ve her satır bir diziye yayılarak karakter dizileri üretilir. {{index [array, "as matrix"]}} -So `rows` holds an array of arrays of characters, the rows of the plan. We can derive the level's width and height from these. But we must still separate the moving elements from the background grid. We'll call moving elements _actors_. They'll be stored in an array of objects. The background will be an array of arrays of strings, holding field types such as `"empty"`, `"wall"`, or `"lava"`. +Yani `rows` karakter dizilerinden oluşan bir diziyi, planın satırlarını tutar. Seviyenin genişliğini ve yüksekliğini bunlardan türetebiliriz. Ancak yine de hareketli öğeleri arka plan ızgarasından ayırmalıyız. Hareketli öğelere _aktörler_ diyeceğiz. Bunlar bir dizi nesne içinde saklanacaktır. Arka plan, `"empty"`, `"wall"` veya `"lava"` gibi alan türlerini tutan dizelerden oluşan bir dizi olacaktır. {{index "map method"}} -To create these arrays, we map over the rows and then over their content. Remember that `map` passes the array index as a second argument to the mapping function, which tells us the x- and y-coordinates of a given character. Positions in the game will be stored as pairs of coordinates, with the top left being 0,0 and each background square being 1 unit high and wide. +Bu dizileri oluşturmak için, satırları ve ardından içeriklerini eşleriz. Unutmayın ki `map` dizinin indeksini eşleme fonksiyonuna ikinci bir argüman olarak aktarır, bu da bize belirli bir karakterin x ve y koordinatlarını söyler. Oyundaki konumlar, sol üst 0,0 ve her arka plan karesi 1 birim yüksekliğinde ve genişliğinde olacak şekilde koordinat çiftleri olarak saklanacaktır. {{index "static method"}} -To interpret the characters in the plan, the `Level` constructor uses the `levelChars` object, which, for each character used in the level descriptions, holds a string if it is a background type, and a class if it produces an actor. When `type` is an actor class, its static `create` method is used to create an object, which is added to `startActors`, and the mapping function returns `"empty"` for this background square. +Plandaki karakterleri yorumlamak için, `Level` kurucusu, seviye açıklamalarında kullanılan her karakter için, bir arka plan türüyse bir dize ve bir aktör üretiyorsa bir sınıf tutan `levelChars` nesnesini kullanır. `type` bir aktör sınıfı olduğunda, `startActors` öğesine eklenen bir nesne oluşturmak için statik `create` yöntemi kullanılır ve eşleme işlevi bu arka plan karesi için `"empty"` döndürür. {{index "Vec class"}} -The position of the actor is stored as a `Vec` object. This is a two-dimensional vector, an object with `x` and `y` properties, as seen in the exercises of [Chapter ?](object#exercise_vector). +Aktörün konumu bir `Vec` nesnesi olarak saklanır. Bu iki boyutlu bir vektördür, [bölüm ?](object#exercise_vector) içindeki alıştırmalarında görüldüğü gibi `x` ve `y` özelliklerine sahip bir nesnedir. {{index [state, in objects]}} -As the game runs, actors will end up in different places or even disappear entirely (as coins do when collected). We'll use a `State` class to track the state of a running game. +Oyun çalıştıkça, aktörler farklı yerlere gidecek veya hatta tamamen kaybolacaktır (madeni paraların toplandığında yaptığı gibi). Çalışan bir oyunun durumunu izlemek için bir `State` sınıfı kullanacağız. ```{includeCode: true} class State { @@ -166,25 +166,25 @@ class State { } ``` -The `status` property will switch to `"lost"` or `"won"` when the game has ended. +Oyun sona erdiğinde `status` özelliği `"lost"` veya `"won"` olarak değişecektir. -This is again a persistent data structure—updating the game state creates a new state and leaves the old one intact. +Bu yine kalıcı bir veri yapısıdır-oyun durumunu güncellemek yeni bir durum oluşturur ve eskisini olduğu gibi bırakır. -## Actors +## Aktörler {{index actor, "Vec class", [interface, object]}} -Actor objects represent the current position and state of a given moving element in our game. All actor objects conform to the same interface. They have `size` and `pos` properties holding the size and the coordinates of the top-left corner of the rectangle representing this actor. +Aktör nesneleri, oyunumuzdaki belirli bir hareketli öğenin mevcut konumunu ve durumunu temsil eder. Tüm aktör nesneleri aynı arayüze uygundur. Onların `pos` özelliği elemanın sol üst köşesinin koordinatlarını tutar ve `size` özelliği de boyutunu tutar. -Then they have an `update` method, which is used to compute their new state and position after a given time step. It simulates the thing the actor does—moving in response to the arrow keys for the player and bouncing back and forth for the lava—and returns a new, updated actor object. +Daha sonra, belirli bir zaman adımından sonra yeni durumlarını ve konumlarını hesaplamak için kullanılan bir `update` yöntemine sahiptirler. Aktörün yaptığı şeyi simüle eder -oyuncu için ok tuşlarına yanıt olarak hareket eder ve lav için ileri geri zıplar- ve yeni, güncellenmiş bir aktör nesnesi döndürür. -A `type` property contains a string that identifies the type of the actor—`"player"`, `"coin"`, or `"lava"`. This is useful when drawing the game—the look of the rectangle drawn for an actor is based on its type. +Bir `type` özelliği, aktörün türünü tanımlayan bir dize içerir - `"player"`, `"coin"` veya `"lava"`. Bu, oyunu çizerken kullanışlıdır; bir aktör için çizilen dikdörtgenin görünümü aktörün türüne bağlıdır. -Actor classes have a static `create` method that is used by the `Level` constructor to create an actor from a character in the level plan. It is given the coordinates of the character and the character itself, which is needed because the `Lava` class handles several different characters. +Aktör sınıfları, seviye planındaki bir karakterden bir aktör oluşturmak için `Level` kurucusu tarafından kullanılan statik bir `create` yöntemine sahiptir. Karakterin koordinatları ve karakterin kendisi verilir; `Lava` sınıfı birkaç farklı karakteri işlediği için bu gereklidir. {{id vector}} -This is the `Vec` class that we'll use for our two-dimensional values, such as the position and size of actors. +Bu, aktörlerin konumu ve boyutu gibi iki boyutlu değerlerimiz için kullanacağımız `Vec` sınıfıdır. ```{includeCode: true} class Vec { @@ -202,13 +202,13 @@ class Vec { {{index "times method", multiplication}} -The `times` method scales a vector by a given number. It will be useful when we need to multiply a speed vector by a time interval to get the distance traveled during that time. +`times` yöntemi bir vektörü belirli bir sayı ile ölçeklendirir. Bir hız vektörünü bir zaman aralığıyla çarparak o süre içinde kat edilen mesafeyi elde etmemiz gerektiğinde faydalı olacaktır. -The different types of actors get their own classes since their behavior is very different. Let's define these classes. We'll get to their `update` methods later. +Farklı aktör türleri, davranışları çok farklı olduğu için kendi sınıflarına sahip olurlar. Şimdi bu sınıfları tanımlayalım. Onların `update` yöntemlerine daha sonra değineceğiz. {{index simulation, "Player class"}} -The player class has a property `speed` that stores its current speed to simulate momentum and gravity. +Oyuncu sınıfı, momentum ve yerçekimini simüle etmek için mevcut hızını depolayan bir `speed` özelliğine sahiptir. ```{includeCode: true} class Player { @@ -228,15 +228,15 @@ class Player { Player.prototype.size = new Vec(0.8, 1.5); ``` -Because a player is one-and-a-half squares high, its initial position is set to be half a square above the position where the `@` character appeared. This way, its bottom aligns with the bottom of the square it appeared in. +Bir oyuncu bir buçuk kare yüksekliğinde olduğu için, ilk konumu `@` karakterinin göründüğü konumdan yarım kare yukarıda olacak şekilde ayarlanır. Bu şekilde, alt kısmı göründüğü karenin alt kısmıyla hizalanır. -The `size` property is the same for all instances of `Player`, so we store it on the prototype rather than on the instances themselves. We could have used a ((getter)) like `type`, but that would create and return a new `Vec` object every time the property is read, which would be wasteful. (Strings, being ((immutable)), don't have to be re-created every time they are evaluated.) +Boyut özelliği tüm `Player` örnekleri için aynıdır, bu nedenle bunu örneklerin kendileri yerine prototipte saklarız. `type` gibi bir ((getter)) kullanabilirdik, ancak bu, özellik her okunduğunda yeni bir `Vec` nesnesi oluşturacak ve döndürecektir, bu da israf olacaktır. (Dizeler, ((değişmez)) olduklarından, her değerlendirildiklerinde yeniden oluşturulmaları gerekmez). {{index "Lava class", bouncing}} -When constructing a `Lava` actor, we need to initialize the object differently depending on the character it is based on. Dynamic lava moves along at its current speed until it hits an obstacle. At that point, if it has a `reset` property, it will jump back to its start position (dripping). If it does not, it will invert its speed and continue in the other direction (bouncing). +Bir `Lava` aktörü oluştururken, nesneyi dayandığı karaktere bağlı olarak farklı şekilde başlatmamız gerekir. Dinamik lav, bir engele çarpana kadar mevcut hızında ilerler. Bu noktada, eğer `reset` özelliğine sahipse, başlangıç konumuna (damlayarak) geri atlayacaktır. Eğer yoksa, hızını tersine çevirir ve diğer yönde devam eder (zıplama). -The `create` method looks at the character that the `Level` constructor passes and creates the appropriate lava actor. +`create` yöntemi `Level` kurucusunun aktardığı karaktere bakar ve uygun lav aktörünü oluşturur. ```{includeCode: true} class Lava { @@ -264,7 +264,7 @@ Lava.prototype.size = new Vec(1, 1); {{index "Coin class", animation}} -`Coin` actors are relatively simple. They mostly just sit in their place. But to liven up the game a little, they are given a "wobble", a slight vertical back-and-forth motion. To track this, a coin object stores a base position as well as a `wobble` property that tracks the ((phase)) of the bouncing motion. Together, these determine the coin's actual position (stored in the `pos` property). +`coin` aktörleri nispeten basittir. Çoğunlukla sadece yerlerinde otururlar. Ancak oyunu biraz canlandırmak için, onlara hafif bir dikey ileri geri hareket olan bir "yalpalama" verilir. Bunu izlemek için, bir madeni para nesnesi bir temel konumun yanı sıra zıplama hareketinin ((fazını)) izleyen bir `wobble` özelliği saklar. Bunlar birlikte madeni paranın gerçek konumunu belirler (`pos` özelliğinde saklanır). ```{includeCode: true} class Coin { @@ -288,15 +288,15 @@ Coin.prototype.size = new Vec(0.6, 0.6); {{index "Math.random function", "random number", "Math.sin function", sine, wave}} -In [Chapter ?](dom#sin_cos), we saw that `Math.sin` gives us the y-coordinate of a point on a circle. That coordinate goes back and forth in a smooth waveform as we move along the circle, which makes the sine function useful for modeling a wavy motion. +[Bölüm ?](dom#sin_cos) içinde, `Math.sin`'in bize daire üzerindeki bir noktanın y-koordinatını verdiğini gördük. Bu koordinat, daire boyunca hareket ettikçe düzgün bir dalga formunda ileri geri gider, bu da sinüs fonksiyonunu dalgalı bir hareketi modellemek için kullanışlı hale getirir. {{index pi}} -To avoid a situation where all coins move up and down synchronously, the starting phase of each coin is randomized. The period of `Math.sin`'s wave, the width of a wave it produces, is 2π. We multiply the value returned by `Math.random` by that number to give the coin a random starting position on the wave. +Tüm madeni paraların eşzamanlı olarak yukarı ve aşağı hareket ettiği bir durumdan kaçınmak için, her madeni paranın başlangıç aşaması rastgele belirlenir. `Math.sin` dalgasının periyodu, yani ürettiği dalganın genişliği 2π'dir. Madeni paraya dalga üzerinde rastgele bir başlangıç konumu vermek için `Math.random` tarafından döndürülen değeri bu sayı ile çarpıyoruz. {{index map, [object, "as map"]}} -We can now define the `levelChars` object that maps plan characters to either background grid types or actor classes. +Artık plan karakterlerini arka plan ızgara türlerine veya aktör sınıflarına eşleyen `levelChars` nesnesini tanımlayabiliriz. ```{includeCode: true} const levelChars = { @@ -306,7 +306,7 @@ const levelChars = { }; ``` -That gives us all the parts needed to create a `Level` instance. +Bu bize bir `Level` örneği oluşturmak için gereken tüm parçaları verir. ```{includeCode: strip_log} let simpleLevel = new Level(simpleLevelPlan); @@ -314,25 +314,39 @@ console.log(`${simpleLevel.width} by ${simpleLevel.height}`); // → 22 by 9 ``` -The task ahead is to display such levels on the screen and to model time and motion inside them. +Önümüzdeki görev, bu seviyeleri ekranda görüntülemek ve içlerindeki zaman ve hareketi modellemektir. + +## Bir yük olarak kapsülleme + +{{index "programming style", "program size", complexity}} + +Bu bölümdeki kodların çoğu iki nedenden dolayı ((kapsülleme)) hakkında çok fazla endişelenmez. Birincisi, kapsülleme fazladan çaba gerektirir. Programları büyütür ve ek kavram ve arayüzlerin tanıtılmasını gerektirir. Bir okuyucunun gözleri kamaşmadan önce ona ancak bu kadar çok kod atabileceğiniz için, programı küçük tutmaya gayret ettim. + +{{index [interface, design]}} + +İkincisi, bu oyundaki çeşitli unsurlar birbirine o kadar sıkı bağlıdır ki, bunlardan birinin davranışı değişirse, diğerlerinin aynı kalması pek olası değildir. Unsurlar arasındaki arayüzler, oyunun çalışma şekli hakkında pek çok varsayımı kodlar hale gelecektir. Bu da onları çok daha az etkili hale getirir - sistemin bir parçasını değiştirdiğinizde, bunun diğer parçaları nasıl etkileyeceği konusunda endişelenmeniz gerekir çünkü arayüzleri yeni durumu kapsamayacaktır. + +Bir sistemdeki bazı _((kesme noktası))lar_ kendilerini titiz arayüzler yoluyla ayırmaya iyi bir şekilde borçludur, ancak diğerleri değildir. Uygun bir sınır olmayan bir şeyi kapsüllemeye çalışmak, çok fazla enerji harcamanın kesin bir yoludur. Bu hatayı yaptığınızda, genellikle arayüzlerinizin garip bir şekilde büyük ve ayrıntılı hale geldiğini ve program geliştikçe sık sık değiştirilmeleri gerektiğini fark edeceksiniz. + +{{index graphics, encapsulation, graphics}} + +Kapsülleyeceğimiz tek bir şey var, o da ((çizim)) alt sistemi. Bunun nedeni, aynı oyunu [bir sonraki bölümde](canvas#canvasdisplay) farklı bir şekilde ((görüntüleyeceğiz)). Çizimi bir arayüzün arkasına koyarak, aynı oyun programını oraya yükleyebilir ve yeni bir ekran ((modülü)) takabiliriz. {{id domdisplay}} -## Drawing +## Çizmek {{index graphics, encapsulation, "DOMDisplay class", [DOM, graphics]}} -In the [next chapter](canvas#canvasdisplay), we'll ((display)) the same game in a different way. To make that possible, we put the drawing logic behind an interface, and pass it to the game as an argument. That way, we can use the same game program with different new display ((module))s. - -A game display object draws a given ((level)) and state. We pass its constructor to the game to allow it to be replaced. The display class we define in this chapter is called `DOMDisplay` because it uses DOM elements to show the level. +((Çizim)) kodunun kapsüllenmesi, belirli bir ((seviye)) ve durumu gösteren bir _((display))_ nesnesi tanımlanarak yapılır. Bu bölümde tanımladığımız görüntüleme türüne `DOMDisplay` adı verilir çünkü seviyeyi göstermek için DOM öğelerini kullanır. {{index "style attribute", CSS}} -We'll be using a style sheet to set the actual colors and other fixed properties of the elements that make up the game. It would also be possible to directly assign to the elements' `style` property when we create them, but that would produce more verbose programs. +Oyunu oluşturan öğelerin gerçek renklerini ve diğer sabit özelliklerini ayarlamak için bir stil sayfası kullanacağız. Öğeleri oluştururken doğrudan `style` özelliğine atama yapmak da mümkün olabilir, ancak bu daha ayrıntılı programlar üretecektir. {{index "class attribute"}} -The following helper function provides a succinct way to create an element and give it some attributes and child nodes: +Aşağıdaki yardımcı fonksiyon, bir eleman oluşturmak ve ona bazı nitelikler ve alt düğümler vermek için kısa ve öz bir yol sağlar: ```{includeCode: true} function elt(name, attrs, ...children) { @@ -347,7 +361,7 @@ function elt(name, attrs, ...children) { } ``` -A display is created by giving it a parent element to which it should append itself and a ((level)) object. +Bir ekran, kendisini eklemesi gereken bir üst öğe ve bir ((level)) nesnesi verilerek oluşturulur. ```{includeCode: true} class DOMDisplay { @@ -363,11 +377,11 @@ class DOMDisplay { {{index level}} -The level's ((background)) grid, which never changes, is drawn once. Actors are redrawn every time the display is updated with a given state. The `actorLayer` property will be used to track the element that holds the actors so that they can be easily removed and replaced. +Seviyenin hiç değişmeyen ((arka plan)) ızgarası bir kez çizilir. Aktörler, ekran belirli bir durumla her güncellendiğinde yeniden çizilir. Aktörleri tutan öğeyi izlemek için `actorLayer` özelliği kullanılır, böylece kolayca kaldırılabilir ve değiştirilebilirler. {{index scaling, "DOMDisplay class"}} -Our ((coordinates)) and sizes are tracked in ((grid)) units, where a size or distance of 1 means one grid block. When setting ((pixel)) sizes, we will have to scale these coordinates up—everything in the game would be ridiculously small at a single pixel per square. The `scale` constant gives the number of pixels that a single unit takes up on the screen. +((Koordinatlarımız)) ve boyutlarımız ((ızgara)) birimlerinde izlenir; burada 1'lik bir boyut veya mesafe bir ızgara bloğu anlamına gelir. ((piksel)) boyutlarını ayarlarken, bu koordinatları ölçeklendirmemiz gerekecektir-oyundaki her şey kare başına tek bir pikselde gülünç derecede küçük olacaktır. `scale` sabiti, tek bir birimin ekranda kapladığı piksel sayısını verir. ```{includeCode: true} const scale = 20; @@ -385,11 +399,11 @@ function drawGrid(level) { {{index "table (HTML tag)", "tr (HTML tag)", "td (HTML tag)", "spread operator"}} -The `<table>` element's form nicely corresponds to the structure of the `rows` property of the level—each row of the grid is turned into a table row (`<tr>` element). The strings in the grid are used as class names for the table cell (`<td>`) elements. The code uses the spread (triple dot) operator to pass arrays of child nodes to `elt` as separate arguments. +Belirtildiği gibi, arka plan bir `<table>` öğesi olarak çizilir. Bu, seviyenin `rows` özelliğinin yapısına güzel bir şekilde karşılık gelir - ızgaranın her satırı bir tablo satırına (`<tr>` elemanı) dönüştürülür. Izgaradaki dizeler, tablo hücresi (`<td>`) elemanları için sınıf adları olarak kullanılır. Yayma (üçlü nokta) operatörü, çocuk düğüm dizilerini `elt` öğesine ayrı argümanlar olarak iletmek için kullanılır. {{id game_css}} -The following ((CSS)) makes the table look like the background we want: +Aşağıdaki ((CSS)) tablonun istediğimiz arka plan gibi görünmesini sağlar: ```{lang: "css"} .background { background: rgb(52, 166, 251); @@ -402,15 +416,15 @@ The following ((CSS)) makes the table look like the background we want: {{index "padding (CSS)"}} -Some of these (`table-layout`, `border-spacing`, and `padding`) are used to suppress unwanted default behavior. We don't want the layout of the ((table)) to depend upon the contents of its cells, and we don't want space between the ((table)) cells or padding inside them. +Bunlardan bazıları (`table-layout`, `border-spacing` ve `padding`) istenmeyen varsayılan davranışı bastırmak için kullanılır. ((table))'ın düzeninin hücrelerinin içeriğine bağlı olmasını istemiyoruz ve ((table)) hücreleri arasında boşluk veya içlerinde dolgu istemiyoruz. {{index "background (CSS)", "rgb (CSS)", CSS}} -The `background` rule sets the background color. CSS allows colors to be specified both as words (`white`) or with a format such as `rgb(R, G, B)`, where the red, green, and blue components of the color are separated into three numbers from 0 to 255. So, in `rgb(52, 166, 251)`, the red component is 52, green is 166, and blue is 251. Since the blue component is the largest, the resulting color will be bluish. In the `.lava` rule, the first number (red) is the largest. +`background` kuralı arka plan rengini belirler. CSS, renklerin hem sözcük olarak (`white`) hem de rengin kırmızı, yeşil ve mavi bileşenlerinin 0 ile 255 arasında üç sayıya ayrıldığı `rgb(R, G, B)` gibi bir formatla belirtilmesine izin verir. Yani, `rgb(52, 166, 251)`de kırmızı bileşen 52, yeşil 166 ve mavi 251'dir. Mavi bileşen en büyük olduğundan, ortaya çıkan renk mavimsi olacaktır. `.lava` kuralında ilk sayının (kırmızı) en büyük olduğunu görebilirsiniz. {{index [DOM, graphics]}} -We draw each ((actor)) by creating a DOM element for it and setting that element's position and size based on the actor's properties. The values have to be multiplied by `scale` to go from game units to pixels. +Her ((aktör)) için bir DOM öğesi oluşturarak ve bu öğenin konumunu ve boyutunu aktörün özelliklerine göre ayarlayarak çiziyoruz. Oyun birimlerinden piksellere geçmek için değerlerin `scale` ile çarpılması gerekir. ```{includeCode: true} function drawActors(actors) { @@ -427,7 +441,7 @@ function drawActors(actors) { {{index "position (CSS)", "class attribute"}} -To give an element more than one class, we separate the class names by spaces. In the ((CSS)) code shown next, the `actor` class gives the actors their absolute position. Their type name is used as an extra class to give them a color. We don't have to define the `lava` class again because we're reusing the class for the lava grid squares we defined earlier. +Bir öğeye birden fazla sınıf vermek için, sınıf adlarını boşluklarla ayırırız. Yanda gösterilen ((CSS)) kodunda, `actor` sınıfı aktörlere mutlak konumlarını verir. Tür adları, onlara bir renk vermek için ekstra bir sınıf olarak kullanılır. Daha önce tanımladığımız lav ızgarası kareleri için bu sınıfı yeniden kullandığımızdan `lava` sınıfını yeniden tanımlamamız gerekmiyor. ```{lang: "css"} .actor { position: absolute; } @@ -437,7 +451,7 @@ To give an element more than one class, we separate the class names by spaces. I {{index graphics, optimization, efficiency, [state, "of application"], [DOM, graphics]}} -The `syncState` method is used to make the display show a given state. It first removes the old actor graphics, if any, and then redraws the actors in their new positions. It may be tempting to try to reuse the DOM elements for actors, but to make that work, we would need a lot of additional bookkeeping to associate actors with DOM elements and to make sure we remove elements when their actors vanish. Since there will typically be only a handful of actors in the game, redrawing all of them is not expensive. +Ekranın belirli bir durumu göstermesini sağlamak için `syncState` yöntemi kullanılır. Önce varsa eski aktör grafiklerini kaldırır ve ardından aktörleri yeni konumlarında yeniden çizer. Aktörler için DOM öğelerini yeniden kullanmayı denemek cazip gelebilir, ancak bunun işe yaraması için, aktörleri DOM öğeleriyle ilişkilendirmek ve aktörleri kaybolduğunda öğeleri kaldırdığımızdan emin olmak için çok fazla ek defter tutmamız gerekir. Oyunda genellikle sadece bir avuç aktör olacağından, hepsini yeniden çizmek pahalı değildir. ```{includeCode: true} DOMDisplay.prototype.syncState = function(state) { @@ -451,7 +465,7 @@ DOMDisplay.prototype.syncState = function(state) { {{index level, "class attribute"}} -By adding the level's current status as a class name to the wrapper, we can style the player actor slightly differently when the game is won or lost by adding a ((CSS)) rule that takes effect only when the player has an ((ancestor element)) with a given class. +Seviyenin mevcut durumunu sarmalayıcıya bir sınıf adı olarak ekleyerek, yalnızca oyuncunun belirli bir sınıfa sahip bir ((ata öğesi)) olduğunda etkili olan bir ((CSS)) kuralı ekleyerek oyun kazanıldığında veya kaybedildiğinde oyuncu aktörünü biraz farklı şekillendirebiliriz. ```{lang: "css"} .lost .player { @@ -464,13 +478,13 @@ By adding the level's current status as a class name to the wrapper, we can styl {{index player, "box shadow (CSS)"}} -After touching ((lava)), the player's color turns dark red, suggesting scorching. When the last coin has been collected, we add two blurred white shadows—one to the top left and one to the top right—to create a white halo effect. +((Lav))'a dokunduktan sonra oyuncunun rengi koyu kırmızıya dönerek kavrulduğunu gösteriyor. Son para toplandığında, beyaz bir hale efekti oluşturmak için biri sol üstte diğeri sağ üstte olmak üzere iki bulanık beyaz gölge ekliyoruz. {{id viewport}} {{index "position (CSS)", "max-width (CSS)", "overflow (CSS)", "max-height (CSS)", viewport, scrolling, [DOM, graphics]}} -We can't assume that the level always fits in the _viewport_—the element into which we draw the game. That is why the `scrollPlayerIntoView` call is needed. It ensures that if the level is protruding outside the viewport, we scroll that viewport to make sure the player is near its center. The following ((CSS)) gives the game's wrapping DOM element a maximum size and ensures that anything that sticks out of the element's box is not visible. We also give it a relative position so that the actors inside it are positioned relative to the level's top-left corner. +Seviyenin her zaman _viewport_-oyunu içine çizdiğimiz öğeye sığdığını varsayamayız. Bu yüzden `scrollPlayerIntoView` çağrısına ihtiyaç vardır. Eğer seviye görüntü alanının dışına taşıyorsa, oyuncunun görüntü alanının merkezine yakın olduğundan emin olmak için görüntü alanını kaydırmamızı sağlar. Aşağıdaki ((CSS)), oyunun saran DOM öğesine maksimum bir boyut verir ve öğenin kutusunun dışına çıkan herhangi bir şeyin görünmemesini sağlar. Ayrıca, içindeki oyuncuların seviyenin sol üst köşesine göre konumlandırılması için ona göreli bir konum veriyoruz. ```{lang: css} .game { @@ -483,7 +497,7 @@ We can't assume that the level always fits in the _viewport_—the element into {{index scrolling}} -In the `scrollPlayerIntoView` method, we find the player's position and update the wrapping element's scroll position. We change the scroll position by manipulating that element's `scrollLeft` and `scrollTop` properties when the player is too close to the edge. +`scrollPlayerIntoView` yönteminde, oyuncunun konumunu buluruz ve saran öğenin kaydırma konumunu güncelleriz. Oyuncu kenara çok yaklaştığında, bu öğenin `scrollLeft` ve `scrollTop` özelliklerini manipüle ederek kaydırma konumunu değiştiririz. ```{includeCode: true} DOMDisplay.prototype.scrollPlayerIntoView = function(state) { @@ -514,17 +528,17 @@ DOMDisplay.prototype.scrollPlayerIntoView = function(state) { {{index center, coordinates, readability}} -The way the player's center is found shows how the methods on our `Vec` type allow computations with objects to be written in a relatively readable way. To find the actor's center, we add its position (its top-left corner) and half its size. That is the center in level coordinates, but we need it in pixel coordinates, so we then multiply the resulting vector by our display scale. +Oyuncunun merkezinin bulunma şekli, `Vec` tipimizdeki yöntemlerin nesnelerle hesaplamaların nispeten okunabilir bir şekilde yazılmasına nasıl izin verdiğini göstermektedir. Oyuncunun merkezini bulmak için, konumunu (sol üst köşesi) ve boyutunun yarısını ekliyoruz. Bu, seviye koordinatlarındaki merkezdir, ancak piksel koordinatlarında ihtiyacımız var, bu yüzden ortaya çıkan vektörü ekran ölçeğimizle çarpıyoruz. {{index validation}} -Next, a series of checks verifies that the player position isn't outside of the allowed range. Note that sometimes this will set nonsense scroll coordinates that are below zero or beyond the element's scrollable area. This is okay—the DOM will constrain them to acceptable values. Setting `scrollLeft` to -10 will cause it to become 0. +Ardından, bir dizi kontrol, oyuncu konumunun izin verilen aralığın dışında olmadığını doğrular. Bunun bazen sıfırın altında veya öğenin kaydırılabilir alanının ötesinde olan saçma kaydırma koordinatlarını ayarlayacağını unutmayın. Bu sorun değildir; DOM bunları kabul edilebilir değerlerle sınırlayacaktır. `scrollLeft` değerinin -10 olarak ayarlanması 0 olmasına neden olacaktır. -It would have been slightly simpler to always try to scroll the player to the center of the ((viewport)). But this creates a rather jarring effect. As you are jumping, the view will constantly shift up and down. It is more pleasant to have a "neutral" area in the middle of the screen where you can move around without causing any scrolling. +Oynatıcıyı her zaman ((viewport))'un merkezine kaydırmaya çalışmak biraz daha basit olabilirdi. Ancak bu oldukça sarsıcı bir etki yaratır. Siz zıplarken, görünüm sürekli olarak yukarı ve aşağı kayacaktır. Ekranın ortasında herhangi bir kaydırmaya neden olmadan hareket edebileceğiniz "nötr" bir alana sahip olmak daha hoştur. {{index [game, screenshot]}} -We are now able to display our tiny level. +Artık küçük seviyemizi görüntüleyebiliyoruz. ```{lang: html} <link rel="stylesheet" href="css/game.css"> @@ -538,39 +552,39 @@ We are now able to display our tiny level. {{if book -{{figure {url: "img/game_simpleLevel.png", alt: "Screenshot of the rendered level", width: "7cm"}}} +{{figure {url: "img/game_simpleLevel.png", alt: "Oluşturulan seviyenin ekran görüntüsü", width: "7cm"}}} if}} {{index "link (HTML tag)", CSS}} -The `<link>` tag, when used with `rel="stylesheet"`, is a way to load a CSS file into a page. The file `game.css` contains the styles necessary for our game. +`<link>` etiketi, `rel="stylesheet"` ile birlikte kullanıldığında, bir CSS dosyasını sayfaya yüklemenin bir yoludur. `game.css` dosyası oyunumuz için gerekli stilleri içerir. -## Motion and collision +## Hareket ve çarpışma {{index physics, [animation, "platform game"]}} -Now we're at the point where we can start adding motion. The basic approach, taken by most games like this, is to split ((time)) into small steps and, for each step, move the actors by a distance corresponding to their speed multiplied by the size of the time step. We'll measure time in seconds, so speeds are expressed in units per second. +Şimdi hareket eklemeye başlayabileceğimiz noktadayız. Bunun gibi çoğu oyun tarafından benimsenen temel yaklaşım, ((zaman)) küçük adımlara bölmek ve her adımda aktörleri hızlarının zaman adımının boyutuyla çarpımına karşılık gelen bir mesafe kadar hareket ettirmektir. Zamanı saniye cinsinden ölçeceğiz, bu nedenle hızlar saniye başına birim olarak ifade edilir. {{index obstacle, "collision detection"}} -Moving things is easy. The difficult part is dealing with the interactions between the elements. When the player hits a wall or floor, they should not simply move through it. The game must notice when a given motion causes an object to hit another object and respond accordingly. For walls, the motion must be stopped. When hitting a coin, that coin must be collected. When touching lava, the game should be lost. +Eşyaları taşımak kolaydır. Zor olan kısım, öğeler arasındaki etkileşimlerle başa çıkmaktır. Oyuncu bir duvara veya zemine çarptığında, sadece içinden geçmemelidir. Oyun, belirli bir hareketin bir nesnenin başka bir nesneye çarpmasına neden olduğunu fark etmeli ve buna göre yanıt vermelidir. Duvarlar için hareket durdurulmalıdır. Bir madeni paraya çarpıldığında, para toplanmalıdır. Lavlara dokunulduğunda oyun kaybedilmelidir. -Solving this for the general case is a big task. You can find libraries, usually called _((physics engine))s_, that simulate interaction between physical objects in two or three ((dimensions)). We'll take a more modest approach in this chapter, handling only collisions between rectangular objects and handling them in a rather simplistic way. +Bunu genel durum için çözmek büyük bir görevdir. Fiziksel nesneler arasındaki etkileşimi iki veya üç ((boyutta)) simüle eden, genellikle _((fizik motoru))s_ olarak adlandırılan kütüphaneler bulabilirsiniz. Bu bölümde daha mütevazı bir yaklaşım benimseyeceğiz, sadece dikdörtgen nesneler arasındaki çarpışmaları ele alacağız ve bunları oldukça basit bir şekilde işleyeceğiz. {{index bouncing, "collision detection", [animation, "platform game"]}} -Before moving the ((player)) or a block of ((lava)), we test whether the motion would take it inside of a wall. If it does, we simply cancel the motion altogether. The response to such a collision depends on the type of actor—the player will stop, whereas a lava block will bounce back. +((oyuncu)) veya bir ((lav)) bloğunu hareket ettirmeden önce, hareketin onu bir duvarın içine alıp almayacağını test ederiz. Eğer yaparsa, hareketi tamamen iptal ederiz. Böyle bir çarpışmaya verilecek tepki aktörün türüne bağlıdır; oyuncu dururken lav bloğu geri seker. {{index discretization}} -This approach requires our ((time)) steps to be rather small since it will cause motion to stop before the objects actually touch. If the time steps (and thus the motion steps) are too big, the player would end up hovering a noticeable distance above the ground. Another approach, arguably better but more complicated, would be to find the exact collision spot and move there. We will take the simple approach and hide its problems by ensuring the animation proceeds in small steps. +Bu yaklaşım, ((zaman)) adımlarımızın oldukça küçük olmasını gerektirir çünkü nesneler gerçekten temas etmeden önce hareketin durmasına neden olur. Zaman adımları (ve dolayısıyla hareket adımları) çok büyük olursa, oyuncu yerden belirgin bir mesafe yukarıda asılı kalacaktır. Muhtemelen daha iyi ancak daha karmaşık olan bir başka yaklaşım ise tam çarpışma noktasını bulmak ve oraya hareket etmek olacaktır. Biz basit yaklaşımı benimseyeceğiz ve animasyonun küçük adımlarla ilerlemesini sağlayarak sorunlarını gizleyeceğiz. {{index obstacle, "touches method", "collision detection"}} {{id touches}} -This method tells us whether a ((rectangle)) (specified by a position and a size) touches a grid element of the given type. +Bu yöntem bize bir ((dikdörtgen)) (bir konum ve bir boyut ile belirtilen) verilen türdeki bir ızgara elemanına dokunup dokunmadığını söyler. ```{includeCode: true} Level.prototype.touches = function(pos, size, type) { @@ -593,13 +607,13 @@ Level.prototype.touches = function(pos, size, type) { {{index "Math.floor function", "Math.ceil function"}} -The method computes the set of grid squares that the body ((overlap))s with by using `Math.floor` and `Math.ceil` on its ((coordinates)). Remember that ((grid)) squares are 1 by 1 units in size. By ((rounding)) the sides of a box up and down, we get the range of ((background)) squares that the box touches. +Yöntem, ((koordinatları)) üzerinde `Math.floor` ve `Math.ceil` kullanarak gövdenin ((örtüştüğü)) ızgara kareler kümesini hesaplar. ((Izgara)) karelerinin 1'e 1 birim boyutunda olduğunu unutmayın. Bir kutunun kenarlarını yukarı ve aşağı ((yuvarlayarak)), kutunun temas ettiği ((arka plan)) karelerinin aralığını elde ederiz. -{{figure {url: "img/game-grid.svg", alt: "Diagram showing a grid with a black box overlaid on it. All of the grid squares that are partially covered by the block are marked.", width: "3cm"}}} +{{figure {url: "img/game-grid.svg", alt: "Üzerine siyah bir kutu yerleştirilmiş bir ızgarayı gösteren diyagram. Blok tarafından kısmen kapsanan tüm ızgara kareleri işaretlenmiştir.", width: "3cm"}}} -We loop over the block of ((grid)) squares found by ((rounding)) the ((coordinates)) and return `true` when a matching square is found. Squares outside of the level are always treated as `"wall"` to ensure that the player can't leave the world and that we won't accidentally try to read outside of the bounds of our `rows` array. +((koordinatları)) ((yuvarlayarak)) bulunan ((ızgara)) kareler bloğu üzerinde döngü yaparız ve eşleşen bir kare bulunduğunda `true` döndürürüz. Seviyenin dışındaki kareler, oyuncunun dünyayı terk edemeyeceğinden ve yanlışlıkla `rows` dizimizin sınırlarının dışını okumaya çalışmayacağımızdan emin olmak için her zaman `"wall"` olarak kabul edilir. -The state `update` method uses `touches` to figure out whether the player is touching lava. +Durum `update` yöntemi, oyuncunun lavlara dokunup dokunmadığını anlamak için `touches` kullanır. ```{includeCode: true} State.prototype.update = function(time, keys) { @@ -623,11 +637,11 @@ State.prototype.update = function(time, keys) { }; ``` -The method is passed a time step and a data structure that tells it which keys are being held down. The first thing it does is call the `update` method on all actors, producing an array of updated actors. The actors also get the time step, the keys, and the state, so that they can base their update on those. Only the player will actually read keys, since that's the only actor that's controlled by the keyboard. +Yönteme bir zaman adımı ve hangi anahtarların basılı tutulduğunu söyleyen bir veri yapısı iletilir. Yaptığı ilk şey, tüm aktörler üzerinde `update` yöntemini çağırmak ve güncellenmiş aktörlerden oluşan bir dizi üretmektir. Aktörler ayrıca zaman adımını, anahtarları ve durumu alırlar, böylece güncellemelerini bunlara dayandırabilirler. Klavye tarafından kontrol edilen tek aktör olduğu için aslında sadece oyuncu tuşları okuyacaktır. -If the game is already over, no further processing has to be done (the game can't be won after being lost, or vice versa). Otherwise, the method tests whether the player is touching background lava. If so, the game is lost, and we're done. Finally, if the game really is still going on, it sees whether any other actors overlap the player. +Eğer oyun zaten bitmişse, başka bir işlem yapılmasına gerek yoktur (oyun kaybedildikten sonra kazanılamaz ya da tam tersi). Aksi takdirde, yöntem oyuncunun arka plandaki lavlara dokunup dokunmadığını test eder. Eğer öyleyse, oyun kaybedilir ve işimiz biter. Son olarak, eğer oyun gerçekten devam ediyorsa, başka aktörlerin oyuncuyla çakışıp çakışmadığına bakılır. -Overlap between actors is detected with the `overlap` function. It takes two actor objects and returns true when they touch—which is the case when they overlap both along the x-axis and along the y-axis. +Aktörler arasındaki çakışma `overlap` fonksiyonu ile tespit edilir. İki aktör nesnesi alır ve dokunduklarında true döndürür - bu, hem x ekseni hem de y ekseni boyunca üst üste geldikleri durumdur. ```{includeCode: true} function overlap(actor1, actor2) { @@ -638,7 +652,7 @@ function overlap(actor1, actor2) { } ``` -If any actor does overlap, its `collide` method gets a chance to update the state. Touching a lava actor sets the game status to `"lost"`. Coins vanish when you touch them and set the status to `"won"` when they are the last coin of the level. +Herhangi bir aktör çakışırsa, `collide` yöntemi durumu güncelleme şansı elde eder. Bir lav aktörüne dokunmak oyun durumunu `"lost"` olarak ayarlar. Paralar, onlara dokunduğunuzda kaybolur ve seviyenin son parası olduklarında durumu `"won"` olarak ayarlar. ```{includeCode: true} Lava.prototype.collide = function(state) { @@ -655,11 +669,11 @@ Coin.prototype.collide = function(state) { {{id actors}} -## Actor updates +## Aktör güncellemeleri {{index actor, "Lava class", lava}} -Actor objects' `update` methods take as arguments the time step, the state object, and a `keys` object. The one for the `Lava` actor type ignores the `keys` object. +Aktör nesnelerinin `update` yöntemleri argüman olarak zaman adımını, durum nesnesini ve bir `keys` nesnesini alır. `Lava` aktör tipi için olan `keys` nesnesini yok sayar. ```{includeCode: true} Lava.prototype.update = function(time, state) { @@ -676,11 +690,11 @@ Lava.prototype.update = function(time, state) { {{index bouncing, multiplication, "Vec class", "collision detection"}} -This `update` method computes a new position by adding the product of the ((time)) step and the current speed to its old position. If no obstacle blocks that new position, it moves there. If there is an obstacle, the behavior depends on the type of the ((lava)) block—dripping lava has a `reset` position, to which it jumps back when it hits something. Bouncing lava inverts its speed by multiplying it by -1 so that it starts moving in the opposite direction. +Bu `update` yöntemi, ((zaman)) adımı ile mevcut hızın çarpımını eski konumuna ekleyerek yeni bir konum hesaplar. Yeni konumu engelleyen bir engel yoksa, oraya hareket eder. Bir engel varsa, davranış ((lav)) bloğunun türüne bağlıdır - damlayan lavın bir `reset` konumu vardır ve bir şeye çarptığında geri atlar. Zıplayan lav, hızını -1 ile çarparak tersine çevirir, böylece ters yönde hareket etmeye başlar. {{index "Coin class", coin, wave}} -Coins use their `update` method to wobble. They ignore collisions with the grid since they are simply wobbling around inside of their own square. +Madeni paralar sallanmak için `update` yöntemini kullanırlar. Sadece kendi karelerinin içinde yalpaladıkları için ızgara ile çarpışmaları göz ardı ederler. ```{includeCode: true} const wobbleSpeed = 8, wobbleDist = 0.07; @@ -695,11 +709,11 @@ Coin.prototype.update = function(time) { {{index "Math.sin function", sine, phase}} -The `wobble` property is incremented to track time and then used as an argument to `Math.sin` to find the new position on the ((wave)). The coin's current position is then computed from its base position and an offset based on this wave. +Zamanı izlemek için `wobble` özelliği artırılır ve ardından ((dalga)) üzerindeki yeni konumu bulmak için `Math.sin` için bir argüman olarak kullanılır. Madeni paranın mevcut konumu daha sonra temel konumundan ve bu dalgaya dayalı bir ofsetten hesaplanır. {{index "collision detection", "Player class"}} -That leaves the ((player)) itself. Player motion is handled separately per ((axis)) because hitting the floor should not prevent horizontal motion, and hitting a wall should not stop falling or jumping motion. +Geriye ((oyuncu))'nun kendisi kalıyor. Oyuncu hareketi her ((axis)) için ayrı ayrı ele alınır çünkü yere çarpmak yatay hareketi engellememelidir ve bir duvara çarpmak düşme veya zıplama hareketini durdurmamalıdır. ```{includeCode: true} const playerXSpeed = 7; @@ -731,31 +745,31 @@ Player.prototype.update = function(time, state, keys) { {{index [animation, "platform game"], keyboard}} -The horizontal motion is computed based on the state of the left and right arrow keys. When there's no wall blocking the new position created by this motion, it is used. Otherwise, the old position is kept. +Yatay hareket, sol ve sağ ok tuşlarının durumuna göre hesaplanır. Bu hareket tarafından oluşturulan yeni konumu engelleyen bir duvar yoksa kullanılır. Aksi takdirde, eski konum korunur. {{index acceleration, physics}} -Vertical motion works in a similar way but has to simulate ((jumping)) and ((gravity)). The player's vertical speed (`ySpeed`) is first accelerated to account for ((gravity)). +Dikey hareket benzer şekilde çalışır ancak ((zıplama)) ve ((yerçekimi)) simüle edilmelidir. Oyuncunun dikey hızı (`ySpeed`) ilk olarak ((yerçekimi)) hesaba katmak için hızlandırılır. {{index "collision detection", keyboard, jumping}} -We check for walls again. If we don't hit any, the new position is used. If there _is_ a wall, there are two possible outcomes. When the up arrow is pressed _and_ we are moving down (meaning the thing we hit is below us), the speed is set to a relatively large, negative value. This causes the player to jump. If that is not the case, the player simply bumped into something, and the speed is set to zero. +Duvarları tekrar kontrol ederiz. Herhangi birine çarpmazsak, yeni konum kullanılır. Eğer bir duvar varsa, iki olası sonuç vardır. Yukarı oka basıldığında _ve_ aşağı doğru hareket ettiğimizde (yani çarptığımız şey altımızda olduğunda), hız nispeten büyük, negatif bir değere ayarlanır. Bu da oyuncunun zıplamasına neden olur. Eğer durum böyle değilse, oyuncu basitçe bir şeye çarpmıştır ve hız sıfıra ayarlanmıştır. -The gravity strength, ((jumping)) speed, and other ((constant))s in the game were determined by simply trying out some numbers and seeing which ones felt right. You can try experimenting with them. +Bu oyundaki yerçekimi gücü, ((zıplama)) hızı ve hemen hemen tüm diğer ((sabitler)) tamamen ((deneme yanılma)) ile ayarlanmıştır. Beğendiğim bir kombinasyon bulana kadar değerleri test ettim. -## Tracking keys +## İzleme tuşları {{index keyboard}} -For a ((game)) like this, we do not want keys to take effect once per keypress. Rather, we want their effect (moving the player figure) to stay active as long as they are held. +Bunun gibi bir ((oyun)) için, tuşların her basışta bir kez etkili olmasını istemiyoruz. Aksine, etkilerinin (oyuncu figürünü hareket ettirme) basılı tutuldukları sürece aktif kalmasını istiyoruz. {{index "preventDefault method"}} -We need to set up a key handler that stores the current state of the left, right, and up arrow keys. We will also want to call `preventDefault` for those keys so that they don't end up ((scrolling)) the page. +Sol, sağ ve yukarı ok tuşlarının mevcut durumunu saklayan bir tuş işleyici ayarlamamız gerekir. Ayrıca, bu tuşlar için `preventDefault` özelliğini çağırmak isteyeceğiz, böylece sayfayı ((kaydırma)) sonlandırmayacaklar. {{index "trackKeys function", "key code", "event handling", "addEventListener method"}} -The following function, when given an array of key names, will return an object that tracks the current position of those keys. It registers event handlers for `"keydown"` and `"keyup"` events and, when the key code in the event is present in the set of codes that it is tracking, updates the object. +Aşağıdaki fonksiyon, bir dizi anahtar adı verildiğinde, bu anahtarların geçerli konumunu izleyen bir nesne döndürür. `"keydown"` ve `"keyup"` olayları için olay işleyicileri kaydeder ve olaydaki anahtar kodu, izlediği kod kümesinde mevcut olduğunda nesneyi günceller. ```{includeCode: true} function trackKeys(keys) { @@ -777,19 +791,19 @@ const arrowKeys = {{index "keydown event", "keyup event"}} -The same handler function is used for both event types. It looks at the event object's `type` property to determine whether the key state should be updated to true (`"keydown"`) or false (`"keyup"`). +Her iki olay türü için de aynı işleyici işlevi kullanılır. Anahtar durumunun true (`"keydown"`) veya false (`"keyup"`) olarak güncellenmesi gerekip gerekmediğini belirlemek için olay nesnesinin `type` özelliğine bakar. {{id runAnimation}} -## Running the game +## Oyunu çalıştırmak {{index "requestAnimationFrame function", [animation, "platform game"]}} -The `requestAnimationFrame` function, which we saw in [Chapter ?](dom#animationFrame), provides a good way to animate a game. But its interface is quite primitive—using it requires us to track the time at which our function was called the last time around and call `requestAnimationFrame` again after every frame. +[Bölüm ?](dom#animationFrame) içinde gördüğümüz `requestAnimationFrame` fonksiyonu bir oyunu canlandırmak için iyi bir yol sağlar. Ancak arayüzü oldukça ilkeldir - onu kullanmak, fonksiyonumuzun en son çağrıldığı zamanı takip etmemizi ve her kareden sonra `requestAnimationFrame` fonksiyonunu tekrar çağırmamızı gerektirir. {{index "runAnimation function", "callback function", [function, "as value"], [function, "higher-order"], [animation, "platform game"]}} -Let's define a helper function that wraps all that in a convenient interface and allows us to simply call `runAnimation`, giving it a function that expects a time difference as an argument and draws a single frame. When the frame function returns the value `false`, the animation stops. +Bu sıkıcı kısımları kullanışlı bir arayüzle saran ve basitçe `runAnimation` çağrısı yapmamızı sağlayan bir yardımcı fonksiyon tanımlayalım ve ona argüman olarak bir zaman farkı bekleyen ve tek bir kare çizen bir fonksiyon verelim. Frame fonksiyonu `false` değerini döndürdüğünde animasyon durur. ```{includeCode: true} function runAnimation(frameFunc) { @@ -808,13 +822,13 @@ function runAnimation(frameFunc) { {{index time, discretization}} -I have set a maximum frame step of 100 milliseconds (one-tenth of a second). When the browser tab or window with our page is hidden, `requestAnimationFrame` calls will be suspended until the tab or window is shown again. In this case, the difference between `lastTime` and `time` will be the entire time in which the page was hidden. Advancing the game by that much in a single step would look silly and might cause weird side effects, such as the player falling through the floor. +Maksimum çerçeve adımını 100 milisaniye (saniyenin onda biri) olarak belirledim. Sayfamızın bulunduğu tarayıcı sekmesi veya penceresi gizlendiğinde, `requestAnimationFrame` çağrıları sekme veya pencere tekrar gösterilinceye kadar askıya alınacaktır. Bu durumda, `lastTime` ile `time` arasındaki fark, sayfanın gizlendiği sürenin tamamı olacaktır. Oyunu tek bir adımda bu kadar ilerletmek aptalca görünür ve oyuncunun yere düşmesi gibi garip yan etkilere neden olabilir. -The function also converts the time steps to seconds, which are an easier quantity to think about than milliseconds. +Fonksiyon ayrıca zaman adımlarını milisaniyeden daha kolay düşünülebilen saniyelere dönüştürür. {{index "callback function", "runLevel function", [animation, "platform game"]}} -The `runLevel` function takes a `Level` object and a ((display)) constructor and returns a promise. It displays the level (in `document.body`) and lets the user play through it. When the level is finished (lost or won), `runLevel` waits one more second (to let the user see what happens) and then clears the display, stops the animation, and resolves the promise to the game's end status. +`runLevel` fonksiyonu bir `Level` nesnesi ve bir ((display)) yapıcı alır ve bir söz döndürür. Seviyeyi görüntüler (`document.body` içinde) ve kullanıcının oynamasına izin verir. Seviye bittiğinde (kaybedildiğinde veya kazanıldığında), `runLevel` bir saniye daha bekler (kullanıcının ne olduğunu görmesini sağlamak için) ve ardından ekranı temizler, animasyonu durdurur ve sözü oyunun bitiş durumuna çözer. ```{includeCode: true} function runLevel(level, Display) { @@ -842,7 +856,7 @@ function runLevel(level, Display) { {{index "runGame function"}} -A game is a sequence of ((level))s. Whenever the ((player)) dies, the current level is restarted. When a level is completed, we move on to the next level. This can be expressed by the following function, which takes an array of level plans (strings) and a ((display)) constructor: +Bir oyun bir dizi ((seviye))dir. ((oyuncu)) her öldüğünde, mevcut seviye yeniden başlatılır. Bir seviye tamamlandığında, bir sonraki seviyeye geçilir. Bu, bir dizi seviye planı (string) ve bir ((display)) yapıcısı alan aşağıdaki fonksiyonla ifade edilebilir: ```{includeCode: true} async function runGame(plans, Display) { @@ -857,11 +871,11 @@ async function runGame(plans, Display) { {{index "asynchronous programming", "event handling"}} -Because we made `runLevel` return a promise, `runGame` can be written using an `async` function, as shown in [Chapter ?](async). It returns another promise, which resolves when the player finishes the game. +`runLevel`ın bir promise döndürmesini sağladığımız için, `runGame` [Bölüm ?](async) içinde gösterildiği gibi bir `async` fonksiyonu kullanılarak yazılabilir. Oyuncu oyunu bitirdiğinde çözümlenen başka bir söz döndürür. -{{index game, "GAME_LEVELS data set"}} +{{index game, "GAME_LEVELS dataset"}} -There is a set of ((level)) plans available in the `GAME_LEVELS` binding in [this chapter's sandbox](https://eloquentjavascript.net/code#16)[ ([_https://eloquentjavascript.net/code#16_](https://eloquentjavascript.net/code#16))]{if book}. This page feeds them to `runGame`, starting an actual game. +[Bu bölümün sanal alanı](https://eloquentjavascript.net/code#16)[ ([_https://eloquentjavascript.net/code#16_](https://eloquentjavascript.net/code#16))]{if book} içinde `GAME_LEVELS` bağlayıcısında bir dizi ((seviye)) planı mevcuttur. Bu sayfa onları `runGame` ile besleyerek gerçek bir oyun başlatır. ```{sandbox: null, focus: yes, lang: html, startCode: true} <link rel="stylesheet" href="css/game.css"> @@ -875,21 +889,21 @@ There is a set of ((level)) plans available in the `GAME_LEVELS` binding in [thi {{if interactive -See if you can beat those. I had fun building them. +Bakalım onları yenebilecek misin? Onları yaparken çok eğlendim. if}} -## Exercises +## Egzersizler -### Game over +### Oyun bitti {{index "lives (exercise)", game}} -It's traditional for ((platform game))s to have the player start with a limited number of _lives_ and subtract one life each time they die. When the player is out of lives, the game restarts from the beginning. +((Platform oyunları)) için geleneksel olan, oyuncunun sınırlı sayıda _can_ ile başlaması ve her öldüğünde bir can eksiltmesidir. Oyuncunun canı bittiğinde, oyun baştan başlar. {{index "runGame function"}} -Adjust `runGame` to implement lives. Have the player start with three. Output the current number of lives (using `console.log`) every time a level starts. +Canları uygulamak için `runGame`i ayarlayın. Oyuncunun üç canla başlamasını sağlayın. Bir seviye her başladığında mevcut can sayısını (`console.log` kullanarak) çıktı olarak verin. {{if interactive @@ -914,23 +928,23 @@ Adjust `runGame` to implement lives. Have the player start with three. Output th if}} -### Pausing the game +### Oyunu durdurmak -{{index "pausing (exercise)", "escape key", keyboard}} +{{index "pausing (exercise)", "escape key", keyboard, "runLevel function", "event handling"}} -Make it possible to pause (suspend) and unpause the game by pressing the Esc key. +Esc tuşuna basarak oyunu duraklatmayı (askıya almayı) ve duraklatmayı kaldırmayı mümkün kılın. {{index "runLevel function", "event handling"}} -This can be done by changing the `runLevel` function to set up a keyboard event handler that interrupts or resumes the animation whenever the Esc key is hit. +Bu, `runLevel` işlevini başka bir klavye olay işleyicisi kullanacak şekilde değiştirerek ve Esc tuşuna her basıldığında animasyonu keserek veya devam ettirerek yapılabilir. {{index "runAnimation function"}} -The `runAnimation` interface may not look like it is suitable for this at first glance, but it is if you rearrange the way `runLevel` calls it. +İlk bakışta `runAnimation` arayüzü bunun için uygun gibi görünmeyebilir, ancak `runLevel` arayüzünü çağırma şeklini yeniden düzenlerseniz uygundur. {{index [binding, global], "trackKeys function"}} -When you have that working, there is something else you could try. The way we have been registering keyboard event handlers is somewhat problematic. The `arrowKeys` object is currently a global binding, and its event handlers are kept around even when no game is running. You could say they _((leak))_ out of our system. Extend `trackKeys` to provide a way to unregister its handlers and then change `runLevel` to register its handlers when it starts and unregister them again when it is finished. +Bunu çalıştırdığınızda, deneyebileceğiniz başka bir şey daha var. Klavye olay işleyicilerini kaydetme şeklimiz biraz sorunlu. `arrowKeys` nesnesi şu anda küresel bir bağlayıcıdır ve olay işleyicileri oyun çalışmadığında bile etrafta tutulur. Sistemimizden _((sızıntı))_ yaptıklarını söyleyebilirsiniz. `trackKeys`i genişleterek işleyicilerinin kaydını kaldırmanın bir yolunu sağlayın ve ardından `runLevel`ı, başladığında işleyicilerini kaydedecek ve bittiğinde tekrar kaydını kaldıracak şekilde değiştirin. {{if interactive @@ -972,29 +986,29 @@ if}} {{index "pausing (exercise)", [animation, "platform game"]}} -An animation can be interrupted by returning `false` from the function given to `runAnimation`. It can be continued by calling `runAnimation` again. +Bir animasyon `runAnimation`a verilen fonksiyondan `false` döndürülerek kesilebilir. Animasyon `runAnimation` tekrar çağrılarak devam ettirilebilir. {{index closure}} -So we need to communicate the fact that we are pausing the game to the function given to `runAnimation`. For that, you can use a binding that both the event handler and that function have access to. +Bu yüzden oyunu duraklattığımızı `runAnimation`a verilen fonksiyona iletmemiz gerekiyor. Bunun için, hem olay işleyicinin hem de bu fonksiyonun erişebileceği bir bağlayıcı kullanabilirsiniz. {{index "event handling", "removeEventListener method", [function, "as value"]}} -When finding a way to unregister the handlers registered by `trackKeys`, remember that the _exact_ same function value that was passed to `addEventListener` must be passed to `removeEventListener` to successfully remove a handler. Thus, the `handler` function value created in `trackKeys` must be available to the code that unregisters the handlers. +`trackKeys` tarafından kaydedilen işleyicilerin kaydını silmenin bir yolunu bulurken, bir işleyiciyi başarıyla kaldırmak için `addEventListener` fonksiyonuna aktarılan _aynı_ fonksiyon değerinin `removeEventListener` fonksiyonuna da aktarılması gerektiğini unutmayın. Bu nedenle, `trackKeys` içinde oluşturulan `handler` fonksiyon değeri, işleyicilerin kaydını kaldıran kod tarafından kullanılabilir olmalıdır. -You can add a property to the object returned by `trackKeys`, containing either that function value or a method that handles the unregistering directly. +`trackKeys` tarafından döndürülen nesneye, bu işlev değerini ya da kaydı kaldırma işlemini doğrudan gerçekleştiren bir yöntemi içeren bir özellik ekleyebilirsiniz. hint}} -### A monster +### Bir canavar {{index "monster (exercise)"}} -It is traditional for platform games to have enemies that you can jump on top of to defeat. This exercise asks you to add such an actor type to the game. +Platform oyunlarında yenmek için üzerine atlayabileceğiniz düşmanların olması gelenekseldir. Bu alıştırma sizden oyuna böyle bir aktör tipi eklemenizi istiyor. -We'll call it a monster. Monsters move only horizontally. You can make them move in the direction of the player, bounce back and forth like horizontal lava, or have any movement pattern you want. The class doesn't have to handle falling, but it should make sure the monster doesn't walk through walls. +Biz buna canavar diyeceğiz. Canavarlar sadece yatay olarak hareket eder. Oyuncunun yönünde hareket etmelerini, yatay lav gibi ileri geri sıçramalarını veya istediğiniz herhangi bir hareket modeline sahip olmalarını sağlayabilirsiniz. Sınıfın düşmeyi idare etmesi gerekmez, ancak canavarın duvarlardan geçmediğinden emin olmalıdır. -When a monster touches the player, the effect depends on whether the player is jumping on top of them or not. You can approximate this by checking whether the player's bottom is near the monster's top. If this is the case, the monster disappears. If not, the game is lost. +Bir canavar oyuncuya dokunduğunda, etki oyuncunun üzerine atlayıp atlamadığına bağlıdır. Oyuncunun alt kısmının canavarın üst kısmına yakın olup olmadığını kontrol ederek bunu yaklaşık olarak yapabilirsiniz. Eğer durum böyleyse, canavar kaybolur. Değilse, oyun kaybedilir. {{if interactive @@ -1047,12 +1061,12 @@ if}} {{index "monster (exercise)", "persistent data structure"}} -If you want to implement a type of motion that is stateful, such as bouncing, make sure you store the necessary state in the actor object—include it as constructor argument and add it as a property. +Zıplama gibi duruma bağlı bir hareket türü uygulamak istiyorsanız, gerekli durumu aktör nesnesinde sakladığınızdan emin olun; bunu yapıcı argüman olarak dahil edin ve bir özellik olarak ekleyin. -Remember that `update` returns a _new_ object, rather than changing the old one. +Unutmayın ki `update` eskisini değiştirmek yerine _new_ bir nesne döndürür. {{index "collision detection"}} -When handling collision, find the player in `state.actors` and compare its position to the monster's position. To get the _bottom_ of the player, you have to add its vertical size to its vertical position. The creation of an updated state will resemble either `Coin`'s `collide` method (removing the actor) or `Lava`'s (changing the status to `"lost"`), depending on the player position. +Çarpışmayı ele alırken, oyuncuyu `state.actors` içinde bulun ve konumunu canavarın konumuyla karşılaştırın. Oyuncunun _altını_ elde etmek için, dikey boyutunu dikey konumuna eklemeniz gerekir. Güncellenmiş bir durumun oluşturulması, oyuncunun konumuna bağlı olarak ya `Coin`in `collide` yöntemine (aktörü kaldırmak) ya da `Lava`nınkine (durumu `lost` olarak değiştirmek) benzeyecektir. hint}} diff --git a/17_canvas.md b/17_canvas.md index 4b5d64b5..738aad5e 100644 --- a/17_canvas.md +++ b/17_canvas.md @@ -1,36 +1,36 @@ {{meta {load_files: ["code/chapter/16_game.js", "code/levels.js", "code/_stop_keys.js", "code/chapter/17_canvas.js"], zip: "html include=[\"img/player.png\", \"img/sprites.png\"]"}}} -# Drawing on Canvas +# Tuval Üzerine Çizim -{{quote {author: "M.C. Escher", title: "cited by Bruno Ernst in The Magic Mirror of M.C. Escher", chapter: true} +{{quote {author: "M.C. Escher", title: "Bruno Ernst tarafından M.C. Escher'in Sihirli Aynası'nda alıntılanmıştır", chapter: true} -Drawing is deception. +Çizim bir aldatmacadır. quote}} {{index "Escher, M.C."}} -{{figure {url: "img/chapter_picture_17.jpg", alt: "Illustration showing an industrial-looking robot arm drawing a city on a piece of paper", chapter: "framed"}}} +{{figure {url: "img/chapter_picture_17.jpg", alt: "Endüstriyel görünümlü bir robot kolunun bir kağıt parçasına bir şehir çizdiğini gösteren illüstrasyon", chapter: "framed"}}} {{index CSS, "transform (CSS)", [DOM, graphics]}} -Browsers give us several ways to display ((graphics)). The simplest way is to use styles to position and color regular DOM elements. This can get you quite far, as the game in the [previous chapter](game) showed. By adding partially transparent background ((image))s to the nodes, we can make them look exactly the way we want. It is even possible to rotate or skew nodes with the `transform` style. +Tarayıcılar bize ((grafik)) görüntülemek için çeşitli yollar sunar. En basit yol, normal DOM öğelerini konumlandırmak ve renklendirmek için stilleri kullanmaktır. Bu, [önceki bölüm](game)'daki oyunun gösterdiği gibi sizi oldukça ileriye götürebilir. Düğümlere kısmen saydam arka plan ((resim)) ekleyerek, tam olarak istediğimiz şekilde görünmelerini sağlayabiliriz. Hatta `transform` stili ile düğümleri döndürmek ya da eğmek bile mümkündür. -But we'd be using the DOM for something that it wasn't originally designed for. Some tasks, such as drawing a ((line)) between arbitrary points, are extremely awkward to do with regular HTML elements. +Ancak DOM'u başlangıçta tasarlanmadığı bir şey için kullanmış oluruz. Rastgele noktalar arasında bir ((çizgi)) çizmek gibi bazı görevleri normal HTML öğeleriyle yapmak son derece gariptir. {{index SVG, "img (HTML tag)"}} -There are two alternatives. The first is DOM-based but utilizes _Scalable Vector Graphics_ (SVG), rather than HTML. Think of SVG as a ((document))-markup dialect that focuses on ((shape))s rather than text. You can embed an SVG document directly in an HTML document or include it with an `<img>` tag. +İki alternatif vardır. İlki, DOM tabanlıdır ancak HTML yerine _Scalable Vector Graphics_ (SVG) kullanır. SVG'yi, metin yerine ((şekil))lere odaklanan bir ((belge))-markup diyalektiği olarak düşünebilirsiniz. Bir SVG belgesini doğrudan bir HTML belgesine gömebilir veya bir `<img>` etiketi ile dahil edebilirsiniz. {{index clearing, [DOM graphics], [interface, canvas]}} -The second alternative is called a _((canvas))_. A canvas is a single DOM element that encapsulates a ((picture)). It provides a programming interface for drawing ((shape))s onto the space taken up by the node. The main difference between a canvas and an SVG picture is that in SVG the original description of the shapes is preserved so that they can be moved or resized at any time. A canvas, on the other hand, converts the shapes to ((pixel))s (colored dots on a raster) as soon as they are drawn and does not remember what these pixels represent. The only way to move a shape on a canvas is to clear the canvas (or the part of the canvas around the shape) and redraw it with the shape in a new position. +İkinci alternatif _((canvas))_ olarak adlandırılır. Tuval, bir ((resim))'i kapsülleyen tek bir DOM öğesidir. Düğüm tarafından kaplanan alana ((şekil)) çizmek için bir programlama arayüzü sağlar. Bir tuval ile bir SVG resmi arasındaki temel fark, SVG'de şekillerin orijinal tanımının korunması ve böylece herhangi bir zamanda taşınabilmeleri veya yeniden boyutlandırılabilmeleridir. Öte yandan bir tuval, şekilleri çizildikleri anda ((piksel))lere (bir raster üzerindeki renkli noktalar) dönüştürür ve bu piksellerin neyi temsil ettiğini hatırlamaz. Tuval üzerindeki bir şekli taşımanın tek yolu, tuvali (veya tuvalin şeklin etrafındaki kısmını) temizlemek ve şekli yeni bir konuma getirerek yeniden çizmektir. ## SVG -This book will not go into ((SVG)) in detail, but I will briefly explain how it works. At the [end of the chapter](canvas#graphics_tradeoffs), I'll come back to the trade-offs that you must consider when deciding which ((drawing)) mechanism is appropriate for a given application. +Bu kitap ((SVG))'yi ayrıntılı olarak ele almayacak, ancak nasıl çalıştığını kısaca açıklayacağım. [Bölümün sonunda](canvas#graphics_tradeoffs), belirli bir uygulama için hangi ((çizim)) mekanizmasının uygun olduğunu belirlerken göz önünde bulundurmanız gereken ödünleşmelere tekrar döneceğim. -This is an HTML document with a simple SVG ((picture)) in it: +Bu, içinde basit bir SVG ((resim)) bulunan bir HTML belgesidir: ```{lang: html, sandbox: "svg"} <p>Normal HTML here.</p> @@ -43,44 +43,44 @@ This is an HTML document with a simple SVG ((picture)) in it: {{index "circle (SVG tag)", "rect (SVG tag)", "XML namespace", XML, "xmlns attribute"}} -The `xmlns` attribute changes an element (and its children) to a different _XML namespace_. This namespace, identified by a ((URL)), specifies the dialect that we are currently speaking. The `<circle>` and `<rect>` tags, which do not exist in HTML, do have a meaning in SVG—they draw shapes using the style and position specified by their attributes. +`xmlns` özelliği, bir öğeyi (ve çocuklarını) farklı bir _XML ad alanına_ değiştirir. Bu ad alanı, bir ((URL)) ile tanımlanır ve şu anda konuştuğumuz diyalektiği belirtir. HTML'de bulunmayan `<circle>` ve `<rect>` etiketleri, SVG'de bir anlama sahiptir—özellikleriyle belirtilen stil ve pozisyonu kullanarak şekiller çizerler. {{if book -The document is displayed like this: +Belge şu şekilde görüntülenir: -{{figure {url: "img/svg-demo.png", alt: "Screenshot showing an SVG image embedded in an HTML document", width: "4.5cm"}}} +{{figure {url: "img/svg-demo.png", alt: "Bir HTML belgesine gömülmüş SVG görüntüsünü gösteren ekran görüntüsü", width: "4.5cm"}}} if}} {{index [DOM, graphics]}} -These tags create DOM elements, just like HTML tags, that scripts can interact with. For example, this changes the `<circle>` element to be ((color))ed cyan instead: +Bu etiketler, tıpkı HTML etiketleri gibi, komut dosyalarının etkileşime girebileceği DOM öğeleri oluşturur. Örneğin, bu `<circle>` öğesini ((color))ed cyan olarak değiştirir: ```{sandbox: "svg"} let circle = document.querySelector("circle"); circle.setAttribute("fill", "cyan"); ``` -## The canvas element +## Canvas öğesi {{index [canvas, size], "canvas (HTML tag)"}} -Canvas ((graphics)) can be drawn onto a `<canvas>` element. You can give such an element `width` and `height` attributes to determine its size in ((pixel))s. +Canvas ((grafikleri)), bir `<canvas>` öğesi üzerine çizilebilir. Böyle bir öğeye, boyutunu ((piksel)) cinsinden belirlemek için `width` ve `height` özellikleri verebilirsiniz. -A new canvas is empty, meaning it is entirely ((transparent)) and thus shows up as empty space in the document. +Yeni bir canvas boştur, yani tamamen ((şeffaf))tır ve bu nedenle belgede boş alan olarak görünür. {{index "2d (canvas context)", "webgl (canvas context)", OpenGL, [canvas, context], dimensions, [interface, canvas]}} -The `<canvas>` tag is intended to allow different styles of ((drawing)). To get access to an actual drawing interface, we first need to create a _((context))_, an object whose methods provide the drawing interface. There are currently three widely supported drawing styles: `"2d"` for two-dimensional graphics, `"webgl"` for three-dimensional graphics through the OpenGL interface, and `"webgpu"`, a more modern and flexible alternative to WebGL. +`<canvas>` etiketi, farklı ((çizim)) stillerine olanak tanımak için tasarlanmıştır. Gerçek bir çizim arayüzüne erişmek için önce bir _((context))_ oluşturmamız gerekir; bu, yöntemleri çizim arayüzünü sağlayan bir nesnedir. Şu anda yaygın olarak desteklenen üç çizim stili vardır: iki boyutlu grafikler için `"2d"`, OpenGL arayüzü aracılığıyla üç boyutlu grafikler için `"webgl"` ve WebGL ile aynı rolü dolduran, ancak daha modern bir arayüz sunan `"webgpu"`. {{index rendering, graphics, efficiency}} -This book won't discuss WebGL or WebGPU—we'll stick to two dimensions. But if you are interested in three-dimensional graphics, I do encourage you to look into WebGPU. It provides a direct interface to graphics hardware and allows you to render even complicated scenes efficiently, using JavaScript. +Bu kitap WebGL veya WebGPU'yu ele almayacak—iki boyutla sınırlı kalacağız. Ancak üç boyutlu grafiklere ilgi duyuyorsanız, WebGPU'yu incelemenizi tavsiye ederim. Grafik donanımına doğrudan bir arayüz sağlar ve JavaScript kullanarak karmaşık sahneleri bile verimli bir şekilde render etmenizi sağlar. {{index "getContext method", [canvas, context]}} -You create a ((context)) with the `getContext` method on the `<canvas>` DOM element. +`<canvas>` DOM öğesi üzerinde `getContext` yöntemiyle bir ((context)) oluşturursunuz. ```{lang: html} <p>Before canvas.</p> @@ -94,41 +94,41 @@ You create a ((context)) with the `getContext` method on the `<canvas>` DOM elem </script> ``` -After creating the context object, the example draws a red ((rectangle)) 100 ((pixel))s wide and 50 pixels high, with its top-left corner at coordinates (10,10). +Örnek, bağlam nesnesini oluşturduktan sonra, sol üst köşesi (10,10) koordinatlarında olacak şekilde 100 ((piksel)) genişliğinde ve 50 piksel yüksekliğinde kırmızı bir ((dikdörtgen)) çizer. {{if book -{{figure {url: "img/canvas_fill.png", alt: "Screenshot of a canvas with a rectangle on it", width: "2.5cm"}}} +{{figure {url: "img/canvas_fill.png", alt: "Üzerinde dikdörtgen bulunan bir tuvalin ekran görüntüsü", width: "2.5cm"}}} if}} {{index SVG, coordinates}} -Just like in HTML (and SVG), the coordinate system that the canvas uses puts (0,0) at the top-left corner, and the positive y-((axis)) goes down from there. So (10,10) is 10 pixels below and to the right of the top-left corner. +Tıpkı HTML'de (ve SVG'de) olduğu gibi, tuvalin kullandığı koordinat sistemi (0,0)'ı sol üst köşeye koyar ve pozitif y-((eksen)) oradan aşağı iner. Yani (10,10) sol üst köşenin 10 piksel altında ve sağındadır. {{id fill_stroke}} -## Lines and surfaces +## Çizgiler ve yüzeyler {{index filling, stroking, drawing, SVG}} -In the ((canvas)) interface, a shape can be _filled_, meaning its area is given a certain color or pattern, or it can be _stroked_, which means a ((line)) is drawn along its edge. The same terminology is used by SVG. +((Canvas)) arayüzünde, bir şekil _doldurulabilir_, yani alanına belirli bir renk veya desen verilebilir veya _okşanabilir_, yani kenarı boyunca bir ((çizgi)) çizilebilir. Aynı terminoloji SVG tarafından da kullanılır. {{index "fillRect method", "strokeRect method"}} -The `fillRect` method fills a ((rectangle)). It takes first the x- and y-((coordinates)) of the rectangle's top-left corner, then its width, and then its height. A similar method called `strokeRect` draws the ((outline)) of a rectangle. +`fillRect` yöntemi bir ((dikdörtgen)) doldurur. Önce dikdörtgenin sol üst köşesinin x- ve y-((koordinatlarını)), sonra genişliğini ve sonra da yüksekliğini alır. Benzer bir yöntem olan `strokeRect`, bir dikdörtgenin ((anahatlarını)) çizer. {{index [state, "of canvas"]}} -Neither method takes any further parameters. The color of the fill, thickness of the stroke, and so on, are not determined by an argument to the method, as you might reasonably expect, but rather by properties of the context object. +Her iki yöntem de başka parametre almaz. Dolgunun rengi, konturun kalınlığı ve benzerleri, yöntemin bir argümanı tarafından değil (makul olarak bekleyebileceğiniz gibi), bağlam nesnesinin özellikleri tarafından belirlenir. {{index filling, "fillStyle property"}} -The `fillStyle` property controls the way shapes are filled. It can be set to a string that specifies a ((color)), using the color notation used by ((CSS)). +`fillStyle` özelliği şekillerin doldurulma şeklini kontrol eder. ((CSS)) tarafından kullanılan renk gösterimini kullanarak bir ((renk)) belirten bir dizeye ayarlanabilir. {{index stroking, "line width", "strokeStyle property", "lineWidth property", canvas}} -The `strokeStyle` property works similarly but determines the color used for a stroked line. The width of that line is determined by the `lineWidth` property, which may contain any positive number. +`strokeStyle` özelliği de benzer şekilde çalışır, ancak konturlu bir çizgi için kullanılan rengi belirler. Bu çizginin genişliği, herhangi bir pozitif sayı içerebilen `lineWidth` özelliği tarafından belirlenir. ```{lang: html} <canvas></canvas> @@ -143,21 +143,21 @@ The `strokeStyle` property works similarly but determines the color used for a s {{if book -This code draws two blue squares, using a thicker line for the second one. +Bu kod, ikincisi için daha kalın bir çizgi kullanarak iki mavi kare çizer. -{{figure {url: "img/canvas_stroke.png", alt: "Screenshot showing two outlined squares", width: "5cm"}}} +{{figure {url: "img/canvas_stroke.png", alt: "İki ana hatlı kareyi gösteren ekran görüntüsü", width: "5cm"}}} if}} {{index "default value", [canvas, size]}} -When no `width` or `height` attribute is specified, as in the example, a canvas element gets a default width of 300 pixels and height of 150 pixels. +Örnekte olduğu gibi `width` veya `height` niteliği belirtilmediğinde, bir canvas öğesi varsayılan olarak 300 piksel genişlik ve 150 piksel yükseklik alır. -## Paths +## Yollar {{index [path, canvas], [interface, design], [canvas, path]}} -A path is a sequence of ((line))s. The 2D canvas interface takes a peculiar approach to describing such a path. It is done entirely through ((side effect))s. Paths are not values that can be stored and passed around. Instead, if you want to do something with a path, you make a sequence of method calls to describe its shape. +Bir yol, ((çizgi))lerin bir dizisidir. 2B tuval arayüzü böyle bir yolu tanımlamak için kendine özgü bir yaklaşım benimser. Bu tamamen ((yan etki))ler aracılığıyla yapılır. Yollar saklanabilen ve aktarılabilen değerler değildir. Bunun yerine, bir yolla bir şey yapmak istiyorsanız, şeklini tanımlamak için bir dizi yöntem çağrısı yaparsınız. ```{lang: html} <canvas></canvas> @@ -174,19 +174,19 @@ A path is a sequence of ((line))s. The 2D canvas interface takes a peculiar appr {{index canvas, "stroke method", "lineTo method", "moveTo method", shape}} -This example creates a path with a number of horizontal ((line)) segments and then strokes it using the `stroke` method. Each segment created with `lineTo` starts at the path's _current_ position. That position is usually the end of the last segment, unless `moveTo` was called. In that case, the next segment would start at the position passed to `moveTo`. +Bu örnek, bir dizi yatay ((çizgi)) parçadan oluşan bir yol oluşturur ve ardından `stroke` yöntemini kullanarak bu yolu konturlar. `lineTo` ile oluşturulan her segment yolun _current_ konumundan başlar. Bu konum, `moveTo` çağrılmadığı sürece, genellikle son segmentin sonudur. Bu durumda, bir sonraki segment `moveTo` metoduna aktarılan pozisyondan başlar. {{if book -The path described by the previous program looks like this: +Önceki program tarafından tanımlanan yol şu şekildedir: -{{figure {url: "img/canvas_path.png", alt: "Screenshot showing a number of vertical lines", width: "2.1cm"}}} +{{figure {url: "img/canvas_path.png", alt: "Bir dizi dikey çizgiyi gösteren ekran görüntüsü", width: "2.1cm"}}} if}} {{index [path, canvas], filling, [path, closing], "fill method"}} -When filling a path (using the `fill` method), each ((shape)) is filled separately. A path can contain multiple shapes—each `moveTo` motion starts a new one. But the path needs to be _closed_ (meaning its start and end are in the same position) before it can be filled. If the path is not already closed, a line is added from its end to its start, and the shape enclosed by the completed path is filled. +Bir yol doldurulurken (`fill` yöntemi kullanılarak), her ((shape)) ayrı ayrı doldurulur. Bir yol birden fazla şekil içerebilir - her `moveTo` hareketi yeni bir tane başlatır. Ancak yolun doldurulabilmesi için önce _kapalı_ olması (yani başlangıç ve bitişinin aynı konumda olması) gerekir. Yol zaten kapalı değilse, sonundan başlangıcına bir çizgi eklenir ve tamamlanan yol tarafından çevrelenen şekil doldurulur. ```{lang: html} <canvas></canvas> @@ -200,27 +200,27 @@ When filling a path (using the `fill` method), each ((shape)) is filled separate </script> ``` -This example draws a filled triangle. Note that only two of the triangle's sides are explicitly drawn. The third, from the bottom-right corner back to the top, is implied and wouldn't be there when you stroke the path. +Bu örnekte içi dolu bir üçgen çizilmektedir. Üçgenin kenarlarından yalnızca ikisinin açıkça çizildiğine dikkat edin. Üçüncüsü, sağ alt köşeden yukarıya doğru, ima edilmiştir ve yolu vurduğunuzda orada olmayacaktır. {{if book -{{figure {url: "img/canvas_triangle.png", alt: "Screenshot showing a filled path", width: "2.2cm"}}} +{{figure {url: "img/canvas_triangle.png", alt: "Doldurulmuş bir yolu gösteren ekran görüntüsü", width: "2.2cm"}}} if}} {{index "stroke method", "closePath method", [path, closing], canvas}} -You could also use the `closePath` method to explicitly close a path by adding an actual ((line)) segment back to the path's start. This segment _is_ drawn when stroking the path. +Ayrıca, yolun başlangıcına gerçek bir ((çizgi)) segment ekleyerek bir yolu açıkça kapatmak için `closePath` yöntemini de kullanabilirsiniz. Bu parça, yola vurulduğunda \_çizilir. -## Curves +## Eğriler {{index [path, canvas], canvas, drawing}} -A path may also contain ((curve))d ((line))s. These are unfortunately a bit more involved to draw. +Bir yol ayrıca ((eğri))d ((çizgi))ler de içerebilir. Bunların çizimi ne yazık ki biraz daha karmaşıktır. {{index "quadraticCurveTo method"}} -The `quadraticCurveTo` method draws a curve to a given point. To determine the curvature of the line, the method is given a ((control point)) as well as a destination point. Imagine this control point as _attracting_ the line, giving it its curve. The line won't go through the control point, but its direction at the start and end points will be such that a straight line in that direction would point toward the control point. The following example illustrates this: +`quadraticCurveTo` yöntemi, verilen bir noktaya bir eğri çizer. Çizginin eğriliğini belirlemek için, yönteme bir hedef noktasının yanı sıra bir ((kontrol noktası)) verilir. Bu kontrol noktasını çizgiyi _çeken_ ve ona eğrisini veren nokta olarak düşünün. Çizgi kontrol noktasından geçmeyecektir, ancak başlangıç ve bitiş noktalarındaki yönü, o yöndeki düz bir çizginin kontrol noktasını göstereceği şekilde olacaktır. Aşağıdaki örnek bunu göstermektedir: ```{lang: html} <canvas></canvas> @@ -228,7 +228,7 @@ The `quadraticCurveTo` method draws a curve to a given point. To determine the c let cx = document.querySelector("canvas").getContext("2d"); cx.beginPath(); cx.moveTo(10, 90); - // control=(60,10) goal=(90,90) + // control=(60, 10) goal=(90, 90) cx.quadraticCurveTo(60, 10, 90, 90); cx.lineTo(60, 10); cx.closePath(); @@ -238,19 +238,19 @@ The `quadraticCurveTo` method draws a curve to a given point. To determine the c {{if book -It produces a path that looks like this: +Şuna benzeyen bir yol üretir: -{{figure {url: "img/canvas_quadraticcurve.png", alt: "Screenshot of a quadratic curve", width: "2.3cm"}}} +{{figure {url: "img/canvas_quadraticcurve.png", alt: "İkinci dereceden bir eğrinin ekran görüntüsü", width: "2.3cm"}}} if}} {{index "stroke method"}} -We draw a ((quadratic curve)) from the left to the right, with (60,10) as control point, and then draw two ((line)) segments going through that control point and back to the start of the line. The result somewhat resembles a _((Star Trek))_ insignia. You can see the effect of the control point: the lines leaving the lower corners start off in the direction of the control point and then ((curve)) toward their target. +Kontrol noktası (60,10) olacak şekilde soldan sağa doğru bir ((ikinci dereceden eğri)) çiziyoruz ve ardından bu kontrol noktasından geçip doğrunun başlangıcına geri dönen iki ((doğru)) parçası çiziyoruz. Sonuç biraz _((Star Trek))_ amblemine benziyor. Kontrol noktasının etkisini görebilirsiniz: alt köşelerden çıkan çizgiler kontrol noktası yönünde başlar ve sonra hedeflerine doğru ((eğrilir)). {{index canvas, "bezierCurveTo method"}} -The `bezierCurveTo` method draws a similar kind of curve. Instead of a single ((control point)), this one has two—one for each of the ((line))'s endpoints. Here is a similar sketch to illustrate the behavior of such a curve: +`bezierCurveTo` yöntemi de benzer türde bir eğri çizer. Tek bir ((kontrol noktası)) yerine, bunun iki tane ((çizgi))'nin uç noktalarının her biri için bir tane vardır. İşte böyle bir eğrinin davranışını göstermek için benzer bir taslak: ```{lang: html} <canvas></canvas> @@ -258,7 +258,7 @@ The `bezierCurveTo` method draws a similar kind of curve. Instead of a single (( let cx = document.querySelector("canvas").getContext("2d"); cx.beginPath(); cx.moveTo(10, 90); - // control1=(10,10) control2=(90,10) goal=(50,90) + // control1=(10, 10) control2=(90, 10) goal=(50, 90) cx.bezierCurveTo(10, 10, 90, 10, 50, 90); cx.lineTo(90, 10); cx.lineTo(10, 10); @@ -267,34 +267,34 @@ The `bezierCurveTo` method draws a similar kind of curve. Instead of a single (( </script> ``` -The two control points specify the direction at both ends of the curve. The farther they are away from their corresponding point, the more the curve will "bulge" in that direction. +İki kontrol noktası eğrinin her iki ucundaki yönü belirler. Karşılık gelen noktadan ne kadar uzakta olurlarsa, eğri o yönde o kadar fazla "çıkıntı" yapacaktır. {{if book -{{figure {url: "img/canvas_beziercurve.png", alt: "Screenshot of a bezier curve", width: "2.2cm"}}} +{{figure {url: "img/canvas_beziercurve.png", alt: "Bir bezier eğrisinin ekran görüntüsü", width: "2.2cm"}}} if}} {{index "trial and error"}} -Such ((curve))s can be hard to work with—it's not always clear how to find the ((control point))s that provide the ((shape)) you are looking for. Sometimes you can compute them, and sometimes you'll just have to find a suitable value by trial and error. +Bu tür ((eğri))lerle çalışmak zor olabilir - aradığınız ((şekli)) sağlayan ((kontrol noktası))ları nasıl bulacağınız her zaman net değildir. Bazen bunları hesaplayabilirsiniz, bazen de deneme yanılma yoluyla uygun bir değer bulmanız gerekir. {{index "arc method", arc}} -The `arc` method is a way to draw a line that curves along the edge of a circle. It takes a pair of ((coordinates)) for the arc's center, a radius, and then a start angle and end angle. +`arc` yöntemi, bir dairenin kenarı boyunca kıvrılan bir çizgi çizmenin bir yoludur. Yay merkezi için bir çift ((koordinat)), bir yarıçap ve ardından bir başlangıç açısı ve bitiş açısı alır. {{index pi, "Math.PI constant"}} -Those last two parameters make it possible to draw only part of the circle. The ((angle))s are measured in ((radian))s, not ((degree))s. This means a full ((circle)) has an angle of 2π, or `2 * Math.PI`, which is about 6.28. The angle starts counting at the point to the right of the circle's center and goes clockwise from there. You can use a start of 0 and an end bigger than 2π (say, 7) to draw a full circle. +Bu son iki parametre dairenin sadece bir kısmını çizmeyi mümkün kılar. ((açı))lar ((derece))lerle değil ((radyan))larla ölçülür. Bu, tam bir ((daire))'nin 2π veya `2 * Math.PI` açısına sahip olduğu anlamına gelir, bu da yaklaşık 6.28'dir. Açı, dairenin merkezinin sağındaki noktadan saymaya başlar ve oradan saat yönünde ilerler. Tam bir daire çizmek için 0'lık bir başlangıç ve 2π'den büyük bir son (örneğin 7) kullanabilirsiniz. ```{lang: html} <canvas></canvas> <script> let cx = document.querySelector("canvas").getContext("2d"); cx.beginPath(); - // center=(50,50) radius=40 angle=0 to 7 + // center=(50, 50) radius=40 angle=0 to 7 cx.arc(50, 50, 40, 0, 7); - // center=(150,50) radius=40 angle=0 to ½π + // center=(150, 50) radius=40 angle=0 to ½π cx.arc(150, 50, 40, 0, 0.5 * Math.PI); cx.stroke(); </script> @@ -302,23 +302,25 @@ Those last two parameters make it possible to draw only part of the circle. The {{index "moveTo method", "arc method", [path, " canvas"]}} -The resulting picture contains a ((line)) from the right of the full circle (first call to `arc`) to the right of the quarter-((circle)) (second call). Like other path-drawing methods, a line drawn with `arc` is connected to the previous path segment. You can call `moveTo` or start a new path to avoid this. +Sonuçta ortaya çıkan resim, tam dairenin sağından (`arc`'a ilk çağrı) çeyrek-((daire))'nin sağına (ikinci çağrı) bir ((çizgi)) içerir. Diğer yol çizme yöntemlerinde olduğu gibi, `arc` ile çizilen bir çizgi bir önceki yol parçasına bağlanır. Bunu önlemek için `moveTo` çağrısı yapabilir veya yeni bir yol başlatabilirsiniz. {{if book -{{figure {url: "img/canvas_circle.png", alt: "Screenshot of a circle", width: "4.9cm"}}} +{{figure {url: "img/canvas_circle.png", alt: "Bir dairenin ekran görüntüsü", width: "4.9cm"}}} if}} +Like other path-drawing methods, a line drawn with `arc` is connected to the previous path segment.You can call `moveTo` or start a new path to avoid this. + {{id pie_chart}} -## Drawing a pie chart +## Pasta grafiği çizme {{index "pie chart example"}} -Imagine you've just taken a ((job)) at EconomiCorp, Inc., and your first assignment is to draw a pie chart of its customer satisfaction ((survey)) results. +EconomiCorp, Inc. şirketinde yeni bir ((iş)) aldığınızı ve ilk görevinizin müşteri memnuniyeti ((anket)) sonuçlarının bir pasta grafiğini çizmek olduğunu düşünün. -The `results` binding contains an array of objects that represent the survey responses. +`results` bağlayıcısı, anket yanıtlarını temsil eden bir dizi nesne içerir. ```{sandbox: "pie", includeCode: true} const results = [ @@ -331,7 +333,7 @@ const results = [ {{index "pie chart example"}} -To draw a pie chart, we draw a number of pie slices, each made up of an ((arc)) and a pair of ((line))s to the center of that arc. We can compute the ((angle)) taken up by each arc by dividing a full circle (2π) by the total number of responses and then multiplying that number (the angle per response) by the number of people who picked a given choice. +Bir pasta grafiği çizmek için, her biri bir ((yay)) ve bu yayın merkezine bir çift ((çizgi))'den oluşan bir dizi pasta dilimi çizeriz. Tam bir daireyi (2π) toplam yanıt sayısına bölerek ve ardından bu sayıyı (yanıt başına açı) belirli bir seçeneği işaretleyen kişi sayısıyla çarparak her bir yay tarafından kaplanan ((açıyı)) hesaplayabiliriz. ```{lang: html, sandbox: "pie"} <canvas width="200" height="200"></canvas> @@ -358,15 +360,15 @@ To draw a pie chart, we draw a number of pie slices, each made up of an ((arc)) {{if book -This draws the following chart: +Bu, aşağıdaki tabloyu çizer: -{{figure {url: "img/canvas_pie_chart.png", alt: "Screenshot showing a pie chart", width: "5cm"}}} +{{figure {url: "img/canvas_pie_chart.png", alt: "Pasta grafiğini gösteren ekran görüntüsü", width: "5cm"}}} if}} -But a chart that doesn't tell us what the slices mean isn't very helpful. We need a way to draw text to the ((canvas)). +Ancak dilimlerin ne anlama geldiğini bize söylemeyen bir grafik çok yararlı değildir. Metni ((tuval)) üzerine çizmek için bir yola ihtiyacımız var. -## Text +## Metin {{index stroking, filling, "fillStyle property", "fillText method", "strokeText method"}} @@ -382,25 +384,25 @@ A 2D canvas drawing context provides the methods `fillText` and `strokeText`. Th </script> ``` -You can specify the size, style, and ((font)) of the text with the `font` property. This example just gives a font size and family name. It is also possible to add `italic` or `bold` to the start of the string to select a style. +2B tuval çizim bağlamı `fillText` ve `strokeText` yöntemlerini sağlar. İkincisi harflerin ana hatlarını çizmek için yararlı olabilir, ancak genellikle ihtiyacınız olan şey `fillText`tir. Verilen ((metin)) ana hatlarını geçerli `fillStyle` ile dolduracaktır. -{{index "fillText method", "strokeText method", "textAlign property", "textBaseline property"}} +Metnin boyutunu, stilini ve ((yazı tipi)) `font` özelliği ile belirtebilirsiniz. Bu örnek sadece bir yazı tipi boyutu ve aile adı verir. Bir stil seçmek için dizenin başına `italic` veya `bold` eklemek de mümkündür. -The last two arguments to `fillText` and `strokeText` provide the position at which the font is drawn. By default, they indicate the position of the start of the text's alphabetic baseline, which is the line that letters "stand" on, not counting hanging parts in letters such as _j_ or _p_. You can change the horizontal position by setting the `textAlign` property to `"end"` or `"center"` and the vertical position by setting `textBaseline` to `"top"`, `"middle"`, or `"bottom"`. +`fillText` ve `strokeText` için son iki bağımsız değişken, yazı tipinin çizileceği konumu sağlar. Varsayılan olarak, metnin alfabetik taban çizgisinin başlangıcının konumunu belirtirler; bu, _j_ veya _p_ gibi harflerdeki asılı kısımları saymazsak, harflerin "üzerinde durduğu" çizgidir. Yatay konumu `textAlign` özelliğini `"end"` veya `"center"` olarak ayarlayarak, dikey konumu ise `textBaseline` özelliğini `"top"`, `"middle"` veya `"bottom"` olarak ayarlayarak değiştirebilirsiniz. {{index "pie chart example"}} -We'll come back to our pie chart, and the problem of ((label))ing the slices, in the [exercises](canvas#exercise_pie_chart) at the end of the chapter. +Pasta grafiğimize ve dilimleri ((etiketleme)) sorununa bölümün sonundaki [alıştırmalar](canvas#exercise_pie_chart) kısmında geri döneceğiz. -## Images +## Görüntüler {{index "vector graphics", "bitmap graphics"}} -In computer ((graphics)), a distinction is often made between _vector_ graphics and _bitmap_ graphics. The first is what we have been doing so far in this chapter—specifying a picture by giving a logical description of ((shape))s. Bitmap graphics, on the other hand, don't specify actual shapes but rather work with ((pixel)) data (rasters of colored dots). +Bilgisayar ((grafikleri))nde, _vektör_ grafikleri ve _bitmap_ grafikleri arasında genellikle bir ayrım yapılır. İlk olarak bu bölümde şu ana kadar yaptığımız şey, bir resmi ((şekil))lerin mantıksal bir tanımını vererek belirlemektir. Öte yandan, bitmap grafikleri, gerçek şekilleri belirtmez, bunun yerine ((piksel)) verileriyle (renkli noktaların rastraları) çalışır. {{index "load event", "event handling", "img (HTML tag)", "drawImage method"}} -The `drawImage` method allows us to draw ((pixel)) data onto a ((canvas)). This pixel data can originate from an `<img>` element or from another canvas. The following example creates a detached `<img>` element and loads an image file into it. But it cannot immediately start drawing from this picture because the browser may not have loaded it yet. To deal with this, we register a `"load"` event handler and do the drawing after the image has loaded. +`drawImage` metodu, bir ((canvas)) üzerine ((piksel)) verisi çizmemizi sağlar. Bu piksel verisi bir `<img>` öğesinden veya başka bir canvas'tan gelebilir. Aşağıdaki örnek, bağımsız bir `<img>` öğesi oluşturur ve içine bir görüntü dosyası yükler. Ancak, bu resimden hemen çizmeye başlayamaz çünkü tarayıcı henüz yüklemeyi tamamlamamış olabilir. Bunu çözmek için bir `"load"` olay işleyicisi kaydederiz ve resim yüklendikten sonra çizimi yaparız. ```{lang: html} <canvas></canvas> @@ -418,27 +420,27 @@ The `drawImage` method allows us to draw ((pixel)) data onto a ((canvas)). This {{index "drawImage method", scaling}} -By default, `drawImage` will draw the image at its original size. You can also give it two additional arguments to set a different width and height. +Varsayılan olarak, `drawImage`, resmi orijinal boyutunda çizecektir. Ayrıca farklı bir genişlik ve yükseklik ayarlamak için iki ek argüman verebilirsiniz. -When `drawImage` is given _nine_ arguments, it can be used to draw only a fragment of an image. The second through fifth arguments indicate the rectangle (x, y, width, and height) in the source image that should be copied, and the sixth to ninth arguments give the rectangle (on the canvas) into which it should be copied. +`drawImage`'e _dokuz_ argüman verildiğinde, yalnızca bir resmin bir parçasını çizmek için kullanılabilir. İkinci ila beşinci argümanlar, kaynak görüntüde kopyalanması gereken dikdörtgeni (x, y, width ve height) belirtir ve altıncı ila dokuzuncu argümanlar, bunun kopyalanması gereken (canvas üzerindeki) dikdörtgeni belirtir. {{index "player", "pixel art"}} -This can be used to pack multiple _((sprite))s_ (image elements) into a single image file and then draw only the part you need. For example, we have this picture containing a game character in multiple ((pose))s: +Bu, birden fazla _((sprite))_ (görüntü öğesi) öğesini tek bir görüntü dosyasına sığdırmak ve ardından yalnızca ihtiyacınız olan kısmı çizmek için kullanılabilir. Örneğin, birden fazla ((poz))da oyun karakteri içeren bu resme sahibiz: -{{figure {url: "img/player_big.png", alt: "Pixel art showing a computer game character in 10 different poses. The first 8 form its running animation cycle, the 9th has the character standing still, and the 10th shows him jumping.", width: "6cm"}}} +{{figure {url: "img/player_big.png", alt: "Bir bilgisayar oyunu karakterini 10 farklı pozda gösteren piksel sanatı. İlk 8'i koşma animasyon döngüsünü oluşturuyor, 9'uncuda karakter hareketsiz duruyor ve 10'uncusu zıplamasını gösteriyor.", width: "6cm"}}} {{index [animation, "platform game"]}} -By alternating which pose we draw, we can show an animation that looks like a walking character. +Hangi pozu çizeceğimizi değiştirerek, yürüyen bir karakter gibi görünen bir animasyon gösterebiliriz. {{index "fillRect method", "clearRect method", clearing}} -To animate a ((picture)) on a ((canvas)), the `clearRect` method is useful. It resembles `fillRect`, but instead of coloring the rectangle, it makes it ((transparent)), removing the previously drawn pixels. +Bir ((tuval)) üzerindeki bir ((resmi)) canlandırmak için `clearRect` yöntemi kullanışlıdır. Bu yöntem `fillRect` yöntemine benzer, ancak dikdörtgeni renklendirmek yerine, önceden çizilmiş pikselleri kaldırarak ((saydam)) hale getirir. {{index "setInterval function", "img (HTML tag)"}} -We know that each _((sprite))_, each subpicture, is 24 ((pixel))s wide and 30 pixels high. The following code loads the image and then sets up an interval (repeated timer) to draw the next ((frame)): +Her _((sprite))_, her alt resmin 24 ((piksel)) genişliğinde ve 30 piksel yüksekliğinde olduğunu biliyoruz. Aşağıdaki kod görüntüyü yükler ve ardından bir sonraki ((frame)) çizmek için bir aralık (tekrarlanan zamanlayıcı) ayarlar: ```{lang: html} <canvas></canvas> @@ -464,19 +466,19 @@ We know that each _((sprite))_, each subpicture, is 24 ((pixel))s wide and 30 pi {{index "remainder operator", "% operator", [animation, "platform game"]}} -The `cycle` binding tracks our position in the animation. For each ((frame)), it is incremented and then clipped back to the 0 to 7 range by using the remainder operator. This binding is then used to compute the x-coordinate that the sprite for the current pose has in the picture. +`cycle` bağı, animasyondaki konumumuzu izler. Her bir ((kare)) için arttırılır ve ardından kalan operatörü kullanılarak 0 ile 7 aralığına geri döndürülür. Bu bağlam, mevcut poz için sprite'ın resimdeki x koordinatını hesaplamak için kullanılır. -## Transformation +## Dönüşüm {{index transformation, mirroring}} {{indexsee flipping, mirroring}} -But what if we want our character to walk to the left instead of to the right? We could draw another set of sprites, of course. But we can also instruct the ((canvas)) to draw the picture the other way round. +Peki ya karakterimizin sağa değil de sola yürümesini istersek? Elbette başka bir sprite seti çizebiliriz. Ancak ((canvas))'a resmi ters yönde çizmesini de söyleyebiliriz. {{index "scale method", scaling}} -Calling the `scale` method will cause anything drawn after it to be scaled. This method takes two parameters, one to set a horizontal scale and one to set a vertical scale. +`scale` metodunu çağırmak, ondan sonra çizilen her şeyin ölçeklenmesine neden olur. Bu metod iki parametre alır: biri yatay ölçeği, diğeri dikey ölçeği ayarlamak için kullanılır. ```{lang: html} <canvas></canvas> @@ -492,37 +494,37 @@ Calling the `scale` method will cause anything drawn after it to be scaled. This {{if book -Because of the call to `scale`, the circle is drawn three times as wide and half as high. +`scale` çağrısından dolayı, daire üç kat geniş ve yarı yüksek olarak çizilir. -{{figure {url: "img/canvas_scale.png", alt: "Screenshot of a scaled circle", width: "6.6cm"}}} +{{figure {url: "img/canvas_scale.png", alt: "Ölçeklendirilmiş bir dairenin ekran görüntüsü", width: "6.6cm"}}} if}} {{index mirroring}} -Scaling will cause everything about the drawn image, including the ((line width)), to be stretched out or squeezed together as specified. Scaling by a negative amount will flip the picture around. The flipping happens around point (0,0), which means it will also flip the direction of the coordinate system. When a horizontal scaling of -1 is applied, a shape drawn at x position 100 will end up at what used to be position -100. +Ölçekleme, çizilen resimdeki her şeyi, ((çizgi genişliği)) de dahil olmak üzere belirtilen şekilde genişletir veya sıkıştırır. Negatif bir miktarla ölçekleme yapmak resmi ters çevirir. Ters çevirme, (0,0) noktasında gerçekleşir, bu da koordinat sisteminin yönünü de tersine çevireceği anlamına gelir. -1 yatay ölçek uygulandığında, x konumunda 100 olan bir şekil, artık -100 olan konumda sona erer. {{index "drawImage method"}} -So to turn a picture around, we can't simply add `cx.scale(-1, 1)` before the call to `drawImage` because that would move our picture outside of the ((canvas)), where it won't be visible. You could adjust the ((coordinates)) given to `drawImage` to compensate for this by drawing the image at x position -50 instead of 0. Another solution, which doesn't require the code that does the drawing to know about the scale change, is to adjust the ((axis)) around which the scaling happens. +Bu nedenle, bir resmi ters çevirmek için `drawImage` çağrısından önce basitçe `cx.scale(-1, 1)` ekleyemeyiz çünkü bu, resmimizi ((canvas)) dışına taşıyacak ve bu da görünmez olmasına neden olacaktır. Bu durumu telafi etmek için resmi x konumunda 0 yerine -50'de çizerek `drawImage`'a verilen ((koordinatları)) ayarlayabilirsiniz. Çizim yapan kodun ölçek değişikliğinden haberdar olmasını gerektirmeyen bir başka çözüm ise ölçeklemenin gerçekleştiği ((eksen))i ayarlamaktır. {{index "rotate method", "translate method", transformation}} -There are several other methods besides `scale` that influence the coordinate system for a ((canvas)). You can rotate subsequently drawn shapes with the `rotate` method and move them with the `translate` method. The interesting—and confusing—thing is that these transformations _stack_, meaning that each one happens relative to the previous transformations. +`scale` dışında, bir ((canvas)) için koordinat sistemini etkileyen birkaç başka metod daha vardır. `rotate` metodunu kullanarak daha sonra çizilen şekilleri döndürebilir ve `translate` metodu ile onları hareket ettirebilirsiniz. İlginç—ve kafa karıştırıcı—olan şey, bu dönüşümlerin _üst üste binmesi_, yani her birinin önceki dönüşümlere göre gerçekleşmesidir. {{index "rotate method", "translate method"}} -So if we translate by 10 horizontal pixels twice, everything will be drawn 20 pixels to the right. If we first move the center of the coordinate system to (50,50) and then rotate by 20 ((degree))s (about 0.1π ((radian))s), that rotation will happen _around_ point (50,50). +Yani, iki kez 10 yatay piksel kadar öteleme yaparsak, her şey sağa doğru 20 piksel kaydırılacaktır. İlk olarak koordinat sisteminin merkezini (50,50) noktasına taşıyıp ardından 20 ((derece)) (yaklaşık 0.1π ((radyan))) döndürürsek, bu döndürme _(50,50) noktası etrafında_ gerçekleşecektir. -{{figure {url: "img/transform.svg", alt: "Diagram showing the result of stacking transformations. The first diagram translates and then rotates, causing the translation to happen normally and rotation to happen around the target of the translation. The second diagram first rotates, and then translates, causing the rotation to happen around the origin and the translation direction to be tilted by that rotation.", width: "9cm"}}} +{{figure {url: "img/transform.svg", alt: "Dönüşümlerin üst üste binmesinin sonucunu gösteren diyagram. İlk diyagram, önce öteleme yapar ve ardından döndürme yapar, bu da ötelemenin normal şekilde gerçekleşmesine ve döndürmenin ötelemenin hedefi etrafında gerçekleşmesine neden olur. İkinci diyagram, önce döndürür ve ardından öteleme yapar, bu da döndürmenin orijin etrafında olmasına ve öteleme yönünün bu döndürme ile eğilmesine neden olur.", width: "9cm"}}} {{index coordinates}} -But if we _first_ rotate by 20 degrees and _then_ translate by (50,50), the translation will happen in the rotated coordinate system and thus produce a different orientation. The order in which transformations are applied matters. +Ancak önce 20 derece döndürme ve _sonra_ (50,50) öteleme yaparsak, öteleme döndürülmüş koordinat sisteminde gerçekleşir ve böylece farklı bir yönlenme oluşturur. Dönüşümlerin uygulanma sırası önemlidir. {{index axis, mirroring}} -To flip a picture around the vertical line at a given x position, we can do the following: +Belirli bir x konumundaki dikey çizgi etrafında bir resmi ters çevirmek için şu adımları izleyebiliriz: ```{includeCode: true} function flipHorizontally(context, around) { @@ -534,15 +536,15 @@ function flipHorizontally(context, around) { {{index "flipHorizontally method"}} -We move the y-((axis)) to where we want our ((mirror)) to be, apply the mirroring, and finally move the y-axis back to its proper place in the mirrored universe. The following picture explains why this works: +Y-((ekseni))ni aynanın olması gereken yere taşıyoruz, aynalamayı uyguluyoruz ve son olarak y-ekseni aynalanmış evrendeki doğru yerine geri taşıyoruz. Aşağıdaki resim bunun neden işe yaradığını açıklıyor: -{{figure {url: "img/mirror.svg", alt: "Diagram showing the effect of translating and mirroring a triangle", width: "8cm"}}} +{{figure {url: "img/mirror.svg", alt: "Üçgenin taşınması ve aynalanmasının etkisini gösteren diyagram", width: "8cm"}}} {{index "translate method", "scale method", transformation, canvas}} -This shows the coordinate systems before and after mirroring across the central line. The triangles are numbered to illustrate each step. If we draw a triangle at a positive x position, it would, by default, be in the place where triangle 1 is. A call to `flipHorizontally` first does a translation to the right, which gets us to triangle 2. It then scales, flipping the triangle over to position 3. This is not where it should be, if it were mirrored in the given line. The second `translate` call fixes this—it "cancels" the initial translation and makes triangle 4 appear exactly where it should. +Bu, merkez çizgi boyunca aynalanmadan önce ve sonraki koordinat sistemlerini gösterir. Üçgenler, her adımı açıklamak için numaralandırılmıştır. Eğer pozitif bir x konumunda bir üçgen çizersek, varsayılan olarak üçgen 1'in bulunduğu yerde olurdu. `flipHorizontally` çağrısı ilk olarak sağa doğru bir öteleme yapar, bu da bizi üçgen 2'ye getirir. Ardından ölçeklendirme yapılır ve üçgeni pozisyon 3'e çevirir. Bu, verilen çizgide aynalanmış olması durumunda olması gereken yer değildir. İkinci `translate` çağrısı bunu düzeltir—ilk ötelemeyi "iptal eder" ve üçgen 4'ü tam olarak olması gereken yere getirir. -We can now draw a mirrored character at position (100,0) by flipping the world around the character's vertical center. +Şimdi, karakterin dikey merkezi etrafında dünyayı çevirerek (100,0) konumunda aynalanmış bir karakter çizebiliriz. ```{lang: html} <canvas></canvas> @@ -559,23 +561,23 @@ We can now draw a mirrored character at position (100,0) by flipping the world a </script> ``` -## Storing and clearing transformations +## Dönüşümlerin depolanması ve temizlenmesi {{index "side effect", canvas, transformation}} -Transformations stick around. Everything else we draw after ((drawing)) that mirrored character would also be mirrored. That might be inconvenient. +Dönüşümler kalıcıdır. Aynalanmış karakteri çizdikten sonra çizdiğimiz her şey de aynalanmış olacaktır. Bu, rahatsız edici olabilir. -It is possible to save the current transformation, do some drawing and transforming, and then restore the old transformation. This is usually the proper thing to do for a function that needs to temporarily transform the coordinate system. First, we save whatever transformation the code that called the function was using. Then the function does its thing, adding more transformations on top of the current transformation. Finally, we revert to the transformation we started with. +Geçerli dönüşümü kaydedip, bazı çizimler ve dönüşümler yapıp, ardından eski dönüşümü geri yüklemek mümkündür. Bu, genellikle koordinat sistemini geçici olarak dönüştürmesi gereken bir fonksiyon için yapılması gereken uygun bir işlemdir. İlk olarak, fonksiyonu çağıran kodun kullandığı dönüşüm ne olursa olsun kaydedilir. Ardından, fonksiyon kendi işlemlerini yapar ve mevcut dönüşümün üzerine daha fazla dönüşüm ekler. Son olarak, başladığımız dönüşüme geri döneriz. {{index "save method", "restore method", [state, "of canvas"]}} -The `save` and `restore` methods on the 2D ((canvas)) context do this ((transformation)) management. They conceptually keep a stack of transformation states. When you call `save`, the current state is pushed onto the stack, and when you call `restore`, the state on top of the stack is taken off and used as the context's current transformation. You can also call `resetTransform` to fully reset the transformation. +2D ((canvas)) bağlamındaki `save` ve `restore` metodları, bu ((dönüşüm)) yönetimini yapar. Kavramsal olarak, bir dönüşüm durumu yığını tutarlar. `save` çağrıldığında, mevcut durum yığına itilir ve `restore` çağrıldığında, yığının üstündeki durum alınır ve bağlamın geçerli dönüşümü olarak kullanılır. Ayrıca `resetTransform` çağrısıyla dönüşümü tamamen sıfırlayabilirsiniz. {{index "branching recursion", "fractal example", recursion}} -The `branch` function in the following example illustrates what you can do with a function that changes the transformation and then calls a function (in this case itself), which continues drawing with the given transformation. +Aşağıdaki örnekteki `branch` fonksiyonu, dönüşümü değiştiren ve ardından (bu durumda kendisi) bir fonksiyonu çağıran bir fonksiyonla neler yapabileceğinizi gösterir. Bu fonksiyon, verilen dönüşümle çizim yapmaya devam eder. -This function draws a treelike shape by drawing a line, moving the center of the coordinate system to the end of the line, and calling itself twice—first rotated to the left and then rotated to the right. Every call reduces the length of the branch drawn, and the recursion stops when the length drops below 8. +Bu fonksiyon, bir çizgi çizerek, koordinat sisteminin merkezini çizginin sonuna taşıyarak ve kendisini iki kez çağırarak—ilk önce sola, sonra sağa döndürerek—ağaç benzeri bir şekil çizer. Her çağrı, çizilen dalın uzunluğunu azaltır ve uzunluk 8'in altına düştüğünde özyineleme durur. ```{lang: html} <canvas width="600" height="300"></canvas> @@ -599,31 +601,31 @@ This function draws a treelike shape by drawing a line, moving the center of the {{if book -The result is a simple fractal. +Sonuç, basit bir fraktal olur. -{{figure {url: "img/canvas_tree.png", alt: "Screenshot of a fractal", width: "5cm"}}} +{{figure {url: "img/canvas_tree.png", alt: "Fraktalın ekran görüntüsü", width: "5cm"}}} if}} {{index "save method", "restore method", canvas, "rotate method"}} -If the calls to `save` and `restore` were not there, the second recursive call to `branch` would end up with the position and rotation created by the first call. It wouldn't be connected to the current branch but rather to the innermost, rightmost branch drawn by the first call. The resulting shape might also be interesting, but it is definitely not a tree. +Eğer `save` ve `restore` çağrıları olmasaydı, `branch` fonksiyonunun ikinci özyinelemeli çağrısı, ilk çağrı tarafından oluşturulan konum ve döndürme ile sonuçlanırdı. Mevcut dala bağlı olmazdı, bunun yerine ilk çağrı tarafından çizilen en içteki, en sağdaki dala bağlı olurdu. Ortaya çıkan şekil de ilginç olabilir, ancak kesinlikle bir ağaç olmazdı. {{id canvasdisplay}} -## Back to the game +## Oyuna geri dönelim {{index "drawImage method"}} -We now know enough about ((canvas)) drawing to start working on a ((canvas))-based ((display)) system for the ((game)) from the [previous chapter](game). The new display will no longer be showing just colored boxes. Instead, we'll use `drawImage` to draw pictures that represent the game's elements. +Artık ((canvas)) çizimi hakkında yeterince bilgiye sahibiz, [önceki bölümdeki](game) ((oyun)) için ((canvas)) tabanlı bir ((görüntüleme)) sistemi üzerinde çalışmaya başlayabiliriz. Yeni görüntüleme sistemi artık sadece renkli kutular göstermeyecek. Bunun yerine, oyunun öğelerini temsil eden resimleri çizmek için `drawImage` kullanacağız. {{index "CanvasDisplay class", "DOMDisplay class", [interface, object]}} -We define another display object type called `CanvasDisplay`, supporting the same interface as `DOMDisplay` from [Chapter ?](game#domdisplay), namely, the methods `syncState` and `clear`. +`DOMDisplay` gibi bir arabirimi destekleyen, `CanvasDisplay` adında başka bir görüntüleme nesne türü tanımlıyoruz, yani `syncState` ve `clear` metodları. {{index [state, "in objects"]}} -This object keeps a little more information than `DOMDisplay`. Rather than using the scroll position of its DOM element, it tracks its own ((viewport)), which tells us what part of the level we are currently looking at. Finally, it keeps a `flipPlayer` property so that even when the player is standing still, it keeps facing the direction it last moved in. +Bu nesne, `DOMDisplay`'den biraz daha fazla bilgi tutar. DOM öğesinin kaydırma konumunu kullanmak yerine, şu anda seviyenin hangi bölümüne baktığımızı bize bildiren kendi ((görünüm alanını)) izler. Son olarak, oyuncu sabit durduğunda bile son hareket ettiği yöne bakmasını sağlamak için bir `flipPlayer` özelliği tutar. ```{sandbox: "game", includeCode: true} class CanvasDisplay { @@ -650,7 +652,7 @@ class CanvasDisplay { } ``` -The `syncState` method first computes a new viewport and then draws the game scene at the appropriate position. +`syncState` metodu, önce yeni bir görünüm alanı (viewport) hesaplar ve ardından oyun sahnesini uygun konumda çizer. ```{sandbox: "game", includeCode: true} CanvasDisplay.prototype.syncState = function(state) { @@ -663,11 +665,11 @@ CanvasDisplay.prototype.syncState = function(state) { {{index scrolling, clearing}} -Contrary to `DOMDisplay`, this display style _does_ have to redraw the background on every update. Because shapes on a canvas are just ((pixel))s, after we draw them there is no good way to move them (or remove them). The only way to update the canvas display is to clear it and redraw the scene. We may also have scrolled, which requires the background to be in a different position. +`DOMDisplay`'in aksine, bu görüntüleme stili her güncellemede arka planı yeniden çizmek zorundadır. Çünkü bir canvas üzerindeki şekiller sadece ((piksel))lerden oluşur; onları çizdikten sonra hareket ettirmek veya kaldırmak için iyi bir yol yoktur. Canvas görüntülemeyi güncellemenin tek yolu, canvas'ı temizlemek ve sahneyi yeniden çizmektir. Ayrıca kaydırma yapmış olabiliriz, bu da arka planın farklı bir konumda olmasını gerektirir. {{index "CanvasDisplay class"}} -The `updateViewport` method is similar to `DOMDisplay`'s `scrollPlayerIntoView` method. It checks whether the player is too close to the edge of the screen and moves the ((viewport)) when this is the case. +`updateViewport` metodu, `DOMDisplay`'in `scrollPlayerIntoView` metoduna benzer. Oyuncunun ekranın kenarına çok yakın olup olmadığını kontrol eder ve bu durumda ((görünüm alanını)) hareket ettirir. ```{sandbox: "game", includeCode: true} CanvasDisplay.prototype.updateViewport = function(state) { @@ -692,9 +694,9 @@ CanvasDisplay.prototype.updateViewport = function(state) { {{index boundary, "Math.max function", "Math.min function", clipping}} -The calls to `Math.max` and `Math.min` ensure that the viewport does not end up showing space outside of the level. `Math.max(x, 0)` makes sure the resulting number is not less than zero. `Math.min` similarly guarantees that a value stays below a given bound. +`Math.max` ve `Math.min` çağrıları, görünüm alanının seviyenin dışındaki alanı göstermemesini sağlar. `Math.max(x, 0)`, elde edilen sayının sıfırdan küçük olmadığından emin olur. Benzer şekilde, `Math.min` bir değerin belirli bir sınırın altında kalmasını garanti eder. -When ((clearing)) the display, we'll use a slightly different ((color)) depending on whether the game is won (brighter) or lost (darker). +Görüntüleme ((temizlenirken)), oyunun kazanılıp kazanılmadığına bağlı olarak (kazanıldıysa daha parlak, kaybedildiyse daha koyu) biraz farklı bir ((renk)) kullanacağız. ```{sandbox: "game", includeCode: true} CanvasDisplay.prototype.clearDisplay = function(status) { @@ -712,7 +714,7 @@ CanvasDisplay.prototype.clearDisplay = function(status) { {{index "Math.floor function", "Math.ceil function", rounding}} -To draw the background, we run through the tiles that are visible in the current viewport, using the same trick used in the `touches` method from the [previous chapter](game#touches). +Arka planı çizmek için, [önceki bölümdeki](game#touches) `touches` metodunda kullanılan aynı yöntemi kullanarak, mevcut görünüm alanında görünen fayanslar arasında dolaşırız. Bu sayede sadece görünüm alanında olan fayanslar işlenir ve çizilir. ```{sandbox: "game", includeCode: true} let otherSprites = document.createElement("img"); @@ -742,25 +744,25 @@ CanvasDisplay.prototype.drawBackground = function(level) { {{index "drawImage method", sprite, tile}} -Tiles that are not empty are drawn with `drawImage`. The `otherSprites` image contains the pictures used for elements other than the player. It contains, from left to right, the wall tile, the lava tile, and the sprite for a coin. +Boş olmayan fayanslar `drawImage` ile çizilir. `otherSprites` resmi, oyuncu dışında kalan öğeler için kullanılan resimleri içerir. Soldan sağa, duvar fayansı, lav fayansı ve bir para sprite'ı içerir. -{{figure {url: "img/sprites_big.png", alt: "Pixel art showing three sprites: a piece of wall, made out of small white stones, a square of orange lava, and a round coin.", width: "1.4cm"}}} +{{figure {url: "img/sprites_big.png", alt: "Piksel sanatı, üç sprite'ı gösteriyor: küçük beyaz taşlardan yapılmış bir duvar parçası, bir kare turuncu lav ve yuvarlak bir para.", width: "1.4cm"}}} {{index scaling}} -Background tiles are 20 by 20 pixels since we will use the same scale that we used in `DOMDisplay`. Thus, the offset for lava tiles is 20 (the value of the `scale` binding), and the offset for walls is 0. +Arka plan fayansları 20 x 20 pikseldir, çünkü `DOMDisplay`'de kullandığımız ölçeği (scale) aynı şekilde kullanacağız. Bu nedenle, lav fayanslarının kaydırma değeri 20'dir (`scale` bağlamının değeri) ve duvarlar için kaydırma değeri 0'dır. {{index drawing, "load event", "drawImage method"}} -We don't bother waiting for the sprite image to load. Calling `drawImage` with an image that hasn't been loaded yet will simply do nothing. Thus, we might fail to draw the game properly for the first few ((frame))s, while the image is still loading, but that is not a serious problem. Since we keep updating the screen, the correct scene will appear as soon as the loading finishes. +Sprite resmi yüklenmesini beklemiyoruz. Henüz yüklenmemiş bir resimle `drawImage` çağrısı yapmak, hiçbir şey yapmaz. Bu nedenle, resim hala yüklenirken ilk birkaç ((kare))de oyunu doğru şekilde çizemeyebiliriz, ancak bu ciddi bir sorun değildir. Ekranı sürekli olarak güncellediğimiz için yükleme tamamlandığında doğru sahne görünecektir. {{index "player", [animation, "platform game"], drawing}} -The ((walking)) character shown earlier will be used to represent the player. The code that draws it needs to pick the right ((sprite)) and direction based on the player's current motion. The first eight sprites contain a walking animation. When the player is moving along a floor, we cycle through them based on the current time. We want to switch frames every 60 milliseconds, so the ((time)) is divided by 60 first. When the player is standing still, we draw the ninth sprite. During jumps, which are recognized by the fact that the vertical speed is not zero, we use the tenth, rightmost sprite. +Daha önce gösterilen ((yürüyen)) karakter, oyuncuyu temsil etmek için kullanılacaktır. Bunu çizen kod, oyuncunun mevcut hareketine göre doğru ((sprite))'ı ve yönü seçmelidir. İlk sekiz sprite, bir yürüme animasyonu içerir. Oyuncu bir zeminde hareket ederken, mevcut zamana göre bu animasyon kareleri arasında geçiş yaparız. Kareleri her 60 milisaniyede bir değiştirmek istiyoruz, bu yüzden ((zaman)) önce 60'a bölünür. Oyuncu hareketsiz durduğunda, dokuzuncu sprite'ı çizeriz. Dikey hızın sıfır olmamasıyla tanınan zıplamalar sırasında, sağdaki onuncu sprite'ı kullanırız. {{index "flipHorizontally function", "CanvasDisplay class"}} -Because the ((sprite))s are slightly wider than the player object—24 instead of 16 pixels to allow some space for feet and arms—the method has to adjust the x-coordinate and width by a given amount (`playerXOverlap`). +Çünkü ((sprite))ler, ayaklar ve kollar için biraz yer sağlamak amacıyla oyuncu nesnesinden biraz daha geniştir—24 piksel yerine 16 piksel—, metod x-koordinatını ve genişliği belirli bir miktar (`playerXOverlap`) ayarlamak zorundadır. ```{sandbox: "game", includeCode: true} let playerSprites = document.createElement("img"); @@ -793,7 +795,7 @@ CanvasDisplay.prototype.drawPlayer = function(player, x, y, }; ``` -The `drawPlayer` method is called by `drawActors`, which is responsible for drawing all the actors in the game. +`drawPlayer` metodu, oyundaki tüm aktörleri çizmekten sorumlu olan `drawActors` tarafından çağrılır. ```{sandbox: "game", includeCode: true} CanvasDisplay.prototype.drawActors = function(actors) { @@ -814,15 +816,15 @@ CanvasDisplay.prototype.drawActors = function(actors) { }; ``` -When ((drawing)) something that is not the ((player)), we look at its type to find the offset of the correct sprite. The ((lava)) tile is found at offset 20, and the ((coin)) sprite is found at 40 (two times `scale`). +Oyuncu dışındaki bir şeyi ((çizerken)), doğru sprite'ın kaydırma değerini bulmak için türüne bakarız. ((Lava)) fayansı 20 kaydırma değerinde, ((coin)) sprite'ı ise 40 kaydırma değerinde (`scale`'in iki katı) bulunur. {{index viewport}} -We have to subtract the viewport's position when computing the actor's position since (0,0) on our ((canvas)) corresponds to the top left of the viewport, not the top left of the level. We could also have used `translate` for this. Either way works. +Aktörün pozisyonunu hesapladığımızda görünüm alanının konumunu çıkarmamız gerekir çünkü (0,0) canvas'ımızda seviyenin sol üst köşesi yerine görünüm alanının sol üst köşesine karşılık gelir. Bunun için `translate` de kullanılabilirdi. Her iki yöntem de işe yarar. {{if interactive -This document plugs the new display into `runGame`: +Bu belge, yeni görüntüleme sistemini `runGame`'e bağlar: ```{lang: html, sandbox: game, focus: yes, startCode: true} <body> @@ -838,91 +840,91 @@ if}} {{index [game, screenshot], [game, "with canvas"]}} -That concludes the new ((display)) system. The resulting game looks something like this: +Bu, yeni ((görüntüleme)) sistemini tamamlar. Ortaya çıkan oyun aşağıdaki gibi görünür: -{{figure {url: "img/canvas_game.png", alt: "Screenshot of the game as shown on canvas", width: "8cm"}}} +{{figure {url: "img/canvas_game.png", alt: "Canvas üzerinde gösterilen oyunun ekran görüntüsü", width: "8cm"}}} if}} {{id graphics_tradeoffs}} -## Choosing a graphics interface +## Bir grafik arayüzü seçme -Thus, when you need to generate graphics in the browser, you can choose between plain HTML, ((SVG)), and ((canvas)). There is no single _best_ approach that works in all situations. Each option has strengths and weaknesses. +Bu nedenle, tarayıcıda grafik üretmeniz gerektiğinde, düz HTML, ((SVG)) ve ((canvas)) arasında seçim yapabilirsiniz. Tüm durumlarda işe yarayan tek bir _en iyi_ yaklaşım yoktur. Her seçeneğin güçlü ve zayıf yönleri vardır. {{index "text wrapping"}} -Plain HTML has the advantage of being simple. It also integrates well with ((text)). Both SVG and canvas allow you to draw text, but they won't help you position that text or wrap it when it takes up more than one line. In an HTML-based picture, it is much easier to include blocks of text. +Düz HTML'nin basit olma avantajı vardır. Ayrıca, ((metin)) ile iyi entegre olur. Hem SVG hem de canvas metin çizmenizi sağlar, ancak bu metni konumlandırmanıza veya birden fazla satır aldığında sarmanıza yardımcı olmaz. HTML tabanlı bir resimde, metin bloklarını dahil etmek çok daha kolaydır. {{index zooming, SVG}} -SVG can be used to produce ((crisp)) ((graphics)) that look good at any zoom level. Unlike HTML, it is designed for drawing and is thus more suitable for that purpose. +SVG, herhangi bir yakınlaştırma seviyesinde iyi görünen keskin ((grafikler)) üretmek için kullanılabilir. HTML'den farklı olarak, çizim için tasarlanmıştır ve bu nedenle bu amaç için daha uygundur. {{index [DOM, graphics], SVG, "event handling", ["data structure", tree]}} -Both SVG and HTML build up a data structure (the DOM) that represents your picture. This makes it possible to modify elements after they are drawn. If you need to repeatedly change a small part of a big ((picture)) in response to what the user is doing or as part of an ((animation)), doing it in a canvas can be needlessly expensive. The DOM also allows us to register mouse event handlers on every element in the picture (even on shapes drawn with SVG). You can't do that with canvas. +Hem SVG hem de HTML, resminizi temsil eden bir veri yapısı (DOM) oluşturur. Bu, çizildikten sonra öğeleri değiştirmenizi sağlar. Kullanıcının yaptığı şeye yanıt olarak veya bir ((animasyon))un parçası olarak büyük bir ((resmin)) küçük bir bölümünü tekrar tekrar değiştirmeniz gerekiyorsa, bunu canvas'ta yapmak gereksiz yere pahalı olabilir. DOM ayrıca resimdeki her öğe üzerinde (SVG ile çizilen şekillerde bile) fare olay işleyicileri kaydetmemize olanak tanır. Bunu canvas ile yapamazsınız. -{{index performance, optimization}} +{{index performance, optimization, "ray tracer"}} -But ((canvas))'s ((pixel))-oriented approach can be an advantage when drawing a huge number of tiny elements. The fact that it does not build up a data structure but only repeatedly draws onto the same pixel surface gives canvas a lower cost per shape. +Ancak ((canvas))'ın piksel odaklı yaklaşımı, çok sayıda küçük öğe çizerken avantaj sağlayabilir. Bir veri yapısı oluşturmaması ve yalnızca aynı piksel yüzeyine tekrar tekrar çizim yapması nedeniyle, canvas her şekil için daha düşük maliyete sahiptir. {{index "ray tracer"}} -There are also effects, such as rendering a scene one ((pixel)) at a time (for example, using a ray tracer) or postprocessing an image with JavaScript (blurring or distorting it), that are only practical with a canvas element. +Bir sahneyi bir seferde bir piksel olarak işlemek (örneğin, bir ışın izleyici kullanarak) veya bir görüntüyü JavaScript ile son işleme tabi tutmak (bulanıklaştırma veya bozma gibi) gibi bazı efektler, sadece bir piksel tabanlı yaklaşımla gerçekçi bir şekilde ele alınabilir. -In some cases, you may want to combine several of these techniques. For example, you might draw a ((graph)) with ((SVG)) or ((canvas)) but show ((text))ual information by positioning an HTML element on top of the picture. +Bazı durumlarda, bu tekniklerin birkaçını birleştirmek isteyebilirsiniz. Örneğin, bir ((grafik))i ((SVG)) veya ((canvas)) ile çizebilir, ancak resmin üzerinde bir HTML öğesi konumlandırarak ((metin))sel bilgileri gösterebilirsiniz. {{index display}} -For nondemanding applications, it really doesn't matter much which interface you choose. The display we built for our game in this chapter could have been implemented using any of these three ((graphics)) technologies since it does not need to draw text, handle mouse interaction, or work with an extraordinarily large number of elements. +Düşük gereksinimli uygulamalarda, hangi arayüzü seçeceğiniz gerçekten çok önemli değildir. Bu bölümde oyunumuz için oluşturduğumuz görüntüleme, metin çizmeye, fare etkileşimini işlemeye veya olağanüstü büyük sayıda öğe ile çalışmaya gerek duymadığı için, bu üç ((grafik)) teknolojisinden herhangi biri kullanılarak uygulanabilirdi. -## Summary +## Özet -In this chapter we discussed techniques for drawing graphics in the browser, focusing on the `<canvas>` element. +Bu bölümde, tarayıcıda grafik çizme tekniklerini, özellikle `<canvas>` öğesine odaklanarak ele aldık. -A canvas node represents an area in a document that our program may draw on. This drawing is done through a drawing context object, created with the `getContext` method. +Bir canvas düğümü, programımızın üzerinde çizebileceği bir belge alanını temsil eder. Bu çizim, `getContext` metodu ile oluşturulan bir çizim bağlamı nesnesi aracılığıyla yapılır. -The 2D drawing interface allows us to fill and stroke various shapes. The context's `fillStyle` property determines how shapes are filled. The `strokeStyle` and `lineWidth` properties control the way lines are drawn. +2D çizim arayüzü, çeşitli şekilleri doldurmamıza ve çizmemize olanak tanır. Bağlamın `fillStyle` özelliği, şekillerin nasıl doldurulacağını belirler. `strokeStyle` ve `lineWidth` özellikleri, çizgilerin nasıl çizileceğini kontrol eder. -Rectangles and pieces of text can be drawn with a single method call. The `fillRect` and `strokeRect` methods draw rectangles, and the `fillText` and `strokeText` methods draw text. To create custom shapes, we must first build up a path. +Dikdörtgenler ve metin parçaları tek bir metod çağrısı ile çizilebilir. `fillRect` ve `strokeRect` metodları dikdörtgenleri çizer, `fillText` ve `strokeText` metodları ise metin çizer. Özel şekiller oluşturmak için önce bir yol oluşturmamız gerekir. {{index stroking, filling}} -Calling `beginPath` starts a new path. A number of other methods add lines and curves to the current path. For example, `lineTo` can add a straight line. When a path is finished, it can be filled with the `fill` method or stroked with the `stroke` method. +`beginPath` çağrısı, yeni bir yol başlatır. Bir dizi başka metod, mevcut yola çizgiler ve eğriler ekler. Örneğin, `lineTo` düz bir çizgi ekleyebilir. Bir yol tamamlandığında, `fill` metodu ile doldurulabilir veya `stroke` metodu ile çizilebilir. -Moving pixels from an image or another canvas onto our canvas is done with the `drawImage` method. By default, this method draws the whole source image, but by giving it more parameters, you can copy a specific area of the image. We used this for our game by copying individual poses of the game character out of an image that contained many such poses. +Bir görüntüden veya başka bir canvastan pikselleri canvasımıza taşımak `drawImage` metodu ile yapılır. Varsayılan olarak, bu metot tüm kaynak görüntüyü çizer, ancak ona daha fazla parametre vererek görüntünün belirli bir alanını kopyalayabilirsiniz. Oyunumuzda, bu yöntemi, birden fazla poz içeren bir görüntüden oyun karakterinin tek tek pozlarını kopyalamak için kullandık. -Transformations allow you to draw a shape in multiple orientations. A 2D drawing context has a current transformation that can be changed with the `translate`, `scale`, and `rotate` methods. These will affect all subsequent drawing operations. A transformation state can be saved with the `save` method and restored with the `restore` method. +Dönüşümler, bir şekli birden fazla yönde çizmenize olanak tanır. Bir 2D çizim bağlamı, `translate`, `scale` ve `rotate` metodları ile değiştirilebilen mevcut bir dönüşüme sahiptir. Bu, sonraki tüm çizim işlemlerini etkiler. Bir dönüşüm durumu `save` metodu ile kaydedilebilir ve `restore` metodu ile geri yüklenebilir. -When showing an animation on a canvas, the `clearRect` method can be used to clear part of the canvas before redrawing it. +Canvas üzerinde bir animasyon gösterilirken, yeniden çizmeden önce canvasın bir kısmını temizlemek için `clearRect` metodu kullanılabilir. -## Exercises +## Egzersizler -### Shapes +### Şekiller {{index "shapes (exercise)"}} -Write a program that draws the following ((shape))s on a ((canvas)): +Aşağıdaki ((şekil))leri bir ((canvas)) üzerine çizen bir program yazın: {{index rotation}} -1. A ((trapezoid)) (a ((rectangle)) that is wider on one side) +1. Bir ((trapezoid)) (bir tarafı daha geniş olan bir ((dikdörtgen))) -2. A red ((diamond)) (a rectangle rotated 45 degrees or ¼π radians) +2. Kırmızı bir ((elmas)) (45 derece veya ¼π radyan döndürülmüş bir dikdörtgen) -3. A zigzagging ((line)) +3. Zigzag şeklinde bir ((çizgi)) -4. A ((spiral)) made up of 100 straight line segments +4. 100 düz çizgi parçasından oluşan bir ((spiral)) -5. A yellow ((star)) +5. Sarı bir ((yıldız)) -{{figure {url: "img/exercise_shapes.png", alt: "Picture showing the shapes you are asked to draw", width: "8cm"}}} +{{figure {url: "img/exercise_shapes.png", alt: "Çizmeniz istenen şekilleri gösteren resim", width: "8cm"}}} -When drawing the last two, you may want to refer to the explanation of `Math.cos` and `Math.sin` in [Chapter ?](dom#sin_cos), which describes how to get coordinates on a circle using these functions. +Son iki şekli çizerken, bu fonksiyonları kullanarak bir çember üzerindeki koordinatları nasıl elde edeceğinizi açıklayan [bölüm ?](dom#sin_cos) içindeki `Math.cos` ve `Math.sin` açıklamasına başvurmak isteyebilirsiniz. -{{index readability, "hard-coding"}} +{{index readability, "hardcoding"}} -I recommend creating a function for each shape. Pass the position, and optionally other properties such as the size or the number of points, as parameters. The alternative, which is to hard-code numbers all over your code, tends to make the code needlessly hard to read and modify. +Her şekil için bir fonksiyon oluşturmanızı öneririm. Pozisyonu ve isteğe bağlı olarak boyut veya nokta sayısı gibi diğer özellikleri parametre olarak geçirin. Alternatif olarak, kodunuzda her yere sabit sayılar yazmak, kodu gereksiz yere okunması ve değiştirilmesi zor hale getirme eğilimindedir. {{if interactive @@ -941,35 +943,35 @@ if}} {{index [path, canvas], "shapes (exercise)"}} -The ((trapezoid)) (1) is easiest to draw using a path. Pick suitable center coordinates and add each of the four corners around the center. +((Trapezoid)) (1) bir yol kullanılarak çizilmesi en kolay olanıdır. Uygun merkez koordinatlarını seçin ve merkezin etrafına dört köşeyi ekleyin. {{index "flipHorizontally function", rotation}} -The ((diamond)) (2) can be drawn the straightforward way, with a path, or the interesting way, with a `rotate` ((transformation)). To use rotation, you will have to apply a trick similar to what we did in the `flipHorizontally` function. Because you want to rotate around the center of your rectangle and not around the point (0,0), you must first `translate` to there, then rotate, and then translate back. +((Diamond)) (2) bir yol ile doğrudan veya ilginç bir şekilde `rotate` ((dönüşüm))ü kullanarak çizilebilir. Dönüşüm kullanmak için, `flipHorizontally` fonksiyonunda yaptığımıza benzer bir hile uygulamanız gerekecek. Dikdörtgeninizin merkezi etrafında ve (0,0) noktası etrafında döndürmek istemediğinizden, önce oraya `translate` yapmalı, sonra döndürmeli ve ardından geri `translate` yapmalısınız. -Make sure you reset the transformation after drawing any shape that creates one. +Herhangi bir şekil çizdikten sonra, oluşturulan dönüşümün sıfırlandığından emin olun. {{index "remainder operator", "% operator"}} -For the ((zigzag)) (3) it becomes impractical to write a new call to `lineTo` for each line segment. Instead, you should use a ((loop)). You can have each iteration draw either two ((line)) segments (right and then left again) or one, in which case you must use the evenness (`% 2`) of the loop index to determine whether to go left or right. +((Zigzag)) (3) için, her bir çizgi parçası için yeni bir `lineTo` çağrısı yazmak pratik olmaz. Bunun yerine bir ((döngü)) kullanmalısınız. Her yineleme iki ((çizgi)) segmenti (önce sağa, sonra tekrar sola) çizebilir veya bir segment çizebilir; bu durumda döngü indeksinin çiftliğini (`% 2`) kullanarak sola mı yoksa sağa mı gideceğinizi belirlemelisiniz. -You'll also need a loop for the ((spiral)) (4). If you draw a series of points, with each point moving further along a circle around the spiral's center, you get a circle. If, during the loop, you vary the radius of the circle on which you are putting the current point and go around more than once, the result is a spiral. +((Spiral)) (4) için de bir döngüye ihtiyacınız olacak. Eğer spiral merkezinin etrafında bir daire boyunca ilerleyen bir dizi nokta çizerseniz, bir daire elde edersiniz. Döngü sırasında, mevcut noktayı koyduğunuz dairenin yarıçapını değiştirir ve birden fazla kez çevirirseniz, sonuç bir spiral olur. {{index "quadraticCurveTo method"}} -The ((star)) (5) depicted is built out of `quadraticCurveTo` lines. You could also draw one with straight lines. Divide a circle into eight pieces for a star with eight points, or however many pieces you want. Draw lines between these points, making them curve toward the center of the star. With `quadraticCurveTo`, you can use the center as the control point. +Görseldeki ((yıldız)) (5), `quadraticCurveTo` çizgilerinden oluşmuştur. Düz çizgilerle de bir yıldız çizebilirsiniz. Sekiz noktaya sahip bir yıldız için bir çemberi sekiz parçaya bölün veya istediğiniz kadar parça yapın. Bu noktalar arasında çizgiler çizin, onları yıldızın merkezine doğru eğin. `quadraticCurveTo` ile merkezi kontrol noktası olarak kullanabilirsiniz. hint}} {{id exercise_pie_chart}} -### The pie chart +### Pasta grafiği {{index label, text, "pie chart example"}} -[Earlier](canvas#pie_chart) in the chapter, we saw an example program that drew a pie chart. Modify this program so that the name of each category is shown next to the slice that represents it. Try to find a pleasing-looking way to automatically position this text that would work for other data sets as well. You may assume that categories are big enough to leave enough room for their labels. +Bölümün [daha önceki](canvas#pie_chart) kısmında, bir pasta grafiği çizen örnek bir program gördük. Bu programı, her kategorinin adının, onu temsil eden dilimin yanında gösterilecek şekilde değiştireceğiz. Diğer veri setleri için de işe yarayacak, hoş görünümlü bir yol bulmaya çalışın. Kategorilerin, etiketleri için yeterince alan bırakacak kadar büyük olduğunu varsayabilirsiniz. -You might need `Math.sin` and `Math.cos` again, which are described in [Chapter ?](dom#sin_cos). +Yine `Math.sin` ve `Math.cos` fonksiyonlarına ihtiyaç duyabilirsiniz; bu fonksiyonlar [bölüm ?](dom#sin_cos) içinde açıklanmıştır. {{if interactive @@ -1002,11 +1004,11 @@ if}} {{index "fillText method", "textAlign property", "textBaseline property", "pie chart example"}} -You will need to call `fillText` and set the context's `textAlign` and `textBaseline` properties in such a way that the text ends up where you want it. +Etiketlerin konumlandırılması için `fillText` çağırmanız ve bağlamın `textAlign` ve `textBaseline` özelliklerini metnin istediğiniz yerde olması için ayarlamanız gerekecek. -A sensible way to position the labels would be to put the text on the line going from the center of the pie through the middle of the slice. You don't want to put the text directly against the side of the pie but rather move the text out to the side of the pie by a given number of pixels. +Etiketleri konumlandırmanın mantıklı bir yolu, metni pastanın merkezinden dilimin ortasından geçen çizgi üzerinde yerleştirmek olacaktır. Metni pastanın yanına doğrudan koymak yerine, pastanın kenarından belirli bir piksel sayısı kadar dışarı taşımak isteyebilirsiniz. -The ((angle)) of this line is `currentAngle + 0.5 * sliceAngle`. The following code finds a position on this line 120 pixels from the center: +Bu çizginin ((açısı)) `currentAngle + 0.5 * sliceAngle` şeklindedir. Aşağıdaki kod, merkezden 120 piksel uzaklıkta bu çizgi üzerindeki bir konumu bulur: ```{test: no} let middleAngle = currentAngle + 0.5 * sliceAngle; @@ -1014,19 +1016,19 @@ let textX = Math.cos(middleAngle) * 120 + centerX; let textY = Math.sin(middleAngle) * 120 + centerY; ``` -For `textBaseline`, the value `"middle"` is probably appropriate when using this approach. What to use for `textAlign` depends on which side of the circle we are on. On the left, it should be `"right"`, and on the right, it should be `"left"`, so that the text is positioned away from the pie. +`textBaseline` için `"middle"` değeri, bu yaklaşımı kullanırken muhtemelen uygun olacaktır. `textAlign` için hangi değerin kullanılacağı, çemberin hangi tarafında olduğumuza bağlıdır. Sol tarafta, `"right"` kullanılmalı ve sağ tarafta `"left"` kullanılmalı, böylece metin pastadan uzağa konumlandırılır. {{index "Math.cos function"}} -If you are not sure how to find out which side of the circle a given angle is on, look to the explanation of `Math.cos` in [Chapter ?](dom#sin_cos). The cosine of an angle tells us which x-coordinate it corresponds to, which in turn tells us exactly which side of the circle we are on. +Belirli bir açının çemberin hangi tarafında olduğunu nasıl bulacağınızdan emin değilseniz, [bölüm ?](dom#sin_cos) içindeki `Math.cos` açıklamasına bakabilirsiniz. Bir açının kosinüsü, hangi x-koordinatına karşılık geldiğini ve dolayısıyla tam olarak çemberin hangi tarafında olduğumuzu bize bildirir. hint}} -### A bouncing ball +### Zıplayan bir top {{index [animation, "bouncing ball"], "requestAnimationFrame function", bouncing}} -Use the `requestAnimationFrame` technique that we saw in [Chapter ?](dom#animationFrame) and [Chapter ?](game#runAnimation) to draw a ((box)) with a bouncing ((ball)) in it. The ball moves at a constant ((speed)) and bounces off the box's sides when it hits them. +[Bölüm ?](dom#animationFrame) ve [bölüm ?](game#runAnimation) içinde gördüğümüz `requestAnimationFrame` tekniğini kullanarak bir ((kutu)) içinde zıplayan bir ((top)) çizin. Top sabit bir ((hız))da hareket eder ve kutunun kenarlarına çarptığında sekerek geri döner. {{if interactive @@ -1057,37 +1059,36 @@ if}} {{index "strokeRect method", animation, "arc method"}} -A ((box)) is easy to draw with `strokeRect`. Define a binding that holds its size or define two bindings if your box's width and height differ. To create a round ((ball)), start a path and call `arc(x, y, radius, 0, 7)`, which creates an arc going from zero to more than a whole circle. Then fill the path. +Bir ((kutu)) `strokeRect` ile kolayca çizilebilir. Kutu genişliği ve yüksekliği farklıysa, boyutunu tutan bir bağlama veya iki bağlama tanımlayın. Yuvarlak bir ((top)) oluşturmak için bir yol başlatın ve `arc(x, y, radius, 0, 7)` çağrısı yapın; bu, sıfırdan tam bir çemberden daha fazlasına kadar bir yay oluşturur. Ardından yolu doldurun. {{index "collision detection", "Vec class"}} -To model the ball's position and ((speed)), you can use the `Vec` class from [Chapter ?](game#vector)[ (which is available on this page)]{if interactive}. Give it a starting speed, preferably one that is not purely vertical or horizontal, and for every ((frame)) multiply that speed by the amount of time that elapsed. When the ball gets too close to a vertical wall, invert the x component in its speed. Likewise, invert the y component when it hits a horizontal wall. +Topun konumunu ve ((hızını)) modellemek için [bölüm ?](game#vector) içindeki `Vec` sınıfını kullanabilirsiniz [(bu sayfada mevcuttur)]{if interactive}. Başlangıçta, tercihen tamamen dikey veya yatay olmayan bir hız verin ve her ((kare))de bu hızı geçen zaman miktarıyla çarpın. Top dikey bir duvara çok yaklaştığında, hızının x bileşenini ters çevirin. Aynı şekilde, yatay bir duvara çarptığında y bileşenini ters çevirin. {{index "clearRect method", clearing}} -After finding the ball's new position and speed, use `clearRect` to delete the scene and redraw it using the new position. +Topun yeni konumunu ve hızını bulduktan sonra, sahneyi silmek için `clearRect` kullanın ve yeni konumunu kullanarak sahneyi yeniden çizin. hint}} -### Precomputed mirroring +### Önceden hesaplanmış yansıtma {{index optimization, "bitmap graphics", mirror}} -One unfortunate thing about ((transformation))s is that they slow down the drawing of bitmaps. The position and size of each ((pixel)) has to be transformed, and though it is possible that ((browser))s will get cleverer about transformation in the ((future)), they currently cause a measurable increase in the time it takes to draw a bitmap. +Dönüşümlerin (transformations) talihsiz bir yanı, bit eşlemlerinin (bitmaps) çizimini yavaşlatmalarıdır. Her ((piksel))in konumu ve boyutu dönüştürülmek zorundadır ve ((gelecekte)) tarayıcıların dönüşüm konusunda daha akıllı hale gelmesi mümkün olsa da, şu anda bu işlem bir bit eşlem çizmek için geçen sürede ölçülebilir bir artışa neden olur. -In a game like ours, where we are drawing only a single transformed sprite, this is a nonissue. But imagine that we need to draw hundreds of characters or thousands of rotating particles from an explosion. +Bizimki gibi sadece tek bir dönüştürülmüş sprite çizen bir oyunda bu bir sorun değildir. Ancak, yüzlerce karakter veya bir patlamadan gelen binlerce dönen parçacık çizmemiz gerektiğini hayal edin. -Think of a way to allow us to draw an inverted character without loading additional image files and without having to make transformed `drawImage` calls every frame. +Ek resim dosyaları yüklemeden ve her karede dönüştürülmüş `drawImage` çağrıları yapmadan ters çevrilmiş bir karakter çizmenin bir yolunu düşünün. {{hint {{index mirror, scaling, "drawImage method"}} -The key to the solution is the fact that we can use a ((canvas)) element as a source image when using `drawImage`. It is possible to create an extra `<canvas>` element, without adding it to the document, and draw our inverted sprites to it, once. When drawing an actual frame, we just copy the already inverted sprites to the main canvas. +Çözümün anahtarı, `drawImage` kullanırken bir ((canvas)) öğesini kaynak resim olarak kullanabilmemizdir. Belgeye eklemeden, ek bir `<canvas>` öğesi oluşturmak ve ters çevrilmiş sprite'larımızı bir kez ona çizmek mümkündür. Gerçek bir kare çizerken, sadece önceden ters çevrilmiş sprite'ları ana canvas'a kopyalarız. {{index "load event"}} -Some care would be required because images do not load instantly. We do the inverted drawing only once, and if we do it before the image loads, it won't draw anything. A `"load"` handler on the image can be used to draw the inverted images to the extra canvas. This canvas can be used as a drawing source immediately (it'll simply be blank until we draw the character onto it). +Dikkat edilmesi gereken bazı noktalar vardır, çünkü görüntüler anında yüklenmez. Ters çevrilmiş çizim işlemi yalnızca bir kez yapılır ve eğer görüntü yüklenmeden önce yaparsak, hiçbir şey çizilmeyecektir. Görüntü üzerine bir `"load"` olay işleyicisi yerleştirilebilir ve bu, ters çevrilmiş görüntüleri ek canvas'a çizebilir. Bu canvas, hemen bir çizim kaynağı olarak kullanılabilir (karakteri üzerine çizene kadar sadece boş olacaktır). hint}} - diff --git a/18_http.md b/18_http.md index 3903b960..afc2492c 100644 --- a/18_http.md +++ b/18_http.md @@ -1,26 +1,26 @@ {{meta {}}} -# HTTP and Forms +# HTTP ve Formlar -{{quote {author: "Tim Berners-Lee", chapter: true} +{{quote {author: "Roy Fielding", title: "Mimari Tarzlar ve Ağ Tabanlı Yazılım Mimarilerinin Tasarımı", chapter: true} -What was often difficult for people to understand about the design was that there was nothing else beyond URLs, HTTP and HTML. There was no central computer "controlling" the Web, no single network on which these protocols worked, not even an organisation anywhere that "ran" the Web. The Web was not a physical "thing" that existed in a certain "place". It was a "space" in which information could exist. +İletişim doğası gereği durumsuz olmalıdır [...] öyle ki istemciden sunucuya yapılan her talep, talebin anlaşılması için gerekli tüm bilgileri içermelidir ve sunucuda depolanmış herhangi bir bağlamdan yararlanamaz. quote}} {{index "Fielding, Roy"}} -{{figure {url: "img/chapter_picture_18.jpg", alt: "Illustration showing a web sign-up form on a parchment scroll", chapter: "framed"}}} +{{figure {url: "img/chapter_picture_18.jpg", alt: "Parşömen parşömen üzerinde bir web kayıt formunu gösteren illüstrasyon", chapter: "framed"}}} {{index [browser, environment]}} -The _Hypertext Transfer Protocol_, already mentioned in [Chapter ?](browser#web), is the mechanism through which data is requested and provided on the ((World Wide Web)). This chapter describes the ((protocol)) in more detail and explains the way browser JavaScript has access to it. +[Bölüm ?](browser#web) içinde daha önce bahsedilen _Hypertext Transfer Protocol_, ((World Wide Web))'de verilerin talep edildiği ve sağlandığı mekanizmadır. Bu bölüm ((protokol))'ü daha ayrıntılı olarak tanımlamakta ve tarayıcı JavaScript'in buna nasıl eriştiğini açıklamaktadır. -## The protocol +## Protokol {{index "IP address"}} -If you type _eloquentjavascript.net/18_http.html_ into your browser's ((address bar)), the ((browser)) first looks up the ((address)) of the server associated with _eloquentjavascript.net_ and tries to open a ((TCP)) ((connection)) to it on ((port)) 80, the default port for ((HTTP)) traffic. If the ((server)) exists and accepts the connection, the browser might send something like this: +Tarayıcınızın ((adres çubuğuna)) _eloquentjavascript.net/18_http.html_ yazarsanız, ((tarayıcı)) önce _eloquentjavascript.net_ ile ilişkili sunucunun ((adresini)) arar ve ((HTTP)) trafiği için varsayılan bağlantı noktası olan ((bağlantı noktası)) 80'de ((TCP)) ((bağlantı)) açmaya çalışır. Eğer ((sunucu)) mevcutsa ve bağlantıyı kabul ederse, tarayıcı buna benzer bir şey gönderebilir: ```{lang: http} GET /18_http.html HTTP/1.1 @@ -28,7 +28,7 @@ Host: eloquentjavascript.net User-Agent: Your browser's name ``` -Then the server responds, through that same connection. +Ardından sunucu aynı bağlantı üzerinden yanıt verir. ```{lang: http} HTTP/1.1 200 OK @@ -40,11 +40,11 @@ Last-Modified: Fri, 13 Oct 2023 10:05:41 GMT ... the rest of the document ``` -The browser takes the part of the ((response)) after the blank line, its _body_ (not to be confused with the HTML `<body>` tag), and displays it as an ((HTML)) document. +Tarayıcı, ((yanıt))'ın boş satırdan sonraki kısmını, _body_ (HTML `<body>` etiketiyle karıştırılmamalıdır) alır ve bunu bir ((HTML)) belgesi olarak görüntüler. {{index HTTP}} -The information sent by the client is called the _((request))_. It starts with this line: +İstemci tarafından gönderilen bilgiye _((istek))_ denir. Bu satır ile başlar: ```{lang: http} GET /18_http.html HTTP/1.1 @@ -52,19 +52,19 @@ GET /18_http.html HTTP/1.1 {{index "DELETE method", "PUT method", "GET method", [method, HTTP]}} -The first word is the _method_ of the ((request)). `GET` means that we want to _get_ the specified resource. Other common methods are `DELETE` to delete a resource, `PUT` to create or replace it, and `POST` to send information to it. Note that the ((server)) is not obliged to carry out every request it gets. If you walk up to a random website and tell it to `DELETE` its main page, it'll probably refuse. +İlk kelime ((istek))'in _metod_'udur. `GET` belirtilen kaynağı _get_ etmek istediğimiz anlamına gelir. Diğer yaygın yöntemler bir kaynağı silmek için `DELETE`, oluşturmak ya da değiştirmek için `PUT` ve ona bilgi göndermek için `POST`'tur. ((Sunucu))'nun aldığı her isteği yerine getirmek zorunda olmadığını unutmayın. Rastgele bir web sitesine gidip ana sayfasını `DELETE` etmesini söylerseniz, muhtemelen reddedecektir. {{index [path, URL], GitHub, [file, resource]}} -The part after the method name is the path of the _((resource))_ the request applies to. In the simplest case, a resource is simply a file on the ((server)), but the protocol doesn't require it to be. A resource may be anything that can be transferred _as if_ it is a file. Many servers generate the responses they produce on the fly. For example, if you open [_https://github.com/marijnh_](https://github.com/marijnh), the server looks in its database for a user named "marijnh", and if it finds one, it will generate a profile page for that user. +Yöntem adından sonraki kısım, isteğin uygulandığı _((kaynağın))_ yoludur. En basit durumda, bir kaynak basitçe ((sunucu)) üzerindeki bir dosyadır, ancak protokol öyle olmasını gerektirmez. Bir kaynak, bir dosyaymış gibi aktarılabilen herhangi bir şey olabilir. Birçok sunucu ürettikleri yanıtları anında oluşturur. Örneğin, [_https://github.com/marijnh_](https://github.com/marijnh) adresini açarsanız, sunucu veritabanında "marijnh" adında bir kullanıcı arar ve bulursa, bu kullanıcı için bir profil sayfası oluşturur. -After the resource path, the first line of the request mentions `HTTP/1.1` to indicate the ((version)) of the ((HTTP)) ((protocol)) it is using. +Kaynak yolundan sonra, isteğin ilk satırı, kullandığı ((HTTP)) ((protokol))'ün ((sürüm))'ünü belirtmek için `HTTP/1.1`den bahseder. -In practice, many sites use HTTP version 2, which supports the same concepts as version 1.1 but is a lot more complicated so that it can be faster. Browsers will automatically switch to the appropriate protocol version when talking to a given server, and the outcome of a request is the same regardless of which version is used. Because version 1.1 is more straightforward and easier to play around with, we'll use that to illustrate the protocol. +Pratikte birçok site, 1.1 sürümüyle aynı kavramları destekleyen ancak daha hızlı olabilmek için çok daha karmaşık olan HTTP sürüm 2'yi kullanır. Tarayıcılar belirli bir sunucuyla konuşurken otomatik olarak uygun protokol sürümüne geçer ve bir isteğin sonucu hangi sürümün kullanıldığına bakılmaksızın aynıdır. Sürüm 1.1 daha basit ve üzerinde oynaması daha kolay olduğu için buna odaklanacağız. {{index "status code"}} -The server's ((response)) will start with a version as well, followed by the status of the response, first as a three-digit status code and then as a human-readable string. +Sunucunun ((yanıtı)) da bir sürümle başlayacak, ardından önce üç basamaklı bir durum kodu ve ardından insan tarafından okunabilir bir dize olarak yanıtın durumu gelecektir. ```{lang: http} HTTP/1.1 200 OK @@ -72,13 +72,13 @@ HTTP/1.1 200 OK {{index "200 (HTTP status code)", "error response", "404 (HTTP status code)"}} -Status codes starting with a 2 indicate that the request succeeded. Codes starting with 4 mean there was something wrong with the ((request)). 404 is probably the most famous HTTP status code—it means that the resource could not be found. Codes that start with 5 mean an error happened on the ((server)) and the request is not to blame. +2 ile başlayan durum kodları isteğin başarılı olduğunu gösterir. 4 ile başlayan kodlar ((istek)) ile ilgili bir sorun olduğu anlamına gelir. 404 muhtemelen en ünlü HTTP durum kodudur - kaynağın bulunamadığı anlamına gelir. 5 ile başlayan kodlar ((sunucu)) üzerinde bir hata olduğu ve isteğin suçlanamayacağı anlamına gelir. {{index HTTP}} {{id headers}} -The first line of a request or response may be followed by any number of _((header))s_. These are lines in the form `name: value` that specify extra information about the request or response. These headers were part of the example ((response)): +Bir istek veya yanıtın ilk satırını herhangi bir sayıda _((header))s_ takip edebilir. Bunlar, istek veya yanıt hakkında ekstra bilgi belirten `name: value` biçimindeki satırlardır. Bu başlıklar örnek ((yanıt))'ın bir parçasıydı: ```{lang: null} Content-Length: 87320 @@ -88,25 +88,25 @@ Last-Modified: Fri, 13 Oct 2023 10:05:41 GMT {{index "Content-Length header", "Content-Type header", "Last-Modified header"}} -This tells us the size and type of the response document. In this case, it is an HTML document of 87,320 bytes. It also tells us when that document was last modified. +Bu bize yanıt belgesinin boyutunu ve türünü gösterir. Bu durumda, 87.320 baytlık bir HTML belgesidir. Ayrıca bize bu belgenin en son ne zaman değiştirildiğini de söyler. -The client and server are free to decide what ((header))s to include in their ((request))s or ((response))s. But some of them are necessary for things to work. For example, without a `Content-Type` header in the response, the browser won't know how to display the document. +İstemci ve sunucu, ((istek))lerine veya ((yanıt))larına hangi ((başlık))ları ekleyeceklerine karar vermekte özgürdür. Ancak bunların bazıları işlerin yürümesi için gereklidir. Örneğin, yanıtta `Content-Type` başlığı olmadan, tarayıcı belgeyi nasıl görüntüleyeceğini bilemez. {{index "GET method", "DELETE method", "PUT method", "POST method", "body (HTTP)"}} -After the headers, both requests and responses may include a blank line followed by a body, which contains the actual document being sent. `GET` and `DELETE` requests don't send along any data, but `PUT` and `POST` requests do. Some response types, such as error responses, also don't require a body. +Başlıklardan sonra, hem istekler hem de yanıtlar boş bir satır ve ardından gönderilen gerçek belgeyi içeren bir gövde içerebilir. `GET` ve `DELETE` istekleri herhangi bir veri göndermez, ancak `PUT` ve `POST` istekleri gönderir. Hata yanıtları gibi bazı yanıt türleri de bir gövde gerektirmez. -## Browsers and HTTP +## Tarayıcılar ve HTTP {{index HTTP, [file, resource]}} -As we saw, a ((browser)) will make a request when we enter a ((URL)) in its ((address bar)). When the resulting HTML page references other files, such as ((image))s and JavaScript files, it will retrieve those as well. +Örnekte gördüğümüz gibi, bir ((tarayıcı)), ((adres çubuğuna)) bir ((URL)) girdiğimizde bir istekte bulunacaktır. Ortaya çıkan HTML sayfası ((resim)) ve JavaScript dosyaları gibi diğer dosyalara referans verdiğinde, bunlar da alınır. {{index parallelism, "GET method"}} -A moderately complicated ((website)) can easily include anywhere from 10 to 200 ((resource))s. To be able to fetch those quickly, browsers will make several `GET` requests simultaneously, rather than waiting for the responses one at a time. +Orta derecede karmaşık bir ((web sitesi)) kolayca 10 ila 200 ((kaynak)) içerebilir. Bunları hızlı bir şekilde alabilmek için, tarayıcılar yanıtları teker teker beklemek yerine aynı anda birkaç `GET` isteği yapacaktır. -HTML pages may include _((form))s_, which allow the user to fill out information and send it to the server. This is an example of a form: +HTML sayfaları, kullanıcının bilgileri doldurmasına ve sunucuya göndermesine olanak tanıyan _((form))lar_ içerebilir. Bu bir form örneğidir: ```{lang: html} <form method="GET" action="example/message.html"> @@ -118,9 +118,9 @@ HTML pages may include _((form))s_, which allow the user to fill out information {{index form, "method attribute", "GET method"}} -This code describes a form with two ((field))s: a small one asking for a name and a larger one to write a message in. When you click the Send ((button)), the form is _submitted_, meaning that the content of its field is packed into an HTTP request and the browser navigates to the result of that request. +Bu kod, iki ((alan)) içeren bir formu tanımlamaktadır: küçük olanı bir ad sorar ve daha büyük olanı bir mesaj yazmak içindir. Gönder ((düğmesini)) tıkladığınızda, form _gönderilir_, yani alanının içeriği bir HTTP isteğine paketlenir ve tarayıcı bu isteğin sonucuna gider. -When the `<form>` element's `method` attribute is `GET` (or is omitted), the information in the form is added to the end of the `action` URL as a _((query string))_. The browser might make a request to this URL: +`<form>` öğesinin `method` niteliği `GET` olduğunda (veya atlandığında), formdaki bilgiler `action` URL'sinin sonuna _((query string))_ olarak eklenir. Tarayıcı bu URL'ye bir istekte bulunabilir: ```{lang: null} GET /example/message.html?name=Jean&message=Yes%3F HTTP/1.1 @@ -128,11 +128,11 @@ GET /example/message.html?name=Jean&message=Yes%3F HTTP/1.1 {{index "ampersand character"}} -The ((question mark)) indicates the end of the path part of the URL and the start of the query. It is followed by pairs of names and values, corresponding to the `name` attribute on the form field elements and the content of those elements, respectively. An ampersand character (`&`) is used to separate the pairs. +((soru işareti)) URL'nin yol kısmının sonunu ve sorgunun başlangıcını gösterir. Bunu, sırasıyla form alanı öğelerindeki `name` niteliğine ve bu öğelerin içeriğine karşılık gelen ad ve değer çiftleri izler. Çiftleri ayırmak için bir ampersand karakteri (`&`) kullanılır. {{index [escaping, "in URLs"], "hexadecimal number", "encodeURIComponent function", "decodeURIComponent function"}} -The actual message encoded in the URL is "Yes?", but the question mark is replaced by a strange code. Some characters in query strings must be escaped. The question mark, represented as `%3F`, is one of those. There seems to be an unwritten rule that every format needs its own way of escaping characters. This one, called _((URL encoding))_, uses a ((percent sign)) followed by two hexadecimal (base 16) digits that encode the character code. In this case, 3F, which is 63 in decimal notation, is the code of a question mark character. JavaScript provides the `encodeURIComponent` and `decodeURIComponent` functions to encode and decode this format. +URL'de kodlanan asıl mesaj "Evet mi?" şeklindedir, ancak soru işareti garip bir kodla değiştirilmiştir. Sorgu dizelerindeki bazı karakterlerin öncelenmesi gerekir. Soru işareti, `%3F` olarak gösterilir, bunlardan biridir. Her formatın kendi karakter kaçış yöntemine ihtiyacı olduğuna dair yazılı olmayan bir kural var gibi görünüyor. Bu, _((URL kodlaması))_ olarak adlandırılır ve bir ((yüzde işareti)) ve ardından karakter kodunu kodlayan iki onaltılık (taban 16) basamak kullanır. Bu durumda, ondalık gösterimde 63 olan 3F, bir soru işareti karakterinin kodudur. JavaScript, bu biçimi kodlamak ve kodunu çözmek için `encodeURIComponent` ve `decodeURIComponent` işlevlerini sağlar. ``` console.log(encodeURIComponent("Yes?")); @@ -143,7 +143,7 @@ console.log(decodeURIComponent("Yes%3F")); {{index "body (HTTP)", "POST method"}} -If we change the `method` attribute of the HTML form in the example we saw earlier to `POST`, the ((HTTP)) request made to submit the ((form)) will use the `POST` method and put the ((query string)) in the body of the request, rather than adding it to the URL. +Daha önce gördüğümüz örnekteki HTML formunun `method` özelliğini `POST` olarak değiştirirsek, ((formu)) göndermek için yapılan ((HTTP)) isteği `POST` yöntemini kullanacak ve ((query string)) URL'ye eklemek yerine isteğin gövdesine koyacaktır. ```{lang: http} POST /example/message.html HTTP/1.1 @@ -153,9 +153,9 @@ Content-type: application/x-www-form-urlencoded name=Jean&message=Yes%3F ``` -`GET` requests should be used for requests that do not have ((side effect))s but simply ask for information. Requests that change something on the server, for example creating a new account or posting a message, should be expressed with other methods, such as `POST`. Client-side software such as a browser knows that it shouldn't blindly make `POST` requests but will often implicitly make `GET` requests—for example to prefetch a resource it believes the user will soon need. +`GET` istekleri, ((yan etkisi)) olmayan ancak sadece bilgi isteyen istekler için kullanılmalıdır. Sunucuda bir şeyi değiştiren istekler, örneğin yeni bir hesap oluşturma veya bir mesaj gönderme, `POST` gibi diğer yöntemlerle ifade edilmelidir. Tarayıcı gibi istemci tarafı yazılımlar körü körüne `POST` istekleri yapmamaları gerektiğini bilirler, ancak genellikle dolaylı olarak `GET` istekleri yaparlar - örneğin kullanıcının yakında ihtiyaç duyacağını düşündüğü bir kaynağı önceden almak için. -We'll come back to forms and how to interact with them from JavaScript [later in the chapter](http#forms). +Formlara ve JavaScript'ten onlarla nasıl etkileşim kuracağımıza [bölümün ilerleyen kısımlarında] geri döneceğiz (http#forms). {{id fetch}} @@ -163,7 +163,7 @@ We'll come back to forms and how to interact with them from JavaScript [later in {{index "fetch function", "Promise class", [interface, module]}} -The interface through which browser JavaScript can make HTTP requests is called `fetch`. +Tarayıcı JavaScript'inin HTTP istekleri yapabildiği arayüze `fetch` adı verilir. Nispeten yeni olduğu için, uygun bir şekilde vaatleri kullanır. ```{test: no} fetch("example/data.txt").then(response => { @@ -176,17 +176,17 @@ fetch("example/data.txt").then(response => { {{index "Response class", "status property", "headers property"}} -Calling `fetch` returns a promise that resolves to a `Response` object holding information about the server's response, such as its status code and its headers. The headers are wrapped in a `Map`-like object that treats its keys (the header names) as case insensitive because header names are not supposed to be case sensitive. This means `headers.get("Content-Type")` and `headers.get("content-TYPE")` will return the same value. +`fetch` çağrısı, durum kodu ve başlıkları gibi sunucunun yanıtı hakkında bilgi tutan bir `Response` nesnesine çözümlenen bir söz döndürür. Başlıklar, anahtarlarını (başlık adları) büyük/küçük harf duyarsız olarak ele alan `Map` benzeri bir nesneye sarılır, çünkü başlık adlarının büyük/küçük harf duyarlı olması gerekmez. Bu, `headers.get("Content-Type")` ve `headers.get("content-TYPE")` öğelerinin aynı değeri döndüreceği anlamına gelir. -Note that the promise returned by `fetch` resolves successfully even if the server responded with an error code. It can also be rejected if there is a network error or if the ((server)) that the request is addressed to can't be found. +Sunucu bir hata koduyla yanıt verse bile `fetch` tarafından döndürülen sözün başarıyla çözümlendiğini unutmayın. Bir ağ hatası varsa veya isteğin gönderildiği ((sunucu)) bulunamazsa da reddedilebilir. {{index [path, URL], "relative URL"}} -The first argument to `fetch` is the URL that should be requested. When that ((URL)) doesn't start with a protocol name (such as _http:_), it is treated as _relative_, which means it is interpreted relative to the current document. When it starts with a slash (/), it replaces the current path, which is the part after the server name. When it does not, the part of the current path up to and including its last ((slash character)) is put in front of the relative URL. +`fetch`'e ilk argüman, talep edilmesi gereken URL'dir. Bu ((URL)) bir protokol adıyla başlamadığında (_http:_ gibi), _relative_ olarak ele alınır, yani geçerli belgeye göre yorumlanır. Eğik çizgi (/) ile başladığında, sunucu adından sonraki kısım olan geçerli yolun yerini alır. Aksi takdirde, geçerli yolun son ((eğik çizgi karakteri)) kısmına kadar olan kısmı göreli URL'nin önüne konur. {{index "text method", "body (HTTP)", "Promise class"}} -To get at the actual content of a response, you can use its `text` method. Because the initial promise is resolved as soon as the response's headers have been received and because reading the response body might take a while longer, this again returns a promise. +Bir yanıtın gerçek içeriğine ulaşmak için `text` yöntemini kullanabilirsiniz. İlk söz, yanıtın üstbilgileri alınır alınmaz çözümlendiğinden ve yanıt gövdesini okumak biraz daha uzun sürebileceğinden, bu yine bir söz döndürür. ```{test: no} fetch("example/data.txt") @@ -197,11 +197,11 @@ fetch("example/data.txt") {{index "json method"}} -A similar method, called `json`, returns a promise that resolves to the value you get when parsing the body as ((JSON)) or rejects if it's not valid JSON. +Benzer bir yöntem olan `json`, gövdeyi ((JSON)) olarak çözümlediğinizde elde ettiğiniz değeri çözümleyen veya geçerli JSON değilse reddeden bir söz döndürür. {{index "GET method", "body (HTTP)", "DELETE method", "method property"}} -By default, `fetch` uses the `GET` method to make its request and does not include a request body. You can configure it differently by passing an object with extra options as a second argument. For example, this request tries to delete `example/data.txt`: +Varsayılan olarak, `fetch` istek yapmak için `GET` yöntemini kullanır ve bir istek gövdesi içermez. İkinci argüman olarak ekstra seçenekler içeren bir nesne ileterek farklı şekilde yapılandırabilirsiniz. Örneğin, bu istek `example/data.txt` dosyasını silmeye çalışır: ```{test: no} fetch("example/data.txt", {method: "DELETE"}).then(resp => { @@ -212,11 +212,11 @@ fetch("example/data.txt", {method: "DELETE"}).then(resp => { {{index "405 (HTTP status code)"}} -The 405 status code means "method not allowed", an HTTP server's way of saying "I'm afraid I can't do that". +405 durum kodu, HTTP sunucusunun "bunu yapamam" deme şekli olan "yönteme izin verilmiyor" anlamına gelir. {{index "Range header", "body property", "headers property"}} -To add a request body, you can include a `body` option. To set headers, there's the `headers` option. For example, this request includes a `Range` header, which instructs the server to return only part of a document. +Bir istek gövdesi eklemek için bir `body` seçeneği ekleyebilirsiniz. Başlıkları ayarlamak için `headers` seçeneği vardır. Örneğin, bu istek, sunucuya bir belgenin yalnızca bir kısmını döndürmesi talimatını veren bir `Range` başlığı içerir. ```{test: no} fetch("example/data.txt", {headers: {Range: "bytes=8-19"}}) @@ -225,75 +225,75 @@ fetch("example/data.txt", {headers: {Range: "bytes=8-19"}}) // → the content ``` -The browser will automatically add some request ((header))s, such as "Host" and those needed for the server to figure out the size of the body. But adding your own headers is often useful to include things such as authentication information or to tell the server which file format you'd like to receive. +Tarayıcı, "Host" gibi bazı istek ((başlık))larını ve sunucunun gövde boyutunu anlaması için gerekenleri otomatik olarak ekleyecektir. Ancak kendi başlıklarınızı eklemek, kimlik doğrulama bilgileri gibi şeyleri dahil etmek veya sunucuya hangi dosya biçimini almak istediğinizi söylemek için genellikle yararlıdır. {{id http_sandbox}} -## HTTP sandboxing +## HTTP kum havuzlamak {{index sandbox, [browser, security]}} -Making ((HTTP)) requests in web page scripts once again raises concerns about ((security)). The person who controls the script might not have the same interests as the person on whose computer it is running. More specifically, if I visit _themafia.org_, I do not want its scripts to be able to make a request to _mybank.com_, using identifying information from my browser, with instructions to transfer away all my money. +Web sayfası komut dosyalarında ((HTTP)) istekleri yapmak bir kez daha ((güvenlik)) ile ilgili endişeleri gündeme getirmektedir. Komut dosyasını kontrol eden kişi, bilgisayarında komut dosyası çalışan kişiyle aynı çıkarlara sahip olmayabilir. Daha açık bir ifadeyle, _themafia.org_ adresini ziyaret ettiğimde, script'in tarayıcımdaki kimlik bilgilerini kullanarak _mybank.com_ adresine tüm paramı transfer etme talimatları içeren bir talepte bulunmasını istemiyorum. -For this reason, browsers protect us by disallowing scripts to make HTTP requests to other ((domain))s (names such as _themafia.org_ and _mybank.com_). +Bu nedenle tarayıcılar, komut dosyalarının diğer ((domain))lere (_themafia.org_ ve _mybank.com_ gibi isimler) HTTP istekleri yapmasına izin vermeyerek bizi korur. {{index "Access-Control-Allow-Origin header", "cross-domain request"}} -This can be an annoying problem when building systems that want to access several domains for legitimate reasons. Fortunately, ((server))s can include a ((header)) like this in their ((response)) to explicitly indicate to the browser that it is okay for the request to come from another domain: +Bu, meşru nedenlerle birkaç etki alanına erişmek isteyen sistemler oluştururken can sıkıcı bir sorun olabilir. Neyse ki, ((sunucu))'lar ((yanıt))'larına bunun gibi bir ((başlık)) ekleyerek tarayıcıya isteğin başka bir etki alanından gelmesinin uygun olduğunu açıkça belirtebilirler: ```{lang: null} Access-Control-Allow-Origin: * ``` -## Appreciating HTTP +## HTTP'i takdir etmek {{index client, HTTP, [interface, HTTP]}} -When building a system that requires ((communication)) between a JavaScript program running in the ((browser)) (client-side) and a program on a ((server)) (server-side), there are several different ways to model this communication. +((Tarayıcı)) (istemci tarafı) üzerinde çalışan bir JavaScript programı ile ((sunucu)) (sunucu tarafı) üzerindeki bir program arasında ((iletişim)) gerektiren bir sistem oluştururken, bu iletişimi modellemenin birkaç farklı yolu vardır. {{index [network, abstraction], abstraction}} -A commonly used model is that of _((remote procedure call))s_. In this model, communication follows the patterns of normal function calls, except that the function is actually running on another machine. Calling it involves making a request to the server that includes the function's name and arguments. The response to that request contains the returned value. +Yaygın olarak kullanılan bir model _((remote procedure call))s_ modelidir. Bu modelde iletişim, işlevin aslında başka bir makinede çalışıyor olması dışında, normal işlev çağrılarının kalıplarını izler. Fonksiyonun çağrılması, sunucuya fonksiyonun adını ve argümanlarını içeren bir istek yapılmasını içerir. Bu isteğe verilen yanıt, döndürülen değeri içerir. -When thinking in terms of remote procedure calls, HTTP is just a vehicle for communication, and you will most likely write an abstraction layer that hides it entirely. +Uzaktan yordam çağrıları açısından düşündüğünüzde, HTTP sadece iletişim için bir araçtır ve büyük olasılıkla bunu tamamen gizleyen bir soyutlama katmanı yazacaksınız. {{index "media type", "document format", [method, HTTP]}} -Another approach is to build your communication around the concept of ((resource))s and ((HTTP)) methods. Instead of a remote procedure called `addUser`, you use a `PUT` request to `/users/larry`. Instead of encoding that user's properties in function arguments, you define a JSON document format (or use an existing format) that represents a user. The body of the `PUT` request to create a new resource is then such a document. A resource is fetched by making a `GET` request to the resource's URL (for example, `/user/larry`), which again returns the document representing the resource. +Diğer bir yaklaşım ise iletişiminizi ((kaynak)) ve ((HTTP)) yöntemleri kavramı etrafında oluşturmaktır. `addUser` adlı bir uzak prosedür yerine, `/users/larry` için bir `PUT` isteği kullanırsınız. Kullanıcının özelliklerini işlev argümanlarında kodlamak yerine, kullanıcıyı temsil eden bir JSON belge biçimi tanımlarsınız (veya mevcut bir biçimi kullanırsınız). Yeni bir kaynak oluşturmak için `PUT` isteğinin gövdesi böyle bir belgedir. Bir kaynak, kaynağın URL'sine (örneğin, `/user/larry`) bir `GET` isteği yapılarak getirilir ve bu istek yine kaynağı temsil eden belgeyi döndürür. -This second approach makes it easier to use some of the features that HTTP provides, such as support for caching resources (keeping a copy of a resource on the client for fast access). The concepts used in HTTP, which are well designed, can provide a helpful set of principles to design your server interface around. +Bu ikinci yaklaşım, kaynakların önbelleğe alınması (hızlı erişim için istemcide bir kopyasının tutulması) desteği gibi HTTP'nin sağladığı bazı özelliklerin kullanılmasını kolaylaştırır. HTTP'de kullanılan ve iyi tasarlanmış olan kavramlar, sunucu arayüzünüzü tasarlamak için yararlı bir dizi ilke sağlayabilir. -## Security and HTTPS +## Güvenlik ve HTTPS {{index "man-in-the-middle", security, HTTPS, [network, security]}} -Data traveling over the Internet tends to follow a long, dangerous road. To get to its destination, it must hop through anything from coffee shop Wi-Fi hotspots to networks controlled by various companies and states. At any point along its route it may be inspected or even modified. +İnternet üzerinden seyahat eden veriler uzun ve tehlikeli bir yol izleme eğilimindedir. Hedefine ulaşmak için kahve dükkanı Wi-Fi bağlantı noktalarından çeşitli şirketler ve devletler tarafından kontrol edilen ağlara kadar her yerden geçmesi gerekir. Güzergahı boyunca herhangi bir noktada denetlenebilir ve hatta değiştirilebilir. {{index tampering}} -If it is important that something remain secret, such as the ((password)) to your ((email)) account, or that it arrive at its destination unmodified, such as the account number you transfer money to via your bank's website, plain HTTP is not good enough. +((E-posta)) hesabınızın ((parolası)) gibi bir şeyin gizli kalması veya bankanızın web sitesi üzerinden para aktardığınız hesap numarası gibi hedefine değiştirilmeden ulaşması önemliyse, düz HTTP yeterince iyi değildir. {{index cryptography, encryption}} {{indexsee "Secure HTTP", HTTPS, [browser, security]}} -The secure ((HTTP)) protocol, used for ((URL))s starting with _https://_, wraps HTTP traffic in a way that makes it harder to read and tamper with. Before exchanging data, the client verifies that the server is who it claims to be by asking it to prove that it has a cryptographic ((certificate)) issued by a certificate authority that the browser recognizes. Next, all data going over the ((connection)) is encrypted in a way that should prevent eavesdropping and tampering. +_https://_ ile başlayan ((URL))ler için kullanılan güvenli ((HTTP)) protokolü, HTTP trafiğini okumayı ve kurcalamayı zorlaştıracak şekilde sarar. Veri alışverişinden önce istemci, sunucunun iddia ettiği kişi olduğunu, tarayıcının tanıdığı bir sertifika yetkilisi tarafından verilen kriptografik ((sertifika)) sahibi olduğunu kanıtlamasını isteyerek doğrular. Daha sonra, ((bağlantı)) üzerinden giden tüm veriler, gizli dinleme ve kurcalamayı önleyecek şekilde şifrelenir. -Thus, when it works right, ((HTTPS)) prevents other people from impersonating the website you are trying to talk to _and_ from snooping on your communication. It is not perfect, and there have been various incidents where HTTPS failed because of forged or stolen certificates and broken software, but it is a _lot_ safer than plain HTTP. +Böylece, doğru çalıştığında, ((HTTPS)) diğer kişilerin konuşmaya çalıştığınız web sitesini taklit etmesini _ve_ iletişiminizi gözetlemesini önler. Mükemmel değildir ve HTTPS'nin sahte veya çalıntı sertifikalar ve bozuk yazılımlar nedeniyle başarısız olduğu çeşitli olaylar olmuştur, ancak düz HTTP'den _çok_ daha güvenlidir. {{id forms}} -## Form fields +## Form alanları -Forms were originally designed for the pre-JavaScript Web to allow web sites to send user-submitted information in an HTTP request. This design assumes that interaction with the server always happens by navigating to a new page. +Formlar ilk olarak JavaScript öncesi Web için, web sitelerinin kullanıcı tarafından gönderilen bilgileri bir HTTP isteğiyle göndermesini sağlamak üzere tasarlanmıştır. Bu tasarım, sunucu ile etkileşimin her zaman yeni bir sayfaya gidilerek gerçekleştiğini varsayar. {{index [DOM, fields]}} -But their elements are part of the DOM like the rest of the page, and the DOM elements that represent form ((field))s support a number of properties and events that are not present on other elements. These make it possible to inspect and control such input fields with JavaScript programs and do things such as adding new functionality to a form or using forms and fields as building blocks in a JavaScript application. +Ancak öğeleri sayfanın geri kalanı gibi DOM'un bir parçasıdır ve form ((alan))'ları temsil eden DOM öğeleri diğer öğelerde bulunmayan bir dizi özelliği ve olayı destekler. Bunlar, bu tür giriş alanlarını JavaScript programlarıyla incelemeyi ve kontrol etmeyi ve bir forma yeni işlevler eklemek veya formları ve alanları bir JavaScript uygulamasında yapı taşları olarak kullanmak gibi şeyler yapmayı mümkün kılar. {{index "form (HTML tag)"}} -A web form consists of any number of input ((field))s grouped in a `<form>` tag. HTML allows several different styles of fields, ranging from simple on/off checkboxes to drop-down menus and fields for text input. This book won't try to comprehensively discuss all field types, but we'll start with a rough overview. +Bir web formu, bir `<form>` etiketi içinde gruplandırılmış herhangi bir sayıda girdi ((alan)) içerir. HTML, basit açma/kapama onay kutularından açılır menülere ve metin girişi için alanlara kadar çeşitli farklı alan stillerine izin verir. Bu kitap tüm alan türlerini kapsamlı bir şekilde tartışmaya çalışmayacaktır, ancak kabaca bir genel bakışla başlayacağız. {{index "input (HTML tag)", "type attribute"}} @@ -303,17 +303,17 @@ A lot of field types use the `<input>` tag. This tag's `type` attribute is used {{table {cols: [1,5]}}} -| `text` | A single-line ((text field)) +| `text` | A single-line ((text field)) | `password` | Same as `text` but hides the text that is typed | `checkbox` | An on/off switch -| `color` | A color -| `date` | A calendar date -| `radio` | (Part of) a ((multiple-choice)) field -| `file` | Allows the user to choose a file from their computer +| `color` | A color +| `date` | A calendar date +| `radio` | (Part of) a ((multiple-choice)) field +| `file` | Allows the user to choose a file from their computer {{index "value attribute", "checked attribute", "form (HTML tag)"}} -Form fields do not necessarily have to appear in a `<form>` tag. You can put them anywhere in a page. Such form-less fields cannot be ((submit))ted (only a form as a whole can), but when responding to input with JavaScript, we often don't want to submit our fields normally anyway. +Form alanlarının mutlaka bir `<form>` etiketi içinde görünmesi gerekmez. Bunları sayfanın herhangi bir yerine koyabilirsiniz. Bu tür formsuz alanlar ((submit)) edilemez (yalnızca bir bütün olarak form edilebilir), ancak JavaScript ile girdiye yanıt verirken, genellikle alanlarımızı normal şekilde göndermek istemeyiz. ```{lang: html} <p><input type="text" value="abc"> (text)</p> @@ -329,17 +329,17 @@ Form fields do not necessarily have to appear in a `<form>` tag. You can put the {{if book -The fields created with this HTML code look like this: +Bu HTML kodu ile oluşturulan alanlar aşağıdaki gibi görünür: -{{figure {url: "img/form_fields.png", alt: "Screenshot showing various types of input tags", width: "4cm"}}} +{{figure {url: "img/form_fields.png", alt: "Çeşitli giriş etiketi türlerini gösteren ekran görüntüsü", width: "4cm"}}} if}} -The JavaScript interface for such elements differs with the type of the element. +Bu tür öğeler için JavaScript arayüzü, öğenin türüne göre farklılık gösterir. {{index "textarea (HTML tag)", "text field"}} -Multiline text fields have their own tag, `<textarea>`, mostly because using an attribute to specify a multiline starting value would be awkward. The `<textarea>` tag requires a matching `</textarea>` closing tag and uses the text between those two, instead of the `value` attribute, as starting text. +Çok satırlı metin alanlarının kendine özgü bir etiketi vardır: `<textarea>`. Bunun nedeni, çok satırlı bir başlangıç değerini belirtmek için bir özellik kullanmanın garip olmasıdır. `<textarea>` etiketi, bir eşleşen `</textarea>` kapanış etiketine ihtiyaç duyar ve başlangıç metni olarak `value` özelliği yerine bu iki etiket arasındaki metni kullanır. ```{lang: html} <textarea> @@ -351,7 +351,7 @@ three {{index "select (HTML tag)", "option (HTML tag)", "multiple choice", "drop-down menu"}} -Finally, the `<select>` tag is used to create a field that allows the user to select from a number of predefined options. +Son olarak, `<select>` etiketi, kullanıcının önceden tanımlanmış seçenekler arasından seçim yapmasını sağlayan bir alan oluşturmak için kullanılır. ```{lang: html} <select> @@ -363,31 +363,31 @@ Finally, the `<select>` tag is used to create a field that allows the user to se {{if book -Such a field looks like this: +Böyle bir alan şu şekilde görünür: -{{figure {url: "img/form_select.png", alt: "Screenshot showing a select field", width: "4cm"}}} +{{figure {url: "img/form_select.png", alt: "Ekran görüntüsü, bir `<select>` alanını gösteriyor.", width: "4cm"}}} if}} {{index "change event"}} -Whenever the value of a form field changes, it will fire a `"change"` event. +Bir form alanının değeri her değiştiğinde, bir `"change"` olayı tetiklenir. -## Focus +## Odak {{index keyboard, focus}} {{indexsee "keyboard focus", focus}} -Unlike most elements in HTML documents, form fields can get _keyboard ((focus))_. When clicked, moved to with the [tab]{keyname} key, or activated in some other way, they become the currently active element and the recipient of keyboard ((input)). +HTML belgelerindeki çoğu elementin aksine, form alanları _klavye ((odak))_ alabilir. Tıklandığında, [tab]{keyname} tuşu ile geçildiğinde veya başka bir şekilde etkinleştirildiğinde, o anda aktif olan element haline gelir ve klavye ((girdisi)) alıcısı olur. {{index "option (HTML tag)", "select (HTML tag)"}} -Thus, you can type into a ((text field)) only when it is focused. Other fields respond differently to keyboard events. For example, a `<select>` menu tries to move to the option that contains the text the user typed and responds to the arrow keys by moving its selection up and down. +Bu nedenle, bir ((metin alanı))na yalnızca odaklanıldığında yazabilirsiniz. Diğer alanlar klavye olaylarına farklı şekilde tepki verir. Örneğin, bir `<select>` menüsü, kullanıcının yazdığı metni içeren seçeneğe geçmeye çalışır ve ok tuşlarına yukarı ve aşağı seçim yaparak yanıt verir. {{index "focus method", "blur method", "activeElement property"}} -We can control ((focus)) from JavaScript with the `focus` and `blur` methods. The first moves focus to the DOM element it is called on, and the second removes focus. The value in `document.activeElement` corresponds to the currently focused element. +JavaScript ile ((odak)) kontrolünü `focus` ve `blur` metodlarıyla sağlayabiliriz. İlk metod, çağrıldığı DOM elementine odaklanmayı taşır, ikinci metod ise odağı kaldırır. `document.activeElement` içindeki değer, şu anda odaklanılmış olan elemana karşılık gelir. ```{lang: html} <input type="text"> @@ -403,11 +403,11 @@ We can control ((focus)) from JavaScript with the `focus` and `blur` methods. Th {{index "autofocus attribute"}} -For some pages, the user is expected to want to interact with a form field immediately. JavaScript can be used to ((focus)) this field when the document is loaded, but HTML also provides the `autofocus` attribute, which produces the same effect while letting the browser know what we are trying to achieve. This gives the browser the option to disable the behavior when it is not appropriate, such as when the user has put the focus on something else. +Bazı sayfalarda, kullanıcının bir form alanıyla hemen etkileşime geçmesi beklenir. Belge yüklendiğinde JavaScript kullanılarak bu alan ((odaklanabilir)), ancak HTML ayrıca aynı etkiyi sağlayan `autofocus` özelliğini sunar ve tarayıcının ne yapmaya çalıştığımızı anlamasını sağlar. Bu, tarayıcıya, kullanıcının odağı başka bir yere koyduğu durumlarda bu davranışı devre dışı bırakma seçeneği sunar. {{index "tab key", keyboard, "tabindex attribute", "a (HTML tag)"}} -Browsers allow the user to move the focus through the document by pressing the [tab]{keyname} key to move to the next focusable element, and [shift-tab]{keyname} to move back to the previous element. By default, elements are visited in the order they appear in the document. It is possible to use the `tabindex` attribute to change this order. The following example document will let the focus jump from the text input to the OK button, rather than going through the help link first: +Tarayıcılar ayrıca kullanıcının [tab]{keyname} tuşunu basarak odağı belge boyunca hareket ettirmesine, bir sonraki odaklanabilir elemente geçmesine ve [shift-tab]{keyname} tuşunu basarak bir önceki elemana geri dönmesine olanak tanır. Varsayılan olarak, elemanlar belgede göründükleri sırayla ziyaret edilir. Bu sıralamayı değiştirmek için `tabindex` özelliği kullanılabilir. Aşağıdaki örnek belge, odağın önce yardım bağlantısına gitmek yerine, metin girişinden OK butonuna atlamasına olanak tanır: ```{lang: html, focus: true} <input type="text" tabindex=1> <a href=".">(help)</a> @@ -416,40 +416,40 @@ Browsers allow the user to move the focus through the document by pressing the [ {{index "tabindex attribute"}} -By default, most types of HTML elements cannot be focused. But you can add a `tabindex` attribute to any element that will make it focusable. A `tabindex` of 0 makes an element focusable without affecting the focus order. +Varsayılan olarak, çoğu HTML elemanı odaklanabilir değildir. Ancak, odaklanabilir hale getirmek için herhangi bir elemana `tabindex` özelliği ekleyebilirsiniz. Bir `tabindex` değeri 0 olan bir eleman, odak sırasını etkilemeden odaklanabilir hale gelir. -## Disabled fields +## Engelli alanlar {{index "disabled attribute"}} -All ((form)) ((field))s can be _disabled_ through their `disabled` attribute. It is an ((attribute)) that can be specified without value—the fact that it is present at all disables the element. +Tüm ((form)) ((alanları)) `disabled` özelliği aracılığıyla _devre dışı_ bırakılabilir. Bu, değeri olmadan belirtilebilen bir ((özelliktir)); yalnızca mevcut olması, elementi devre dışı bırakır. ```{lang: html} <button>I'm all right</button> <button disabled>I'm out</button> ``` -Disabled fields cannot be ((focus))ed or changed, and browsers make them look gray and faded. +Devre dışı alanlar ((odaklanamaz)) veya değiştirilemez ve tarayıcılar, bunları gri ve solmuş şekilde gösterir. {{if book -{{figure {url: "img/button_disabled.png", alt: "Screenshot of a disabled button", width: "3cm"}}} +{{figure {url: "img/button_disabled.png", alt: "Devre dışı bırakılmış bir butonun ekran görüntüsü", width: "3cm"}}} if}} {{index "user experience"}} -When a program is in the process of handling an action caused by some ((button)) or other control that might require communication with the server and thus take a while, it can be a good idea to disable the control until the action finishes. That way, when the user gets impatient and clicks it again, they don't accidentally repeat their action. +Bir program, bazı ((buton)) veya başka bir kontrol tarafından tetiklenen ve sunucu ile iletişim gerektirebilecek (ve dolayısıyla bir süre alabilecek) bir eylemi işlerken, eylem bitene kadar kontrolü devre dışı bırakmak iyi bir fikir olabilir. Böylece, kullanıcı sabırsızlanıp tekrar tıkladığında, eylemi yanlışlıkla tekrarlamamış olur. -## The form as a whole +## Formun tamamı {{index "array-like object", "form (HTML tag)", "form property", "elements property"}} -When a ((field)) is contained in a `<form>` element, its DOM element will have a `form` property linking back to the form's DOM element. The `<form>` element, in turn, has a property called `elements` that contains an array-like collection of the fields inside it. +Bir ((alan)) bir `<form>` elemanının içinde bulunduğunda, DOM elemanı, formun DOM elemanına geri bağlanan bir `form` özelliğine sahip olacaktır. `<form>` elemanı ise, içinde bulunan alanların array-benzeri bir koleksiyonunu içeren `elements` adında bir özelliğe sahiptir. {{index "elements property", "name attribute"}} -The `name` attribute of a form field determines the way its value will be identified when the form is ((submit))ted. It can also be used as a property name when accessing the form's `elements` property, which acts both as an array-like object (accessible by number) and a ((map)) (accessible by name). +Bir form alanının `name` özelliği, form ((gönderildiğinde)) değerinin nasıl tanımlanacağını belirler. Ayrıca, formun `elements` özelliğine erişirken bir özellik adı olarak da kullanılabilir; bu özellik hem array-benzeri bir nesne (sayıyla erişilebilir) hem de bir ((harita)) (isimle erişilebilir) olarak işlev görür. ```{lang: html} <form action="example/submit.html"> @@ -470,11 +470,11 @@ The `name` attribute of a form field determines the way its value will be identi {{index "button (HTML tag)", "type attribute", submit, "enter key"}} -A button with a `type` attribute of `submit` will, when pressed, cause the form to be submitted. Pressing [enter]{keyname} when a form field is focused has the same effect. +Bir `type` özelliği `submit` olan bir buton, tıklandığında formun gönderilmesine neden olur. Bir form alanı odaklandığında [enter]{keyname} tuşuna basmak aynı etkiye yol açar. {{index "submit event", "event handling", "preventDefault method", "page reload", "GET method", "POST method"}} -Submitting a ((form)) normally means that the ((browser)) navigates to the page indicated by the form's `action` attribute, using either a `GET` or a `POST` ((request)). But before that happens, a `"submit"` event is fired. You can handle this event with JavaScript and prevent this default behavior by calling `preventDefault` on the event object. +Bir ((form))u göndermek genellikle, ((tarayıcı))nın formun `action` özelliğinde belirtilen sayfaya, ya bir `GET` ya da bir `POST` ((isteği)) kullanarak yönlendirilmesi anlamına gelir. Ancak bundan önce, bir `"submit"` olayı tetiklenir. Bu olayı JavaScript ile işleyebilir ve olay nesnesi üzerinde `preventDefault` çağrısı yaparak bu varsayılan davranışı engelleyebilirsiniz. ```{lang: html} <form> @@ -492,21 +492,21 @@ Submitting a ((form)) normally means that the ((browser)) navigates to the page {{index "submit event", validation}} -Intercepting `"submit"` events in JavaScript has various uses. We can write code to verify that the values the user entered make sense and immediately show an error message instead of submitting the form. Or we can disable the regular way of submitting the form entirely, as in the example, and have our program handle the input, possibly using `fetch` to send it to a server without reloading the page. +JavaScript'te `"submit"` olaylarını yakalamanın çeşitli kullanımları vardır. Kullanıcının girdiği değerlerin mantıklı olup olmadığını doğrulayan bir kod yazabilir ve formu göndermek yerine hemen bir hata mesajı gösterebiliriz. Veya formun gönderilme işleminin normal yolunu tamamen devre dışı bırakabiliriz, örneğin bu örnekte olduğu gibi, ve programımızın girdiyi işlemesini sağlayabiliriz, muhtemelen sayfayı yenilemeden sunucuya göndermek için `fetch` kullanarak. -## Text fields +## Metin alanları {{index "value attribute", "input (HTML tag)", "text field", "textarea (HTML tag)", [DOM, fields], [interface, object]}} -Fields created by `<textarea>` tags, or `<input>` tags with a type of `text` or `password`, share a common interface. Their DOM elements have a `value` property that holds their current content as a string value. Setting this property to another string changes the field's content. +`<textarea>` etiketleriyle oluşturulan alanlar veya `text` veya `password` türünde olan `<input>` etiketleri, ortak bir arayüze sahiptir. Bu elemanların DOM elemanları, mevcut içeriklerini bir string değeri olarak tutan bir `value` özelliğine sahiptir. Bu özelliği başka bir string ile ayarlamak, alanın içeriğini değiştirir. {{index "selectionStart property", "selectionEnd property"}} -The `selectionStart` and `selectionEnd` properties of ((text field))s give us information about the ((cursor)) and ((selection)) in the ((text)). When nothing is selected, these two properties hold the same number, indicating the position of the cursor. For example, 0 indicates the start of the text, and 10 indicates the cursor is after the 10^th^ ((character)). When part of the field is selected, the two properties will differ, giving us the start and end of the selected text. Like `value`, these properties may also be written to. +((Metin alanı))nın `selectionStart` ve `selectionEnd` özellikleri, ((kursor)) ve ((seçim)) hakkında bize bilgi verir. Hiçbir şey seçilmediğinde, bu iki özellik aynı sayıyı tutar ve bu da kursorun konumunu belirtir. Örneğin, 0 metnin başlangıcını, 10 ise kursorun 10^'uncu^ ((karakter))den sonrasını belirtir. Alanın bir kısmı seçildiğinde, bu iki özellik farklı olur ve bize seçilen metnin başlangıcını ve sonunu verir. `value` gibi, bu özelliklere de yazılabilir. {{index Khasekhemwy, "textarea (HTML tag)", keyboard, "event handling"}} -Imagine you are writing an article about Khasekhemwy but have some trouble spelling his name. The following code wires up a `<textarea>` tag with an event handler that, when you press F2, inserts the string "Khasekhemwy" for you. +Farz edelim ki Khasekhemwy hakkında bir makale yazıyorsunuz, ancak adını yazmakta zorlanıyorsunuz. Aşağıdaki kod, F2 tuşuna basıldığında "Khasekhemwy" stringini sizin için ekleyen bir olay işleyicisiyle bir `<textarea>` etiketini bağlar. ```{lang: html} <textarea></textarea> @@ -531,13 +531,13 @@ Imagine you are writing an article about Khasekhemwy but have some trouble spell {{index "replaceSelection function", "text field"}} -The `replaceSelection` function replaces the currently selected part of a text field's content with the given word and then moves the ((cursor)) after that word so that the user can continue typing. +`replaceSelection` fonksiyonu, bir metin alanının mevcut seçili kısmını verilen kelimeyle değiştirir ve ardından ((kursor))u o kelimenin sonrasına taşır, böylece kullanıcı yazmaya devam edebilir. {{index "change event", "input event"}} -The `"change"` event for a ((text field)) does not fire every time something is typed. Rather, it fires when the field loses ((focus)) after its content was changed. To respond immediately to changes in a text field, you should register a handler for the `"input"` event instead, which fires for every time the user types a character, deletes text, or otherwise manipulates the field's content. +Bir ((metin alanı)) için `"change"` olayı, her seferinde bir şey yazıldığında tetiklenmez. Bunun yerine, alanın içeriği değiştikten sonra odağını kaybettiğinde tetiklenir. Bir metin alanındaki değişikliklere hemen yanıt vermek için, bunun yerine kullanıcı her karakter yazdığında, metin sildiğinde veya alanın içeriğini başka şekilde manipüle ettiğinde tetiklenen `"input"` olayı için bir işleyici kaydetmelisiniz. -The following example shows a text field and a counter displaying the current length of the text in the field: +Aşağıdaki örnek, bir metin alanını ve alandaki metnin mevcut uzunluğunu gösteren bir sayacı gösterir: ```{lang: html} <input type="text"> length: <span id="length">0</span> @@ -550,11 +550,11 @@ The following example shows a text field and a counter displaying the current le </script> ``` -## Checkboxes and radio buttons +## Onay kutuları ve radyo düğmeleri {{index "input (HTML tag)", "checked attribute"}} -A ((checkbox)) field is a binary toggle. Its value can be extracted or changed through its `checked` property, which holds a Boolean value. +Bir ((checkbox)) alanı ikili bir anahtarlamadır. Değeri, bir Boolean değeri tutan `checked` özelliği aracılığıyla alınabilir veya değiştirilebilir. ```{lang: html} <label> @@ -571,11 +571,11 @@ A ((checkbox)) field is a binary toggle. Its value can be extracted or changed t {{index "for attribute", "id attribute", focus, "label (HTML tag)", labeling}} -The `<label>` tag associates a piece of document with an input ((field)). Clicking anywhere on the label will activate the field, which focuses it and toggles its value when it is a checkbox or radio button. +`<label>` etiketi, bir belge parçasını bir input ((alanı))yla ilişkilendirir. Etikete herhangi bir yere tıklamak, alanı etkinleştirir, ona odaklanır ve eğer bir checkbox veya radyo butonuysa, değerini değiştirir. {{index "input (HTML tag)", "multiple-choice"}} -A ((radio button)) is similar to a checkbox, but it's implicitly linked to other radio buttons with the same `name` attribute so that only one of them can be active at any time. +Bir ((radyo butonu)), bir checkbox'a benzer, ancak aynı `name` özelliğine sahip diğer radyo butonlarıyla örtük olarak ilişkilendirilir, böylece yalnızca bir tanesi her zaman aktif olabilir. ```{lang: html} Color: @@ -600,29 +600,29 @@ Color: {{index "name attribute", "querySelectorAll method"}} -The ((square brackets)) in the CSS query given to `querySelectorAll` are used to match attributes. It selects elements whose `name` attribute is `"color"`. +`querySelectorAll`'a verilen CSS sorgusunda, ((köşeli parantezler)) özellikleri eşleştirmek için kullanılır. Bu, `name` özelliği `"color"` olan elemanları seçer. -## Select fields +## Seçim alanları {{index "select (HTML tag)", "multiple-choice", "option (HTML tag)"}} -Select fields are conceptually similar to radio buttons—they also allow the user to choose from a set of options. But where a radio button puts the layout of the options under our control, the appearance of a `<select>` tag is determined by the browser. +Select alanları, kavramsal olarak radyo butonlarına benzer—kullanıcının bir dizi seçenek arasından seçim yapmasına olanak tanır. Ancak bir radyo butonu seçeneklerin düzenini bizim kontrolümüze bırakırken, `<select>` etiketinin görünümü tarayıcı tarafından belirlenir. {{index "multiple attribute", "drop-down menu"}} -Select fields also have a variant that is more akin to a list of checkboxes, rather than radio boxes. When given the `multiple` attribute, a `<select>` tag will allow the user to select any number of options, rather than just a single option. Whereas a regular select field is drawn as a _drop-down_ control, which shows the inactive options only when you open it, a field with `multiple` enabled shows multiple options at the same time, allowing the user to enable or disable them individually. +Select alanlarının, radyo kutularına değil, daha çok bir dizi checkbox'a benzeyen bir varyantı da vardır. `multiple` özelliği verildiğinde, bir `<select>` etiketi, kullanıcıya yalnızca bir seçenek yerine istediği sayıda seçenek seçme olanağı tanır. Bu, çoğu tarayıcıda, genellikle seçenekleri yalnızca açıldığında gösteren bir _açılır_ kontrolü olarak çizilen normal bir select alanından farklı olarak görüntülenir. {{index "option (HTML tag)", "value attribute"}} -Each `<option>` tag has a value. This value can be defined with a `value` attribute. When that is not given, the ((text)) inside the option will count as its value. The `value` property of a `<select>` element reflects the currently selected option. For a `multiple` field, though, this property doesn't mean much since it will give the value of only _one_ of the currently selected options. +Her `<option>` etiketinin bir değeri vardır. Bu değer, bir `value` özelliği ile tanımlanabilir. Eğer bu verilmemişse, seçeneğin içindeki ((metin)) değeri olarak sayılır. Bir `<select>` elemanının `value` özelliği, şu anda seçili olan seçeneği yansıtır. Ancak bir `multiple` alanı için bu özellik çok anlamlı değildir, çünkü yalnızca şu anda seçili olan _bir_ seçeneğin değerini verir. {{index "select (HTML tag)", "options property", "selected attribute"}} -The `<option>` tags for a `<select>` field can be accessed as an array-like object through the field's `options` property. Each option has a property called `selected`, which indicates whether that option is currently selected. The property can also be written to select or deselect an option. +Bir `<select>` alanı için `<option>` etiketlerine, alanın `options` özelliği aracılığıyla array-benzeri bir nesne olarak erişilebilir. Her seçeneğin, o seçeneğin şu anda seçili olup olmadığını belirten `selected` adında bir özelliği vardır. Bu özellik, bir seçeneği seçmek veya seçiliğini kaldırmak için de yazılabilir. {{index "multiple attribute", "binary number"}} -This example extracts the selected values from a `multiple` select field and uses them to compose a binary number from individual bits. Hold [control]{keyname} (or [command]{keyname} on a Mac) to select multiple options. +Bu örnek, bir `multiple` select alanından seçili değerleri çıkarır ve bunları bireysel bitlerden bir ikili sayı oluşturmak için kullanır. Birden fazla seçenek seçmek için [control]{keyname} tuşunu (veya bir Mac'te [command]{keyname} tuşunu) basılı tutun. ```{lang: html} <select multiple> @@ -646,13 +646,13 @@ This example extracts the selected values from a `multiple` select field and use </script> ``` -## File fields +## Dosya alanları -{{index file, "hard drive", "file system", security, "file field", "input (HTML tag)"}} +{{index file, "hard drive", "filesystem", security, "file field", "input (HTML tag)"}} -File fields were originally designed as a way to ((upload)) files from the user's machine through a form. In modern browsers, they also provide a way to read such files from JavaScript programs. The field acts as a kind of gatekeeper. The script cannot simply start reading private files from the user's computer, but if the user selects a file in such a field, the browser interprets that action to mean that the script may read the file. +Dosya alanları, başlangıçta kullanıcının bilgisayarından bir dosya yüklemek için bir form aracılığıyla tasarlanmıştı. Modern tarayıcılarda, bunlar aynı zamanda JavaScript programlarından bu tür dosyaları okuma yolu da sağlar. Alan, bir tür kapı bekçisi gibi davranır. Script, kullanıcının bilgisayarındaki özel dosyaları doğrudan okumaya başlayamaz, ancak kullanıcı bu alanda bir dosya seçtiğinde, tarayıcı bu eylemi scriptin dosyayı okuyabileceği şeklinde yorumlar. -A file field usually looks like a button labeled with something like "choose file" or "browse", with information about the chosen file next to it. +Bir dosya alanı genellikle "dosya seç" veya "göz at" gibi bir etiketle yazılmış bir buton gibi görünür ve yanındaki seçilen dosya hakkında bilgi içerir. ```{lang: html} <input type="file"> @@ -670,17 +670,17 @@ A file field usually looks like a button labeled with something like "choose fil {{index "multiple attribute", "files property"}} -The `files` property of a ((file field)) element is an ((array-like object)) (once again, not a real array) containing the files chosen in the field. It is initially empty. The reason there isn't simply a `file` property is that file fields also support a `multiple` attribute, which makes it possible to select multiple files at the same time. +Bir ((dosya alanı)) elemanının `files` özelliği, alanda seçilen dosyaları içeren bir ((array-benzeri nesne))dir (yine, gerçek bir dizi değildir). Başlangıçta boştur. Basitçe bir `file` özelliği olmamasının nedeni, dosya alanlarının aynı zamanda bir `multiple` özelliğini desteklemesidir; bu da aynı anda birden fazla dosya seçmeyi mümkün kılar. {{index "File type"}} -The objects in `files` have properties such as `name` (the filename), `size` (the file's size in bytes, which are chunks of 8 bits), and `type` (the media type of the file, such as `text/plain` or `image/jpeg`). +`files` içindeki nesneler, `name` (dosya adı), `size` (dosyanın boyutu byte cinsinden, 8 bitlik parçalar), ve `type` (dosyanın medya türü, örneğin `text/plain` veya `image/jpeg`) gibi özelliklere sahiptir. {{index ["asynchronous programming", "reading files"], "file reading", "FileReader class"}} {{id filereader}} -What it does not have is a property that contains the content of the file. Getting at that is a little more involved. Since reading a file from disk can take time, the interface is asynchronous to avoid freezing the window. +Dosyanın içeriğini içeren bir özelliğe sahip değildir. Buna erişmek biraz daha karmaşıktır. Diskten bir dosya okumak zaman alabileceğinden, belgenin donmaması için arayüzün asenkron olması gerekir. ```{lang: html} <input type="file" multiple> @@ -701,11 +701,11 @@ What it does not have is a property that contains the content of the file. Getti {{index "FileReader class", "load event", "readAsText method", "result property"}} -Reading a file is done by creating a `FileReader` object, registering a `"load"` event handler for it, and calling its `readAsText` method, giving it the file we want to read. Once loading finishes, the reader's `result` property contains the file's content. +Bir dosya okumak, bir `FileReader` nesnesi oluşturmak, ona bir `"load"` olay işleyicisi kaydetmek ve `readAsText` metodunu çağırarak okumak istediğimiz dosyayı vermekle yapılır. Yükleme tamamlandığında, okuyucunun `result` özelliği dosyanın içeriğini içerir. {{index "error event", "FileReader class", "Promise class"}} -`FileReader`s also fire an `"error"` event when reading the file fails for any reason. The error object itself will end up in the reader's `error` property. This interface was designed before promises became part of the language. You could wrap it in a promise like this: +`FileReader`'lar, dosya okuma herhangi bir nedenle başarısız olduğunda bir `"error"` olayı da tetikler. Hata nesnesi, okuyucunun `error` özelliğinde bulunur. Bu arayüz, promises dilin bir parçası olmadan önce tasarlanmıştır. Bunu bir promise içinde şöyle sarmalayabilirsiniz: ``` function readFileText(file) { @@ -720,19 +720,19 @@ function readFileText(file) { } ``` -## Storing data client-side +## Verilerin istemci tarafında depolanması {{index "web application"}} -Simple ((HTML)) pages with a bit of JavaScript can be a great format for "((mini application))s"—small helper programs that automate basic tasks. By connecting a few form ((field))s with event handlers, you can do anything from converting between centimeters and inches to computing passwords from a master password and a website name. +Basit ((HTML)) sayfaları ve biraz JavaScript, "((mini uygulama))lar" için harika bir format olabilir—temel görevleri otomatikleştiren küçük yardımcı programlar. Birkaç form ((alanı))nı olay işleyicileriyle bağlayarak, santimetre ve inç arasında dönüşüm yapmaktan, bir ana şifre ve bir web sitesi adıyla şifreler hesaplamaya kadar her şeyi yapabilirsiniz. {{index persistence, [binding, "as state"], [browser, storage]}} -When such an application needs to remember something between sessions, you cannot use JavaScript bindings—those are thrown away every time the page is closed. You could set up a server, connect it to the Internet, and have your application store something there. We will see how to do that in [Chapter ?](node). But that's a lot of extra work and complexity. Sometimes it is enough to just keep the data in the ((browser)). +Böyle bir uygulama oturumlar arasında bir şey hatırlaması gerektiğinde, JavaScript bağlamaları kullanamazsınız—bunlar sayfa her kapandığında silinir. Bir sunucu kurabilir, onu İnternete bağlayabilir ve uygulamanızın verileri orada depolamasını sağlayabilirsiniz. Bunu nasıl yapacağımızı [Bölüm ?](node)'de göreceğiz. Ama bu, çok fazla ekstra iş ve karmaşıklık anlamına gelir. Bazen veriyi sadece ((tarayıcı))da tutmak yeterli olabilir. {{index "localStorage object", "setItem method", "getItem method", "removeItem method"}} -The `localStorage` object can be used to store data in a way that survives ((page reload))s. This object allows you to file string values under names. +`localStorage` nesnesi, verilerin ((sayfa yeniden yükleme))lerine rağmen saklanmasını sağlar. Bu nesne, adlar altında dize (string) değerler dosyalamanıza olanak tanır. ``` localStorage.setItem("username", "marijn"); @@ -743,19 +743,19 @@ localStorage.removeItem("username"); {{index "localStorage object"}} -A value in `localStorage` sticks around until it is overwritten, it is removed with `removeItem`, or the user clears their local data. +`localStorage`'daki bir değer, üzerine yazılana kadar kalır, `removeItem` ile silinir veya kullanıcı yerel verilerini temizlerse kaldırılır. {{index security}} -Sites from different ((domain))s get different storage compartments. That means data stored in `localStorage` by a given website can, in principle, be read (and overwritten) only by scripts on that same site. +Farklı ((domain))lerden gelen siteler, farklı depolama bölmeleri alır. Bu, bir web sitesinin `localStorage`'a kaydettiği verilerin, prensipte yalnızca o aynı sitedeki betikler tarafından okunabilir (ve üzerine yazılabilir) olduğu anlamına gelir. {{index "localStorage object"}} -Browsers do enforce a limit on the size of the data a site can store in `localStorage`. That restriction, along with the fact that filling up people's ((hard drive))s with junk is not really profitable, prevents the feature from eating up too much space. +Tarayıcılar, bir sitenin `localStorage`'a depolayabileceği veri miktarı üzerinde bir sınır koyar. Bu kısıtlama, ayrıca insanların ((hard disk))lerini gereksiz verilerle doldurmanın gerçekten karlı olmaması gerçeği, bu özelliğin çok fazla alan kaplamasını engeller. {{index "localStorage object", "note-taking example", "select (HTML tag)", "button (HTML tag)", "textarea (HTML tag)"}} -The following code implements a crude note-taking application. It keeps a set of named notes and allows the user to edit notes and create new ones. +Aşağıdaki kod, basit bir not alma uygulamasını uygular. Adlandırılmış bir dizi not tutar ve kullanıcıya notları düzenleme ve yenilerini oluşturma imkanı verir. ```{lang: html, startCode: true} Notes: <select></select> <button>Add</button><br> @@ -807,23 +807,23 @@ Notes: <select></select> <button>Add</button><br> {{index "getItem method", JSON, "?? operator", "default value"}} -The script gets its starting state from the `"Notes"` value stored in `localStorage` or, if that is missing, creates an example state that has only a shopping list in it. Reading a field that does not exist from `localStorage` will yield `null`. Passing `null` to `JSON.parse` will make it parse the string `"null"` and return `null`. Thus, the `??` operator can be used to provide a default value in a situation like this. +Betik, başlangıç durumunu `localStorage`'da depolanan `"Notes"` değerinden alır veya bu değer eksikse içinde yalnızca bir alışveriş listesi bulunan örnek bir durum oluşturur. `localStorage`'dan var olmayan bir alan okunduğunda `null` döner. `null`'ı `JSON.parse`'a geçirmek, `"null"` dizesini çözümlemesine ve `null` döndürmesine neden olur. Bu nedenle, `||` operatörü, böyle bir durumda varsayılan bir değer sağlamak için kullanılabilir. -The `setState` method makes sure the DOM is showing a given state and stores the new state to `localStorage`. Event handlers call this function to move to a new state. +`setState` metodu, DOM'un verilen bir durumu gösterdiğinden emin olur ve yeni durumu `localStorage`'a depolar. Olay işleyicileri, yeni bir duruma geçmek için bu fonksiyonu çağırır. {{index [object, creation], property, "computed property"}} -The `...` syntax in the example is used to create a new object that is a clone of the old `state.notes`, but with one property added or overwritten. It uses ((spread)) syntax to first add the properties from the old object, and then set a new property. The ((square brackets)) notation in the object literal is used to create a property whose name is based on some dynamic value. +Örnekteki `...` sözdizimi, eski `state.notes` nesnesinin bir kopyasını oluşturan yeni bir nesne yaratmak için kullanılır, ancak bir özellik eklenir veya üzerine yazılır. İlk olarak eski nesneden özellikleri eklemek için ((spread)) sözdizimi kullanılır, ardından yeni bir özellik atanır. Nesne literal'inde ((square brackets)) gösterimi, adının bazı dinamik değerlere dayalı olduğu bir özellik oluşturmak için kullanılır. {{index "sessionStorage object", [browser, storage]}} -There is another object, similar to `localStorage`, called `sessionStorage`. The difference between the two is that the content of `sessionStorage` is forgotten at the end of each _((session))_, which for most browsers means whenever the browser is closed. +`localStorage`'a benzer bir başka nesne daha vardır, o da `sessionStorage`'dır. İkisi arasındaki fark, `sessionStorage`'ın içeriğinin her _((session))_ sonunda unutulmasıdır; bu, çoğu tarayıcı için tarayıcı kapandığında anlamına gelir. -## Summary +## Özet -In this chapter, we discussed how the HTTP protocol works. A _client_ sends a request, which contains a method (usually `GET`) and a path that identifies a resource. The _server_ then decides what to do with the request and responds with a status code and a response body. Both requests and responses may contain headers that provide additional information. +Bu bölümde, HTTP protokolünün nasıl çalıştığını tartıştık. Bir _istemci_ bir istek gönderir, bu istek genellikle bir `GET` metodu ve bir kaynağı tanımlayan bir yol içerir. _Sunucu_ ise isteği ne yapacağına karar verir ve bir durum kodu ve yanıt gövdesi ile yanıt verir. Hem istekler hem de yanıtlar, ek bilgi sağlayan başlıklar içerebilir. -The interface through which browser JavaScript can make HTTP requests is called `fetch`. Making a request looks like this: +Tarayıcı JavaScript'inin HTTP istekleri yapabileceği arayüz `fetch` olarak adlandırılır. Bir istek yapmak şu şekilde görünür: ``` fetch("/18_http.html").then(r => r.text()).then(text => { @@ -831,40 +831,40 @@ fetch("/18_http.html").then(r => r.text()).then(text => { }); ``` -Browsers make `GET` requests to fetch the resources needed to display a web page. A page may also contain forms, which allow information entered by the user to be sent as a request for a new page when the form is submitted. +Tarayıcılar, bir web sayfasını görüntülemek için gerekli kaynakları almak amacıyla `GET` istekleri yapar. Bir sayfa ayrıca, kullanıcı tarafından girilen bilgilerin, form gönderildiğinde yeni bir sayfa için istek olarak gönderilmesine olanak tanıyan formlar içerebilir. -HTML can represent various types of form fields, such as text fields, checkboxes, multiple-choice fields, and file pickers. +HTML, metin alanları, onay kutuları, çoktan seçmeli alanlar ve dosya seçiciler gibi çeşitli form alanlarını temsil edebilir. -Such fields can be inspected and manipulated with JavaScript. They fire the `"change"` event when changed, fire the `"input"` event when text is typed, and receive keyboard events when they have keyboard focus. Properties like `value` (for text and select fields) or `checked` (for checkboxes and radio buttons) are used to read or set the field's content. +Bu tür alanlar JavaScript ile denetlenebilir ve manipüle edilebilir. Değiştirildiklerinde `"change"` olayı tetiklerler, metin yazıldığında `"input"` olayı tetiklerler ve klavye odaklandığında klavye olaylarını alırlar. `value` (metin ve seçme alanları için) veya `checked` (onay kutuları ve radyo düğmeleri için) gibi özellikler, alanın içeriğini okumak veya ayarlamak için kullanılır. -When a form is submitted, a `"submit"` event is fired on it. A JavaScript handler can call `preventDefault` on that event to disable the browser's default behavior. Form field elements may also occur outside of a form tag. +Bir form gönderildiğinde, üzerine bir `"submit"` olayı tetiklenir. Bir JavaScript işleyicisi, bu olay üzerinde `preventDefault` çağrısı yaparak tarayıcının varsayılan davranışını devre dışı bırakabilir. Form alanı elemanları, bir form etiketi dışında da bulunabilir. -When the user has selected a file from their local file system in a file picker field, the `FileReader` interface can be used to access the content of this file from a JavaScript program. +Kullanıcı, bir dosya seçici alanında yerel dosya sisteminden bir dosya seçtiğinde, `FileReader` arayüzü, JavaScript programından bu dosyanın içeriğine erişmek için kullanılabilir. -The `localStorage` and `sessionStorage` objects can be used to save information in a way that survives page reloads. The first object saves the data forever (or until the user decides to clear it), and the second saves it until the browser is closed. +`localStorage` ve `sessionStorage` nesneleri, sayfa yeniden yüklense bile bilgiyi kaydetmek için kullanılabilir. İlk nesne veriyi sonsuza kadar (veya kullanıcı temizlemeye karar verene kadar) saklar, ikinci nesne ise veriyi tarayıcı kapatılana kadar saklar. -## Exercises +## Egzersizler -### Content negotiation +### İçerik müzakeresi {{index "Accept header", "media type", "document format", "content negotiation (exercise)"}} -One of the things HTTP can do is called _content negotiation_. The `Accept` request header is used to tell the server what type of document the client would like to get. Many servers ignore this header, but when a server knows of various ways to encode a resource, it can look at this header and send the one that the client prefers. +HTTP'nin yapabileceği şeylerden biri de _içerik müzakeresi_ olarak adlandırılır. `Accept` istek başlığı, istemcinin almak istediği belge türünü sunucuya bildirmek için kullanılır. Birçok sunucu bu başlığı görmezden gelir, ancak bir sunucu, bir kaynağı kodlamak için çeşitli yollar bildiğinde, bu başlığa bakarak istemcinin tercih ettiği belgeyi gönderebilir. {{index "MIME type"}} -The URL [_https://eloquentjavascript.net/author_](https://eloquentjavascript.net/author) is configured to respond with either plaintext, HTML, or JSON, depending on what the client asks for. These formats are identified by the standardized _((media type))s_ `text/plain`, `text/html`, and `application/json`. +[_https://eloquentjavascript.net/author_](https://eloquentjavascript.net/author) URL'su, istemcinin talep ettiği formata göre düz metin, HTML veya JSON ile yanıt verecek şekilde yapılandırılmıştır. Bu formatlar, standartlaştırılmış _((medya türü))_ `text/plain`, `text/html` ve `application/json` ile tanımlanır. {{index "headers property", "fetch function"}} -Send requests to fetch all three formats of this resource. Use the `headers` property in the options object passed to `fetch` to set the header named `Accept` to the desired media type. +Bu kaynağın tüm üç formatını almak için istekler gönderin. `fetch`'e geçirilen seçenekler nesnesinde `headers` özelliğini kullanarak `Accept` başlığını istenen medya türüne ayarlayın. -Finally, try asking for the media type `application/rainbows+unicorns` and see which status code that produces. +Son olarak, `application/rainbows+unicorns` medya türünü istemeyi deneyin ve hangi durum kodunu ürettiğine bakın. {{if interactive ```{test: no} -// Your code here. +// Kodunuz buraya. ``` if}} @@ -873,23 +873,23 @@ if}} {{index "content negotiation (exercise)"}} -Base your code on the `fetch` examples [earlier in the chapter](http#fetch). +Kodunuzu, [önceki bölümlerdeki `fetch` örneklerine](http#fetch) dayandırın. {{index "406 (HTTP status code)", "Accept header"}} -Asking for a bogus media type will return a response with code 406, "Not acceptable", which is the code a server should return when it can't fulfill the `Accept` header. +Geçersiz bir medya türü istemek, 406 kodlu bir yanıt döndürecektir, "Kabul Edilemez" anlamına gelir. Bu, bir sunucunun `Accept` başlığını yerine getiremeyeceği zaman döndürmesi gereken koddur. hint}} -### A JavaScript workbench +### Bir JavaScript çalışma tezgahı {{index "JavaScript console", "workbench (exercise)"}} -Build an interface that allows people to type and run pieces of JavaScript code. +İnsanların JavaScript kodu yazıp çalıştırmalarına olanak tanıyan bir arayüz oluşturun. {{index "textarea (HTML tag)", "button (HTML tag)", "Function constructor", "error message"}} -Put a button next to a `<textarea>` field that, when pressed, uses the `Function` constructor we saw in [Chapter ?](modules#eval) to wrap the text in a function and call it. Convert the return value of the function, or any error it raises, to a string and display it below the text field. +Yanına bir `<textarea>` alanı ekleyin ve bu alana basıldığında, [Bölüm ?](modules#eval)'de gördüğümüz `Function` constructor'ını kullanarak metni bir fonksiyonla sarıp çağıran bir buton ekleyin. Fonksiyonun döndürdüğü değeri veya oluşturduğu hatayı bir string'e çevirin ve bu metni, metin alanının altına görüntüleyin. {{if interactive @@ -899,7 +899,7 @@ Put a button next to a `<textarea>` field that, when pressed, uses the `Function <pre id="output"></pre> <script> - // Your code here. + // Kodunuz buraya. </script> ``` @@ -909,39 +909,39 @@ if}} {{index "click event", "mousedown event", "Function constructor", "workbench (exercise)"}} -Use `document.querySelector` or `document.getElementById` to get access to the elements defined in your HTML. An event handler for `"click"` or `"mousedown"` events on the button can get the `value` property of the text field and call `Function` on it. +HTML'nizde tanımlanan elemanlara erişmek için `document.querySelector` veya `document.getElementById` kullanın. Butona tıklama veya fareyle tıklama `"click"` ya da `"mousedown"` olayları için bir olay işleyicisi, metin alanının `value` özelliğini alabilir ve buna `Function` çağırabilir. {{index "try keyword", "exception handling"}} -Make sure you wrap both the call to `Function` and the call to its result in a `try` block so you can catch the exceptions it produces. In this case, we really don't know what type of exception we are looking for, so catch everything. +Hem `Function` çağrısını hem de sonucuna yapılan çağrıyı bir `try` bloğuna sarmayı unutmayın, böylece ürettiği istisnaları yakalayabilirsiniz. Bu durumda, hangi türde bir istisna ile karşılaşacağımızı gerçekten bilmiyoruz, bu yüzden her şeyi yakalayın. {{index "textContent property", output, text, "createTextNode method", "newline character"}} -The `textContent` property of the output element can be used to fill it with a string message. Or, if you want to keep the old content around, create a new text node using `document.createTextNode` and append it to the element. Remember to add a newline character to the end so that not all output appears on a single line. +Çıktı öğesinin `textContent` özelliği, onu bir metin mesajı ile doldurmak için kullanılabilir. Veya eski içeriği korumak istiyorsanız, `document.createTextNode` kullanarak yeni bir metin düğümü oluşturun ve bunu öğeye ekleyin. Unutmayın, tüm çıktının tek bir satırda görünmemesi için sonuna bir satır sonu karakteri eklemelisiniz. hint}} -### Conway's Game of Life +### Conway'in Hayat Oyunu {{index "game of life (exercise)", "artificial life", "Conway's Game of Life"}} -Conway's Game of Life is a simple ((simulation)) that creates artificial "life" on a ((grid)), each cell of which is either alive or not. Each ((generation)) (turn), the following rules are applied: +Conway'nin Hayat Oyunu, her hücresinin ya canlı ya da ölü olduğu bir ((ızgara)) üzerinde yapay "hayat" yaratan basit bir ((simülasyon))dur. Her ((nesil)) (tur), aşağıdaki kurallar uygulanır: -* Any live ((cell)) with fewer than two or more than three live ((neighbor))s dies. +- İki veya daha fazla canlı ((komşu))ya sahip olan herhangi bir canlı ((hücre)) ölür. -* Any live cell with two or three live neighbors lives on to the next generation. +- İki veya üç canlı komşuya sahip olan herhangi bir canlı hücre bir sonraki nesile geçer. -* Any dead cell with exactly three live neighbors becomes a live cell. +- Tam olarak üç canlı komşuya sahip olan herhangi bir ölü hücre, canlı bir hücreye dönüşür. -A _neighbor_ is defined as any adjacent cell, including diagonally adjacent ones. +Bir _komşu_, herhangi bir komşu hücreyi, çapraz komşular dahil olmak üzere tanımlar. {{index "pure function"}} -Note that these rules are applied to the whole grid at once, not one square at a time. That means the counting of neighbors is based on the situation at the start of the generation, and changes happening to neighbor cells during this generation should not influence the new state of a given cell. +Bu kuralların tamamının bir kerede, tüm ızgaraya uygulandığını unutmayın, her bir kareye tek tek değil. Bu, komşuların sayılmasının neslin başlangıcındaki duruma dayandığı anlamına gelir ve bu nesil sırasında komşu hücrelerde meydana gelen değişiklikler, belirli bir hücrenin yeni durumunu etkilememelidir. {{index "Math.random function"}} -Implement this game using whichever ((data structure)) you find appropriate. Use `Math.random` to populate the grid with a random pattern initially. Display it as a grid of ((checkbox)) ((field))s, with a ((button)) next to it to advance to the next ((generation)). When the user checks or unchecks the checkboxes, their changes should be included when computing the next generation. +Bu oyunu, uygun bulduğunuz herhangi bir ((veri yapısı))nı kullanarak uygulayın. İlk başta ızgarayı rastgele bir desenle doldurmak için `Math.random` kullanın. Bunu, yanına bir ((düğme)) ekleyerek ve her bir ((checkbox)) ((alan))ı olarak ızgarayı görüntüleyerek yapın, böylece bir sonraki ((nesil))e geçiş sağlanabilir. Kullanıcı onay kutularını işaretlediğinde veya işaretini kaldırdığında, bu değişiklikler bir sonraki nesli hesaplamada dikkate alınmalıdır. {{if interactive @@ -950,7 +950,7 @@ Implement this game using whichever ((data structure)) you find appropriate. Use <button id="next">Next generation</button> <script> - // Your code here. + // Kodunuz buraya. </script> ``` @@ -960,18 +960,18 @@ if}} {{index "game of life (exercise)"}} -To solve the problem of having the changes conceptually happen at the same time, try to see the computation of a ((generation)) as a ((pure function)), which takes one ((grid)) and produces a new grid that represents the next turn. +Değişikliklerin kavramsal olarak aynı anda gerçekleşmesi sorununu çözmek için, ((nesil)) hesaplamasını bir ((saf fonksiyon)) olarak görmeye çalışın; bu fonksiyon, bir ((ızgara)) alır ve bir sonraki turu temsil eden yeni bir ızgara üretir. -Representing the matrix can be done with a single array of width × height elements, storing values row by row, so, for example, the third element in the fifth row is (using zero-based indexing) stored at position 4 × _width_ + 2. You can count live ((neighbor))s with two nested loops, looping over adjacent coordinates in both dimensions. Take care not to count cells outside of the field and to ignore the cell in the center, whose neighbors we are counting. +Matrisin temsil edilmesi, genişlik × yükseklik öğeleri içeren tek bir diziyle yapılabilir, değerler satır satır saklanır, bu nedenle örneğin beşinci satırdaki üçüncü öğe (sıfır tabanlı indeksleme kullanarak) 4 × _genişlik_ + 2 pozisyonunda saklanır. Canlı ((komşu)) sayısını, her iki boyutta bitişik koordinatlar üzerinde dönen iki iç içe döngüyle sayabilirsiniz. Alanın dışındaki hücreleri saymamaya ve saydığımız hücrenin komşusu olan merkez hücresini görmezden gelmeye dikkat edin. {{index "event handling", "change event"}} -Ensuring that changes to ((checkbox))es take effect on the next generation can be done in two ways. An event handler could notice these changes and update the current grid to reflect them, or you could generate a fresh grid from the values in the checkboxes before computing the next turn. +((Checkbox))lerdeki değişikliklerin bir sonraki nesilde etkili olmasını sağlamak iki şekilde yapılabilir. Bir olay işleyicisi bu değişiklikleri fark edebilir ve mevcut ızgarayı yansıtacak şekilde güncelleyebilir, ya da bir sonraki dönüşü hesaplamadan önce, checkbox'lardaki değerlerden taze bir ızgara oluşturabilirsiniz. -If you choose to go with event handlers, you might want to attach ((attribute))s that identify the position that each checkbox corresponds to so that it is easy to find out which cell to change. +Olay işleyicilerini tercih ederseniz, her checkbox'ın hangi hücreye karşılık geldiğini kolayca bulmak için her bir checkbox'a pozisyonu tanımlayan ((özellik))ler eklemek isteyebilirsiniz. {{index drawing, "table (HTML tag)", "br (HTML tag)"}} -To draw the grid of checkboxes, you can either use a `<table>` element (see [Chapter ?](dom#exercise_table)) or simply put them all in the same element and put `<br>` (line break) elements between the rows. +Checkbox'ların ızgarasını çizmek için ya bir `<table>` elementi kullanabilirsiniz (bkz. [Bölüm ?](dom#exercise_table)) ya da hepsini aynı elementte toplayıp satırlar arasına `<br>` (satır sonu) elemanları ekleyebilirsiniz. hint}} diff --git a/19_paint.md b/19_paint.md index b3fe33cb..611fe139 100644 --- a/19_paint.md +++ b/19_paint.md @@ -1,80 +1,80 @@ {{meta {load_files: ["code/chapter/19_paint.js"], zip: "html include=[\"css/paint.css\"]"}}} -# Project: A Pixel Art Editor +# Proje: Bir Piksel Sanatı Editörü -{{quote {author: "Joan Miro", chapter: true} +{{quote {author: "Joan Miró", chapter: true} -I look at the many colors before me. I look at my blank canvas. Then, I try to apply colors like words that shape poems, like notes that shape music. +Önümdeki birçok renge bakıyorum. Boş tuvalime bakıyorum. Sonra, renkleri, şiirleri şekillendiren kelimeler gibi, müziği şekillendiren notalar gibi uygulamaya çalışıyorum. quote}} -{{index "Miro, Joan", "drawing program example", "project chapter"}} +{{index "Miró, Joan", "drawing program example", "project chapter"}} -{{figure {url: "img/chapter_picture_19.jpg", alt: "Illustration showing a mosaic of black tiles, with jars of other tiles next to it", chapter: "framed"}}} +{{figure {url: "img/chapter_picture_19.jpg", alt: "Bir mozaik siyah karolar gösteren illüstrasyon, yanında diğer karoların kavanozları", chapter: "framed"}}} -The material from the previous chapters gives you all the elements you need to build a basic ((web application)). In this chapter, we will do just that. +Önceki bölümlerdeki materyal, size temel bir ((web uygulaması)) oluşturmak için gereken tüm öğeleri sunuyor. Bu bölümde tam olarak bunu yapacağız. {{index [file, image]}} -Our ((application)) will be a ((pixel)) ((drawing)) program, where you can modify a picture pixel by pixel by manipulating a zoomed-in view of it, shown as a grid of colored squares. You can use the program to open image files, scribble on them with your mouse or other pointer device, and save them. This is what it will look like: +((Uygulamamız)), bir ((piksel)) ((çizim)) programı olacak. Bu programda, bir resmi piksel piksel değiştirebilir, renkli karelerden oluşan bir ızgara şeklinde gösterilen büyütülmüş bir görünümünü manipüle ederek düzenleyebilirsiniz. Programı kullanarak görüntü dosyalarını açabilir, fareniz veya başka bir işaretleme cihazıyla üzerine karalama yapabilir ve bunları kaydedebilirsiniz. İşte böyle görünecek: -{{figure {url: "img/pixel_editor.png", alt: "Screenshot of the pixel editor interface, with a grid of colored pixels at the top and a number of controls, in the form of HTML fields and buttons, below that", width: "8cm"}}} +{{figure {url: "img/pixel_editor.png", alt: "Piksel düzenleyicinin arayüzünü gösteren ekran görüntüsü: Üstte renkli piksellerden oluşan bir ızgara ve altında HTML alanları ve düğmeler şeklinde bir dizi kontrol", width: "8cm"}}} -Painting on a computer is great. You don't need to worry about materials, ((skill)), or talent. You just start smearing and see where you end up. +Bilgisayarda resim yapmak harika bir şey. Malzemeler, ((yetenek)) veya beceri konusunda endişelenmenize gerek yok. Sadece karalamaya başlar ve nerede sonlanacağını görürsünüz. -## Components +## Bileşenler {{index drawing, "select (HTML tag)", "canvas (HTML tag)", component}} -The interface for the application shows a big `<canvas>` element on top, with a number of form ((field))s below it. The user draws on the ((picture)) by selecting a tool from a `<select>` field and then clicking, ((touch))ing, or ((dragging)) across the canvas. There are ((tool))s for drawing single pixels or rectangles, for filling an area, and for picking a ((color)) from the picture. +Uygulamanın arayüzü, üstte büyük bir `<canvas>` elemanı ve altında birkaç form ((alanı)) gösterir. Kullanıcı, bir `<select>` alanından bir araç seçip ardından tuvale tıklayarak, ((dokunarak)) veya ((sürükleyerek)) resim üzerinde çizim yapar. Tek pikseller veya dikdörtgenler çizmek, bir alanı doldurmak ve resimden bir ((renk)) seçmek için ((araçlar)) vardır. {{index [DOM, components]}} -We will structure the editor interface as a number of _((component))s_, objects that are responsible for a piece of the DOM and that may contain other components inside them. +Editör arayüzünü, bir kısmı DOM’dan sorumlu olan ve içinde başka bileşenler barındırabilen _((bileşen))ler_ olarak yapılandıracağız. {{index [state, "of application"]}} -The state of the application consists of the current picture, the selected tool, and the selected color. We'll set things up so that the state lives in a single value, and the interface components always base the way they look on the current state. +Uygulamanın durumu (state), mevcut resim, seçilen araç ve seçilen renkten oluşur. Durumun tek bir değer içinde tutulacağı ve arayüz bileşenlerinin görünümlerini her zaman mevcut duruma dayandıracağı şekilde ayarlamalar yapacağız. -To see why this is important, let's consider the alternative—distributing pieces of state throughout the interface. Up to a certain point, this is easier to program. We can just put in a ((color field)) and read its value when we need to know the current color. +Bunun neden önemli olduğunu anlamak için alternatif bir yöntemi düşünelim: durumu arayüz boyunca parçalara dağıtmak. Belirli bir noktaya kadar, bu programlaması daha kolay bir yaklaşımdır. Örneğin, bir ((renk alanı)) koyup, mevcut rengi bilmemiz gerektiğinde değerini okuyabiliriz. -But then we add the ((color picker))—a tool that lets you click the picture to select the color of a given pixel. To keep the color field showing the correct color, that tool would have to know that the color field exists and update it whenever it picks a new color. If you ever add another place that makes the color visible (maybe the mouse cursor could show it), you have to update your color-changing code to keep that synchronized as well. +Ancak ardından bir ((renk seçici)) ekleriz—resimdeki bir pikselin rengini seçmek için tıklamanıza olanak tanıyan bir araç. Renk alanının doğru rengi göstermesini sağlamak için, bu aracın renk alanının var olduğunu bilmesi ve her yeni renk seçtiğinde onu güncellemesi gerekir. Eğer bir gün başka bir yerde rengi görünür hale getiren bir şey eklerseniz (belki fare imleci bunu gösterebilir), renk değiştirme kodunuzu da senkronize tutmak için güncellemeniz gerekir. {{index modularity}} -In effect, this creates a problem where each part of the interface needs to know about all other parts, which is not very modular. For small applications like the one in this chapter, that may not be a problem. For bigger projects, it can turn into a real nightmare. +Bu durum, arayüzün her bir bölümünün diğer tüm bölümleri bilmesi gerektiği bir problem yaratır ki bu çok modüler bir yaklaşım değildir. Bu bölümdeki gibi küçük uygulamalarda bu bir sorun olmayabilir. Ancak daha büyük projelerde tam bir kâbusa dönüşebilir. -To avoid this nightmare on principle, we're going to be strict about _((data flow))_. There is a state, and the interface is drawn based on that state. An interface component may respond to user actions by updating the state, at which point the components get a chance to synchronize themselves with this new state. +Bu kâbustan prensip olarak kaçınmak için _((veri akışı))_ konusunda katı davranacağız. Bir durum vardır ve arayüz bu duruma göre çizilir. Bir arayüz bileşeni, kullanıcı eylemlerine yanıt vererek durumu güncelleyebilir. Bu noktada, bileşenler kendilerini bu yeni duruma göre senkronize etme şansı bulur. {{index library, framework}} -In practice, each ((component)) is set up so that when it is given a new state, it also notifies its child components, insofar as those need to be updated. Setting this up is a bit of a hassle. Making this more convenient is the main selling point of many browser programming libraries. But for a small application like this, we can do it without such infrastructure. +Pratikte, her ((bileşen)), yeni bir durum (state) verildiğinde, güncellenmesi gereken yerlerde çocuk bileşenlerini de bilgilendirecek şekilde yapılandırılır. Bunu ayarlamak biraz zahmetlidir. Bu durumu daha kolay hale getirmek, birçok tarayıcı programlama kütüphanesinin temel satış noktasıdır. Ancak bu gibi küçük bir uygulama için böyle bir altyapıya ihtiyaç duymadan bunu yapabiliriz. {{index [state, transitions]}} -Updates to the state are represented as objects, which we'll call _((action))s_. Components may create such actions and _((dispatch))_ them—give them to a central state management function. That function computes the next state, after which the interface components update themselves to this new state. +Durumdaki güncellemeler, _((eylem))_ (action) adını vereceğimiz nesneler olarak temsil edilir. Bileşenler bu eylemleri oluşturabilir ve _((yönlendirebilir))_ (dispatch)—bunları merkezi bir durum yönetimi fonksiyonuna verebilir. Bu fonksiyon, bir sonraki durumu hesaplar, ardından arayüz bileşenleri kendilerini bu yeni duruma göre günceller. {{index [DOM, components]}} -We're taking the messy task of running a ((user interface)) and applying ((structure)) to it. Though the DOM-related pieces are still full of ((side effect))s, they are held up by a conceptually simple backbone: the state update cycle. The state determines what the DOM looks like, and the only way DOM events can change the state is by dispatching actions to the state. +Bir ((kullanıcı arayüzü)) çalıştırmanın karmaşık işini ele alıp buna biraz ((yapı)) uyguluyoruz. DOM ile ilgili parçalar hala ((yan etki))lerle dolu olsa da, bunlar kavramsal olarak basit bir omurga ile desteklenir: durum güncelleme döngüsü. Durum, DOM’un nasıl göründüğünü belirler ve DOM olaylarının durumu değiştirebilmesinin tek yolu, duruma eylemler yönlendirmektir. {{index "data flow"}} -There are _many_ variants of this approach, each with its own benefits and problems, but their central idea is the same: state changes should go through a single well-defined channel, not happen all over the place. +Bu yaklaşımın _çok_ sayıda varyasyonu vardır; her biri kendi avantaj ve dezavantajlarına sahiptir. Ancak merkezi fikir aynıdır: Durum değişiklikleri, iyi tanımlanmış tek bir kanal üzerinden geçmelidir; her yerde gerçekleşmemelidir. {{index "dom property", [interface, object]}} -Our ((component))s will be ((class))es conforming to an interface. Their constructor is given a state—which may be the whole application state or some smaller value if it doesn't need access to everything—and uses that to build up a `dom` property. This is the DOM element that represents the component. Most constructors will also take some other values that won't change over time, such as the function they can use to ((dispatch)) an action. +Bileşenlerimiz, bir arayüze uyan ((sınıf))lar olacaktır. Constructor'ları bir durum alır—bu durum tüm uygulama durumu ya da her şeye erişim gerektirmeyen daha küçük bir değer olabilir—ve bunu bir `dom` özelliği oluşturmak için kullanır. Bu, bileşeni temsil eden DOM elemanıdır. Çoğu constructor, zamanla değişmeyecek bazı diğer değerler de alır; örneğin, bir eylemi ((yönlendirmek)) için kullanabilecekleri fonksiyon. {{index "syncState method"}} -Each component has a `syncState` method that is used to synchronize it to a new state value. The method takes one argument, the state, which is of the same type as the first argument to its constructor. +Her bileşenin, onu yeni bir durum değeriyle senkronize etmek için kullanılan bir `syncState` metodu vardır. Bu metod, constructor'ının ilk argümanıyla aynı türde bir argüman olan durumu alır. -## The state +## Durum {{index "Picture class", "picture property", "tool property", "color property"}} -The application state will be an object with `picture`, `tool`, and `color` properties. The picture is itself an object that stores the width, height, and pixel content of the picture. The ((pixel))s are stored in a single array, row by row, from top to bottom. +Uygulama durumu, `picture`, `tool` ve `color` özelliklerine sahip bir nesne olacaktır. Resim (picture), genişlik, yükseklik ve piksel içeriğini depolayan bir nesnedir. ((Piksel))ler, yukarıdan aşağıya, sıra sıra tek bir dizi içinde saklanır. ```{includeCode: true} class Picture { @@ -102,23 +102,23 @@ class Picture { {{index "side effect", "persistent data structure"}} -We want to be able to treat a picture as an ((immutable)) value, for reasons that we'll get back to later in the chapter. But we also sometimes need to update a whole bunch of pixels at a time. To be able to do that, the class has a `draw` method that expects an array of updated pixels—objects with `x`, `y`, and `color` properties—and creates a new picture with those pixels overwritten. This method uses `slice` without arguments to copy the entire pixel array—the start of the slice defaults to 0, and the end defaults to the array's length. +Resmi bir ((değişmez)) değer olarak ele almak istiyoruz, bunun nedenini bu bölümde daha sonra açıklayacağız. Ancak bazen bir seferde birçok pikseli güncellememiz gerekir. Bunu yapabilmek için, sınıfta `draw` adında bir metod bulunur. Bu metod, `x`, `y` ve `color` özelliklerine sahip güncellenmiş piksellerden oluşan bir dizi bekler ve bu piksellerin üzerine yazıldığı yeni bir resim oluşturur. Bu metod, tüm piksel dizisini kopyalamak için `slice` metodunu, argümansız olarak kullanır—`slice` metodunun başlangıç değeri varsayılan olarak 0, bitiş değeri ise dizinin uzunluğudur. {{index "Array constructor", "fill method", ["length property", "for array"], [array, creation]}} -The `empty` method uses two pieces of array functionality that we haven't seen before. The `Array` constructor can be called with a number to create an empty array of the given length. The `fill` method can then be used to fill this array with a given value. These are used to create an array in which all pixels have the same color. +`empty` metodu, daha önce görmediğimiz iki dizi işlevini kullanır. `Array` constructor'ı, belirli bir uzunlukta boş bir dizi oluşturmak için bir sayı ile çağrılabilir. Daha sonra `fill` metodu, bu diziyi belirli bir değerle doldurmak için kullanılabilir. Bu yöntem, tüm piksellerin aynı renge sahip olduğu bir dizi oluşturmak için kullanılır. {{index "hexadecimal number", "color component", "color field", "fillStyle property"}} -Colors are stored as strings containing traditional ((CSS)) ((color code))s made up of a ((hash sign)) (`#`) followed by six hexadecimal (base-16) digits—two for the ((red)) component, two for the ((green)) component, and two for the ((blue)) component. This is a somewhat cryptic and inconvenient way to write colors, but it is the format the HTML color input field uses, and it can be used in the `fillStyle` property of a canvas drawing context, so for the ways we'll use colors in this program, it is practical enough. +Renkler, bir ((kare işareti)) (`#`) ile başlayan ve altı onaltılık (taban-16) rakamdan oluşan geleneksel ((CSS)) ((renk kodları)) olarak saklanır—iki tanesi ((kırmızı)) bileşen, iki tanesi ((yeşil)) bileşen ve iki tanesi ((mavi)) bileşen içindir. Bu, renkleri yazmanın biraz karmaşık ve kullanışsız bir yolu olsa da, HTML renk giriş alanının kullandığı format budur ve bir canvas çizim bağlamında `fillStyle` özelliğinde kullanılabilir. Bu nedenle, bu programda renkleri kullanma yollarımız için yeterince pratiktir. {{index black}} -Black, where all components are zero, is written `"#000000"`, and bright ((pink)) looks like `"#ff00ff"`, where the red and blue components have the maximum value of 255, written `ff` in hexadecimal ((digit))s (which use _a_ to _f_ to represent digits 10 to 15). +Tüm bileşenlerin sıfır olduğu siyah, `"#000000"` olarak yazılır ve parlak ((pembe)), kırmızı ve mavi bileşenlerin maksimum değeri olan 255'e (onaltılık ((rakam))larla `ff` olarak yazılır) sahip olduğu `"#ff00ff"` gibi görünür. {{index [state, transitions]}} -We'll allow the interface to ((dispatch)) ((action))s as objects whose properties overwrite the properties of the previous state. The color field, when the user changes it, could dispatch an object like `{color: field.value}`, from which this update function can compute a new state. +Arayüze, önceki durumun özelliklerini geçersiz kılan özelliklere sahip nesneler olarak ((eylem))ler ((yönlendirme)) yetkisi vereceğiz. Örneğin, kullanıcı renk alanını değiştirdiğinde `{color: field.value}` gibi bir nesne yönlendirebilir ve bu güncelleme fonksiyonu yeni bir durum hesaplayabilir. {{index "updateState function"}} @@ -130,13 +130,13 @@ function updateState(state, action) { {{index "period character"}} -This pattern, in which object ((spread)) is used to first add the properties an existing object and then override some of those, is common in JavaScript code that uses ((immutable)) objects. +Bu model, mevcut bir nesnenin özelliklerini önce eklemek ve ardından bazılarını geçersiz kılmak için nesne ((spread)) sözdiziminin kullanıldığı yaygın bir JavaScript desenidir. ((Değişmez)) nesnelerle çalışan kodlarda sıkça görülür. -## DOM building +## DOM oluşturma {{index "createElement method", "elt function", [DOM, construction]}} -One of the main things that interface components do is creating DOM structure. We again don't want to directly use the verbose DOM methods for that, so here's a slightly expanded version of the `elt` function: +Arayüz bileşenlerinin yaptığı ana şeylerden biri, DOM yapısını oluşturmaktır. Yine, bunun için ayrıntılı DOM metotlarını doğrudan kullanmak istemiyoruz, bu nedenle `elt` fonksiyonunun biraz genişletilmiş bir versiyonunu sunuyoruz: ```{includeCode: true} function elt(type, props, ...children) { @@ -152,11 +152,11 @@ function elt(type, props, ...children) { {{index "setAttribute method", "attribute", "onclick property", "click event", "event handling"}} -The main difference between this version and the one we used in [Chapter ?](game#domdisplay) is that it assigns _properties_ to DOM nodes, not _attributes_. This means we can't use it to set arbitrary attributes, but we _can_ use it to set properties whose value isn't a string, such as `onclick`, which can be set to a function to register a click event handler. +Bu versiyon ile [Bölüm ?](game#domdisplay)'de kullandığımız versiyon arasındaki temel fark, _nitelikler_ yerine DOM düğümlerine _özellikler_ atamasıdır. Bu, keyfi nitelikler ayarlamak için kullanılamayacağı anlamına gelir, ancak `onclick` gibi bir değeri dize olmayan özellikleri ayarlamak için kullanılabilir. `onclick`, bir tıklama olay işleyicisi kaydetmek için bir fonksiyona ayarlanabilir. {{index "button (HTML tag)"}} -This allows this convenient style for registering event handlers: +Bu, olay işleyicileri kaydetmek için şu kullanışlı stili mümkün kılar: ```{lang: html} <body> @@ -168,13 +168,13 @@ This allows this convenient style for registering event handlers: </body> ``` -## The canvas +## Tuval -The first component we'll define is the part of the interface that displays the picture as a grid of colored boxes. This component is responsible for two things: showing a picture and communicating ((pointer event))s on that picture to the rest of the application. +Tanımlayacağımız ilk bileşen, resmi renkli kutuların bir ızgarası olarak görüntüleyen arayüz parçasıdır. Bu bileşen iki şeyden sorumludur: bir resmi göstermek ve o resimdeki ((işaretçi olayı))nı uygulamanın geri kalanına iletmek. {{index "PictureCanvas class", "callback function", "scale constant", "canvas (HTML tag)", "mousedown event", "touchstart event", [state, "of application"]}} -As such, we can define it as a component that only knows about the current picture, not the whole application state. Because it doesn't know how the application as a whole works, it cannot directly dispatch ((action))s. Rather, when responding to pointer events, it calls a callback function provided by the code that created it, which will handle the application-specific parts. +Bu nedenle, yalnızca mevcut resmi bilen, tüm uygulama durumu hakkında bilgi sahibi olmayan bir bileşen olarak tanımlayabiliriz. Uygulamanın bir bütün olarak nasıl çalıştığını bilmediği için, doğrudan ((eylem)) yönlendiremez. Bunun yerine, işaretçi olaylarına yanıt verirken, onu oluşturan kod tarafından sağlanan ve uygulamaya özgü parçaları yönetecek bir geri çağırma fonksiyonunu çağırır. ```{includeCode: true} const scale = 10; @@ -197,11 +197,11 @@ class PictureCanvas { {{index "syncState method", efficiency}} -We draw each pixel as a 10-by-10 square, as determined by the `scale` constant. To avoid unnecessary work, the component keeps track of its current picture and does a redraw only when `syncState` is given a new picture. +Her pikseli, `scale` sabiti tarafından belirlenen 10'a 10'luk bir kare olarak çizeriz. Gereksiz işlemleri önlemek için, bileşen mevcut resmini takip eder ve yalnızca `syncState` yeni bir resim verildiğinde yeniden çizer. {{index "drawPicture function"}} -The actual drawing function sets the size of the canvas based on the scale and picture size and fills it with a series of squares, one for each pixel. +Gerçek çizim fonksiyonu, ölçek ve resim boyutuna göre canvas'ın boyutunu ayarlar ve her piksel için bir kare olacak şekilde doldurur. ```{includeCode: true} function drawPicture(picture, canvas, scale) { @@ -220,7 +220,7 @@ function drawPicture(picture, canvas, scale) { {{index "mousedown event", "mousemove event", "button property", "buttons property", "pointerPosition function"}} -When the left mouse button is pressed while the mouse is over the picture canvas, the component calls the `pointerDown` callback, giving it the position of the pixel that was clicked—in picture coordinates. This will be used to implement mouse interaction with the picture. The callback may return another callback function to be notified when the pointer is moved to a different pixel while the button is held down. +Sol fare düğmesine, fare resim canvas'ı üzerindeyken basıldığında, bileşen tıklanan pikselin konumunu (resim koordinatlarında) içeren bir `pointerDown` geri çağırmasını çağırır. Bu, resimle fare etkileşimini gerçekleştirmek için kullanılacaktır. Geri çağırma, düğme basılıyken işaretçi farklı bir piksele taşındığında bilgilendirilmek için başka bir geri çağırma fonksiyonu döndürebilir. ```{includeCode: true} PictureCanvas.prototype.mouse = function(downEvent, onDown) { @@ -250,11 +250,11 @@ function pointerPosition(pos, domNode) { {{index "getBoundingClientRect method", "clientX property", "clientY property"}} -Since we know the size of the ((pixel))s and we can use `getBoundingClientRect` to find the position of the canvas on the screen, it is possible to go from mouse event coordinates (`clientX` and `clientY`) to picture coordinates. These are always rounded down so that they refer to a specific pixel. +((Piksel))lerin boyutunu bildiğimizden ve canvas'ın ekrandaki konumunu bulmak için `getBoundingClientRect` kullanabildiğimizden, fare olayı koordinatlarından (`clientX` ve `clientY`) resim koordinatlarına geçmek mümkündür. Bu koordinatlar her zaman aşağı yuvarlanır, böylece belirli bir piksele işaret eder. {{index "touchstart event", "touchmove event", "preventDefault method"}} -With touch events, we have to do something similar, but using different events and making sure we call `preventDefault` on the `"touchstart"` event to prevent ((panning)). +((Dokunma olayı)) için benzer bir şey yapmamız gerekir, ancak farklı olayları kullanarak ve `"touchstart"` olayında ((kaydırma))yı önlemek için `preventDefault` çağırmayı unutmadan. ```{includeCode: true} PictureCanvas.prototype.touch = function(startEvent, @@ -281,17 +281,17 @@ PictureCanvas.prototype.touch = function(startEvent, {{index "touches property", "clientX property", "clientY property"}} -For touch events, `clientX` and `clientY` aren't available directly on the event object, but we can use the coordinates of the first touch object in the `touches` property. +Dokunma olayları için, `clientX` ve `clientY` doğrudan olay nesnesinde bulunmaz, ancak `touches` özelliğindeki ilk dokunma nesnesinin koordinatlarını kullanabiliriz. -## The application +## Uygulama -To make it possible to build the application piece by piece, we'll implement the main component as a shell around a picture canvas and a dynamic set of ((tool))s and ((control))s that we pass to its constructor. +Uygulamayı parça parça inşa edilebilir hale getirmek için, ana bileşeni bir resim canvas'ı ve constructor'a geçirdiğimiz dinamik bir ((araç)) ve ((kontrol)) seti etrafında bir kabuk olarak uygulayacağız. -The _controls_ are the interface elements that appear below the picture. They'll be provided as an array of ((component)) constructors. +_Kontroller_, resmin altında görünen arayüz elemanlarıdır. Bunlar, bir dizi ((bileşen)) constructor'ı olarak sağlanacaktır. {{index "br (HTML tag)", "flood fill", "select (HTML tag)", "PixelEditor class", dispatch}} -The _tools_ do things like drawing pixels or filling in an area. The application shows the set of available tools as a `<select>` field. The currently selected tool determines what happens when the user interacts with the picture with a pointer device. The set of available tools is provided as an object that maps the names that appear in the drop-down field to functions that implement the tools. Such functions get a picture position, a current application state, and a `dispatch` function as arguments. They may return a move handler function that gets called with a new position and a current state when the pointer moves to a different pixel. +_Araçlar_, piksel çizmek veya bir alanı doldurmak gibi işlemler yapar. Uygulama, kullanılabilir araçları bir `<select>` alanında gösterir. Kullanıcının bir işaretçi cihazıyla resimle etkileşime geçtiğinde ne olacağını, seçili araç belirler. Mevcut araç seti, açılır listede görünen adları araçları uygulayan fonksiyonlara eşleyen bir nesne olarak sağlanır. Bu tür fonksiyonlar, bir resim konumu, mevcut uygulama durumu ve bir `dispatch` fonksiyonu argümanları alır. İşaretçi farklı bir piksele hareket ettiğinde yeni bir konum ve mevcut durumla çağrılan bir hareket işleyici fonksiyonu döndürebilirler. ```{includeCode: true} class PixelEditor { @@ -318,15 +318,15 @@ class PixelEditor { } ``` -The pointer handler given to `PictureCanvas` calls the currently selected tool with the appropriate arguments and, if that returns a move handler, adapts it to also receive the state. +`PictureCanvas`'a verilen işaretçi işleyici, uygun argümanlarla seçili aracı çağırır ve eğer bu bir hareket işleyici döndürürse, onu durumu da alacak şekilde uyarlar. {{index "reduce method", "map method", [whitespace, "in HTML"], "syncState method"}} -All controls are constructed and stored in `this.controls` so that they can be updated when the application state changes. The call to `reduce` introduces spaces between the controls' DOM elements. That way they don't look so pressed together. +Tüm kontroller, uygulama durumu değiştiğinde güncellenebilmeleri için `this.controls` içinde oluşturulup saklanır. `reduce` çağrısı, kontrollerin DOM elemanları arasına boşluklar ekler. Böylece, çok sıkışık görünmezler. {{index "select (HTML tag)", "change event", "ToolSelect class", "syncState method"}} -The first control is the ((tool)) selection menu. It creates a `<select>` element with an option for each tool and sets up a `"change"` event handler that updates the application state when the user selects a different tool. +İlk kontrol, ((araç)) seçim menüsüdür. Her araç için bir seçenek içeren bir `<select>` elementi oluşturur ve kullanıcı farklı bir araç seçtiğinde uygulama durumunu güncelleyen bir `"change"` olay işleyicisi ayarlar. ```{includeCode: true} class ToolSelect { @@ -344,23 +344,23 @@ class ToolSelect { {{index "label (HTML tag)"}} -By wrapping the label text and the field in a `<label>` element, we tell the browser that the label belongs to that field so that you can, for example, click the label to focus the field. +Etiket metnini ve alanı bir `<label>` elementi içinde sararak, tarayıcıya, etiketin o alana ait olduğunu belirtiriz. Bu sayede, örneğin etikete tıklayarak alanı odaklayabilirsiniz. {{index "color field", "input (HTML tag)"}} -We also need to be able to change the color, so let's add a control for that. An HTML `<input>` element with a `type` attribute of `color` gives us a form field that is specialized for selecting colors. Such a field's value is always a CSS color code in `"#RRGGBB"` format (red, green, and blue components, two digits per color). The browser will show a ((color picker)) interface when the user interacts with it. +Ayrıca rengi değiştirebilmemiz gerektiğinden, bunun için bir kontrol ekleyelim. `type` özelliği `color` olan bir HTML `<input>` elementi, renk seçimi için özelleştirilmiş bir form alanı sağlar. Bu tür bir alanın değeri her zaman `"#RRGGBB"` formatında (kırmızı, yeşil ve mavi bileşenler, her renk için iki haneli) bir CSS renk kodudur. Kullanıcı bu alanla etkileşime geçtiğinde, tarayıcı bir ((renk seçici)) arayüz gösterecektir. {{if book -Depending on the browser, the color picker might look like this: +Tarayıcıya bağlı olarak, renk seçici şu şekilde görünebilir: -{{figure {url: "img/color-field.png", alt: "Screenshot of color field", width: "6cm"}}} +{{figure {url: "img/color-field.png", alt: "Renk alanının ekran görüntüsü", width: "6cm"}}} if}} {{index "ColorSelect class", "syncState method"}} -This ((control)) creates such a field and wires it up to stay synchronized with the application state's `color` property. +Bu ((kontrol)), böyle bir alan oluşturur ve uygulama durumunun `color` özelliğiyle senkronize olacak şekilde yapılandırır. ```{includeCode: true} class ColorSelect { @@ -376,13 +376,13 @@ class ColorSelect { } ``` -## Drawing tools +## Çizim araçları -Before we can draw anything, we need to implement the ((tool))s that will control the functionality of mouse or touch events on the canvas. +Bir şey çizebilmeden önce, canvas üzerindeki mouse veya dokunma olaylarının işlevselliğini kontrol edecek ((araç))ları uygulamamız gerekiyor. {{index "draw function"}} -The most basic tool is the draw tool, which changes any ((pixel)) you click or tap to the currently selected color. It dispatches an action that updates the picture to a version in which the pointed-at pixel is given the currently selected color. +En temel araç, herhangi bir tıklanan veya dokunulan ((piksel))i seçili renge dönüştüren çizim aracıdır. Bu araç, işaret edilen pikselin seçili renge sahip olduğu bir versiyonuyla resmi güncelleyen bir eylem ((dispatch)) eder. ```{includeCode: true} function draw(pos, state, dispatch) { @@ -395,11 +395,11 @@ function draw(pos, state, dispatch) { } ``` -The function immediately calls the `drawPixel` function but then also returns it so that it is called again for newly touched pixels when the user drags or ((swipe))s over the picture. +Fonksiyon, hemen `drawPixel` fonksiyonunu çağırır, ardından kullanıcı resmi sürüklerken veya ((kaydırır))ken yeni dokunulan pikseller için tekrar çağrılması amacıyla bu fonksiyonu döndürür. {{index "rectangle function"}} -To draw larger shapes, it can be useful to quickly create ((rectangle))s. The `rectangle` ((tool)) draws a rectangle between the point where you start ((dragging)) and the point that you drag to. +Daha büyük şekiller çizmek için hızlı bir şekilde ((dikdörtgen)) oluşturmak faydalı olabilir. `rectangle` aracı, sürüklemeye başladığınız nokta ile sürüklediğiniz nokta arasında bir dikdörtgen çizer. ```{includeCode: true} function rectangle(start, state, dispatch) { @@ -423,15 +423,15 @@ function rectangle(start, state, dispatch) { {{index "persistent data structure", [state, persistence]}} -An important detail in this implementation is that when dragging, the rectangle is redrawn on the picture from the _original_ state. That way, you can make the rectangle larger and smaller again while creating it, without the intermediate rectangles sticking around in the final picture. This is one of the reasons why ((immutable)) picture objects are useful—we'll see another reason later. +Bu uygulamadaki önemli bir detay, sürükleme sırasında dikdörtgenin _orijinal_ durumdan itibaren resme yeniden çizilmesidir. Bu sayede, dikdörtgeni oluştururken boyutunu büyütüp küçültebilir ve ara dikdörtgenler son resimde kalmaz. Bu, ((immutable)) resim nesnelerinin neden faydalı olduğuna dair bir örnek sunar—bunun başka bir nedenini ileride göreceğiz. -Implementing ((flood fill)) is somewhat more involved. This is a ((tool)) that fills the pixel under the pointer and all adjacent pixels that have the same color. "Adjacent" means directly horizontally or vertically adjacent, not diagonally. This picture illustrates the set of ((pixel))s colored when the flood fill tool is used at the marked pixel: +((Alan doldurma)) işlemini uygulamak biraz daha karmaşıktır. Bu araç, işaretçi altındaki pikseli ve aynı renge sahip olan tüm bitişik pikselleri doldurur. "Bitişik", doğrudan yatay veya dikey bitişik anlamına gelir, çapraz bitişik değil. Bu resim, alan doldurma aracının işaretlenen pikselde kullanıldığında boyadığı piksellerin setini gösterir: -{{figure {url: "img/flood-grid.svg", alt: "Diagram of a pixel grid showing the area filled by a flood fill operation", width: "6cm"}}} +{{figure {url: "img/flood-grid.svg", alt: "Alan doldurma işleminin sonucunu gösteren bir piksel ızgarasının diyagramı", width: "6cm"}}} {{index "fill function"}} -Interestingly, the way we'll do this looks a bit like the ((pathfinding)) code from [Chapter ?](robot). Whereas that code searched through a graph to find a route, this code searches through a grid to find all "connected" pixels. The problem of keeping track of a branching set of possible routes is similar. +İlginç bir şekilde, bunu yapma yöntemi, [Bölüm ?](robot) içerisindeki ((yol bulma)) koduna benzer. O kod bir rota bulmak için bir grafiği arıyordu; bu kod ise "bağlantılı" tüm pikselleri bulmak için bir ızgarayı arıyor. Dallanmış bir olası yollar kümesini takip etme problemi, her iki durumda da benzerdir. ```{includeCode: true} const around = [{dx: -1, dy: 0}, {dx: 1, dy: 0}, @@ -457,11 +457,11 @@ function fill({x, y}, state, dispatch) { } ``` -The array of drawn pixels doubles as the function's ((work list)). For each pixel reached, we have to see whether any adjacent pixels have the same color and haven't already been painted over. The loop counter lags behind the length of the `drawn` array as new pixels are added. Any pixels ahead of it still need to be explored. When it catches up with the length, no unexplored pixels remain, and the function is done. +Çizilen piksellerin dizisi, fonksiyonun ((iş listesi)) olarak kullanılır. Ulaşılan her piksel için, herhangi bir bitişik pikselin aynı renge sahip olup olmadığını ve daha önce boyanıp boyanmadığını kontrol etmemiz gerekir. Döngü sayacı, yeni pikseller eklendikçe `drawn` dizisinin uzunluğunun gerisinde kalır. Sayacın önündeki herhangi bir piksel hâlâ keşfedilmesi gereken bir durumdadır. Sayaç dizinin uzunluğuna ulaştığında, keşfedilmemiş piksel kalmaz ve fonksiyon tamamlanır. {{index "pick function"}} -The final ((tool)) is a ((color picker)), which allows you to point at a color in the picture to use it as the current drawing color. +Son ((araç)) bir ((renk seçici))dir ve resimde bir rengi işaret ederek onu mevcut çizim rengi olarak kullanmanızı sağlar. ```{includeCode: true} function pick(pos, state, dispatch) { @@ -471,7 +471,7 @@ function pick(pos, state, dispatch) { {{if interactive -We can now test our application! +Artık uygulamamızı test edebiliriz! ```{lang: html} <div></div> @@ -495,11 +495,11 @@ We can now test our application! if}} -## Saving and loading +## Kaydetme ve yükleme {{index "SaveButton class", "drawPicture function", [file, image]}} -When we've drawn our masterpiece, we'll want to save it for later. We should add a button for ((download))ing the current picture as an image file. This ((control)) provides that button: +Başyapıtımızı çizdiğimizde, daha sonrası için kaydetmek isteyeceğiz. Mevcut resmi bir resim dosyası olarak ((indirmek)) için bir düğme eklemeliyiz. Bu ((kontrol)) o düğmeyi sağlar: ```{includeCode: true} class SaveButton { @@ -526,19 +526,21 @@ class SaveButton { {{index "canvas (HTML tag)"}} -The component keeps track of the current picture so that it can access it when saving. To create the image file, it uses a `<canvas>` element that it draws the picture on (at a scale of one pixel per pixel). +Bileşen, kaydederken erişebilmek için mevcut resmin kaydını tutar. Resim dosyasını oluşturmak için, resmi üzerine çizdiği bir `<canvas>` öğesi kullanır (piksel başına bir piksel ölçekte). {{index "toDataURL method", "data URL"}} -The `toDataURL` method on a canvas element creates a URL that starts with `data:`. Unlike `http:` and `https:` URLs, data URLs contain the whole resource in the URL. They are usually very long, but they allow us to create working links to arbitrary pictures, right here in the browser. +Bir canvas öğesindeki `toDataURL` yöntemi, `data:` ile başlayan bir URL oluşturur. http:`ve`https:` URL`lerinin aksine, data URL`leri URL`deki tüm kaynağı içerir. Genellikle çok uzundurlar, ancak tarayıcıda rastgele resimlere çalışan bağlantılar oluşturmamızı sağlarlar. {{index "a (HTML tag)", "download attribute"}} -To actually get the browser to download the picture, we then create a ((link)) element that points at this URL and has a `download` attribute. Such links, when clicked, make the browser show a file save dialog. We add that link to the document, simulate a click on it, and remove it again. You can do a lot with ((browser)) technology, but sometimes the way to do it is rather odd. +Tarayıcının resmi indirmesini sağlamak için, bu URL'yi işaret eden ve `download` niteliğine sahip bir ((link)) öğesi oluştururuz. Bu tür bağlantılar tıklandığında tarayıcının bir dosya kaydetme iletişim kutusu göstermesini sağlar. Bu bağlantıyı belgeye ekliyoruz, üzerine tıklanmasını simüle ediyoruz ve tekrar kaldırıyoruz. + +((Tarayıcı)) teknolojisi ile çok şey yapabilirsiniz, ancak bazen bunu yapmanın yolu oldukça gariptir. {{index "LoadButton class", control, [file, image]}} -And it gets worse. We'll also want to be able to load existing image files into our application. To do that, we again define a button component. +Ve durum daha da kötüleşiyor. Mevcut resim dosyalarını da uygulamamıza yükleyebilmek isteyeceğiz. Bunu yapmak için yine bir düğme bileşeni tanımlıyoruz. ```{includeCode: true} class LoadButton { @@ -563,11 +565,11 @@ function startLoad(dispatch) { {{index [file, access], "input (HTML tag)"}} -To get access to a file on the user's computer, we need the user to select the file through a file input field. But I don't want the load button to look like a file input field, so we create the file input when the button is clicked and then pretend that this file input itself was clicked. +Kullanıcının bilgisayarındaki bir dosyaya erişmek için, kullanıcının bir dosya giriş alanı aracılığıyla dosyayı seçmesi gerekir. Ancak yükleme düğmesinin bir dosya giriş alanı gibi görünmesini istemiyorum, bu nedenle düğmeye tıklandığında dosya girişini oluşturuyoruz ve ardından bu dosya girişinin kendisine tıklanmış gibi davranıyoruz. {{index "FileReader class", "img (HTML tag)", "readAsDataURL method", "Picture class"}} -When the user has selected a file, we can use `FileReader` to get access to its contents, again as a ((data URL)). That URL can be used to create an `<img>` element, but because we can't get direct access to the pixels in such an image, we can't create a `Picture` object from that. +Kullanıcı bir dosya seçtiğinde, içeriğine erişmek için `FileReader` kullanabiliriz ve bu içeriğe tekrar bir ((veri URL'si)) olarak erişebiliriz. Bu URL bir `<img>` elementi oluşturmak için kullanılabilir, ancak böyle bir görüntünün piksellerine doğrudan erişemediğimiz için bir `Picture` nesnesi oluşturamayız. ```{includeCode: true} function finishLoad(file, dispatch) { @@ -587,7 +589,7 @@ function finishLoad(file, dispatch) { {{index "canvas (HTML tag)", "getImageData method", "pictureFromImage function"}} -To get access to the pixels, we must first draw the picture to a `<canvas>` element. The canvas context has a `getImageData` method that allows a script to read its ((pixel))s. So, once the picture is on the canvas, we can access it and construct a `Picture` object. +Piksellere erişmek için önce resmi bir `<canvas>` elementine çizmeliyiz. Canvas bağlamı, bir betiğin piksellerini okumasına olanak tanıyan bir `getImageData` metoduna sahiptir. Bu nedenle, resim canvas üzerinde olduğunda ona erişebilir ve bir `Picture` nesnesi oluşturabiliriz. ```{includeCode: true} function pictureFromImage(image) { @@ -610,33 +612,33 @@ function pictureFromImage(image) { } ``` -We'll limit the size of images to 100 by 100 pixels since anything bigger will look _huge_ on our display and might slow down the interface. +Görüntülerin boyutunu 100'e 100 piksel ile sınırlandıracağız çünkü daha büyük bir şey ekranımızda _çok büyük_ görünecek ve arayüzü yavaşlatabilir. {{index "getImageData method", color, transparency}} -The `data` property of the object returned by `getImageData` is an array of color components. For each pixel in the rectangle specified by the arguments, it contains four values, which represent the red, green, blue, and _((alpha))_ components of the pixel's color, as numbers between 0 and 255. The alpha part represents opacity—when it is zero, the pixel is fully transparent, and when it is 255, it is fully opaque. For our purpose, we can ignore it. +`getImageData` tarafından döndürülen nesnenin `data` özelliği, renk bileşenlerinden oluşan bir dizidir. Argümanlarla belirtilen dikdörtgendeki her piksel için bu dizi, pikselin renginin kırmızı, yeşil, mavi ve _((alfa))_ bileşenlerini temsil eden dört değer içerir. Bu değerler 0 ile 255 arasında değişir. Alfa kısmı opaklığı temsil eder—0 olduğunda piksel tamamen şeffaf, 255 olduğunda ise tamamen opaktır. Amacımız için bu kısmı görmezden gelebiliriz. {{index "hexadecimal number", "toString method"}} -The two hexadecimal digits per component, as used in our color notation, correspond precisely to the 0 to 255 range—two base-16 digits can express 16^2^ = 256 different numbers. The `toString` method of numbers can be given a base as argument, so `n.toString(16)` will produce a string representation in base 16. We have to make sure that each number takes up two digits, so the `hex` helper function calls `padStart` to add a leading zero when necessary. +Renk notasyonumuzda kullanılan her bileşen için iki onaltılık basamak, tam olarak 0 ile 255 aralığına karşılık gelir—iki taban-16 basamağı, 16^2^ = 256 farklı sayıyı ifade edebilir. Sayıların `toString` metodu bir taban argümanı alabilir, bu yüzden `n.toString(16)` taban 16'da bir string temsil oluşturur. Her sayının iki basamak kapladığından emin olmalıyız, bu yüzden `hex` yardımcı fonksiyonu, gerekirse başa sıfır eklemek için `padStart` çağrısı yapar. -We can load and save now! That leaves one more feature before we're done. +Artık yükleyip kaydedebiliyoruz! Bitirmeden önce sadece bir özellik kaldı. -## Undo history +## Geçmişi geri alma -Half of the process of editing is making little mistakes and correcting them. So an important feature in a drawing program is an ((undo history)). +Düzenleme sürecinin yarısı küçük hatalar yapmak ve bunları düzeltmektir. Bu nedenle, bir çizim programında önemli bir özellik, bir ((geri alma geçmişi))dir. {{index "persistent data structure", [state, "of application"]}} -To be able to undo changes, we need to store previous versions of the picture. Since it's an ((immutable)) value, that is easy. But it does require an additional field in the application state. +Değişiklikleri geri alabilmek için resmin önceki sürümlerini saklamamız gerekiyor. Bu, bir ((değiştirilemez)) değer olduğu için oldukça kolaydır. Ancak uygulama durumunda ek bir alan gerektirir. {{index "done property"}} -We'll add a `done` array to keep previous versions of the ((picture)). Maintaining this property requires a more complicated state update function that adds pictures to the array. +Önceki ((resim)) sürümlerini saklamak için bir `done` dizisi ekleyeceğiz. Bu özelliği sürdürmek, resimleri diziye ekleyen daha karmaşık bir durum güncelleme fonksiyonu gerektirir. {{index "doneAt property", "historyUpdateState function", "Date.now function"}} -But we don't want to store _every_ change, only changes a certain amount of ((time)) apart. To be able to do that, we'll need a second property, `doneAt`, tracking the time at which we last stored a picture in the history. +Ancak _her_ değişikliği saklamak istemiyoruz, yalnızca belirli bir ((zaman)) aralığında olan değişiklikleri. Bunu yapabilmek için, geçmişte bir resmi en son ne zaman sakladığımızı izleyen ikinci bir özellik olan `doneAt`'a ihtiyacımız olacak. ```{includeCode: true} function historyUpdateState(state, action) { @@ -664,13 +666,13 @@ function historyUpdateState(state, action) { {{index "undo history"}} -When the action is an undo action, the function takes the most recent picture from the history and makes that the current picture. It sets `doneAt` to zero so that the next change is guaranteed to store the picture back in the history, allowing you to revert to it another time if you want. +Eylem bir geri alma eylemi olduğunda, fonksiyon geçmişten en son resmi alır ve bunu geçerli resim yapar. `doneAt`'i sıfıra ayarlar, böylece bir sonraki değişikliğin resmi yeniden geçmişe kaydetmesi garanti edilir. Bu, istediğiniz takdirde tekrar ona dönebilmenizi sağlar. -Otherwise, if the action contains a new picture and the last time we stored something is more than a second (1000 milliseconds) ago, the `done` and `doneAt` properties are updated to store the previous picture. +Aksi takdirde, eylem yeni bir resim içeriyorsa ve en son bir şey kaydettiğimiz zaman bir saniyeden (1000 milisaniye) daha önceyse, `done` ve `doneAt` özellikleri önceki resmi saklayacak şekilde güncellenir. {{index "UndoButton class", control}} -The undo button ((component)) doesn't do much. It dispatches undo actions when clicked and disables itself when there is nothing to undo. +Geri alma düğmesi ((bileşeni)) çok fazla iş yapmaz. Tıklandığında geri alma eylemleri gönderir ve geri alınacak bir şey olmadığında kendini devre dışı bırakır. ```{includeCode: true} class UndoButton { @@ -686,11 +688,11 @@ class UndoButton { } ``` -## Let's draw +## Haydi çizelim {{index "PixelEditor class", "startState constant", "baseTools constant", "baseControls constant", "startPixelEditor function"}} -To set up the application, we need to create a state, a set of ((tool))s, a set of ((control))s, and a ((dispatch)) function. We can pass them to the `PixelEditor` constructor to create the main component. Since we'll need to create several editors in the exercises, we first define some bindings. +Uygulamayı kurmak için bir durum, bir dizi ((araç)), bir dizi ((kontrol)) ve bir ((dispatch)) fonksiyonu oluşturmamız gerekiyor. Bunları ana bileşeni oluşturmak için `PixelEditor` constructor'ına iletebiliriz. Egzersizlerde birkaç düzenleyici oluşturmamız gerekeceğinden, önce bazı bağlamalar tanımlıyoruz. ```{includeCode: true} const startState = { @@ -724,9 +726,9 @@ function startPixelEditor({state = startState, {{index "destructuring binding", "= operator", [property, access]}} -When destructuring an object or array, you can use `=` after a binding name to give the binding a ((default value)), which is used when the property is missing or holds `undefined`. The `startPixelEditor` function makes use of this to accept an object with a number of optional properties as an argument. If you don't provide a `tools` property, for example, `tools` will be bound to `baseTools`. +Bir nesneyi veya diziyi parçalarına ayırırken, bir bağlama adına `=` koyarak bir ((varsayılan değer)) atayabilirsiniz. Bu, ilgili özellik eksik olduğunda veya `undefined` içerdiğinde kullanılır. `startPixelEditor` fonksiyonu, bir dizi isteğe bağlı özellik içeren bir nesneyi argüman olarak kabul etmek için bunu kullanır. Örneğin, bir `tools` özelliği sağlamazsanız, `tools` `baseTools`'a bağlanacaktır. -This is how we get an actual editor on the screen: +Bir düzenleyiciyi ekranda bu şekilde elde ederiz: ```{lang: html, startCode: true} <div></div> @@ -738,50 +740,50 @@ This is how we get an actual editor on the screen: {{if interactive -Go ahead and draw something. +Haydi bir şey çiz. if}} -## Why is this so hard? +## Neden bu kadar zor? -Browser technology is amazing. It provides a powerful set of interface building blocks, ways to style and manipulate them, and tools to inspect and debug your applications. The software you write for the ((browser)) can be run on almost every computer and phone on the planet. +Tarayıcı teknolojisi inanılmaz. Güçlü bir dizi arayüz oluşturma bloğu, bunları şekillendirip manipüle etme yolları ve uygulamalarınızı inceleyip hata ayıklama araçları sağlar. Tarayıcı için yazdığınız yazılım, dünyadaki neredeyse her bilgisayar ve telefonda çalıştırılabilir. -At the same time, browser technology is ridiculous. You have to learn a large number of silly tricks and obscure facts to master it, and the default programming model it provides is so problematic that most programmers prefer to cover it in several layers of ((abstraction)) rather than deal with it directly. +Aynı zamanda, tarayıcı teknolojisi saçma bir yapıya sahip. Onu tam anlamıyla öğrenmek için birçok anlamsız numara ve karmaşık bilgi öğrenmeniz gerekiyor. Ayrıca, sağladığı varsayılan programlama modeli o kadar sorunlu ki, çoğu programcı doğrudan bununla uğraşmak yerine birkaç katman ((soyutlama)) ile bunu örtmeyi tercih ediyor. {{index standard, evolution}} -And though the situation is definitely improving, it mostly does so in the form of more elements being added to address shortcomings—creating even more ((complexity)). A feature used by a million websites can't really be replaced. Even if it could, it would be hard to decide what it should be replaced with. +Durum kesinlikle iyileşiyor olsa da, bu genellikle eksiklikleri gidermek için daha fazla öğe eklenmesi şeklinde gerçekleşiyor—bu da daha fazla ((karmaşıklık)) yaratıyor. Bir milyon web sitesi tarafından kullanılan bir özellik kolayca değiştirilemez. Değiştirilebilse bile, yerine ne konulması gerektiğine karar vermek zor olurdu. {{index "social factors", "economic factors", history}} -Technology never exists in a vacuum—we're constrained by our tools and the social, economic, and historical factors that produced them. This can be annoying, but it is generally more productive to try to build a good understanding of how the _existing_ technical reality works—and why it is the way it is—than to rage against it or hold out for another reality. +Teknoloji asla bir boşlukta var olmaz—araçlarımız ve onları üreten sosyal, ekonomik ve tarihsel faktörlerle sınırlıyız. Bu sinir bozucu olabilir, ancak mevcut teknik gerçekliğin nasıl çalıştığını ve neden böyle olduğunu anlamaya çalışmak, buna kızmaktan ya da başka bir gerçeklik için beklemekten genellikle daha üretkendir. -New ((abstraction))s _can_ be helpful. The component model and ((data flow)) convention I used in this chapter is a crude form of that. As mentioned, there are libraries that try to make user interface programming more pleasant. At the time of writing, [React](https://reactjs.org/) and [Svelte](https://svelte.dev/) are popular choices, but there's a whole cottage industry of such frameworks. If you're interested in programming web applications, I recommend investigating a few of them to understand how they work and what benefits they provide. +Yeni ((soyutlama))lar _yararlı_ olabilir. Bu bölümde kullandığım bileşen modeli ve ((veri akışı)) düzeni bunun kaba bir biçimidir. Daha önce de belirtildiği gibi, kullanıcı arayüzü programlamasını daha keyifli hale getirmeye çalışan kütüphaneler vardır. Bu yazının yazıldığı dönemde [React](https://reactjs.org/) ve [Svelte](https://svelte.dev/) popüler seçeneklerdir, ancak bu tür çerçevelerin kendine özgü bir sektörü vardır. Web uygulamaları programlamasıyla ilgileniyorsanız, nasıl çalıştıklarını ve hangi faydaları sağladıklarını anlamak için bunlardan birkaçını incelemenizi öneririm. -## Exercises +## Alıştırmalar -There is still room for improvement in our program. Let's add a few more features as exercises. +Programımızda iyileştirme için hala yer var. Alıştırma olarak birkaç yeni özellik ekleyelim. -### Keyboard bindings +### Klavye kısayolları {{index "keyboard bindings (exercise)"}} -Add ((keyboard)) shortcuts to the application. The first letter of a tool's name selects the tool, and [control]{keyname}-Z or [command]{keyname}-Z activates undo. +Uygulamaya ((klavye)) kısayolları ekleyin. Bir aracın adının ilk harfi o aracı seçer ve [control]{tuşadı}-Z veya [command]{tuşadı}-Z tuş kombinasyonları geri alma işlevini aktif eder. {{index "PixelEditor class", "tabindex attribute", "elt function", "keydown event"}} -Do this by modifying the `PixelEditor` component. Add a `tabIndex` property of 0 to the wrapping `<div>` element so that it can receive keyboard ((focus)). Note that the _property_ corresponding to the `tabindex` _attribute_ is called `tabIndex`, with a capital I, and our `elt` function expects property names. Register the key event handlers directly on that element. This means you have to click, touch, or tab to the application before you can interact with it with the keyboard. +Bunu `PixelEditor` bileşenini değiştirerek yapın. Sarma `<div>` öğesine 0 değeriyle bir `tabIndex` özelliği ekleyin, böylece klavye ((odak)) alabilir. Burada dikkat edilmesi gereken nokta, `tabindex` _özniteliğine_ karşılık gelen _özelliğin_ adının `tabIndex` olduğu ve büyük I harfiyle yazıldığıdır. `elt` fonksiyonumuz, bu özelliğin adını bekler. Tuş olay işleyicilerini doğrudan bu öğe üzerinde kaydedin. Bu, klavye ile uygulama üzerinde işlem yapabilmek için uygulamaya tıklamanız, dokunmanız veya sekme tuşuyla odaklanmanız gerektiği anlamına gelir. {{index "ctrlKey property", "metaKey property", "control key", "command key"}} -Remember that keyboard events have `ctrlKey` and `metaKey` (for the [command]{keyname} key on Mac) properties that you can use to see whether those keys are held down. +Unutmayın, klavye olaylarının `ctrlKey` ve Mac'te [command]{tuşadı} için `metaKey` özellikleri vardır. Bu özellikleri kullanarak bu tuşların basılı olup olmadığını kontrol edebilirsiniz. {{if interactive ```{test: no, lang: html} <div></div> <script> - // The original PixelEditor class. Extend the constructor. + // Orijinal PixelEditor sınıfı. constructor fonksiyonunu devam ettir. class PixelEditor { constructor(state, config) { let {tools, controls, dispatch} = config; @@ -818,35 +820,35 @@ if}} {{index "keyboard bindings (exercise)", "key property", "shift key"}} -The `key` property of events for letter keys will be the lowercase letter itself, if [shift]{keyname} isn't being held. We're not interested in key events with [shift]{keyname} here. +Olayların `key` özelliği, harf tuşları için [shift]{tuşadı} basılı değilse küçük harfini döndürecektir. Bu durumda, [shift]{tuşadı} ile ilgili tuş olaylarına ilgi duymuyoruz. {{index "keydown event"}} -A `"keydown"` handler can inspect its event object to see whether it matches any of the shortcuts. You can automatically get the list of first letters from the `tools` object so that you don't have to write them out. +Bir `"keydown"` işlemcisi, olay nesnesini inceleyerek bu olayın bir kısayolla eşleşip eşleşmediğini kontrol edebilir. `tools` nesnesinden ilk harflerin listesini otomatik olarak alabilirsiniz; böylece bu harfleri elle yazmak zorunda kalmazsınız. {{index "preventDefault method"}} -When the key event matches a shortcut, call `preventDefault` on it and ((dispatch)) the appropriate action. +Eğer tuş olayı bir kısayolla eşleşiyorsa, `preventDefault` çağrısını yaparak varsayılan davranışı engelleyebilir ve ardından ((dispatch)) işlemini gerçekleştirerek uygun eylemi tetikleyebilirsiniz. hint}} -### Efficient drawing +### Verimli çizim {{index "efficient drawing (exercise)", "canvas (HTML tag)", efficiency}} -During drawing, the majority of work that our application does happens in `drawPicture`. Creating a new state and updating the rest of the DOM isn't very expensive, but repainting all the pixels on the canvas is quite a bit of work. +Çizim sırasında, uygulamamızın yaptığı işlemlerin büyük kısmı `drawPicture` içinde gerçekleşir. Yeni bir durum oluşturmak ve DOM'un geri kalanını güncellemek çok maliyetli değildir; ancak canvas üzerindeki tüm piksellerin yeniden boyanması oldukça yoğun bir işlemdir. {{index "syncState method", "PictureCanvas class"}} -Find a way to make the `syncState` method of `PictureCanvas` faster by redrawing only the pixels that actually changed. +`PictureCanvas` sınıfının `syncState` metodunu daha hızlı hale getirmenin bir yolunu bulun ve yalnızca gerçekten değişen pikselleri yeniden çizin. {{index "drawPicture function", compatibility}} -Remember that `drawPicture` is also used by the save button, so if you change it, either make sure the changes don't break the old use or create a new version with a different name. +Unutmayın ki `drawPicture`, kaydetme düğmesi tarafından da kullanılıyor. Eğer değişiklik yaparsanız, eski kullanımı bozmadığınızdan emin olun veya farklı bir adla yeni bir sürüm oluşturun. {{index "width property", "height property"}} -Also note that changing the size of a `<canvas>` element, by setting its `width` or `height` properties, clears it, making it entirely transparent again. +Ayrıca `<canvas>` öğesinin `width` veya `height` özelliklerini değiştirmenin, canvas'ı temizleyerek tamamen şeffaf bir hale getirdiğini unutmayın. {{if interactive @@ -885,23 +887,23 @@ if}} {{index "efficient drawing (exercise)"}} -This exercise is a good example of how ((immutable)) data structures can make code _faster_. Because we have both the old and the new picture, we can compare them and redraw only the pixels that changed color, saving more than 99 percent of the drawing work in most cases. +Bu alıştırma, ((değiştirilemez)) veri yapılarının kodu _daha hızlı_ hale getirebileceği iyi bir örnektir. Eski ve yeni resmi karşılaştırabildiğimiz için yalnızca renk değiştiren pikselleri yeniden çizebiliriz. Bu sayede çoğu durumda çizim işlemlerinin %99'undan fazlasından tasarruf sağlanabilir. {{index "drawPicture function"}} -You can either write a new function `updatePicture` or have `drawPicture` take an extra argument, which may be undefined or the previous picture. For each ((pixel)), the function checks whether a previous picture was passed with the same color at this position and skips the pixel when that is the case. +Yeni bir `updatePicture` fonksiyonu yazabilir veya `drawPicture`'a isteğe bağlı ek bir argüman olarak önceki resmi iletebilirsiniz. Bu fonksiyon, her ((piksel)) için, aynı konumdaki önceki resimde aynı renkte bir renk olup olmadığını kontrol eder ve eğer varsa o pikseli atlar. {{index "width property", "height property", "canvas (HTML tag)"}} -Because the canvas gets cleared when we change its size, you should also avoid touching its `width` and `height` properties when the old picture and the new picture have the same size. If they are different, which will happen when a new picture has been loaded, you can set the binding holding the old picture to null after changing the canvas size because you shouldn't skip any pixels after you've changed the canvas size. +Canvas boyutunu değiştirdiğimizde temizlendiğinden, eski resim ve yeni resim aynı boyutta olduğunda `width` ve `height` özelliklerini değiştirmekten kaçının. Eğer farklılarsa (örneğin yeni bir resim yüklendiğinde), canvas boyutunu değiştirdikten sonra eski resmi tutan referansı null olarak ayarlayın. Bu, yeni bir resim yükledikten sonra piksel atlamamanızı sağlar. hint}} -### Circles +### Daireler {{index "circles (exercise)", dragging}} -Define a ((tool)) called `circle` that draws a filled circle when you drag. The center of the circle lies at the point where the drag or touch gesture starts, and its ((radius)) is determined by the distance dragged. +Bir `circle` adında ((tool)) tanımlayın; bu araç sürüklediğinizde dolu bir daire çizecek. Dairenin merkezi, sürükleme veya dokunma işleminin başladığı noktadadır ve ((radius)) sürükleme mesafesine göre belirlenir. {{if interactive @@ -909,7 +911,7 @@ Define a ((tool)) called `circle` that draws a filled circle when you drag. The <div></div> <script> function circle(pos, state, dispatch) { - // Your code here + // Kodunuz buraya } let dom = startPixelEditor({ @@ -925,33 +927,33 @@ if}} {{index "circles (exercise)", "rectangle function"}} -You can take some inspiration from the `rectangle` tool. Like that tool, you'll want to keep drawing on the _starting_ picture, rather than the current picture, when the pointer moves. +`rectangle` aracından bazı ilhamlar alabilirsiniz. Bu araç gibi, imleç hareket ettiğinde mevcut resmi değil, _başlangıç_ resminde çizmeye devam etmek isteyeceksiniz. -To figure out which pixels to color, you can use the ((Pythagorean theorem)). First figure out the distance between the current pointer position and the start position by taking the square root (`Math.sqrt`) of the sum of the square (`x ** 2`) of the difference in x-coordinates and the square of the difference in y-coordinates. Then loop over a square of pixels around the start position, whose sides are at least twice the ((radius)), and color those that are within the circle's radius, again using the Pythagorean formula to figure out their ((distance)) from the center. +Hangi piksellerin renklendirileceğini bulmak için ((Pisagor teoremi))ni kullanabilirsiniz. Öncelikle, imlecin mevcut pozisyonu ile başlangıç pozisyonu arasındaki mesafeyi `Math.sqrt` fonksiyonu kullanarak x-koordinatlarındaki farkın karesi (`Math.pow(x, 2)`) ve y-koordinatlarındaki farkın karesinin toplamının karekökünü alarak hesaplayın. Daha sonra başlangıç pozisyonunun etrafında, kenar uzunlukları en az iki katı olan bir kare piksel alanında döngü oluşturun ve dairenin yarıçapına dahil olan pikselleri yine Pisagor formülünü kullanarak belirleyin. -Make sure you don't try to color pixels that are outside of the picture's boundaries. +Resim sınırlarının dışındaki pikselleri renklendirmeye çalışmadığınızdan emin olun. hint}} -### Proper lines +### Doğru çizgiler {{index "proper lines (exercise)", "line drawing"}} -This is a more advanced exercise than the preceding two, and it will require you to design a solution to a nontrivial problem. Make sure you have plenty of time and ((patience)) before starting to work on this exercise, and do not get discouraged by initial failures. +Bu, önceki iki egzersizden daha karmaşık bir alıştırma ve çözüm tasarlama yeteneğinizi test eden bir probleme dayanıyor. Bu egzersize başlamadan önce bolca zaman ve ((sabır))ınız olduğundan emin olun ve ilk başarısızlıklardan cesaretinizi kırmayın. {{index "draw function", "mousemove event", "touchmove event"}} -On most browsers, when you select the `draw` ((tool)) and quickly drag across the picture, you don't get a closed line. Rather, you get dots with gaps between them because the `"mousemove"` or `"touchmove"` events did not fire quickly enough to hit every ((pixel)). +Çoğu tarayıcıda, `draw` ((tool)) seçildiğinde ve resmi hızlı bir şekilde sürüklediğinizde, kapalı bir çizgi elde etmezsiniz. Bunun yerine, aralarında boşluklar bulunan noktalar elde edersiniz çünkü `"mousemove"` veya `"touchmove"` olayları yeterince hızlı tetiklenmez ve tüm ((piksel))lere ulaşamaz. -Improve the `draw` tool to make it draw a full line. This means you have to make the motion handler function remember the previous position and connect that to the current one. +`draw` aracını geliştirin, böylece tam bir çizgi çizecek şekilde çalışsın. Bu, hareket işleyici fonksiyonunun önceki pozisyonu hatırlaması ve mevcut pozisyonla birleştirmesi gerektiği anlamına gelir. -To do this, since the pixels can be an arbitrary distance apart, you'll have to write a general line drawing function. +Bunu yapmak için, piksellerin arası mesafe çok farklı olabileceğinden, genel bir çizgi çizme fonksiyonu yazmanız gerekecek. -A line between two pixels is a connected chain of pixels, as straight as possible, going from the start to the end. Diagonally adjacent pixels count as connected. So a slanted line should look like the picture on the left, not the picture on the right. +İki piksel arasındaki çizgi, mümkün olduğunca düz bir şekilde başlangıçtan sona kadar birleştirilen piksel zinciridir. Çapraz olarak komşu olan pikseller de birbirine bağlı kabul edilir. Bu nedenle eğik bir çizgi, soldaki resimdeki gibi görünmelidir; sağdaki gibi olmamalıdır. -{{figure {url: "img/line-grid.svg", alt: "Diagram of two pixelated lines, one light, skipping across pixels diagonally, and one heavy, with all pixels connected horizontally or vertically", width: "6cm"}}} +{{figure {url: "img/line-grid.svg", alt: "İki piksel benzeri çizgi diyagramı: biri açık ve pikselatlar boyunca çapraz atlamalar yaparken, diğeri kalın ve yalnızca yatay veya dikey olarak tüm pikselleri birbirine bağlıyor.", width: "6cm"}}} -Finally, if we have code that draws a line between two arbitrary points, we might as well use it to also define a `line` tool, which draws a straight line between the start and end of a drag. +Son olarak, iki nokta arasında bir çizgi çizen bir kodumuz varsa, bunu aynı zamanda bir `line` aracı tanımlamak için kullanabiliriz. Bu araç, bir sürükleme işleminin başlangıç ve bitiş noktası arasında düz bir çizgi çizecek. {{if interactive @@ -969,7 +971,7 @@ Finally, if we have code that draws a line between two arbitrary points, we migh } function line(pos, state, dispatch) { - // Your code here + // Kodunuz buraya } let dom = startPixelEditor({ @@ -985,21 +987,21 @@ if}} {{index "proper lines (exercise)", "line drawing"}} -The thing about the problem of drawing a pixelated line is that it is really four similar but slightly different problems. Drawing a horizontal line from the left to the right is easy—you loop over the x-coordinates and color a pixel at every step. If the line has a slight slope (less than 45 degrees or ¼π radians), you can interpolate the y-coordinate along the slope. You still need one pixel per _x_ position, with the _y_ position of those pixels determined by the slope. +Pikselle çizgi çekme probleminin karmaşıklığı, aslında dört benzer fakat biraz farklı probleme dayanır. Soldan sağa doğru yatay bir çizgi çekmek kolaydır—x-koordinatları üzerinde bir döngü kurarak her adımda bir piksel renklendirirsiniz. Eğer çizgi hafif bir eğime sahipse (45 dereceden veya ¼π radyanından küçükse), eğim boyunca y-koordinatını içe aktarabilirsiniz. Bu durumda her _x_ pozisyonu için bir piksel gerekir ve bu piksellerin _y_ koordinatları eğime göre belirlenir. -But as soon as your slope goes across 45 degrees, you need to switch the way you treat the coordinates. You now need one pixel per _y_ position since the line goes up more than it goes left. And then, when you cross 135 degrees, you have to go back to looping over the x-coordinates, but from right to left. +Ancak eğim 45 dereceyi geçtiğinde, koordinat işleme şeklini değiştirmeniz gerekir. Artık dikey bir çizgi gibi çalışmalısınız; yani her _y_ pozisyonu için bir piksel renklendirmelisiniz çünkü çizgi yukarı doğru ilerliyor ve sola gitmiyor. Daha sonra 135 dereceyi geçtiğinizde, tekrar x-koordinatları üzerinde döngü kurmalısınız, fakat bu sefer sağdan sola doğru. -You don't actually have to write four loops. Since drawing a line from _A_ to _B_ is the same as drawing a line from _B_ to _A_, you can swap the start and end positions for lines going from right to left and treat them as going left to right. +Aslında dört farklı döngü yazmak zorunda değilsiniz. Çünkü _A_ noktasından _B_ noktasına çizgi çekmek, aynı zamanda _B_ noktasından _A_ noktasına çizgi çekmekle aynıdır. Bu nedenle sağdan sola doğru çizgi çizerken başlangıç ve bitiş noktalarını değiştirebilirsiniz ve bunu sola doğru çizgi çekme olarak ele alabilirsiniz. -So you need two different loops. The first thing your line drawing function should do is check whether the difference between the x-coordinates is larger than the difference between the y-coordinates. If it is, this is a horizontal-ish line, and if not, a vertical-ish one. +Bu durumda yalnızca iki farklı döngüye ihtiyacınız var. Çizgi çekme fonksiyonunuzun yapacağı ilk işlem, x-koordinatları arasındaki farkın y-koordinatları arasındaki farktan büyük olup olmadığını kontrol etmektir. Eğer büyükse bu yatay bir çizgi olur; aksi takdirde dikey bir çizgi olur. {{index "Math.abs function", "absolute value"}} -Make sure you compare the _absolute_ values of the _x_ and _y_ difference, which you can get with `Math.abs`. +_Öncelikle_, x ve y farklarının _mutlak değerlerini_ karşılaştırdığınızdan emin olun; bu işlemi `Math.abs` kullanarak elde edebilirsiniz. {{index "swapping bindings"}} -Once you know along which ((axis)) you will be looping, you can check whether the start point has a higher coordinate along that axis than the endpoint and swap them if necessary. A succinct way to swap the values of two bindings in JavaScript uses ((destructuring assignment)) like this: +((axis)) boyunca döngü kuracağınızı bildiğinizde, başlangıç noktasının bu eksen boyunca son noktadan daha yüksek bir koordinata sahip olup olmadığını kontrol edebilir ve gerekirse değerleri değiştirebilirsiniz. JavaScript'te iki değişkenin değerlerini değiştirmek için kısa bir yöntem ((destructuring assignment)) kullanmaktır: ```{test: no} [start, end] = [end, start]; @@ -1007,6 +1009,6 @@ Once you know along which ((axis)) you will be looping, you can check whether th {{index rounding}} -Then you can compute the ((slope)) of the line, which determines the amount the coordinate on the other axis changes for each step you take along your main axis. With that, you can run a loop along the main axis while also tracking the corresponding position on the other axis, and you can draw pixels on every iteration. Make sure you round the non-main axis coordinates since they are likely to be fractional and the `draw` method doesn't respond well to fractional coordinates. +Ardından, çizginin ((slope)) değerini hesaplayabilirsiniz. Bu, ana eksen boyunca her adım attığınızda diğer eksendeki koordinatın ne kadar değiştiğini belirler. Bu sayede, ana eksen boyunca bir döngü çalıştırabilir ve aynı zamanda diğer eksendeki karşılık gelen konumu takip edebilirsiniz. Her döngü adımında piksel çizebilirsiniz. Diğer eksendeki koordinatlar kesirli olabileceğinden, bunları yuvarladığınızdan emin olun çünkü `draw` metodu kesirli koordinatlarla iyi çalışmaz. hint}} diff --git a/20_node.md b/20_node.md index d4569a12..1bf80023 100644 --- a/20_node.md +++ b/20_node.md @@ -4,54 +4,54 @@ {{quote {author: "Master Yuan-Ma", title: "The Book of Programming", chapter: true} -A student asked, 'The programmers of old used only simple machines and no programming languages, yet they made beautiful programs. Why do we use complicated machines and programming languages?'. Fu-Tzu replied, 'The builders of old used only sticks and clay, yet they made beautiful huts.' +Bir öğrenci sordu: "Eski programcılar yalnızca basit makineler ve programlama dilleri kullanmadan güzel programlar yaptılar. Neden karmaşık makineler ve programlama dilleri kullanıyoruz?" Fu-Tzu cevap verdi: "Eski inşaatçılar yalnızca çubuklar ve kili kullanarak güzel kulübeler yaptılar." quote}} {{index "Yuan-Ma", "Book of Programming"}} -{{figure {url: "img/chapter_picture_20.jpg", alt: "Illustration showing a telephone pole with a tangle of wires going in all directions", chapter: "framed"}}} +{{figure {url: "img/chapter_picture_20.jpg", alt: "Bir telefon direği üzerinde dört bir yana karmaşık şekilde dağılmış tellerin gösterildiği bir illüstrasyon.", chapter: "framed"}}} {{index "command line"}} -So far, we have used the JavaScript language in a single environment: the browser. This chapter and the [next one](skillsharing) will briefly introduce ((Node.js)), a program that allows you to apply your JavaScript skills outside of the browser. With it, you can build anything from small command line tools to HTTP ((server))s that power dynamic ((website))s. +Şu ana kadar yalnızca tarayıcı ortamında JavaScript dilini kullandık. Bu bölüm ve [bir sonraki bölüm](skillsharing), JavaScript becerilerinizi tarayıcı dışında da kullanmanıza olanak tanıyan `((Node.js))` adında bir programı kısa bir şekilde tanıtacaktır. Bu araç sayesinde, küçük komut satırı araçlarından dinamik `((website))`leri çalıştıran HTTP `((server))`lerine kadar birçok şeyi oluşturabilirsiniz. -These chapters aim to teach you the main concepts that Node.js uses and to give you enough information to write useful programs for it. They do not try to be a complete, or even a thorough, treatment of the platform. +Bu bölümler, Node.js’in temel konseptlerini öğretmeyi amaçlıyor ve bu platformda faydalı programlar yazmak için yeterli bilgi sağlıyor. Platformun tam ve kapsamlı bir açıklamasını hedeflemiyor. {{if interactive -Whereas you could run the code in previous chapters directly on these pages, because it was either raw JavaScript or written for the browser, the code samples in this chapter are written for Node and often won't run in the browser. +Önceki bölümlerdeki kodu doğrudan bu sayfalarda çalıştırabiliyordunuz çünkü ya ham JavaScript'ti ya da tarayıcı için yazılmıştı; ancak bu bölümdeki örnekler Node için yazılmış durumda ve genellikle tarayıcıda çalıştırılamazlar. if}} -If you want to follow along and run the code in this chapter, you'll need to install Node.js version 18 or higher. To do so, go to [_https://nodejs.org_](https://nodejs.org) and follow the installation instructions for your operating system. You can also find further ((documentation)) for Node.js there. +Bu bölümü takip edip örnek kodları çalıştırmak isterseniz, Node.js sürüm 18 veya daha üstünü yüklemeniz gerekiyor. Bunu yapmak için [_https://nodejs.org_](https://nodejs.org) adresine gidin ve işletim sisteminize uygun yükleme talimatlarını takip edin. Ayrıca Node.js için daha fazla `((documentation))` bilgisine de buradan ulaşabilirsiniz. -## Background +## Arka Plan {{index responsiveness, input, [network, speed]}} -When building systems that communicate over the network, the way you manage input and ((output))—that is, the reading and writing of data to and from the network and ((hard drive))—can make a big difference in how quickly a system responds to the user or to network requests. +Ağ üzerinden iletişim kuran sistemler yazarken yaşanan en zor sorunlardan biri, giriş ve `((output))` yönetimidir—yani ağdan ve ağlara veri okuma ve yazma işlemleriyle `((hard drive))` arasındaki veri taşınması. Verileri taşımak zaman alır ve bunu akıllıca `((scheduling))` yapmak, bir sistemin kullanıcıya ya da ağ isteklerine yanıt verme hızında büyük fark yaratabilir. {{index ["asynchronous programming", "in Node.js"]}} -In such programs, asynchronous programming is often helpful. It allows the program to send and receive data from and to multiple devices at the same time without complicated thread management and synchronization. +Bu tür programlarda asenkron programlama genellikle yardımcıdır. Asenkron programlama, karmaşık thread yönetimi ve senkronizasyon olmadan aynı anda birden fazla cihazdan veri alıp göndermeyi sağlar. {{index "programming language", "Node.js", standard}} -Node was initially conceived for the purpose of making asynchronous programming easy and convenient. JavaScript lends itself well to a system like Node. It is one of the few programming languages that does not have a built-in way to do in- and output. Thus, JavaScript could be fit onto Node's rather eccentric approach to network and file system programming without ending up with two inconsistent interfaces. In 2009, when Node was being designed, people were already doing callback-based programming in the browser, so the ((community)) around the language was used to an asynchronous programming style. +Node, başlangıçta asenkron programlamayı kolay ve kullanışlı hale getirmek amacıyla tasarlandı. JavaScript, Node gibi bir sistem için uygundur. JavaScript, yerleşik bir giriş-çıkış yöntemi bulunmayan nadir programlama dillerinden biridir. Böylece, JavaScript'in, Node'un giriş-çıkış açısından biraz sıra dışı yaklaşımına uyarlanması, iki tutarsız arayüzün ortaya çıkmasına sebep olmadan gerçekleştirilmiştir. 2009'da Node tasarlandığında, tarayıcıda zaten geri çağırma tabanlı programlamalar yapan insanlar vardı, bu nedenle ((community)), dilin asenkron programlama tarzına alışkındı. -## The node command +## Node Komutu {{index "node program"}} -When ((Node.js)) is installed on a system, it provides a program called `node`, which is used to run JavaScript files. Say you have a file `hello.js`, containing this code: +Bir sistemde ((Node.js)) kurulduğunda, JavaScript dosyalarını çalıştırmak için kullanılan `node` adında bir program sağlar. Diyelim ki `hello.js` adında bir dosyanız var ve şu kodu içeriyor: ``` let message = "Hello world"; console.log(message); ``` -You can then run `node` from the ((command line)) like this to execute the program: +`node` komutunu şu şekilde kullanabilirsiniz: ```{lang: null} $ node hello.js @@ -60,11 +60,11 @@ Hello world {{index "console.log"}} -The `console.log` method in Node does something similar to what it does in the browser. It prints out a piece of text. But in Node, the text will go to the process's ((standard output)) stream, rather than to a browser's ((JavaScript console)). When running `node` from the command line, that means you see the logged values in your ((terminal)). +Node'daki `console.log` metodu, tarayıcıda yaptığı işlemlerle benzer şekilde çalışır. Bir metni ekrana yazdırır. Ancak Node'da bu yazdırılan metin, tarayıcının ((JavaScript console)) yerine işlemin ((standart çıktı)) akışına gider. `node` komutunu komut satırından çalıştırdığınızda, bu durumda yazdırılan değerleri ((terminal)) üzerinde görürsünüz. {{index "node program", "read-eval-print loop"}} -If you run `node` without giving it a file, it provides you with a prompt at which you can type JavaScript code and immediately see the result. +Eğer `node` komutunu bir dosya vermeden çalıştırırsanız, JavaScript kodu yazabileceğiniz bir istemci (prompt) sağlanır ve yazdığınız kodun sonucunu anında görebilirsiniz. ```{lang: null} $ node @@ -78,11 +78,11 @@ $ {{index "process object", "global scope", [binding, global], "exit method", "status code"}} -The `process` binding, just like the `console` binding, is available globally in Node. It provides various ways to inspect and manipulate the current program. The `exit` method ends the process and can be given an exit status code, which tells the program that started `node` (in this case, the command line shell) whether the program completed successfully (code zero) or encountered an error (any other code). +`process` bağlaması, `console` bağlaması gibi Node'da küresel olarak mevcut bir bağlamadır. Mevcut programı incelemek ve manipüle etmek için çeşitli yöntemler sunar. `exit` metodu, işlemi sonlandırır ve bir çıkış durumu kodu verilebilir. Bu durum kodu, `node` komutunu başlatan programa (bu örnekte komut satırı kabuğu) işlemin başarılı bir şekilde tamamlandığını (kod sıfır) ya da bir hata ile karşılaştığını (başka bir kod) belirtir. {{index "command line", "argv property"}} -To find the command line arguments given to your script, you can read `process.argv`, which is an array of strings. Note that it also includes the name of the `node` command and your script name, so the actual arguments start at index 2. If `showargv.js` contains the statement `console.log(process.argv)`, you could run it like this: +Komut dosyanıza verilen komut satırı argümanlarını bulmak için, dizelerden oluşan bir dizi olan `process.argv` dosyasını okuyabilirsiniz. Bu dizinin `node` komutunun adını ve komut dosyanızın adını da içerdiğini, dolayısıyla gerçek argümanların 2. dizinden başladığını unutmayın. Eğer `showargv.js` `console.log(process.argv)` ifadesini içeriyorsa, bunu şu şekilde çalıştırabilirsiniz: ```{lang: null} $ node showargv.js one --and two @@ -91,38 +91,38 @@ $ node showargv.js one --and two {{index [binding, global]}} -All the ((standard)) JavaScript global bindings, such as `Array`, `Math`, and `JSON`, are also present in Node's environment. Browser-related functionality, such as `document` or `prompt`, is not. +`Array`, `Math` ve `JSON` gibi tüm ((standart)) JavaScript global bağları Node ortamında da mevcuttur. Tarayıcı ile ilgili `document` veya `prompt` gibi işlevler ise mevcut değildir. -## Modules +## Modüller {{index "Node.js", "global scope", "module loader"}} -Beyond the bindings I mentioned, such as `console` and `process`, Node puts few additional bindings in the global scope. If you want to access built-in functionality, you have to ask the module system for it. +Bahsettiğim `console` ve `process` gibi bağlayıcıların ötesinde, Node global kapsama birkaç ek bağlayıcı koyar. Yerleşik işlevselliğe erişmek istiyorsanız, modül sisteminden bunu istemeniz gerekir. {{index "require function"}} -Node started out using the ((CommonJS)) module system, based on the `require` function, which we saw in [Chapter ?](modules#commonjs). It will still use this system by default when you load a `.js` file. +Node, [Bölüm ?](modules#commonjs)'de gördüğümüz `require` fonksiyonuna dayanan ((CommonJS)) modül sistemini kullanmaya başladı. Bir `.js` dosyası yüklediğinizde varsayılan olarak bu sistemi kullanmaya devam edecektir. {{index "import keyword", "ES modules"}} -But it also support the more modern ES module system. When a script's filename ends in `.mjs`, it is considered to be such a module, and you can use `import` and `export` in it (but not `require`). We will use ES modules in this chapter. +Ancak daha modern ES modül sistemini de destekler. Bir betiğin dosya adı `.mjs` ile bitiyorsa, böyle bir modül olarak kabul edilir ve içinde `import` ve `export` kullanabilirsiniz (ancak `require` kullanamazsınız). Bu bölümde ES modüllerini kullanacağız. -{{index [path, "file system"], "relative path", resolution}} +{{index [path, "filesystem"], "relative path", resolution}} -When importing a module—whether with `require` or `import`—Node has to resolve the given string to an actual ((file)) that it can load. Names that start with `/`, `./`, or `../` are resolved as files, relative to the current module's path. Here, `.` stands for the current directory, `../` for one directory up, and `/` for the root of the file system. So if you ask for `"./graph.mjs"` from the file `/tmp/robot/robot.mjs`, Node will try to load the file `/tmp/robot/graph.mjs`. +Bir modülü içe aktarırken -ister `require` ister `import` ile olsun-Node, verilen dizeyi yükleyebileceği gerçek bir ((dosya)) olarak çözümlemek zorundadır. `/`, `./` veya `../` ile başlayan isimler, geçerli modülün yoluna göre dosya olarak çözümlenir. Burada `.` geçerli dizini, `../` bir dizin yukarıyı ve `/` dosya sisteminin kökünü temsil eder. Yani `/tmp/robot/robot.mjs` dosyasından `“./graph.mjs”` isterseniz, Node `/tmp/robot/graph.mjs` dosyasını yüklemeye çalışacaktır. {{index "node_modules directory", directory}} -When a string that does not look like a relative or absolute path is imported, it is assumed to refer to either a built-in ((module)) or a module installed in a `node_modules` directory. For example, importing from `"node:fs"` will give you Node's built-in file system module. And importing `"robot"` might try to load the library found in `node_modules/robot/`. A common way to install such libraries is by using ((NPM)), which we'll come back to in a moment. +Göreceli veya mutlak yol gibi görünmeyen bir dize içe aktarıldığında, yerleşik ((modül)) veya `node_modules` dizininde yüklü bir modüle başvurduğu varsayılır. Örneğin, `“node:fs”` modülünü içe aktarmak size Node'un yerleşik dosya sistemi modülünü verecektir. Ve `“robot”` içe aktarıldığında `node_modules/robot/` dizininde bulunan kütüphane yüklenmeye çalışılabilir. Bu tür kütüphaneleri yüklemenin yaygın bir yolu, birazdan geri döneceğimiz ((NPM)) kullanmaktır. {{index "import keyword", "Node.js", "garble example"}} -Let's set up a small project consisting of two files. The first one, called `main.mjs`, defines a script that can be called from the ((command line)) to reverse a string. +İki dosyadan oluşan küçük bir proje kuralım. Bunlardan ilki olan `main.mjs`, bir dizeyi tersine çevirmek için ((komut satırından)) çağrılabilecek bir betik tanımlar. ``` import {reverse} from "./reverse.mjs"; -// Index 2 holds the first actual command line argument +// Index 2 ilk gerçek komut satırı argümanını tutar let argument = process.argv[2]; console.log(reverse(argument)); @@ -130,7 +130,7 @@ console.log(reverse(argument)); {{index reuse, "Array.from function", "join method"}} -The file `reverse.mjs` defines a library for reversing strings, which can be used both by this command line tool and by other scripts that need direct access to a string-reversing function. +The `reverse.mjs` file defines a library for string reversal that can be used both by this command line tool and by other scripts that need direct access to string reversal functionality. ``` export function reverse(string) { @@ -140,24 +140,24 @@ export function reverse(string) { {{index "export keyword", "ES modules", [interface, module]}} -Remember that `export` is used to declare that a binding is part of the module's interface. That allows `main.mjs` to import and use the function. +Bir bağlayıcının modülün arayüzünün bir parçası olduğunu bildirmek için `export` kullanıldığını unutmayın. Bu `main.mjs`nin fonksiyonu içe aktarmasına ve kullanmasına izin verir. -We can now call our tool like this: +Artık aracımızı şu şekilde çağırabiliriz: ```{lang: null} $ node main.mjs JavaScript tpircSavaJ ``` -## Installing with NPM +## NPM ile kurulum {{index NPM, "Node.js", "npm program", library}} -NPM, which was introduced in [Chapter ?](modules#modules_npm), is an online repository of JavaScript ((module))s, many of which are specifically written for Node. When you install Node on your computer, you also get the `npm` command, which you can use to interact with this repository. +[Bölüm ?](modules#modules_npm)'de tanıtılan NPM, birçoğu Node için özel olarak yazılmış JavaScript ((modül))lerinden oluşan çevrimiçi bir depodur. Node'u bilgisayarınıza kurduğunuzda, bu depo ile etkileşimde bulunmak için kullanabileceğiniz `npm` komutunu da alırsınız. {{index "ini package"}} -NPM's main use is ((download))ing packages. We saw the `ini` package in [Chapter ?](modules#modules_ini). We can use NPM to fetch and install that package on our computer. +NPM'nin ana kullanım alanı paketleri ((indirmek))tir. [Bölüm ?](modules#modules_ini)'de `ini` paketini gördük. Bu paketi bilgisayarımıza getirmek ve kurmak için NPM'yi kullanabiliriz. ```{lang: null} $ npm install ini @@ -171,17 +171,17 @@ $ node {{index "require function", "node_modules directory", "npm program"}} -After running `npm install`, ((NPM)) will have created a directory called `node_modules`. Inside that directory will be an `ini` directory that contains the ((library)). You can open it and look at the code. When we import `"ini"`, this library is loaded, and we can call its `parse` property to parse a configuration file. +`npm install` çalıştırıldıktan sonra, ((NPM)) `node_modules` adında bir dizin oluşturacaktır. Bu dizinin içinde ((kütüphane)) içeren bir `ini` dizini olacaktır. Bunu açabilir ve koda bakabilirsiniz. `“ini"`yi içe aktardığımızda, bu kütüphane yüklenir ve bir yapılandırma dosyasını ayrıştırmak için `parse` özelliğini çağırabiliriz. -By default NPM installs packages under the current directory, rather than in a central place. If you are used to other package managers, this may seem unusual, but it has advantages—it puts each application in full control of the packages it installs and makes it easier to manage versions and clean up when removing an application. +NPM varsayılan olarak paketleri merkezi bir yer yerine geçerli dizinin altına yükler. Diğer paket yöneticilerine alışkınsanız, bu alışılmadık görünebilir, ancak avantajları vardır - her uygulamanın yüklediği paketleri tam olarak kontrol etmesini sağlar ve sürümleri yönetmeyi ve bir uygulamayı kaldırırken temizlemeyi kolaylaştırır. -### Package files +### Paket dosyaları {{index "package.json", dependency}} -After running `npm install` to install some package, you will find not only a `node_modules` directory, but also a file called `package.json` in your current directory. It is recommended to have such a file for each project. You can create it manually or run `npm init`. This file contains information about the project, such as its name and ((version)), and lists its dependencies. +Bir paketi yüklemek için `npm install` çalıştırdıktan sonra, yalnızca bir `node_modules` dizini değil, aynı zamanda geçerli dizininizde `package.json` adlı bir dosya da bulacaksınız. Her proje için böyle bir dosyanın olması tavsiye edilir. Bu dosyayı elle oluşturabilir ya da `npm init` komutunu çalıştırabilirsiniz. Bu dosya, proje hakkında adı ve ((sürüm)) gibi bilgileri içerir ve bağımlılıklarını listeler. -The robot simulation from [Chapter ?](robot), as modularized in the exercise in [Chapter ?](modules#modular_robot), might have a `package.json` file like this: +[Bölüm ?](robot)'daki robot simülasyonu, [Bölüm ?](modules#modular_robot)'daki alıştırmada modülerleştirildiği gibi, aşağıdaki gibi bir `package.json` dosyasına sahip olabilir: ```{lang: "json"} { @@ -200,37 +200,37 @@ The robot simulation from [Chapter ?](robot), as modularized in the exercise in {{index "npm program", tool}} -When you run `npm install` without naming a package to install, NPM will install the dependencies listed in `package.json`. When you install a specific package that is not already listed as a dependency, NPM will add it to `package.json`. +Yüklenecek bir paket belirtmeden `npm install` komutunu çalıştırdığınızda, NPM `package.json` dosyasında listelenen bağımlılıkları yükleyecektir. Daha önce bağımlılık olarak listelenmemiş belirli bir paketi yüklediğinizde, NPM bunu `package.json` dosyasına ekleyecektir. -### Versions +### Versiyonlar {{index "package.json", dependency, evolution}} -A `package.json` file lists both the program's own ((version)) and versions for its dependencies. Versions are a way to deal with the fact that ((package))s evolve separately, and code written to work with a package as it existed at one point may not work with a later, modified version of the package. +Bir `package.json` dosyası hem programın kendi ((sürüm))'ünü hem de bağımlılıklarının sürümlerini listeler. Sürümler, ((paket))'lerin ayrı ayrı geliştiği gerçeğiyle başa çıkmanın bir yoludur ve bir noktada var olduğu şekliyle bir paketle çalışmak için yazılan kod, paketin daha sonraki, değiştirilmiş bir sürümüyle çalışmayabilir. {{index compatibility}} -NPM demands that its packages follow a schema called _((semantic versioning))_, which encodes some information about which versions are _compatible_ (don't break the old interface) in the version number. A semantic version consists of three numbers, separated by periods, such as `2.3.0`. Every time new functionality is added, the middle number has to be incremented. Every time compatibility is broken, so that existing code that uses the package might not work with the new version, the first number has to be incremented. +NPM, paketlerinin _((semantic versioning))_ adı verilen ve sürüm numarasında hangi sürümlerin _uyumlu_ (eski arayüzü bozmayan) olduğu hakkında bazı bilgileri kodlayan bir şemayı takip etmesini talep eder. Anlamsal bir sürüm, `2.3.0` gibi noktalarla ayrılmış üç sayıdan oluşur. Her yeni işlevsellik eklendiğinde, ortadaki sayı artırılmalıdır. Uyumluluk her bozulduğunda, böylece paketi kullanan mevcut kod yeni sürümle çalışmayabilir, ilk sayı artırılmalıdır. {{index "caret character"}} -A caret character (`^`) in front of the version number for a dependency in `package.json` indicates that any version compatible with the given number may be installed. So, for example, `"^2.3.0"` would mean that any version greater than or equal to 2.3.0 and less than 3.0.0 is allowed. +`package.json`'daki bir bağımlılığın sürüm numarasının önündeki şapka karakteri (`^`), verilen numarayla uyumlu herhangi bir sürümün yüklenebileceğini gösterir. Örneğin, `“^2.3.0”`, 2.3.0'dan büyük veya eşit ve 3.0.0'dan küçük herhangi bir sürüme izin verildiği anlamına gelir. {{index publishing}} -The `npm` command is also used to publish new packages or new versions of packages. If you run `npm publish` in a ((directory)) that has a `package.json` file, it will publish a package with the name and version listed in the JSON file to the registry. Anyone can publish packages to NPM—though only under a package name that isn't in use yet since it would not be good if random people could update existing packages. +`npm` komutu yeni paketleri veya paketlerin yeni sürümlerini yayınlamak için de kullanılır. Bir `package.json` dosyasına sahip bir ((dizin)) içinde `npm publish` komutunu çalıştırırsanız, JSON dosyasında listelenen ad ve sürüme sahip bir paketi kayıt defterine yayınlayacaktır. Herkes NPM'de paket yayınlayabilir-ancak sadece henüz kullanılmayan bir paket adı altında, çünkü rastgele kişilerin mevcut paketleri güncelleyebilmesi iyi olmaz. -This book won't delve further into the details of ((NPM)) usage. Refer to [_https://npmjs.org_](https://npmjs.org) for further documentation and a way to search for packages. +Bu kitap ((NPM)) kullanımının ayrıntılarına daha fazla girmeyecektir. Daha fazla dokümantasyon ve paket arama yöntemi için [_https://npmjs.org_](https://npmjs.org) adresine bakın. -## The file system module +## Dosya sistemi modülü {{index directory, "node:fs package", "Node.js", [file, access]}} -One of the most commonly used built-in modules in Node is the `node:fs` module, which stands for _((file system))_. It exports functions for working with files and directories. +Node'da en sık kullanılan yerleşik modüllerden biri _((dosya sistemi))_ anlamına gelen `node:fs` modülüdür. Dosya ve dizinlerle çalışmak için fonksiyonları dışa aktarır. {{index "readFile function", "callback function"}} -For example, the function called `readFile` reads a file and then calls a callback with the file's contents. +Örneğin, `readFile` adlı işlev bir dosyayı okur ve ardından dosyanın içeriğiyle birlikte bir geri arama çağırır. ``` import {readFile} from "node:fs"; @@ -242,7 +242,7 @@ readFile("file.txt", "utf8", (error, text) => { {{index "Buffer class"}} -The second argument to `readFile` indicates the _((character encoding))_ used to decode the file into a string. There are several ways in which ((text)) can be encoded to ((binary data)), but most modern systems use ((UTF-8)). So unless you have reasons to believe another encoding is used, pass `"utf8"` when reading a text file. If you do not pass an encoding, Node will assume you are interested in the binary data and will give you a `Buffer` object instead of a string. This is an ((array-like object)) that contains numbers representing the bytes (8-bit chunks of data) in the files. +`readFile`'ın ikinci argümanı, dosyayı bir dizeye dönüştürmek için kullanılan _((karakter kodlaması))_ kodunu belirtir. ((metin))'in ((ikili veri))'ye kodlanmasının çeşitli yolları vardır, ancak çoğu modern sistem ((UTF-8)) kullanır. Bu nedenle, başka bir kodlama kullanıldığına inanmak için nedenleriniz yoksa, bir metin dosyasını okurken `“utf8”` kodunu geçirin. Bir kodlama geçmezseniz, Node ikili verilerle ilgilendiğinizi varsayacak ve size bir dize yerine bir `Buffer` nesnesi verecektir. Bu, dosyalardaki baytları (8 bitlik veri parçaları) temsil eden sayıları içeren bir ((dizi benzeri nesne)). ``` import {readFile} from "node:fs"; @@ -253,9 +253,9 @@ readFile("file.txt", (error, buffer) => { }); ``` -{{index "writeFile function", "file system", [file, access]}} +{{index "writeFile function", "filesystem", [file, access]}} -A similar function, `writeFile`, is used to write a file to disk. +Benzer bir işlev olan `writeFile`, bir dosyayı diske yazmak için kullanılır. ``` import {writeFile} from "node:fs"; @@ -267,19 +267,19 @@ writeFile("graffiti.txt", "Node was here", err => { {{index "Buffer class", "character encoding"}} -Here it was not necessary to specify the encoding—`writeFile` will assume that when it is given a string to write, rather than a `Buffer` object, it should write it out as text using its default character encoding, which is ((UTF-8)). +Burada kodlamayı belirtmek gerekli değildi - `writeFile` kendisine yazması için bir `Buffer` nesnesi yerine bir dize verildiğinde, bunu varsayılan karakter kodlaması olan ((UTF-8)) kullanarak metin olarak yazması gerektiğini varsayacaktır. {{index "node:fs package", "readdir function", "stat function", "rename function", "unlink function"}} -The `node:fs` module contains many other useful functions: `readdir` will give you the files in a ((directory)) as an array of strings, `stat` will retrieve information about a file, `rename` will rename a file, `unlink` will remove one, and so on. See the documentation at [_https://nodejs.org_](https://nodejs.org) for specifics. +`node:fs` modülü başka birçok faydalı fonksiyon içerir: `readdir` bir ((dizin)) içindeki dosyaları bir dizi olarak döndürür, `stat` bir dosya hakkında bilgi alır, `rename` bir dosyayı yeniden adlandırır, `unlink` bir dosyayı kaldırır, vb. Ayrıntılar için [_https://nodejs.org_](https://nodejs.org) adresindeki belgelere bakın. {{index ["asynchronous programming", "in Node.js"], "Node.js", "error handling", "callback function"}} -Most of these take a callback function as the last parameter, which they call either with an error (the first argument) or with a successful result (the second). As we saw in [Chapter ?](async), there are downsides to this style of programming—the biggest one being that error handling becomes verbose and error-prone. +Bunların çoğu son parametre olarak ya bir hata (ilk argüman) ya da başarılı bir sonuç (ikinci) ile çağırdıkları bir geri arama fonksiyonu alır. [Bölüm ?](async)'de gördüğümüz gibi, bu tarz programlamanın dezavantajları vardır; bunlardan en önemlisi hata işlemenin ayrıntılı ve hataya açık hale gelmesidir. {{index "Promise class", "node:fs/promises package"}} -The `node:fs/promises` module exports most of the same functions as the old `node:fs` module, but uses promises rather than callback functions. +`node:fs/promises` modülü eski `node:fs` modülüyle aynı işlevlerin çoğunu dışa aktarır, ancak geri arama işlevleri yerine vaatler kullanır. ``` import {readFile} from "node:fs/promises"; @@ -289,7 +289,7 @@ readFile("file.txt", "utf8") {{index "synchronous programming", "node:fs package", "readFileSync function"}} -Sometimes you don't need asynchronicity, and it just gets in the way. Many of the functions in `node:fs` also have a synchronous variant, which has the same name with `Sync` added to the end. For example, the synchronous version of `readFile` is called `readFileSync`. +Bazen eşzamansızlığa ihtiyacınız olmaz ve bu sadece yolunuza çıkar. `node:fs` içindeki fonksiyonların birçoğunun, sonuna `Sync` eklenmiş aynı isme sahip senkronize bir versiyonu da vardır. Örneğin, `readFile` fonksiyonunun senkron versiyonu `readFileSync` olarak adlandırılır. ``` import {readFileSync} from "node:fs"; @@ -299,17 +299,17 @@ console.log("The file contains:", {{index optimization, performance, blocking}} -Do note that while such a synchronous operation is being performed, your program is stopped entirely. If it should be responding to the user or to other machines on the network, being stuck on a synchronous action might produce annoying delays. +Böyle bir eşzamanlı işlem gerçekleştirilirken programınızın tamamen durdurulduğunu unutmayın. Kullanıcıya veya ağdaki diğer makinelere yanıt vermesi gerekiyorsa, eşzamanlı bir eylemde takılı kalmak can sıkıcı gecikmelere neden olabilir. -## The HTTP module +## HTTP modülü {{index "Node.js", "node:http package", [HTTP, server]}} -Another central module is called `node:http`. It provides functionality for running an HTTP ((server)). +Bir diğer merkezi modül `node:http` olarak adlandırılır. HTTP ((sunucu))ları çalıştırmak ve HTTP ((istek))leri yapmak için işlevsellik sağlar. {{index "listening (TCP)", "listen method", "createServer function"}} -This is all it takes to start an HTTP server: +Bir HTTP sunucusu başlatmak için gereken tek şey budur: ``` import {createServer} from "node:http"; @@ -326,63 +326,63 @@ console.log("Listening! (port 8000)"); {{index port, localhost}} -If you run this script on your own machine, you can point your web browser at [_http://localhost:8000/hello_](http://localhost:8000/hello) to make a request to your server. It will respond with a small HTML page. +Bu betiği kendi makinenizde çalıştırırsanız, sunucunuza bir istekte bulunmak için web tarayıcınızı [_http://localhost:8000/hello_](http://localhost:8000/hello) adresine yönlendirebilirsiniz. Küçük bir HTML sayfası ile yanıt verecektir. {{index "createServer function", HTTP}} -The function passed as argument to `createServer` is called every time a client connects to the server. The `request` and `response` bindings are objects representing the incoming and outgoing data. The first contains information about the ((request)), such as its `url` property, which tells us to what URL the request was made. +`createServer`'a argüman olarak aktarılan fonksiyon, bir istemci sunucuya her bağlandığında çağrılır. `request` ve `response` bağları gelen ve giden verileri temsil eden nesnelerdir. İlki, isteğin hangi URL'ye yapıldığını söyleyen `url` özelliği gibi ((istek)) hakkında bilgiler içerir. -So, when you open that page in your browser, it sends a request to your own computer. This causes the server function to run and send back a response, which you can then see in the browser. +Yani, bu sayfayı tarayıcınızda açtığınızda, kendi bilgisayarınıza bir istek gönderir. Bu, sunucu işlevinin çalışmasına ve daha sonra tarayıcıda görebileceğiniz bir yanıt göndermesine neden olur. {{index "200 (HTTP status code)", "Content-Type header", "writeHead method"}} -To send something to the client, you call methods on the `response` object. The first, `writeHead`, will write out the ((response)) ((header))s (see [Chapter ?](http#headers)). You give it the status code (200 for "OK" in this case) and an object that contains header values. The example sets the `Content-Type` header to inform the client that we'll be sending back an HTML document. +İstemciye bir şey göndermek için `response` nesnesi üzerindeki yöntemleri çağırırsınız. İlki, `writeHead`, ((yanıt)) ((başlık))ları yazacaktır (bkz. [Bölüm ?](http#headers)). Ona durum kodunu (bu durumda “OK” için 200) ve başlık değerlerini içeren bir nesne verirsiniz. Örnek, istemciye bir HTML belgesi göndereceğimizi bildirmek için `Content-Type` başlığını ayarlar. {{index "writable stream", "body (HTTP)", stream, "write method", "end method"}} -Next, the actual response body (the document itself) is sent with `response.write`. You are allowed to call this method multiple times if you want to send the response piece by piece, for example to stream data to the client as it becomes available. Finally, `response.end` signals the end of the response. +Ardından, asıl yanıt gövdesi (belgenin kendisi) `response.write` ile gönderilir. Yanıtı parça parça göndermek istiyorsanız, örneğin istemciye kullanılabilir hale geldikçe veri akışı sağlamak için bu yöntemi birden çok kez çağırmanıza izin verilir. Son olarak, `response.end` yanıtın sona erdiğini bildirir. {{index "listen method"}} -The call to `server.listen` causes the ((server)) to start waiting for connections on ((port)) 8000. This is why you have to connect to _localhost:8000_ to speak to this server, rather than just _localhost_, which would use the default port 80. +`server.listen` çağrısı ((sunucu))'nun ((port)) 8000 üzerinde bağlantı beklemeye başlamasına neden olur. Bu nedenle, bu sunucuyla konuşmak için varsayılan 80 numaralı bağlantı noktasını kullanacak olan _localhost_ yerine _localhost:8000_ adresine bağlanmanız gerekir. {{index "Node.js", "kill process"}} -When you run this script, the process just sits there and waits. When a script is listening for events—in this case, network connections—`node` will not automatically exit when it reaches the end of the script. To close it, press [control]{keyname}-C. +Bu betiği çalıştırdığınızda, süreç orada oturur ve bekler. Bir kod olayları dinlerken (bu durumda, ağ bağlantıları), kodun sonuna ulaştığında `node` otomatik olarak çıkmayacaktır. Kapatmak için [control] tuşuna basın{keyname}-C. {{index [method, HTTP]}} -A real web ((server)) usually does more than the one in the example—it looks at the request's ((method)) (the `method` property) to see what action the client is trying to perform and looks at the request's ((URL)) to find out which resource this action is being performed on. We'll see a more advanced server [later in this chapter](node#file_server). +Gerçek bir web ((sunucu)) genellikle örnektekinden daha fazlasını yapar - istemcinin hangi eylemi gerçekleştirmeye çalıştığını görmek için isteğin ((yöntem))'ine (`method` özelliği) bakar ve bu eylemin hangi kaynak üzerinde gerçekleştirildiğini bulmak için isteğin ((URL))'sine bakar. Daha gelişmiş bir sunucuyu [bu bölümün ilerleyen kısımlarında](node#file_server) göreceğiz. {{index "node:http package", "request function", "fetch function", [HTTP, client]}} -The `node:http` module also provides a `request` function, which can be used to make HTTP requests. However, it is a lot more cumbersome to use than `fetch`, which we saw in [Chapter ?](http). Fortunately, `fetch` is also available in Node, as a global binding. Unless you want to do something very specific, such as processing the response document piece by piece as the data comes in over the network, I recommend sticking to `fetch`. +`node:http` modülü ayrıca HTTP istekleri yapmak için kullanılabilecek bir `request` fonksiyonu da sağlar. Ancak, kullanımı [Bölüm ?](http)'de gördüğümüz `fetch` fonksiyonundan çok daha zahmetlidir. Neyse ki, `fetch` Node'da global bir bağlayıcı olarak da mevcuttur. Veriler ağ üzerinden geldikçe yanıt belgesini parça parça işlemek gibi çok özel bir şey yapmak istemiyorsanız, `fetch` kullanmanızı öneririm. -## Streams +## Stream'ler {{index "Node.js", stream, "writable stream", "callback function", ["asynchronous programming", "in Node.js"], "write method", "end method", "Buffer class"}} -The response object that the HTTP server could write to is an example of a _writable stream_ object, which is a widely used concept in Node. Such objects have a `write` method that can be passed a string or a `Buffer` object to write something to the stream. Their `end` method closes the stream and optionally takes a value to write to the stream before closing. Both of these methods can also be given a callback as an additional argument, which they will call when the writing or closing has finished. +HTTP sunucusunun yazabileceği yanıt nesnesi, Node'da yaygın olarak kullanılan bir _writable stream_ nesnesi örneğidir. Bu tür nesneler, bir akışa bir şey yazmak için bir string veya bir `Buffer` nesnesi geçirilebilen bir `write` metoduna sahiptir. `end` metodları akışı kapatır ve kapatmadan önce akışa yazmak için isteğe bağlı bir değer alabilir. Bu metodların her ikisine de ek bir argüman olarak bir callback verilebilir ve yazma veya kapatma işlemi tamamlandığında bu callback çağrılır. {{index "createWriteStream function", "writeFile function", [file, stream]}} -It is possible to create a writable stream that points at a file with the `createWriteStream` function from the `node:fs` module. You can then use the `write` method on the resulting object to write the file one piece at a time, rather than in one shot as with `writeFile`. +`node:fs` modülünden `createWriteStream` fonksiyonuyla bir dosyaya işaret eden bir writable stream oluşturmak mümkündür. Ortaya çıkan nesne üzerindeki `write` metodu, dosyayı `writeFile` ile tek seferde yazmaktan ziyade, parça parça yazmak için kullanılabilir. {{index "createServer function", "request function", "event handling", "readable stream"}} -_Readable ((stream))s_ are a little more involved. The `request` argument to the HTTP server's callback is a readable stream. Reading from a stream is done using event handlers, rather than methods. +\_Readable ((stream))\_ler biraz daha karmaşıktır. HTTP sunucusunun callback'ine iletilen `request` argümanı bir readable stream'dir. Bir akıştan okuma işlemi, metodlar yerine event handler'lar kullanılarak yapılır. {{index "on method", "addEventListener method"}} -Objects that emit events in Node have a method called `on` that is similar to the `addEventListener` method in the browser. You give it an event name and then a function, and it will register that function to be called whenever the given event occurs. +Node'da olay yayını yapan nesnelerin, tarayıcıdaki `addEventListener` metoduna benzer bir `on` metodu vardır. Bu metoda bir olay adı ve bir fonksiyon verirsiniz; belirtilen olay gerçekleştiğinde bu fonksiyon çağrılır. {{index "createReadStream function", "data event", "end event", "readable stream"}} -Readable ((stream))s have `"data"` and `"end"` events. The first is fired every time data comes in, and the second is called whenever the stream is at its end. This model is most suited for _streaming_ data that can be immediately processed, even when the whole document isn't available yet. A file can be read as a readable stream by using the `createReadStream` function from `node:fs`. +_Readable ((stream))\_ler `"data"` ve `"end"` olaylarına sahiptir. İlki, her veri geldiğinde tetiklenir; ikincisi ise akışın sonuna gelindiğinde çağrılır. Bu model, tüm belge henüz mevcut olmasa bile hemen işlenebilecek \_streaming_ veri için en uygunudur. Bir dosya, `node:fs` modülünden `createReadStream` fonksiyonu kullanılarak readable stream olarak okunabilir. {{index "upcasing server example", capitalization, "toUpperCase method"}} -This code creates a ((server)) that reads request bodies and streams them back to the client as all-uppercase text: +Bu kod, istek gövdelerini okuyan ve bunları büyük harfli metin olarak istemciye geri gönderen bir ((server)) oluşturur: ``` import {createServer} from "node:http"; @@ -396,9 +396,9 @@ createServer((request, response) => { {{index "Buffer class", "toString method"}} -The `chunk` value passed to the data handler will be a binary `Buffer`. We can convert this to a string by decoding it as UTF-8 encoded characters with its `toString` method. +Veri handler'ına iletilen `chunk` değeri bir ikili `Buffer` olacaktır. Bu, `toString` metodu ile UTF-8 kodlu karakterler olarak çözülerek bir string'e dönüştürülebilir. -The following piece of code, when run with the uppercasing server active, will send a request to that server and write out the response it gets: +Aşağıdaki kod parçası, büyük harfe dönüştürme sunucusu aktifken çalıştırıldığında, bu sunucuya bir istek gönderecek ve aldığı yanıtı yazdıracaktır: ``` fetch("http://localhost:8000/", { @@ -410,23 +410,23 @@ fetch("http://localhost:8000/", { {{id file_server}} -## A file server +## Bir dosya sunucusu {{index "file server example", "Node.js", [HTTP, server]}} -Let's combine our newfound knowledge about HTTP ((server))s and working with the ((file system)) to create a bridge between the two: an HTTP server that allows ((remote access)) to a file system. Such a server has all kinds of uses—it allows web applications to store and share data, or it can give a group of people shared access to a bunch of files. +HTTP ((server))ler ve ((file system)) ile çalışma konusundaki yeni bilgilerimizi birleştirerek, dosya sistemine ((remote access)) sağlayan bir HTTP sunucusu oluşturabiliriz. Böyle bir sunucunun birçok kullanım alanı vardır—web uygulamalarının veri depolamasına ve paylaşmasına olanak tanır ya da bir grup insana bir dizi dosyaya ortak erişim sağlar. {{index [path, URL], "GET method", "PUT method", "DELETE method", [file, resource]}} -When we treat files as HTTP ((resource))s, the HTTP methods `GET`, `PUT`, and `DELETE` can be used to read, write, and delete the files, respectively. We will interpret the path in the request as the path of the file that the request refers to. +Dosyaları HTTP ((resource))leri olarak ele aldığımızda, HTTP metodları olan `GET`, `PUT` ve `DELETE`, sırasıyla dosyaları okumak, yazmak ve silmek için kullanılabilir. İstek yolunu, isteğin atıfta bulunduğu dosyanın yolu olarak yorumlayacağız. -{{index [path, "file system"], "relative path"}} +{{index [path, "filesystem"], "relative path"}} -We probably don't want to share our whole file system, so we'll interpret these paths as starting in the server's working ((directory)), which is the directory in which it was started. If I ran the server from `/tmp/public/` (or `C:\tmp\public\` on Windows), then a request for `/file.txt` should refer to `/tmp/public/file.txt` (or `C:\tmp\public\file.txt`). +Muhtemelen tüm dosya sistemimizi paylaşmak istemeyiz, bu yüzden bu yolları sunucunun çalışma ((directory))sinde (sunucunun başlatıldığı dizin) başladığı şekilde yorumlayacağız. Eğer sunucuyu `/tmp/public/` (veya Windows'ta `C:\tmp\public\`) dizininden çalıştırırsam, `/file.txt` için yapılan bir istek `/tmp/public/file.txt` (veya `C:\tmp\public\file.txt`) dosyasına atıfta bulunmalıdır. {{index "file server example", "Node.js", "methods object", "Promise class"}} -We'll build the program piece by piece, using an object called `methods` to store the functions that handle the various HTTP methods. Method handlers are `async` functions that get the request object as argument and return a promise that resolves to an object that describes the response. +Programı parça parça oluşturacağız ve çeşitli HTTP metodlarını işleyen fonksiyonları depolamak için `methods` adında bir nesne kullanacağız. Metod işleyicileri, istek nesnesini argüman olarak alan ve yanıtı tanımlayan bir nesneye çözümlenen bir promise döndüren `async` fonksiyonlardır. ```{includeCode: ">code/file_server.mjs"} import {createServer} from "node:http"; @@ -440,7 +440,7 @@ createServer((request, response) => { return {body: String(error), status: 500}; }).then(({body, status = 200, type = "text/plain"}) => { response.writeHead(status, {"Content-Type": type}); - if (body && body.pipe) body.pipe(response); + if (body?.pipe) body.pipe(response); else response.end(body); }); }).listen(8000); @@ -455,26 +455,25 @@ async function notAllowed(request) { {{index "405 (HTTP status code)"}} -This starts a server that just returns 405 error responses, which is the code used to indicate that the server refuses to handle a given method. +Bu, sunucunun yalnızca 405 hata yanıtlarını döndürmesini sağlar. Bu kod, sunucunun belirli bir metodu işlemeyi reddettiğini belirtmek için kullanılır. {{index "500 (HTTP status code)", "error handling", "error response"}} -When a request handler's promise is rejected, the `catch` call translates the error into a response object, if it isn't one already, so that the server can send back an error response to inform the client that it failed to handle the request. +Bir istek işleyicisinin promisi reddedildiğinde, `catch` çağrısı hatayı bir yanıt nesnesine dönüştürür (eğer zaten bir yanıt nesnesi değilse), böylece sunucu, isteği işleyemediğini müşteriye bildirmek için bir hata yanıtı gönderebilir. {{index "200 (HTTP status code)", "Content-Type header"}} -The `status` field of the response description may be omitted, in which case it defaults to 200 (OK). The content type, in the `type` property, can also be left off, in which case the response is assumed to be plain text. +Yanıt tanımındaki `status` alanı atlanabilir ve bu durumda varsayılan olarak 200 (OK) olur. `type` özelliğinde belirtilen içerik türü de bırakılabilir ve bu durumda yanıtın düz metin olduğu varsayılır. {{index "end method", "pipe method", stream}} -When the value of `body` is a ((readable stream)), it will have a `pipe` method that is used to forward all content from a readable stream to a ((writable stream)). If not, it is assumed to be either `null` (no body), a string, or a buffer, and it is passed directly to the ((response))'s `end` method. +`body` değerinin bir ((readable stream)) olması durumunda, tüm içeriği bir readable stream'den bir ((writable stream))e iletmek için kullanılan bir `pipe` metodu olacaktır. Eğer değilse, `null` (gövde yok), bir string veya bir buffer olduğu varsayılır ve doğrudan ((response))'un `end` metoduna iletilir. {{index [path, URL], "urlPath function", "URL class", parsing, [escaping, "in URLs"], "decodeURIComponent function", "startsWith method"}} -To figure out which file path corresponds to a request URL, the `urlPath` function uses the built-in `URL` class (which also exists in the browser) to parse the URL. This constructor expects a full URL, not just the part starting with the slash that we get from `request.url`, so we give it a dummy domain name to fill in. It extracts its pathname, which will be something like `"/file.txt"`, decodes that to get rid of the `%20`-style escape codes, and resolves it relative to the program's working directory. +Bir istek URL'sinin hangi dosya yoluna karşılık geldiğini anlamak için, `urlPath` fonksiyonu Node'un yerleşik `node:url` modülünü kullanarak URL'yi ayrıştırır. Bu fonksiyon, `"/file.txt"` gibi bir `pathname` alır, `%20` tarzı kaçış kodlarını temizlemek için çözer ve bunu programın çalışma dizinine göre çözümler. ```{includeCode: ">code/file_server.mjs"} -import {parse} from "node:url"; import {resolve, sep} from "node:path"; const baseDirectory = process.cwd(); @@ -490,25 +489,25 @@ function urlPath(url) { } ``` -As soon as you set up a program to accept network requests, you have to start worrying about ((security)). In this case, if we aren't careful, it is likely that we'll accidentally expose our whole ((file system)) to the network. +Bir programı ağ isteklerini kabul edecek şekilde kurduğunuzda, ((security)) endişeleriyle ilgilenmeye başlamalısınız. Bu durumda dikkatli olmazsak, tüm ((file system))imizi ağa açma riski taşırız. -File paths are strings in Node. To map such a string to an actual file, there is a nontrivial amount of interpretation going on. Paths may, for example, include `../` to refer to a parent directory. So one obvious source of problems would be requests for paths like `/../secret_file`. +Dosya yolları Node'da string şeklindedir. Bu tür bir string'i gerçek bir dosyaya eşlemek için karmaşık bir yorumlama işlemi yapılır. Örneğin, `../` dizinin üstüne atıfta bulunmak için kullanılabilir. Dolayısıyla `/../secret_file` gibi yollarla yapılan istekler sorunlara neden olabilir. {{index "node:path package", "resolve function", "cwd function", "process object", "403 (HTTP status code)", "sep binding", ["backslash character", "as path separator"], "slash character"}} -To avoid such problems, `urlPath` uses the `resolve` function from the `node:path` module, which resolves relative paths. It then verifies that the result is _below_ the working directory. The `process.cwd` function (where `cwd` stands for "current working directory") can be used to find this working directory. The `sep` binding from the `node:path` package is the system's path separator—a backslash on Windows and a forward slash on most other systems. When the path doesn't start with the base directory, the function throws an error response object, using the HTTP status code indicating that access to the resource is forbidden. +Bu tür sorunları önlemek için, `urlPath` fonksiyonu `node:path` modülünden `resolve` fonksiyonunu kullanır; bu fonksiyon, ilişkisel yolları çözer. Daha sonra bu yolun çalışma dizininin _altında_ olduğunu doğrular. `process.cwd` fonksiyonu (burada `cwd` "current working directory"nin kısaltmasıdır) çalışma dizinini bulmak için kullanılır. `node:path` paketinden gelen `sep` bağlamı, sistemin yol ayırıcı sembolüdür—Windows'ta bir ters eğik çizgi (`\`) ve çoğu sistemde ileri eğik çizgi (`/`) şeklindedir. Eğer yol temel dizinle başlamıyorsa, fonksiyon bir hata yanıt nesnesi oluşturur ve erişimin yasak olduğunu belirten HTTP durum kodu döner. {{index "file server example", "Node.js", "GET method", [file, resource]}} -We'll set up the `GET` method to return a list of files when reading a ((directory)) and to return the file's content when reading a regular file. +Bir ((dizin)) okurken bir dosya listesi döndürmek ve normal bir dosyayı okurken dosyanın içeriğini döndürmek için `GET` yöntemini ayarlayacağız. {{index "media type", "Content-Type header", "mime-types package"}} -One tricky question is what kind of `Content-Type` header we should set when returning a file's content. Since these files could be anything, our server can't simply return the same content type for all of them. ((NPM)) can help us again here. The `mime-types` package (content type indicators like `text/plain` are also called _((MIME type))s_) knows the correct type for a large number of ((file extension))s. +Zor bir soru, bir dosyanın içeriğini döndürürken ne tür bir `Content-Type` başlığı belirlememiz gerektiğidir. Bu dosyalar herhangi bir şey olabileceğinden, sunucumuz hepsi için aynı içerik türünü döndüremez. ((NPM)) burada bize yine yardımcı olabilir. `mime-types` paketi (`text/plain` gibi içerik türü göstergeleri _((MIME type))s_ olarak da adlandırılır) çok sayıda ((file extension))s için doğru türü bilir. {{index "npm program"}} -The following `npm` command, in the directory where the server script lives, installs a specific version of `mime`: +Aşağıdaki `npm` komutu, sunucu betiğinin bulunduğu dizine `mime`ın belirli bir sürümünü yükler: ```{lang: null} $ npm install mime-types@2.1.0 @@ -516,7 +515,7 @@ $ npm install mime-types@2.1.0 {{index "404 (HTTP status code)", "stat function", [file, resource]}} -When a requested file does not exist, the correct HTTP status code to return is 404. We'll use the `stat` function, which looks up information about a file, to find out both whether the file exists and whether it is a ((directory)). +İstenen bir dosya mevcut olmadığında, döndürülmesi gereken doğru HTTP durum kodu 404'tür. Hem dosyanın var olup olmadığını hem de bir ((dizin)) olup olmadığını öğrenmek için bir dosya hakkında bilgi arayan `stat` fonksiyonunu kullanacağız. ```{includeCode: ">code/file_server.mjs"} import {createReadStream} from "node:fs"; @@ -543,21 +542,21 @@ methods.GET = async function(request) { {{index "createReadStream function", ["asynchronous programming", "in Node.js"], "error handling", "ENOENT (status code)", "Error type", inheritance}} -Because it has to touch the disk and thus might take a while, `stat` is asynchronous. Since we're using promises rather than callback style, it has to be imported from `node:fs/promises` instead of directly from `node:fs`. +Diske dokunmak zorunda olduğu ve bu nedenle biraz zaman alabileceği için `stat` asenkrondur. Geri çağırma tarzı yerine vaatler kullandığımız için, doğrudan `node:fs` yerine `promises` içinden içe aktarılması gerekir. -When the file does not exist, `stat` will throw an error object with a `code` property of `"ENOENT"`. These somewhat obscure, ((Unix))-inspired codes are how you recognize error types in Node. +Dosya mevcut olmadığında, `stat` `code` özelliği `“ENOENT”` olan bir hata nesnesi atacaktır. Bu biraz belirsiz, ((Unix))'ten esinlenen kodlar, Node'daki hata türlerini nasıl tanıdığınızı gösterir. {{index "Stats type", "stat function", "isDirectory method"}} -The `stats` object returned by `stat` tells us a number of things about a ((file)), such as its size (`size` property) and its ((modification date)) (`mtime` property). Here we are interested in the question of whether it is a ((directory)) or a regular file, which the `isDirectory` method tells us. +`stat` tarafından döndürülen `stats` nesnesi bize bir ((dosya)) hakkında boyutu (`size` özelliği) ve ((değişiklik tarihi)) (`mtime` özelliği) gibi bir dizi şey söyler. Burada, `isDirectory` yönteminin bize söylediği gibi, bir ((dizin)) mi yoksa normal bir dosya mı olduğu sorusuyla ilgileniyoruz. {{index "readdir function"}} -We use `readdir` to read the array of files in a ((directory)) and return it to the client. For normal files, we create a readable stream with `createReadStream` and return that as the body, along with the content type that the `mime` package gives us for the file's name. +Bir ((dizin)) içindeki dosya dizisini okumak ve istemciye döndürmek için `readdir` kullanıyoruz. Normal dosyalar için `createReadStream` ile okunabilir bir akış oluşturur ve bunu `mime` paketinin dosya adı için bize verdiği içerik türüyle birlikte gövde olarak döndürürüz. {{index "Node.js", "file server example", "DELETE method", "rmdir function", "unlink function"}} -The code to handle `DELETE` requests is slightly simpler. +`DELETE` isteklerini işlemek için kullanılan kod biraz daha basittir. ```{includeCode: ">code/file_server.mjs"} import {rmdir, unlink} from "node:fs/promises"; @@ -579,15 +578,15 @@ methods.DELETE = async function(request) { {{index "204 (HTTP status code)", "body (HTTP)"}} -When an ((HTTP)) ((response)) does not contain any data, the status code 204 ("no content") can be used to indicate this. Since the response to deletion doesn't need to transmit any information beyond whether the operation succeeded, that is a sensible thing to return here. +Bir ((HTTP)) ((yanıt)) herhangi bir veri içermediğinde, bunu belirtmek için durum kodu 204 (“içerik yok”) kullanılabilir. Silme işlemine verilen yanıtın, işlemin başarılı olup olmadığının ötesinde herhangi bir bilgi iletmesi gerekmediğinden, burada döndürülecek en mantıklı şey budur. {{index idempotence, "error response"}} -You may be wondering why trying to delete a nonexistent file returns a success status code, rather than an error. When the file that is being deleted is not there, you could say that the request's objective is already fulfilled. The ((HTTP)) standard encourages us to make requests _idempotent_, which means that making the same request multiple times produces the same result as making it once. In a way, if you try to delete something that's already gone, the effect you were trying to do has been achieved—the thing is no longer there. +Var olmayan bir dosyayı silmeye çalışmanın neden bir hata yerine başarı durum kodu döndürdüğünü merak ediyor olabilirsiniz. Silinmek istenen dosya orada olmadığında, isteğin amacının zaten yerine getirildiğini söyleyebilirsiniz. ((HTTP)) standardı bizi istekleri _idempotent_ yapmaya teşvik eder, bu da aynı isteği birden fazla kez yapmanın bir kez yapmakla aynı sonucu vereceği anlamına gelir. Bir bakıma, zaten gitmiş olan bir şeyi silmeye çalışırsanız, yapmaya çalıştığınız etki elde edilmiştir - o şey artık orada değildir. {{index "file server example", "Node.js", "PUT method"}} -This is the handler for `PUT` requests: +Bu `PUT` istekleri için işleyicidir: ```{includeCode: ">code/file_server.mjs"} import {createWriteStream} from "node:fs"; @@ -610,19 +609,19 @@ methods.PUT = async function(request) { {{index overwriting, "204 (HTTP status code)", "error event", "finish event", "createWriteStream function", "pipe method", stream}} -We don't need to check whether the file exists this time—if it does, we'll just overwrite it. We again use `pipe` to move data from a readable stream to a writable one, in this case from the request to the file. But since `pipe` isn't written to return a promise, we have to write a wrapper, `pipeStream`, that creates a promise around the outcome of calling `pipe`. +Bu sefer dosyanın var olup olmadığını kontrol etmemize gerek yok, eğer varsa üzerine yazacağız. Verileri okunabilir bir akıştan yazılabilir bir akışa, bu durumda istekten dosyaya taşımak için yine `pipe` kullanıyoruz. Ancak `pipe` bir promise döndürmek için yazılmadığından, `pipe` çağrısının sonucu etrafında bir promise oluşturan bir wrapper, `pipeStream` yazmamız gerekiyor. {{index "error event", "finish event"}} -When something goes wrong when opening the file, `createWriteStream` will still return a stream, but that stream will fire an `"error"` event. The stream from the request may also fail, for example if the network goes down. So we wire up both streams' `"error"` events to reject the promise. When `pipe` is done, it will close the output stream, which causes it to fire a `"finish"` event. That's the point where we can successfully resolve the promise (returning nothing). +Dosya açılırken bir şeyler ters giderse, `createWriteStream` yine de bir akış döndürür, ancak bu akış bir `“error”` olayı tetikler. İstekten gelen akış da başarısız olabilir, örneğin ağ çökerse. Bu nedenle, her iki akışın `“error”` olaylarını vaadi reddetmek için bağlarız. `pipe` işi bittiğinde, çıktı akışını kapatacak ve bu da `“finish”` olayını ateşlemesine neden olacaktır. Bu, vaadi başarıyla çözebileceğimiz (hiçbir şey döndürmeyen) noktadır. {{index download, "file server example", "Node.js"}} -The full script for the server is available at [_https://eloquentjavascript.net/code/file_server.mjs_](https://eloquentjavascript.net/code/file_server.mjs). You can download that and, after installing its dependencies, run it with Node to start your own file server. And, of course, you can modify and extend it to solve this chapter's exercises or to experiment. +Sunucu için tam betik [_https://eloquentjavascript.net/code/file_server.mjs_](https://eloquentjavascript.net/code/file_server.mjs) adresinde mevcuttur. Bunu indirebilir ve bağımlılıklarını yükledikten sonra kendi dosya sunucunuzu başlatmak için Node ile çalıştırabilirsiniz. Ve tabii ki, bu bölümün alıştırmalarını çözmek ya da deney yapmak için onu değiştirebilir ve genişletebilirsiniz. {{index "body (HTTP)", "curl program", [HTTP, client], [method, HTTP]}} -The command line tool `curl`, widely available on ((Unix))-like systems (such as macOS and Linux), can be used to make HTTP ((request))s. The following session briefly tests our server. The `-X` option is used to set the request's method, and `-d` is used to include a request body. +((Unix)) benzeri sistemlerde (macOS ve Linux gibi) yaygın olarak bulunan komut satırı aracı `curl`, HTTP ((istek)) yapmak için kullanılabilir. Aşağıdaki oturum sunucumuzu kısaca test etmektedir. `-X` seçeneği isteğin yöntemini ayarlamak için, `-d` seçeneği ise istek gövdesini eklemek için kullanılır. ```{lang: null} $ curl http://localhost:8000/file.txt @@ -635,65 +634,65 @@ $ curl http://localhost:8000/file.txt File not found ``` -The first request for `file.txt` fails since the file does not exist yet. The `PUT` request creates the file, and behold, the next request successfully retrieves it. After deleting it with a `DELETE` request, the file is again missing. +Dosya henüz mevcut olmadığından `file.txt` için yapılan ilk istek başarısız olur. `PUT` isteği dosyayı oluşturur ve bir sonraki istek dosyayı başarıyla alır. Bir `DELETE` isteği ile sildikten sonra, dosya yine kayıptır. -## Summary +## Özet {{index "Node.js"}} -Node is a nice, small system that lets us run JavaScript in a nonbrowser context. It was originally designed for network tasks to play the role of a _node_ in a network. But it lends itself to all kinds of scripting tasks, and if writing JavaScript is something you enjoy, automating tasks with Node works well. +Node, JavaScript'i tarayıcı dışı bir bağlamda çalıştırmamızı sağlayan güzel ve küçük bir sistemdir. Başlangıçta bir ağdaki _node_ rolünü oynamak üzere ağ görevleri için tasarlanmıştır. Ancak kendini her türlü komut dosyası görevine borçludur ve JavaScript yazmak hoşunuza giden bir şeyse, Node ile görevleri otomatikleştirmek işe yarar. -NPM provides packages for everything you can think of (and quite a few things you'd probably never think of), and it allows you to fetch and install those packages with the `npm` program. Node comes with a number of built-in modules, including the `node:fs` module for working with the file system and the `node:http` module for running HTTP servers. +NPM, aklınıza gelebilecek her şey için (ve muhtemelen hiç aklınıza gelmeyecek birkaç şey için) paketler sağlar ve bu paketleri `npm` programı ile getirip yüklemenize olanak tanır. Node, dosya sistemiyle çalışmak için `node:fs` modülü ve HTTP sunucularını çalıştırmak için `node:http` modülü de dahil olmak üzere bir dizi yerleşik modülle birlikte gelir. -All input and output in Node is done asynchronously, unless you explicitly use a synchronous variant of a function, such as `readFileSync`. Node originally used callbacks for asynchronous functionality, but the `node:fs/promises` package provides a promise-based interface to the file system. +Node'daki tüm girdi ve çıktılar, `readFileSync` gibi bir fonksiyonun senkronize bir varyantını açıkça kullanmadığınız sürece asenkron olarak yapılır. Node başlangıçta asenkron işlevsellik için geri aramalar kullanıyordu, ancak `node:fs/promises` paketi dosya sistemine vaat tabanlı bir arayüz sağlar. -## Exercises +## Egzersizler -### Search tool +### Arama aracı {{index grep, "search problem", "search tool (exercise)"}} -On ((Unix)) systems, there is a command line tool called `grep` that can be used to quickly search files for a ((regular expression)). +((Unix)) sistemlerinde, bir ((düzenli ifade)) için dosyaları hızlı bir şekilde aramak için kullanılabilen `grep` adlı bir komut satırı aracı vardır. -Write a Node script that can be run from the ((command line)) and acts somewhat like `grep`. It treats its first command line argument as a regular expression and treats any further arguments as files to search. It should output the names of any file whose content matches the regular expression. +((Komut satırından)) çalıştırılabilen ve bir şekilde `grep` gibi davranan bir Node betiği yazın. İlk komut satırı argümanını düzenli bir ifade olarak ele alır ve diğer argümanları aranacak dosyalar olarak değerlendirir. İçeriği düzenli ifadeyle eşleşen herhangi bir dosyanın adını çıktı olarak vermelidir. -When that works, extend it so that when one of the arguments is a ((directory)), it searches through all files in that directory and its subdirectories. +Bu işe yaradığında, argümanlardan biri ((dizin)) olduğunda, o dizindeki ve alt dizinlerindeki tüm dosyaları arayacak şekilde genişletin. {{index ["asynchronous programming", "in Node.js"], "synchronous programming"}} -Use asynchronous or synchronous file system functions as you see fit. Setting things up so that multiple asynchronous actions are requested at the same time might speed things up a little, but not a huge amount, since most file systems can read only one thing at a time. +Uygun gördüğünüz şekilde eşzamansız veya eşzamanlı dosya sistemi işlevlerini kullanın. İşleri aynı anda birden fazla eşzamansız eylem talep edilecek şekilde ayarlamak işleri biraz hızlandırabilir, ancak çoğu dosya sistemi bir seferde yalnızca bir şeyi okuyabildiğinden çok büyük bir miktar değil. {{hint {{index "RegExp class", "search tool (exercise)"}} -Your first command line argument, the ((regular expression)), can be found in `process.argv[2]`. The input files come after that. You can use the `RegExp` constructor to go from a string to a regular expression object. +İlk komut satırı argümanınız olan ((düzenli ifade)), `process.argv[2]` içinde bulunabilir. Girdi dosyaları bundan sonra gelir. Bir dizeden düzenli ifade nesnesine geçmek için `RegExp` yapıcısını kullanabilirsiniz. {{index "readFileSync function"}} -Doing this synchronously, with `readFileSync`, is more straightforward, but if you use `node:fs/promises` to get promise-returning functions and write an `async` function, the code looks similar. +Bunu `readFileSync` ile eşzamanlı olarak yapmak daha basittir, ancak söz döndüren işlevleri almak için `fs/promises` kullanırsanız ve bir `async` işlevi yazarsanız, kod benzer görünür. {{index "stat function", "statSync function", "isDirectory method"}} -To figure out whether something is a directory, you can again use `stat` (or `statSync`) and the stats object's `isDirectory` method. +Bir şeyin dizin olup olmadığını anlamak için yine `stat` (veya `statSync`) ve stats nesnesinin `isDirectory` yöntemini kullanabilirsiniz. {{index "readdir function", "readdirSync function"}} -Exploring a directory is a branching process. You can do it either by using a recursive function or by keeping an array of work (files that still need to be explored). To find the files in a directory, you can call `readdir` or `readdirSync`. Note the strange capitalization—Node's file system function naming is loosely based on standard Unix functions, such as `readdir`, that are all lowercase, but then it adds `Sync` with a capital letter. +Bir dizini keşfetmek dallanan bir süreçtir. Bunu ya özyinelemeli bir fonksiyon kullanarak ya da bir dizi iş (hala keşfedilmesi gereken dosyalar) tutarak yapabilirsiniz. Bir dizindeki dosyaları bulmak için `readdir` veya `readdirSync` fonksiyonlarını çağırabilirsiniz. Garip büyük harfe dikkat edin-Node'un dosya sistemi fonksiyon isimlendirmesi, `readdir` gibi standart Unix fonksiyonlarına gevşek bir şekilde dayanır, hepsi küçük harftir, ancak daha sonra büyük harfle `Sync` ekler. -To go from a filename read with `readdir` to a full path name, you have to combine it with the name of the directory, either putting `sep` from `node:path` between them, or using the `join` function from that same package. +`readdir` ile okunan bir dosya adından tam bir yol adına gitmek için, ya `node:path`ten `sep`i aralarına koyarak ya da aynı paketten `join` kullanarak dizinin adıyla birleştirmeniz gerekir. hint}} -### Directory creation +### Dizin oluşturma {{index "file server example", "directory creation (exercise)", "rmdir function"}} -Though the `DELETE` method in our file server is able to delete directories (using `rmdir`), the server currently does not provide any way to _create_ a ((directory)). +Dosya sunucumuzdaki `DELETE` yöntemi dizinleri silebilse de (`rmdir` kullanarak), sunucu şu anda bir ((dizin)) _oluşturmak_ için herhangi bir yol sağlamamaktadır. {{index "MKCOL method", "mkdir function"}} -Add support for the `MKCOL` method ("make collection"), which should create a directory by calling `mkdir` from the `node:fs` module. `MKCOL` is not a widely used HTTP method, but it does exist for this same purpose in the _((WebDAV))_ standard, which specifies a set of conventions on top of ((HTTP)) that make it suitable for creating documents. +`MKCOL` yöntemi (“make collection”) için destek ekleyin, bu yöntem `node:fs` modülünden `mkdir` çağrısı yaparak bir dizin oluşturmalıdır. `MKCOL` yaygın olarak kullanılan bir HTTP yöntemi değildir, ancak _((WebDAV))_ standardında aynı amaç için mevcuttur, bu da ((HTTP)) üzerinde belge oluşturmak için uygun hale getiren bir dizi kural belirtir. ```{hidden: true, includeCode: ">code/file_server.mjs"} import {mkdir} from "node:fs/promises"; @@ -717,40 +716,40 @@ methods.MKCOL = async function(request) { {{index "directory creation (exercise)", "file server example", "MKCOL method", "mkdir function", idempotency, "400 (HTTP status code)"}} -You can use the function that implements the `DELETE` method as a blueprint for the `MKCOL` method. When no file is found, try to create a directory with `mkdir`. When a directory exists at that path, you can return a 204 response so that directory creation requests are idempotent. If a nondirectory file exists here, return an error code. Code 400 ("bad request") would be appropriate. +`DELETE` yöntemini uygulayan işlevi `MKCOL` yöntemi için bir taslak olarak kullanabilirsiniz. Dosya bulunamadığında, `mkdir` ile bir dizin oluşturmaya çalışın. Bu yolda bir dizin bulunduğunda, dizin oluşturma isteklerinin idempotent olması için 204 yanıtı döndürebilirsiniz. Burada dizin olmayan bir dosya varsa, bir hata kodu döndürün. Kod 400 (“kötü istek”) uygun olacaktır. hint}} -### A public space on the web +### Web'de kamusal bir alan {{index "public space (exercise)", "file server example", "Content-Type header", website}} -Since the file server serves up any kind of file and even includes the right `Content-Type` header, you can use it to serve a website. Since it allows everybody to delete and replace files, it would be an interesting kind of website: one that can be modified, improved, and vandalized by everybody who takes the time to make the right HTTP request. +Dosya sunucusu her türlü dosyayı sunduğundan ve hatta doğru `Content-Type` başlığını içerdiğinden, bunu bir web sitesi sunmak için kullanabilirsiniz. Herkesin dosyaları silmesine ve değiştirmesine izin verdiğinden, ilginç bir web sitesi türü olacaktır: doğru HTTP isteğini oluşturmak için zaman ayıran herkes tarafından değiştirilebilen, geliştirilebilen ve tahrip edilebilen bir web sitesi. -Write a basic ((HTML)) page that includes a simple JavaScript file. Put the files in a directory served by the file server and open them in your browser. +Basit bir JavaScript dosyası içeren temel bir ((HTML)) sayfası yazın. Dosyaları dosya sunucusu tarafından sunulan bir dizine koyun ve tarayıcınızda açın. -Next, as an advanced exercise or even a ((weekend project)), combine all the knowledge you gained from this book to build a more user-friendly interface for modifying the website—from _inside_ the website. +Daha sonra, ileri düzey bir alıştırma veya hatta bir ((hafta sonu projesi)) olarak, bu kitaptan edindiğiniz tüm bilgileri birleştirerek web sitesini _içinden_ değiştirmek için daha kullanıcı dostu bir arayüz oluşturun. -Use an HTML ((form)) to edit the content of the files that make up the website, allowing the user to update them on the server by using HTTP requests, as described in [Chapter ?](http). +Web sitesini oluşturan dosyaların içeriğini düzenlemek için bir HTML ((form)) kullanın ve [Bölüm ?](http)'de açıklandığı gibi kullanıcının HTTP isteklerini kullanarak bunları sunucuda güncellemesine izin verin. -Start by making only a single file editable. Then make it so that the user can select which file to edit. Use the fact that our file server returns lists of files when reading a directory. +Sadece tek bir dosyayı düzenlenebilir hale getirerek başlayın. Daha sonra kullanıcının hangi dosyayı düzenleyeceğini seçebilmesini sağlayın. Dosya sunucumuzun bir dizini okurken dosya listeleri döndürdüğü gerçeğini kullanın. {{index overwriting}} -Don't work directly in the code exposed by the file server since if you make a mistake, you are likely to damage the files there. Instead, keep your work outside of the publicly accessible directory and copy it there when testing. +Doğrudan dosya sunucusu tarafından açığa çıkarılan kodda çalışmayın, çünkü bir hata yaparsanız buradaki dosyalara zarar verebilirsiniz. Bunun yerine, çalışmanızı herkesin erişebileceği dizinin dışında tutun ve test ederken oraya kopyalayın. {{hint {{index "file server example", "textarea (HTML tag)", "fetch function", "relative path", "public space (exercise)"}} -You can create a `<textarea>` element to hold the content of the file that is being edited. A `GET` request, using `fetch`, can retrieve the current content of the file. You can use relative URLs like _index.html_, instead of [_http://localhost:8000/index.html_](http://localhost:8000/index.html), to refer to files on the same server as the running script. +Düzenlenmekte olan dosyanın içeriğini tutmak için bir `<textarea>` öğesi oluşturabilirsiniz. Bir `GET` isteği, `fetch` kullanarak dosyanın geçerli içeriğini alabilir. Çalışan kodla aynı sunucudaki dosyalara başvurmak için [_http://localhost:8000/index.html_](http://localhost:8000/index.html) yerine _index.html_ gibi göreli URL'ler kullanabilirsiniz. {{index "form (HTML tag)", "submit event", "PUT method"}} -Then, when the user clicks a button (you can use a `<form>` element and `"submit"` event), make a `PUT` request to the same URL, with the content of the `<textarea>` as request body, to save the file. +Ardından, kullanıcı bir düğmeye tıkladığında (bir `<form>` öğesi ve `“submit”` olayı kullanabilirsiniz), dosyayı kaydetmek için istek gövdesi olarak `<textarea>` içeriği ile aynı URL'ye bir `PUT` isteği yapın. {{index "select (HTML tag)", "option (HTML tag)", "change event"}} -You can then add a `<select>` element that contains all the files in the server's top ((directory)) by adding `<option>` elements containing the lines returned by a `GET` request to the URL `/`. When the user selects another file (a `"change"` event on the field), the script must fetch and display that file. When saving a file, use the currently selected filename. +Daha sonra, `/` URL'sine bir `GET` isteği tarafından döndürülen satırları içeren `<option>` öğeleri ekleyerek sunucunun üst kısmındaki ((dizin)) tüm dosyaları içeren bir `<select>` öğesi ekleyebilirsiniz. Kullanıcı başka bir dosya seçtiğinde (alanda bir `“change”` olayı), kod bu dosyayı almalı ve görüntülemelidir. Bir dosyayı kaydederken, o anda seçili olan dosya adını kullanın. hint}} diff --git a/21_skillsharing.md b/21_skillsharing.md index c9f02863..3c6d2f5f 100644 --- a/21_skillsharing.md +++ b/21_skillsharing.md @@ -1,82 +1,86 @@ {{meta {code_links: ["code/skillsharing.zip"]}}} -# Project: Skill-Sharing Website +# Proje: Beceri Paylaşım Web Sitesi {{quote {author: "Margaret Fuller", chapter: true} -If you have knowledge, let others light their candles at it. +Eğer bilginiz varsa, bırakın başkaları da mumlarını yaksın. quote}} {{index "skill-sharing project", meetup, "project chapter"}} -{{figure {url: "img/chapter_picture_21.jpg", alt: "Illustration showing two unicycles leaned against a mailbox", chapter: "framed"}}} +{{figure {url: "img/chapter_picture_21.jpg", alt: "Posta kutusuna yaslanmış iki tek tekerlekli bisikleti gösteren çizim", chapter: "framed"}}} -A _((skill-sharing))_ meeting is an event where people with a shared interest come together and give small, informal presentations about things they know. At a ((gardening)) skill-sharing meeting, someone might explain how to cultivate ((celery)). Or in a programming skill-sharing group, you could drop by and tell people about Node.js. +Bir _((beceri paylaşımı))_ toplantısı, ortak bir ilgi alanına sahip insanların bir araya geldiği ve bildikleri şeyler hakkında küçük, gayri resmi sunumlar yaptığı bir etkinliktir. Bir ((bahçecilik)) beceri paylaşım toplantısında, birisi ((kereviz)) yetiştirmeyi açıklayabilir. Ya da bir programlama beceri paylaşım grubuna uğrayıp insanlara Node.js hakkında bilgi verebilirsiniz. -In this final project chapter, our goal is to set up a ((website)) for managing ((talk))s given at a skill-sharing meeting. Imagine a small group of people meeting up regularly in the office of one of the members to talk about ((unicycling)). The previous organizer of the meetings moved to another town, and nobody stepped forward to take over this task. We want a system that will let the participants propose and discuss talks among themselves, without an active organizer. +{{index learning, "users' group"}} -[Just like in the [previous chapter](node), some of the code in this chapter is written for Node.js, and running it directly in the HTML page that you are looking at is unlikely to work.]{if interactive} The full code for the project can be ((download))ed from [_https://eloquentjavascript.net/code/skillsharing.zip_](https://eloquentjavascript.net/code/skillsharing.zip). +Bilgisayarlarla ilgili olduklarında genellikle _kullanıcı grupları_ olarak da adlandırılan bu tür buluşmalar, bir şeyler öğrenmek veya benzer ilgi alanlarına sahip insanlarla tanışmak için harika bir yol olabilir. Birçok büyük şehirde JavaScript buluşmaları vardır. Bu buluşmalara katılmak genellikle ücretsizdir ve ben ziyaret ettiğim buluşmaları arkadaş canlısı ve misafirperver buldum. -## Design +Bu son proje bölümünde amacımız, bir beceri paylaşım toplantısında verilen ((konuşma))ları yönetmek için bir ((web sitesi)) kurmaktır. Küçük bir grup insanın düzenli olarak üyelerden birinin ofisinde ((unicycling)) hakkında konuşmak için toplandığını hayal edin. Toplantıların önceki organizatörü başka bir şehre taşındı ve kimse bu görevi devralmak için öne çıkmadı. Aktif bir organizatör olmadan katılımcıların kendi aralarında konuşmalar önermesine ve tartışmasına izin verecek bir sistem istiyoruz. + +[Tıpkı [önceki bölüm](node)'da olduğu gibi, bu bölümdeki kodların bazıları Node.js için yazılmıştır ve doğrudan baktığınız HTML sayfasında çalıştırılması pek olası değildir] {if interactive} Projenin tam kodu [_https://eloquentjavascript.net/code/skillsharing.zip_](https://eloquentjavascript.net/code/skillsharing.zip) adresinden ((indirilebilir)). + +## Tasarım {{index "skill-sharing project", persistence}} -There is a _((server))_ part to this project, written for ((Node.js)), and a _((client))_ part, written for the ((browser)). The server stores the system's data and provides it to the client. It also serves the files that implement the client-side system. +Bu projenin ((Node.js)) için yazılmış bir _((sunucu))_ kısmı ve ((tarayıcı)) için yazılmış bir _((istemci))_ kısmı vardır. Sunucu, sistemin verilerini depolar ve istemciye sağlar. Ayrıca istemci tarafı sistemini uygulayan dosyaları da sunar. {{index [HTTP, client]}} -The server keeps the list of ((talk))s proposed for the next meeting, and the client shows this list. Each talk has a presenter name, a title, a summary, and an array of ((comment))s associated with it. The client allows users to propose new talks (adding them to the list), delete talks, and comment on existing talks. Whenever the user makes such a change, the client makes an HTTP ((request)) to tell the server about it. +Sunucu bir sonraki toplantı için önerilen ((konuşma))ların listesini tutar ve istemci bu listeyi gösterir. Her konuşmanın bir sunucu adı, bir başlığı, bir özeti ve onunla ilişkili bir dizi ((yorum)) vardır. İstemci, kullanıcıların yeni konuşmalar önermesine (bunları listeye ekleyerek), konuşmaları silmesine ve mevcut konuşmalar hakkında yorum yapmasına olanak tanır. Kullanıcı böyle bir değişiklik yaptığında, istemci sunucuya bunu bildirmek için bir HTTP ((request)) yapar. -{{figure {url: "img/skillsharing.png", alt: "Screenshot of the skill-sharing website", width: "10cm"}}} +{{figure {url: "img/skillsharing.png", alt: "Beceri paylaşım web sitesinin ekran görüntüsü", width: "10cm"}}} {{index "live view", "user experience", "pushing data", connection}} -The ((application)) will be set up to show a _live_ view of the current proposed talks and their comments. Whenever someone, somewhere, submits a new talk or adds a comment, all people who have the page open in their browsers should immediately see the change. This poses a bit of a challenge—there is no way for a web server to open a connection to a client, nor is there a good way to know which clients are currently looking at a given website. +((Uygulama)), önerilen mevcut konuşmaların ve yorumlarının _canlı_ bir görünümünü gösterecek şekilde ayarlanacaktır. Birisi, bir yerde, yeni bir konuşma gönderdiğinde veya bir yorum eklediğinde, sayfayı tarayıcılarında açık tutan herkes değişikliği hemen görmelidir. Bu biraz zor bir iş; bir web sunucusunun bir istemciyle bağlantı kurmasının bir yolu olmadığı gibi, belirli bir web sitesine o anda hangi istemcilerin baktığını bilmenin de iyi bir yolu yok. {{index "Node.js"}} -A common solution to this problem is called _((long polling))_, which happens to be one of the motivations for Node's design. +Bu soruna yaygın bir çözüm _((long polling))_ olarak adlandırılır ve bu, Node'un tasarımının motivasyonlarından biridir. ## Long polling -{{index firewall, notification, "long polling", network, [browser, security]}} +{{index notification, "long polling", network, [browser, security]}} -To be able to immediately notify a client that something changed, we need a ((connection)) to that client. Since web browsers do not traditionally accept connections and clients are often behind ((router))s that would block such connections anyway, having the server initiate this connection is not practical. +Bir istemciye bir şeyin değiştiğini anında bildirebilmek için, o istemciye bir ((bağlantı)) gerekir. Web tarayıcıları geleneksel olarak bağlantıları kabul etmediğinden ve istemciler genellikle bu tür bağlantıları engelleyecek ((yönlendirici))'lerin arkasında olduğundan, sunucunun bu bağlantıyı başlatması pratik değildir. -We can arrange for the client to open the connection and keep it around so that the server can use it to send information when it needs to do so. +İstemcinin bağlantıyı açmasını ve sunucunun ihtiyaç duyduğunda bilgi göndermek için kullanabilmesi için bağlantıda tutmasını sağlayabiliriz. {{index socket}} -But an ((HTTP)) request allows only a simple flow of information: the client sends a request, the server comes back with a single response, and that is it. There is a technology called _((WebSockets))_ that makes it possible to open ((connection))s for arbitrary data exchange. But using them properly is somewhat tricky. +Ancak bir ((HTTP)) isteği yalnızca basit bir bilgi akışına izin verir: istemci bir istek gönderir, sunucu tek bir yanıtla geri döner ve hepsi bu kadar. Modern tarayıcılar tarafından desteklenen _((WebSockets))_ adında bir teknoloji vardır ve bu teknoloji rastgele veri alışverişi için ((connection))lar açmayı mümkün kılar. Ancak bunları doğru şekilde kullanmak biraz zordur. -In this chapter, we use a simpler technique—((long polling))—where clients continuously ask the server for new information using regular HTTP requests, and the server stalls its answer when it has nothing new to report. +Bu bölümde, istemcilerin normal HTTP isteklerini kullanarak sürekli olarak sunucudan yeni bilgiler istediği ve sunucunun bildirecek yeni bir şeyi olmadığında yanıtını beklettiği daha basit bir teknik -((long polling))\_ kullanıyoruz. {{index "live view"}} -As long as the client makes sure it constantly has a polling request open, it will receive information from the server quickly after it becomes available. For example, if Fatma has our skill-sharing application open in her browser, that browser will have made a request for updates and will be waiting for a response to that request. When Iman submits a talk on Extreme Downhill Unicycling, the server will notice that Fatma is waiting for updates and send a response containing the new talk to her pending request. Fatma's browser will receive the data and update the screen to show the talk. +İstemci sürekli olarak bir yoklama isteğinin açık olduğundan emin olduğu sürece, kullanılabilir hale geldikten sonra sunucudan hızlı bir şekilde bilgi alacaktır. Örneğin, Fatma'nın tarayıcısında beceri paylaşım uygulamamız açıksa, bu tarayıcı güncellemeler için bir istekte bulunmuş ve bu isteğe yanıt bekliyor olacaktır. Iman, Extreme Downhill Unicycling hakkında bir konuşma gönderdiğinde, sunucu Fatma'nın güncellemeleri beklediğini fark edecek ve bekleyen isteğine yeni konuşmayı içeren bir yanıt gönderecektir. Fatma'nın tarayıcısı verileri alacak ve konuşmayı göstermek için ekranı güncelleyecektir. {{index robustness, timeout}} -To prevent connections from timing out (being aborted because of a lack of activity), ((long polling)) techniques usually set a maximum time for each request, after which the server will respond anyway, even though it has nothing to report. The client can then start a new request. Periodically restarting the request also makes the technique more robust, allowing clients to recover from temporary ((connection)) failures or server problems. +Bağlantıların zaman aşımına uğramasını (etkinlik eksikliği nedeniyle iptal edilmesini) önlemek için, ((uzun yoklama)) teknikleri genellikle her istek için maksimum bir süre belirler, bu sürenin sonunda sunucu bildirecek hiçbir şeyi olmasa bile yine de yanıt verir. İstemci daha sonra yeni bir istek başlatabilir. İsteğin periyodik olarak yeniden başlatılması da tekniği daha sağlam hale getirerek istemcilerin geçici ((bağlantı)) arızalarından veya sunucu sorunlarından kurtulmasını sağlar. {{index "Node.js"}} -A busy server that is using long polling may have thousands of waiting requests, and thus ((TCP)) connections, open. Node, which makes it easy to manage many connections without creating a separate thread of control for each one, is a good fit for such a system. +Uzun yoklama kullanan yoğun bir sunucuda binlerce bekleyen istek ve dolayısıyla ((TCP)) bağlantısı açık olabilir. Her biri için ayrı bir kontrol iş parçacığı oluşturmadan birçok bağlantıyı yönetmeyi kolaylaştıran Node, böyle bir sistem için iyi bir seçimdir. -## HTTP interface +## HTTP arayüzü {{index "skill-sharing project", [interface, HTTP]}} -Before we start designing either the server or the client, let's think about the point where they touch: the ((HTTP)) interface over which they communicate. +Sunucuyu ya da istemciyi tasarlamaya başlamadan önce, temas ettikleri noktayı düşünelim: üzerinden iletişim kurdukları ((HTTP)) arayüzü. {{index [path, URL], [method, HTTP]}} -We will use ((JSON)) as the format of our request and response body. Like in the file server from [Chapter ?](node#file_server), we'll try to make good use of HTTP methods and ((header))s. The interface is centered around the `/talks` path. Paths that do not start with `/talks` will be used for serving ((static file))s—the HTML and JavaScript code for the client-side system. +İstek ve yanıt gövdelerimizin formatı olarak ((JSON)) kullanacağız. [Bölüm ?](node#file_server)'daki dosya sunucusunda olduğu gibi, HTTP yöntemlerini ve ((header))'ları iyi kullanmaya çalışacağız. Arayüz `/talks` yolu etrafında merkezlenmiştir. `/talks` ile başlamayan yollar ((statik dosya))ları (istemci tarafı sistemi için HTML ve JavaScript kodu) sunmak için kullanılacaktır. {{index "GET method"}} -A `GET` request to `/talks` returns a JSON document like this: +Bir `GET` isteği `/talks` için aşağıdaki gibi bir JSON belgesi döndürür: ```{lang: "json"} [{"title": "Unituning", @@ -87,18 +91,18 @@ A `GET` request to `/talks` returns a JSON document like this: {{index "PUT method", URL}} -Creating a new talk is done by making a `PUT` request to a URL like `/talks/Unituning`, where the part after the second slash is the title of the talk. The `PUT` request's body should contain a ((JSON)) object that has `presenter` and `summary` properties. +Yeni bir konuşma oluşturmak için `/talks/Unituning` gibi bir URL'ye `PUT` isteği yapılır, burada ikinci eğik çizgiden sonraki kısım konuşmanın başlığıdır. `PUT` isteğinin gövdesi, `presenter` ve `summary` özelliklerine sahip bir ((JSON)) nesnesi içermelidir. {{index "encodeURIComponent function", [escaping, "in URLs"], [whitespace, "in URLs"]}} -Since talk titles may contain spaces and other characters that may not appear normally in a URL, title strings must be encoded with the `encodeURIComponent` function when building up such a URL. +Konuşma başlıkları normalde bir URL'de görünmeyen boşluklar ve diğer karakterler içerebileceğinden, böyle bir URL oluşturulurken başlık dizeleri `encodeURIComponent` işlevi ile kodlanmalıdır. ``` console.log("/talks/" + encodeURIComponent("How to Idle")); // → /talks/How%20to%20Idle ``` -A request to create a talk about idling might look something like this: +Rölanti hakkında bir konuşma oluşturma talebi şöyle görünebilir: ```{lang: http} PUT /talks/How%20to%20Idle HTTP/1.1 @@ -109,11 +113,11 @@ Content-Length: 92 "summary": "Standing still on a unicycle"} ``` -Such URLs also support `GET` requests to retrieve the JSON representation of a talk and `DELETE` requests to delete a talk. +Bu tür URL'ler ayrıca bir konuşmanın JSON temsilini almak için `GET` isteklerini ve bir konuşmayı silmek için `DELETE` isteklerini de destekler. {{index "POST method"}} -Adding a ((comment)) to a talk is done with a `POST` request to a URL like `/talks/Unituning/comments`, with a JSON body that has `author` and `message` properties. +Bir konuşmaya ((yorum)) eklemek, `author` ve `message` özelliklerine sahip bir JSON gövdesi ile `/talks/Unituning/comments` gibi bir URL'ye `POST` isteği ile yapılır. ```{lang: http} POST /talks/Unituning/comments HTTP/1.1 @@ -126,17 +130,17 @@ Content-Length: 72 {{index "query string", timeout, "ETag header", "If-None-Match header"}} -To support ((long polling)), `GET` requests to `/talks` may include extra headers that inform the server to delay the response if no new information is available. We'll use a pair of headers normally intended to manage caching: `ETag` and `If-None-Match`. +((uzun yoklama)) desteklemek için, `/talks` için `GET` istekleri, sunucuya yeni bilgi mevcut değilse yanıtı geciktirmesini bildiren ekstra başlıklar içerebilir. Normalde önbelleğe almayı yönetmek için tasarlanmış bir çift başlık kullanacağız: `ETag` ve `If-None-Match`. {{index "304 (HTTP status code)"}} -Servers may include an `ETag` ("entity tag") header in a response. Its value is a string that identifies the current version of the resource. Clients, when they later request that resource again, may make a _((conditional request))_ by including an `If-None-Match` header whose value holds that same string. If the resource hasn't changed, the server will respond with status code 304, which means "not modified", telling the client that its cached version is still current. When the tag does not match, the server responds as normal. +Sunucular bir yanıta `ETag` (“varlık etiketi”) başlığı ekleyebilir. Değeri, kaynağın geçerli sürümünü tanımlayan bir dizedir. İstemciler, daha sonra bu kaynağı tekrar talep ettiklerinde, değeri aynı dizeyi tutan bir `If-None-Match` başlığı ekleyerek bir _((koşullu istek))_ yapabilir. Kaynak değişmemişse, sunucu “değiştirilmemiş” anlamına gelen 304 durum koduyla yanıt verir ve istemciye önbelleğe alınmış sürümünün hala geçerli olduğunu söyler. Etiket eşleşmediğinde, sunucu normal şekilde yanıt verir. {{index "Prefer header"}} -We need something like this, where the client can tell the server which version of the list of talks it has, and the server responds only when that list has changed. But instead of immediately returning a 304 response, the server should stall the response and return only when something new is available or a given amount of time has elapsed. To distinguish long polling requests from normal conditional requests, we give them another header, `Prefer: wait=90`, which tells the server that the client is willing to wait up to 90 seconds for the response. +İstemcinin sunucuya konuşma listesinin hangi sürümüne sahip olduğunu söyleyebileceği ve sunucunun yalnızca bu liste değiştiğinde yanıt vereceği böyle bir şeye ihtiyacımız var. Ancak sunucu hemen bir 304 yanıtı döndürmek yerine, yanıtı bekletmeli ve yalnızca yeni bir şey mevcut olduğunda veya belirli bir süre geçtiğinde geri dönmelidir. Uzun yoklama isteklerini normal koşullu isteklerden ayırmak için, sunucuya istemcinin yanıt için 90 saniyeye kadar beklemeye istekli olduğunu söyleyen `Prefer: wait=90` adlı başka bir başlık veriyoruz. -The server will keep a version number that it updates every time the talks change and will use that as the `ETag` value. Clients can make requests like this to be notified when the talks change: +Sunucu, görüşmeler her değiştiğinde güncellediği bir sürüm numarası tutacak ve bunu `ETag` değeri olarak kullanacaktır. İstemciler, konuşmalar değiştiğinde haberdar olmak için bunun gibi isteklerde bulunabilirler: ```{lang: null} GET /talks HTTP/1.1 @@ -150,34 +154,34 @@ Content-Type: application/json ETag: "5" Content-Length: 295 -[....] +[...] ``` {{index security}} -The protocol described here does not do any ((access control)). Everybody can comment, modify talks, and even delete them. (Since the Internet is full of ((hooligan))s, putting such a system online without further protection probably wouldn't end well.) +Burada açıklanan protokol herhangi bir ((erişim kontrolü)) yapmaz. Herkes yorum yapabilir, görüşmeleri değiştirebilir ve hatta silebilir. (İnternet ((holigan))larla dolu olduğu için, böyle bir sistemi daha fazla koruma olmadan çevrimiçi hale getirmek muhtemelen iyi sonuçlanmayacaktır). -## The server +## Sunucu {{index "skill-sharing project"}} -Let's start by building the ((server))-side part of the program. The code in this section runs on ((Node.js)). +Programın ((sunucu)) tarafını oluşturarak başlayalım. Bu bölümdeki kod ((Node.js)) üzerinde çalışır. -### Routing +### Yönlendirme {{index "createServer function", [path, URL], [method, HTTP]}} -Our server will use Node's `createServer` to start an HTTP server. In the function that handles a new request, we must distinguish between the various kinds of requests (as determined by the method and the path) that we support. This can be done with a long chain of `if` statements, but there is a nicer way. +Sunucumuz bir HTTP sunucusu başlatmak için Node'un `createServer` özelliğini kullanacaktır. Yeni bir isteği işleyen işlevde, desteklediğimiz çeşitli istek türlerini (yöntem ve yol tarafından belirlendiği gibi) ayırt etmeliyiz. Bu, uzun bir `if` deyimleri zinciri ile yapılabilir, ancak daha güzel bir yol vardır. {{index dispatch}} -A _((router))_ is a component that helps dispatch a request to the function that can handle it. You can tell the router, for example, that `PUT` requests with a path that matches the regular expression `/^\/talks\/([^\/]+)$/` (`/talks/` followed by a talk title) can be handled by a given function. In addition, it can help extract the meaningful parts of the path (in this case the talk title), wrapped in parentheses in the ((regular expression)), and pass them to the handler function. +Bir _((router))_, bir isteği onu işleyebilecek işleve göndermeye yardımcı olan bir bileşendir. Örneğin, yönlendiriciye `/^\/talks\/([^\/]+)$/` (`/talks/` ve ardından bir konuşma başlığı) düzenli ifadesiyle eşleşen bir yola sahip `PUT` isteklerinin belirli bir işlev tarafından işlenebileceğini söyleyebilirsiniz. Buna ek olarak, ((düzenli ifade)) içinde parantez içine alınmış yolun anlamlı kısımlarını (bu durumda konuşma başlığı) ayıklamaya ve bunları işleyici fonksiyona aktarmaya yardımcı olabilir. -There are a number of good router packages on ((NPM)), but here we'll write one ourselves to illustrate the principle. +((NPM))'de bir dizi iyi yönlendirici paketi vardır, ancak burada prensibi göstermek için kendimiz bir tane yazacağız. {{index "import keyword", "Router class", module}} -This is `router.mjs`, which we will later `import` from our server module: +Bu, daha sonra sunucu modülümüzden `import` edeceğimiz `router.mjs` dosyasıdır: ```{includeCode: ">code/skillsharing/router.mjs"} export class Router { @@ -201,19 +205,23 @@ export class Router { {{index "Router class"}} -The module exports the `Router` class. A router object allows you to register handlers for specific methods and URL patterns with its `add` method. When a request is resolved with the `resolve` method, the router calls the handler whose method and URL match the request and return its result. +Modül `Router` sınıfını dışa aktarır. Bir router nesnesi `add` yöntemiyle yeni işleyicilerin kaydedilmesine izin verir ve `resolve` yöntemiyle istekleri çözebilir. + +{{index "some method"}} + +İkincisi, bir işleyici bulunduğunda bir yanıt, aksi takdirde `null` döndürür. Eşleşen bir rota bulunana kadar rotaları teker teker (tanımlandıkları sırayla) dener. {{index "capture group", "decodeURIComponent function", [escaping, "in URLs"]}} -Handler functions are called with the `context` value given to `resolve`. We will use this to give them access to our server state. Additionally, they receive the match strings for any groups they defined in their ((regular expression)), and the request object. The strings have to be URL-decoded since the raw URL may contain `%20`-style codes. +İşleyici işlevleri `context` değeri (bizim durumumuzda sunucu örneği olacaktır), ((düzenli ifade)) içinde tanımladıkları herhangi bir grup için eşleşme dizeleri ve istek nesnesi ile çağrılır. Ham URL `%20` tarzı kodlar içerebileceğinden, dizelerin URL kodu çözülmelidir. -### Serving files +### Dosyaları servis etme -When a request matches none of the request types defined in our router, the server must interpret it as a request for a file in the `public` directory. It would be possible to use the file server defined in [Chapter ?](node#file_server) to serve such files, but we neither need nor want to support `PUT` and `DELETE` requests on files, and we would like to have advanced features such as support for caching. So let's use a solid, well-tested ((static file)) server from ((NPM)) instead. +Bir istek yönlendiricimizde tanımlanan istek türlerinden hiçbiriyle eşleşmediğinde, sunucu bunu `public` dizinindeki bir dosya için istek olarak yorumlamalıdır. Bu tür dosyaları sunmak için [Bölüm ?](node#file_server)'da tanımlanan dosya sunucusunu kullanmak mümkün olabilir, ancak dosyalar üzerinde `PUT` ve `DELETE` isteklerini desteklemeye ne ihtiyacımız var ne de istiyoruz ve önbelleğe alma desteği gibi gelişmiş özelliklere sahip olmak istiyoruz. Bu yüzden bunun yerine ((NPM))'den sağlam, iyi test edilmiş bir ((statik dosya)) sunucusu kullanalım. {{index "createServer function", "serve-static package"}} -I opted for `serve-static`. This isn't the only such server on NPM, but it works well and fits our purposes. The `serve-static` package exports a function that can be called with a root directory to produce a request handler function. The handler function accepts the `request` and `response` arguments provided by the server from `"node:http"`, and a third argument, a function that it will call if no file matches the request. We want our server to first check for requests that we should handle specially, as defined in the router, so we wrap it in another function. +Ben `serve-static`'i seçtim. Bu NPM'deki tek sunucu değil, ancak iyi çalışıyor ve amaçlarımıza uyuyor. `serve-static` paketi, bir istek işleyici işlevi üretmek için bir kök dizinle çağrılabilen bir işlevi dışa aktarır. İşleyici işlev, sunucu tarafından sağlanan `request` ve `response` argümanlarını ve üçüncü bir argümanı, istekle eşleşen bir dosya yoksa çağıracağı bir işlevi kabul eder. Sunucumuzun öncelikle yönlendiricide tanımlandığı gibi özel olarak ele almamız gereken istekleri kontrol etmesini istiyoruz, bu yüzden bunu başka bir fonksiyona sarıyoruz. ```{includeCode: ">code/skillsharing/skillsharing_server.mjs"} import {createServer} from "node:http"; @@ -247,9 +255,9 @@ class SkillShareServer { } ``` -The `serveFromRouter` function has the same interface as `fileServer`, taking `(request, response, next)` arguments. This allows us to “chain” several request handlers, allowing each to either handle the request, or pass responsibility for that on to the next handler. The final handler, `notFound`, simply responds with a “not found” error. +`serveFromRouter` fonksiyonu `fileServer` ile aynı arayüze sahiptir ve `(request, response, next)` argümanlarını alır. Bu, birkaç istek işleyicisini “zincirlememize” olanak tanıyarak her birinin isteği işlemesine veya bunun sorumluluğunu bir sonraki işleyiciye devretmesine izin verir. Son işleyici, `notFound`, sadece “bulunamadı” hatası ile yanıt verir. -Our `serveFromRouter` function uses a similar convention as the file server from the [previous chapter](node) for responses—handlers in the router return promises that resolve to objects describing the response. +Bizim `serveFromRouter` fonksiyonumuz, yanıtlar için [önceki bölüm](node)'daki dosya sunucusuna benzer bir konvansiyon kullanır-yönlendiricideki işleyici, yanıtı tanımlayan nesnelere çözümlenen vaatler döndürür. ```{includeCode: ">code/skillsharing/skillsharing_server.mjs"} import {Router} from "./router.mjs"; @@ -272,13 +280,13 @@ async function serveFromRouter(server, request, } ``` -### Talks as resources +### Kaynak olarak konuşmalar -The ((talk))s that have been proposed are stored in the `talks` property of the server, an object whose property names are the talk titles. We will add some handlers to our router that expose these as HTTP ((resource))s under `/talks/[title]`. +Önerilen ((konuşma))lar, özellik adları konuşma başlıkları olan bir nesne olan sunucunun `talks` özelliğinde saklanır. Bunlar `/talks/[title]` altında HTTP ((resource))ları olarak gösterilecektir, bu nedenle yönlendiricimize istemcilerin bunlarla çalışmak için kullanabileceği çeşitli yöntemleri uygulayan işleyiciler eklememiz gerekir. {{index "GET method", "404 (HTTP status code)" "hasOwn function"}} -The handler for requests that `GET` a single talk must look up the talk and respond either with the talk's JSON data or with a 404 error response. +Tek bir konuşmayı `GET`leyen isteklerin işleyicisi konuşmayı aramalı ve konuşmanın JSON verileriyle ya da 404 hata yanıtıyla yanıt vermelidir. ```{includeCode: ">code/skillsharing/skillsharing_server.mjs"} const talkPath = /^\/talks\/([^\/]+)$/; @@ -295,7 +303,7 @@ router.add("GET", talkPath, async (server, title) => { {{index "DELETE method"}} -Deleting a talk is done by removing it from the `talks` object. +Bir konuşmayı silmek, onu `talks` nesnesinden kaldırarak yapılır. ```{includeCode: ">code/skillsharing/skillsharing_server.mjs"} router.add("DELETE", talkPath, async (server, title) => { @@ -309,15 +317,30 @@ router.add("DELETE", talkPath, async (server, title) => { {{index "long polling", "updated method"}} -The `updated` method, which we will define [later](skillsharing#updated), notifies waiting long polling requests about the change. +[Daha sonra](skillsharing#updated) tanımlayacağımız `updated` yöntemi, bekleyen uzun yoklama isteklerini değişiklik hakkında bilgilendirir. + +{{index "readStream function", "body (HTTP)", stream}} + +Bir istek gövdesinin içeriğini almak için, tüm içeriği bir ((okunabilir akış))'tan okuyan ve bir dizeye çözümlenen bir söz döndüren `readStream` adlı bir işlev tanımlarız. + +```{includeCode: ">code/skillsharing/skillsharing_server.mjs"} +function readStream(stream) { + return new Promise((resolve, reject) => { + let data = ""; + stream.on("error", reject); + stream.on("data", chunk => data += chunk.toString()); + stream.on("end", () => resolve(data)); + }); +} +``` {{index validation, input, "PUT method"}} -One handler that needs to read request bodies is the `PUT` handler, which is used to create new ((talk))s. It has to check whether the data it was given has `presenter` and `summary` properties, which are strings. Any data coming from outside the system might be nonsense, and we don't want to corrupt our internal data model or ((crash)) when bad requests come in. +İstek gövdelerini okuması gereken bir işleyici, yeni ((talk))'lar oluşturmak için kullanılan `PUT` işleyicisidir. Kendisine verilen verinin string olan `presenter` ve `summary` özelliklerine sahip olup olmadığını kontrol etmek zorundadır. Sistem dışından gelen herhangi bir veri saçma olabilir ve kötü istekler geldiğinde dahili veri modelimizi bozmak veya ((çökmek)) istemiyoruz. {{index "updated method"}} -If the data looks valid, the handler stores an object that represents the new talk in the `talks` object, possibly ((overwriting)) an existing talk with this title, and again calls `updated`. +Veriler geçerli görünüyorsa, işleyici yeni konuşmayı temsil eden bir nesneyi `talks` nesnesinde saklar, muhtemelen bu başlığa sahip mevcut bir konuşmayı ((üzerine yazar)) ve tekrar `updated` çağrısı yapar. {{index "node:stream/consumers package", JSON, "readable stream"}} @@ -345,7 +368,9 @@ router.add("PUT", talkPath, }); ``` -Adding a ((comment)) to a ((talk)) works similarly. We use `readJSON` to get the content of the request, validate the resulting data, and store it as a comment when it looks valid. +{{index validation, "readStream function"}} + +Bir ((talk))'a ((comment)) eklemek de benzer şekilde çalışır. İsteğin içeriğini almak, elde edilen verileri doğrulamak ve geçerli göründüğünde bir yorum olarak saklamak için `readStream` kullanıyoruz. ```{includeCode: ">code/skillsharing/skillsharing_server.mjs"} router.add("POST", /^\/talks\/([^\/]+)\/comments$/, @@ -367,15 +392,15 @@ router.add("POST", /^\/talks\/([^\/]+)\/comments$/, {{index "404 (HTTP status code)"}} -Trying to add a comment to a nonexistent talk returns a 404 error. +Var olmayan bir konuşmaya yorum eklemeye çalışmak 404 hatası döndürüyor. -### Long polling support +### Long polling desteği -The most interesting aspect of the server is the part that handles ((long polling)). When a `GET` request comes in for `/talks`, it may be either a regular request or a long polling request. +Sunucunun en ilginç yönü ((uzun yoklama)) ile ilgilenen kısmıdır. Bir `GET` isteği `/talks` için geldiğinde, bu normal bir istek ya da uzun bir yoklama isteği olabilir. {{index "talkResponse method", "ETag header"}} -There will be multiple places in which we have to send an array of talks to the client, so we first define a helper method that builds up such an array and includes an `ETag` header in the response. +İstemciye bir dizi konuşma göndermemiz gereken birden fazla yer olacaktır, bu nedenle önce böyle bir dizi oluşturan ve yanıta bir `ETag` başlığı ekleyen bir yardımcı yöntem tanımlıyoruz. ```{includeCode: ">code/skillsharing/skillsharing_server.mjs"} SkillShareServer.prototype.talkResponse = function() { @@ -392,7 +417,7 @@ SkillShareServer.prototype.talkResponse = function() { {{index "query string", "url package", parsing}} -The handler itself needs to look at the request headers to see whether `If-None-Match` and `Prefer` headers are present. Node stores headers, whose names are specified to be case insensitive, under their lowercase names. +İşleyicinin kendisinin `If-None-Match` ve `Prefer` başlıklarının mevcut olup olmadığını görmek için istek başlıklarına bakması gerekir. Node, adları büyük/küçük harf duyarsız olarak belirtilen başlıkları küçük harf adları altında saklar. ```{includeCode: ">code/skillsharing/skillsharing_server.mjs"} router.add("GET", /^\/talks$/, async (server, request) => { @@ -410,11 +435,11 @@ router.add("GET", /^\/talks$/, async (server, request) => { {{index "long polling", "waitForChanges method", "If-None-Match header", "Prefer header"}} -If no tag was given or a tag was given that doesn't match the server's current version, the handler responds with the list of talks. If the request is conditional and the talks did not change, we consult the `Prefer` header to see whether we should delay the response or respond right away. +Hiçbir etiket verilmemişse veya sunucunun geçerli sürümüyle eşleşmeyen bir etiket verilmişse, işleyici görüşmelerin listesiyle yanıt verir. İstek koşulluysa ve görüşmeler değişmediyse, yanıtı geciktirmemiz veya hemen yanıtlamamız gerekip gerekmediğini görmek için `Prefer` başlığına bakarız. {{index "304 (HTTP status code)", "setTimeout function", timeout, "callback function"}} -Callback functions for delayed requests are stored in the server's `waiting` array so that they can be notified when something happens. The `waitForChanges` method also immediately sets a timer to respond with a 304 status when the request has waited long enough. +Geciken istekler için geri arama işlevleri sunucunun `waiting` dizisinde saklanır, böylece bir şey olduğunda bildirilebilirler. Ayrıca `waitForChanges` yöntemi, istek yeterince uzun süre beklediğinde 304 durumuyla yanıt vermek için hemen bir zamanlayıcı ayarlar. ```{includeCode: ">code/skillsharing/skillsharing_server.mjs"} SkillShareServer.prototype.waitForChanges = function(time) { @@ -433,7 +458,7 @@ SkillShareServer.prototype.waitForChanges = function(time) { {{id updated}} -Registering a change with `updated` increases the `version` property and wakes up all waiting requests. +Bir değişikliği `updated` ile kaydetmek `version` özelliğini artırır ve bekleyen tüm istekleri uyandırır. ```{includeCode: ">code/skillsharing/skillsharing_server.mjs"} SkillShareServer.prototype.updated = function() { @@ -446,25 +471,25 @@ SkillShareServer.prototype.updated = function() { {{index [HTTP, server]}} -That concludes the server code. If we create an instance of `SkillShareServer` and start it on port 8000, the resulting HTTP server serves files from the `public` subdirectory alongside a talk-managing interface under the `/talks` URL. +Sunucu kodu bu kadar. Bir `SkillShareServer` örneği oluşturur ve 8000 numaralı bağlantı noktasında başlatırsak, ortaya çıkan HTTP sunucusu `/talks` URL'si altında bir konuşma yönetimi arayüzünün yanı sıra `public` alt dizinindeki dosyaları sunar. ```{includeCode: ">code/skillsharing/skillsharing_server.mjs"} new SkillShareServer({}).start(8000); ``` -## The client +## Client uygulaması {{index "skill-sharing project"}} -The ((client))-side part of the skill-sharing website consists of three files: a tiny HTML page, a style sheet, and a JavaScript file. +Beceri paylaşım web sitesinin ((istemci)) tarafındaki kısmı üç dosyadan oluşur: küçük bir HTML sayfası, bir stil sayfası ve bir JavaScript dosyası. ### HTML {{index "index.html"}} -It is a widely used convention for web servers to try to serve a file named `index.html` when a request is made directly to a path that corresponds to a directory. The ((file server)) module we use, `serve-static`, supports this convention. When a request is made to the path `/`, the server looks for the file `./public/index.html` (`./public` being the root we gave it) and returns that file if found. +Bir dizine karşılık gelen bir yola doğrudan bir istek yapıldığında `index.html` adlı bir dosyayı sunmaya çalışmak web sunucuları için yaygın olarak kullanılan bir kuraldır. Kullandığımız ((dosya sunucusu)) modülü, `serve-static`, bu geleneği destekler. Bir istek `/` yoluna yapıldığında, sunucu `./public/index.html` dosyasını arar (`./public` ona verdiğimiz köktür) ve bulursa bu dosyayı döndürür. -Thus, if we want a page to show up when a browser is pointed at our server, we should put it in `public/index.html`. This is our index file: +Bu nedenle, bir tarayıcı sunucumuza yönlendirildiğinde bir sayfanın görünmesini istiyorsak, onu `public/index.html` dosyasına koymalıyız. Bu bizim dizin dosyamızdır: ```{lang: "html", includeCode: ">code/skillsharing/public/index.html"} <!doctype html> @@ -479,15 +504,17 @@ Thus, if we want a page to show up when a browser is pointed at our server, we s {{index CSS}} -It defines the document ((title)) and includes a style sheet, which defines a few styles to, among other things, make sure there is some space between talks. Then it adds a heading at the top of the page and loads the script that contains the ((client))-side application. +Belgeyi ((başlık)) tanımlar ve diğer şeylerin yanı sıra konuşmalar arasında biraz boşluk olmasını sağlamak için birkaç stil tanımlayan bir stil sayfası içerir. + +En altta, sayfanın üst kısmına bir başlık ekler ve ((istemci)) tarafındaki uygulamayı içeren komut dosyasını yükler. -### Actions +### Aksiyonlar -The application state consists of the list of talks and the name of the user, and we'll store it in a `{talks, user}` object. We don't allow the user interface to directly manipulate the state or send off HTTP requests. Rather, it may emit _actions_ that describe what the user is trying to do. +Uygulama durumu, konuşmaların listesi ve kullanıcının adından oluşur ve bunu bir `{talks, user}` nesnesinde saklayacağız. Kullanıcı arayüzünün durumu doğrudan manipüle etmesine veya HTTP istekleri göndermesine izin vermiyoruz. Bunun yerine, kullanıcının ne yapmaya çalıştığını tanımlayan _actions_ yayabilir. {{index "handleAction function"}} -The `handleAction` function takes such an action and makes it happen. Because our state updates are so simple, state changes are handled in the same function. +`handleAction` fonksiyonu böyle bir eylemi alır ve gerçekleşmesini sağlar. Durum güncellemelerimiz çok basit olduğu için, durum değişiklikleri aynı fonksiyonda ele alınır. ```{includeCode: ">code/skillsharing/public/skillsharing_client.js", test: no} function handleAction(state, action) { @@ -524,11 +551,11 @@ function handleAction(state, action) { {{index "localStorage object"}} -We'll store the user's name in `localStorage` so that it can be restored when the page is loaded. +Kullanıcının adını `localStorage` içinde saklayacağız, böylece sayfa yüklendiğinde geri yüklenebilir. {{index "fetch function", "status property"}} -The actions that need to involve the server make network requests, using `fetch`, to the HTTP interface described earlier. We use a wrapper function, `fetchOK`, which makes sure the returned promise is rejected when the server returns an error code. +Sunucunun dahil olması gereken eylemler, daha önce açıklanan HTTP arayüzüne `fetch` kullanarak ağ istekleri yapar. Sunucu bir hata kodu döndürdüğünde döndürülen sözün reddedilmesini sağlayan `fetchOK` adlı bir sarmalayıcı işlev kullanıyoruz. ```{includeCode: ">code/skillsharing/public/skillsharing_client.js", test: no} function fetchOK(url, options) { @@ -541,7 +568,7 @@ function fetchOK(url, options) { {{index "talkURL function", "encodeURIComponent function"}} -This helper function is used to build up a ((URL)) for a talk with a given title. +Bu yardımcı işlev, belirli bir başlığa sahip bir konuşma için bir ((URL)) oluşturmak için kullanılır. ```{includeCode: ">code/skillsharing/public/skillsharing_client.js", test: no} function talkURL(title) { @@ -551,7 +578,7 @@ function talkURL(title) { {{index "error handling", "user experience", "reportError function"}} -When the request fails, we don't want to have our page just sit there, doing nothing without explanation. So we define a function called `reportError`, which at least shows the user a dialog that tells them something went wrong. +İstek başarısız olduğunda, sayfamızın hiçbir açıklama yapmadan öylece durmasını istemiyoruz. Bu yüzden `reportError` adında bir fonksiyon tanımlıyoruz, bu fonksiyon en azından kullanıcıya bir şeylerin yanlış gittiğini söyleyen bir diyalog kutusu gösteriyor. ```{includeCode: ">code/skillsharing/public/skillsharing_client.js", test: no} function reportError(error) { @@ -559,11 +586,11 @@ function reportError(error) { } ``` -### Rendering components +### Bileşenlerin gösterimi {{index "renderUserField function"}} -We'll use an approach similar to the one we saw in [Chapter ?](paint), splitting the application into components. But since some of the components either never need to update or are always fully redrawn when updated, we'll define those not as classes but as functions that directly return a DOM node. For example, here is a component that shows the field where the user can enter their name: +[Bölüm ?](paint)'da gördüğümüze benzer bir yaklaşım kullanarak uygulamayı bileşenlere ayıracağız. Ancak bazı bileşenlerin hiçbir zaman güncellenmesi gerekmediğinden ya da güncellendiğinde her zaman tamamen yeniden çizildiğinden, bunları sınıf olarak değil, doğrudan bir DOM düğümü döndüren işlevler olarak tanımlayacağız. Örneğin, burada kullanıcının adını girebileceği alanı gösteren bir bileşen bulunmaktadır: ```{includeCode: ">code/skillsharing/public/skillsharing_client.js", test: no} function renderUserField(name, dispatch) { @@ -579,7 +606,7 @@ function renderUserField(name, dispatch) { {{index "elt function"}} -The `elt` function used to construct DOM elements is the one we used in [Chapter ?](paint). +DOM öğelerini oluşturmak için kullanılan `elt` işlevi [Bölüm ?](paint)'da kullandığımız işlevdir. ```{includeCode: ">code/skillsharing/public/skillsharing_client.js", test: no, hidden: true} function elt(type, props, ...children) { @@ -595,7 +622,7 @@ function elt(type, props, ...children) { {{index "renderTalk function"}} -A similar function is used to render talks, which include a list of comments and a form for adding a new ((comment)). +Benzer bir işlev, yorumların bir listesini ve yeni bir ((yorum)) eklemek için bir form içeren konuşmaları oluşturmak için kullanılır. ```{includeCode: ">code/skillsharing/public/skillsharing_client.js", test: no} function renderTalk(talk, dispatch) { @@ -627,11 +654,11 @@ function renderTalk(talk, dispatch) { {{index "submit event"}} -The `"submit"` event handler calls `form.reset` to clear the form's content after creating a `"newComment"` action. +`“submit“` olay işleyicisi, bir `”newComment"` eylemi oluşturduktan sonra formun içeriğini temizlemek için `form.reset` çağrısında bulunur. -When creating moderately complex pieces of DOM, this style of programming starts to look rather messy. To avoid this, people often use a _((templating language))_, which allows you to write your interface as an HTML file with some special markers to indicate where dynamic elements go. Or they use _((JSX))_, a non-standard JavaScript dialect that allows you to write something very close to HTML tags in your program as if they are JavaScript expressions. Both of these approaches use additional tools to pre-process the code before it can be run, which we will avoid in this chapter. +Orta derecede karmaşık DOM parçaları oluştururken, bu programlama tarzı oldukça dağınık görünmeye başlar. Bundan kaçınmak için, insanlar genellikle dinamik öğelerin nereye gideceğini belirtmek için bazı özel işaretçilerle arayüzünüzü bir HTML dosyası olarak yazmanıza olanak tanıyan bir _((şablonlama dili))_ kullanırlar. Ya da programınızda HTML etiketlerine çok yakın bir şeyi JavaScript ifadeleriymiş gibi yazmanıza olanak tanıyan standart olmayan bir JavaScript lehçesi olan _((JSX))_ kullanırlar. Bu yaklaşımların her ikisi de kodu çalıştırmadan önce ön işleme tabi tutmak için ek araçlar kullanır ki bu bölümde bunlardan kaçınacağız. -Comments are simple to render. +Yorumların işlenmesi kolaydır. ```{includeCode: ">code/skillsharing/public/skillsharing_client.js", test: no} function renderComment(comment) { @@ -643,7 +670,7 @@ function renderComment(comment) { {{index "form (HTML tag)", "renderTalkForm function"}} -Finally, the form that the user can use to create a new talk is rendered like this: +Son olarak, kullanıcının yeni bir konuşma oluşturmak için kullanabileceği form şu şekilde oluşturulur: ```{includeCode: ">code/skillsharing/public/skillsharing_client.js", test: no} function renderTalkForm(dispatch) { @@ -668,7 +695,7 @@ function renderTalkForm(dispatch) { {{index "pollTalks function", "long polling", "If-None-Match header", "Prefer header", "fetch function"}} -To start the app we need the current list of talks. Since the initial load is closely related to the long polling process—the `ETag` from the load must be used when polling—we'll write a function that keeps polling the server for `/talks` and calls a ((callback function)) when a new set of talks is available. +Uygulamayı başlatmak için mevcut konuşma listesine ihtiyacımız var. İlk yükleme uzun yoklama süreciyle yakından ilgili olduğundan -yüklemedeki `ETag` yoklama sırasında kullanılmalıdır- sunucuyu `/talks` için yoklamaya devam eden ve yeni bir konuşma kümesi mevcut olduğunda bir ((geri arama işlevi)) çağıran bir işlev yazacağız. ```{includeCode: ">code/skillsharing/public/skillsharing_client.js", test: no} async function pollTalks(update) { @@ -694,21 +721,21 @@ async function pollTalks(update) { {{index "async function"}} -This is an `async` function so that looping and waiting for the request is easier. It runs an infinite loop that, on each iteration, retrieves the list of talks—either normally or, if this isn't the first request, with the headers included that make it a long polling request. +Bu bir `async` işlevidir, böylece döngü oluşturmak ve isteği beklemek daha kolay olur. Sonsuz bir döngü çalıştırır ve her yinelemede görüşmelerin listesini alır - ya normal olarak ya da bu ilk istek değilse, uzun bir yoklama isteği yapan başlıklarla birlikte. {{index "error handling", "Promise class", "setTimeout function"}} -When a request fails, the function waits a moment and then tries again. This way, if your network connection goes away for a while and then comes back, the application can recover and continue updating. The promise resolved via `setTimeout` is a way to force the `async` function to wait. +Bir istek başarısız olduğunda, işlev bir süre bekler ve ardından tekrar dener. Bu şekilde, ağ bağlantınız bir süreliğine gider ve sonra geri gelirse, uygulama iyileşebilir ve güncellemeye devam edebilir. `setTimeout` aracılığıyla çözümlenen söz, `async` işlevini beklemeye zorlamanın bir yoludur. {{index "304 (HTTP status code)", "ETag header"}} -When the server gives back a 304 response, that means a long polling request timed out, so the function should just immediately start the next request. If the response is a normal 200 response, its body is read as ((JSON)) and passed to the callback, and its `ETag` header value is stored for the next iteration. +Sunucu 304 yanıtı verdiğinde, bu uzun bir yoklama isteğinin zaman aşımına uğradığı anlamına gelir, bu nedenle işlev hemen bir sonraki isteği başlatmalıdır. Yanıt normal bir 200 yanıtı ise, gövdesi ((JSON)) olarak okunur ve geri aramaya aktarılır ve `ETag` başlık değeri bir sonraki yineleme için saklanır. -### The application +### Uygulama {{index "SkillShareApp class"}} -The following component ties the whole user interface together: +Aşağıdaki bileşen tüm kullanıcı arayüzünü birbirine bağlar: ```{includeCode: ">code/skillsharing/public/skillsharing_client.js", test: no} class SkillShareApp { @@ -737,9 +764,9 @@ class SkillShareApp { {{index synchronization, "live view"}} -When the talks change, this component redraws all of them. This is simple but also wasteful. We'll get back to that in the exercises. +Konuşmalar değiştiğinde, bu bileşen hepsini yeniden çizer. Bu basit ama aynı zamanda savurgan bir işlemdir. Bu konuya alıştırmalarda geri döneceğiz. -We can start the application like this: +Uygulamayı şu şekilde başlatabiliriz: ```{includeCode: ">code/skillsharing/public/skillsharing_client.js", test: no} function runApp() { @@ -764,54 +791,54 @@ function runApp() { runApp(); ``` -If you run the server and open two browser windows for [_http://localhost:8000_](http://localhost:8000/) next to each other, you can see that the actions you perform in one window are immediately visible in the other. +Sunucuyu çalıştırır ve [_http://localhost:8000_](http://localhost:8000/) için yan yana iki tarayıcı penceresi açarsanız, bir pencerede gerçekleştirdiğiniz eylemlerin diğerinde hemen görülebildiğini görebilirsiniz. -## Exercises +## Egzersizler {{index "Node.js", NPM}} -The following exercises will involve modifying the system defined in this chapter. To work on them, make sure you ((download)) the code first ([_https://eloquentjavascript.net/code/skillsharing.zip_](https://eloquentjavascript.net/code/skillsharing.zip)), have Node installed ([_https://nodejs.org_](https://nodejs.org)), and install the project's dependency with `npm install`. +Aşağıdaki alıştırmalar bu bölümde tanımlanan sistemi değiştirmeyi içerecektir. Bunlar üzerinde çalışmak için, önce kodu ((indirdiğinizden)) ([_https://eloquentjavascript.net/code/skillsharing.zip_](https://eloquentjavascript.net/code/skillsharing.zip)), Node'un kurulu olduğundan ([_https://nodejs.org_](https://nodejs.org)) ve projenin bağımlılığını `npm install` ile yüklediğinizden emin olun. -### Disk persistence +### Disk kalıcılığı {{index "data loss", persistence, [memory, persistence]}} -The skill-sharing server keeps its data purely in memory. This means that when it ((crash))es or is restarted for any reason, all talks and comments are lost. +Beceri paylaşım sunucusu verilerini tamamen bellekte tutar. Bu, herhangi bir nedenle ((çöktüğünde)) veya yeniden başlatıldığında, tüm konuşmaların ve yorumların kaybolacağı anlamına gelir. {{index "hard drive"}} -Extend the server so that it stores the talk data to disk and automatically reloads the data when it is restarted. Do not worry about efficiency—do the simplest thing that works. +Sunucuyu, konuşma verilerini diske depolayacak ve yeniden başlatıldığında verileri otomatik olarak yeniden yükleyecek şekilde genişletin. Verimlilik konusunda endişelenmeyin - işe yarayan en basit şeyi yapın. {{hint -{{index "file system", "writeFile function", "updated method", persistence}} +{{index "filesystem", "writeFile function", "updated method", persistence}} -The simplest solution I can come up with is to encode the whole `talks` object as ((JSON)) and dump it to a file with `writeFile`. There is already a method (`updated`) that is called every time the server's data changes. It can be extended to write the new data to disk. +Bulabildiğim en basit çözüm, tüm `talks` nesnesini ((JSON)) olarak kodlamak ve `writeFile` ile bir dosyaya dökmek. Sunucunun verileri her değiştiğinde çağrılan bir yöntem (`updated`) zaten var. Yeni verileri diske yazmak için genişletilebilir. {{index "readFile function", "JSON.parse function"}} -Pick a ((file))name, for example `./talks.json`. When the server starts, it can try to read that file with `readFile`, and if that succeeds, the server can use the file's contents as its starting data. +Bir ((dosya)) adı seçin, örneğin `./talks.json`. Sunucu başladığında, bu dosyayı `readFile` ile okumaya çalışabilir ve bu başarılı olursa, sunucu dosyanın içeriğini başlangıç verisi olarak kullanabilir. hint}} -### Comment field resets +### Yorum alanı sıfırlanması {{index "comment field reset (exercise)", template, [state, "of application"]}} -The wholesale redrawing of talks works pretty well because you usually can't tell the difference between a DOM node and its identical replacement. But there are exceptions. If you start typing something in the comment ((field)) for a talk in one browser window and then, in another, add a comment to that talk, the field in the first window will be redrawn, removing both its content and its ((focus)). +Görüşmelerin toptan yeniden çizilmesi oldukça iyi çalışır, çünkü genellikle bir DOM düğümü ile onun aynısı arasındaki farkı anlayamazsınız. Ancak istisnalar da vardır. Bir tarayıcı penceresinde bir konuşma için yorum ((alanına)) bir şeyler yazmaya başlarsanız ve ardından başka bir pencerede bu konuşmaya bir yorum eklerseniz, ilk penceredeki alan hem içeriği hem de ((odağı)) kaldırılarak yeniden çizilecektir. -When multiple people are adding comments at the same time, this would be annoying. Can you come up with a way to solve it? +Birden fazla kişinin aynı anda yorum eklediği hararetli bir tartışmada bu can sıkıcı olabilir. Bunu çözmek için bir yol bulabilir misiniz? {{hint {{index "comment field reset (exercise)", template, "syncState method"}} -The best way to do this is probably to make the talk component an object, with a `syncState` method, so that they can be updated to show a modified version of the talk. During normal operation, the only way a talk can be changed is by adding more comments, so the `syncState` method can be relatively simple. +Bunu yapmanın en iyi yolu muhtemelen konuşma bileşenini bir `syncState` metodu ile bir nesne haline getirmektir, böylece konuşmanın değiştirilmiş bir versiyonunu gösterecek şekilde güncellenebilirler. Normal çalışma sırasında, bir konuşmanın değiştirilebilmesinin tek yolu daha fazla yorum eklemektir, bu nedenle `syncState` yöntemi nispeten basit olabilir. -The difficult part is that, when a changed list of talks comes in, we have to reconcile the existing list of DOM components with the talks on the new list—deleting components whose talk was deleted and updating components whose talk changed. +İşin zor kısmı, değişen bir konuşma listesi geldiğinde, mevcut DOM bileşenleri listesini yeni listedeki konuşmalarla uzlaştırmak zorunda olmamızdır - konuşması silinen bileşenleri silmek ve konuşması değişen bileşenleri güncellemek. {{index synchronization, "live view"}} -To do this, it might be helpful to keep a data structure that stores the talk components under the talk titles so that you can easily figure out whether a component exists for a given talk. You can then loop over the new array of talks, and for each of them, either synchronize an existing component or create a new one. To delete components for deleted talks, you'll have to also loop over the components and check whether the corresponding talks still exist. +Bunu yapmak için, konuşma bileşenlerini konuşma başlıkları altında saklayan bir veri yapısı tutmak yararlı olabilir, böylece belirli bir konuşma için bir bileşenin mevcut olup olmadığını kolayca anlayabilirsiniz. Daha sonra yeni konuşma dizisi üzerinde döngü yapabilir ve her biri için mevcut bir bileşeni senkronize edebilir ya da yeni bir tane oluşturabilirsiniz. Silinen konuşmaların bileşenlerini silmek için, bileşenler üzerinde de döngü yapmanız ve ilgili konuşmaların hala var olup olmadığını kontrol etmeniz gerekir. hint}} diff --git a/README.md b/README.md index dfda9091..25409d27 100644 --- a/README.md +++ b/README.md @@ -51,3 +51,6 @@ to the same language (and possibly never finish it). (Since translations have to retain the license, it is okay to pick up someone else's translation and continue it, even when they have vanished from the internet.) + +I am not interested in machine translations. Please only ask me to +link your translation when it was done by actual people. diff --git a/code/animatevillage.js b/code/animatevillage.js index 0f8efc33..241d7921 100644 --- a/code/animatevillage.js +++ b/code/animatevillage.js @@ -33,12 +33,15 @@ this.node = outer.appendChild(doc.createElement("div")) this.node.style.cssText = "position: relative; line-height: 0.1; margin-left: 10px" this.map = this.node.appendChild(doc.createElement("img")) - this.map.src = "img/village2x.png" + let imgPath = "img/" + if (/\/code($|\/)/.test(outer.ownerDocument.defaultView.location)) imgPath = "../" + imgPath + console.log(outer.ownerDocument.defaultView.location.toString(), /\/code($|\/)/.test(outer.ownerDocument.defaultView.localation), imgPath) + this.map.src = imgPath + "village2x.png" this.map.style.cssText = "vertical-align: -8px" this.robotElt = this.node.appendChild(doc.createElement("div")) this.robotElt.style.cssText = `position: absolute; transition: left ${0.8 / speed}s, top ${0.8 / speed}s;` let robotPic = this.robotElt.appendChild(doc.createElement("img")) - robotPic.src = "img/robot_moving2x.gif" + robotPic.src = imgPath + "robot_moving2x.gif" this.parcels = [] this.text = this.node.appendChild(doc.createElement("span")) diff --git a/code/levels.js b/code/levels.js index 1695cc7d..cfe887b0 100644 --- a/code/levels.js +++ b/code/levels.js @@ -86,7 +86,7 @@ var GAME_LEVELS = [` ++++#.#++++++#.........#+++++#.....................##++++++##..+.....................#######...................... ++++#.#++++++#.........#+++++##.......##############++++++##...+.................................................. ++++#.#++++++#.........#++++++#########++++++++++++++++++##....+.................................................. -++++#.#++++++#.........#++++++++++++++++++++++++++++++++##.....++++++++++++....................................... +++++#.#++++++#.........#++++++++++++++++++++++++++++++++##.....+++++++++++++++++++++++++++++++++++++++++++++++++++ `,` .............................................................................................................. .............................................................................................................. diff --git a/code/solutions/06_3_iterable_groups.js b/code/solutions/06_3_iterable_groups.js index 0dfe8f62..557a35fb 100644 --- a/code/solutions/06_3_iterable_groups.js +++ b/code/solutions/06_3_iterable_groups.js @@ -29,6 +29,9 @@ class Group { } class GroupIterator { + #members; + #position; + constructor(members) { this.#members = members; this.#position = 0; diff --git a/code/solutions/09_1_regexp_golf.js b/code/solutions/09_1_regexp_golf.js index 702f3823..ad84ccd4 100644 --- a/code/solutions/09_1_regexp_golf.js +++ b/code/solutions/09_1_regexp_golf.js @@ -24,7 +24,7 @@ verify(/\p{L}{7}/u, ["Siebentausenddreihundertzweiundzwanzig"], ["no", "three small words"]); -verify(/(^|\P{L})[^\P{L}e]+($|\P{L})/i, +verify(/(^|\P{L})[^\P{L}e]+($|\P{L})/ui, ["red platypus", "wobbling nest"], ["earth bed", "bedrøvet abe", "BEET"]); diff --git a/code/solutions/10_2_roads_module.js b/code/solutions/10_2_roads_module.js index ec83e579..af405b79 100644 --- a/code/solutions/10_2_roads_module.js +++ b/code/solutions/10_2_roads_module.js @@ -1,4 +1,4 @@ -const {buildGraph} = require("./graph"); +import {buildGraph} from "./graph"; const roads = [ "Alice's House-Bob's House", "Alice's House-Cabin", @@ -10,4 +10,4 @@ const roads = [ "Marketplace-Town Hall", "Shop-Town Hall" ]; -exports.roadGraph = buildGraph(roads.map(r => r.split("-"))); +export const roadGraph = buildGraph(roads.map(r => r.split("-"))); diff --git a/epub/frontmatter.xhtml b/epub/frontmatter.xhtml index d9dfbec3..2e9f5331 100644 --- a/epub/frontmatter.xhtml +++ b/epub/frontmatter.xhtml @@ -23,8 +23,7 @@ Pixel art in Chapters 7 and 16 by Antonio Perdomo Pastor. Regular expression diagrams in Chapter 9 generated with <a href="https://regexper.com/">regexper.com</a> by Jeff - Avallone. Village photograph in Chapter 11 by Fabrice Creuzot. - Game concept for Chapter 16 + Avallone. Game concept for Chapter 16 by <a href="http://lessmilk.com">Thomas Palef</a>.</p> <p>A paper version of Eloquent JavaScript, including a bonus diff --git a/html/index.html b/html/index.html index f5ca4eb0..3fd142ca 100644 --- a/html/index.html +++ b/html/index.html @@ -22,107 +22,88 @@ <div id=cover> <p style="margin: 1em 0"> - <a href="https://nostarch.com/ejs3"> + <a href="https://nostarch.com/eloquent-javascript-4th-edition"> <img src="img/cover.jpg" alt="Cover image" style="border: 1px solid black; max-width: 100%; box-shadow: 4px 4px 7px rgba(0, 0, 0, 0.4)"> </a> </p> - <h1>Eloquent JavaScript<div style="font-size: 70%">4th edition (2024)</div></h2> + <h1>Eloquent JavaScript<div style="font-size: 70%">4. Baskı (2024)</div></h2> - <p>This is a book about JavaScript, programming, and the wonders of - the digital. You can read it online here, or buy your own - <a href="https://nostarch.com/ejs3">paperback copy</a> (3rd edition).</p> + <p>Bu kitap JavaScript, programlama ve JavaScript'in harikaları hakkında bir kitaptır. + dijital. Online olarak buradan okuyabilir veya kendi <a href="https://nostarch.com/eloquent-javascript-4th-edition"></a>kopyanızı</a> satın alabilirsiniz + paperback copy.</p> - <p>Written by Marijn Haverbeke.</p> + <p>Yazar, Marijn Haverbeke.</p> <div style="font-size: 80%"> - <p>Licensed under - a <a href="https://creativecommons.org/licenses/by-nc/3.0/">Creative - Commons attribution-noncommercial license</a>. All code in this book - may also be considered licensed under - an <a href="https://eloquentjavascript.net/code/LICENSE">MIT license</a>.</p> - - <p>Illustrations by various artists: Cover - by <a href="http://www.pechane.com/">Péchane Sumi-e</a>. Chapter - illustrations by <a href="http://madalinatantareanu.com/">Madalina - Tantareanu</a>. Pixel art in Chapters 7 and 16 by Antonio Perdomo - Pastor. Regular expression diagrams in Chapter 9 generated - with <a href="https://regexper.com">regexper.com</a> by Jeff - Avallone. Village photograph in Chapter 11 by Fabrice Creuzot. Game - concept for Chapter 16 by <a href="http://lessmilk.com">Thomas - Palef</a>.</p> + <p><a href="https://creativecommons.org/licenses/by-nc/3.0/">Creative Commons atıf-ticari olmayan lisansı</a> altında lisanslanmıştır. Bu kitaptaki tüm kodlar <a href="https://eloquentjavascript.net/code/LICENSE">MIT lisansı</a> altında lisanslanmış olarak da kabul edilebilir. + + <p>İllüstrasyonlar farklı sanatçılar tarafından yapılmıştır: Kapak <a href="http://www.pechane.com/">Péchane Sumi-e</a>. Bölüm illüstrasyonları <a href="http://madalinatantareanu.com/">Madalina Tantareanu</a>. Bölüm 7 ve 16'daki pixel sanat Antonio Perdomo Pastor. Bölüm 9'daki düzenli ifade diyagramları <a href="https://regexper.com">regexper.com</a> aracılığıyla Jeff Avallone tarafından oluşturuldu. Bölüm 16'daki oyun konsepti <a href="http://lessmilk.com">Thomas Palef</a>.</p> </div> </div> <div id=contents> - <h2>Contents</h2> + <h2>İçerik</h2> <ol class=toc> - <li class="contents-intro"><a href="00_intro.html">Introduction</a> + <li class="contents-intro"><a href="00_intro.html">Giriş</a> <li> - <h3>(Part 1: Language)</h3> - <a href="01_values.html">Values, Types, and Operators</a> + <h3>(Bölüm 1: Dil)</h3> + <a href="01_values.html">Değerler, Tipler, ve Operatörler</a> </li> - <li><a href="02_program_structure.html">Program Structure</a> - <li><a href="03_functions.html">Functions</a> - <li><a href="04_data.html">Data Structures: Objects and Arrays</a> - <li><a href="05_higher_order.html">Higher-order Functions</a> - <li><a href="06_object.html">The Secret Life of Objects</a> - <li><a href="07_robot.html">Project: A Robot</a> - <li><a href="08_error.html">Bugs and Errors</a> - <li><a href="09_regexp.html">Regular Expressions</a> - <li><a href="10_modules.html">Modules</a> - <li><a href="11_async.html">Asynchronous Programming</a> - <li><a href="12_language.html">Project: A Programming Language</a> + <li><a href="02_program_structure.html">Program Yapısı</a> + <li><a href="03_functions.html">Fonksiyonlar</a> + <li><a href="04_data.html">Data Yapıları: Nesneler ve Diziler</a> + <li><a href="05_higher_order.html">Yüksek Dereceli Fonksiyonlar</a> + <li><a href="06_object.html">Nesnelerin Gizli Yaşamı</a> + <li><a href="07_robot.html">Proje: Bir Robot</a> + <li><a href="08_error.html">Problemler ve Hatalar</a> + <li><a href="09_regexp.html">Düzenli İfadeler</a> + <li><a href="10_modules.html">Modüller</a> + <li><a href="11_async.html">Asenkron Programlama</a> + <li><a href="12_language.html">Proje: Bir Programlama Dili</a> <li> - <h3>(Part 2: Browser)</h3> - <a href="13_browser.html">JavaScript and the Browser</a> + <h3>(Bölüm 2: Tarayıcı)</h3> + <a href="13_browser.html">JavaScript ve Tarayıcı</a> </li> - <li><a href="14_dom.html">The Document Object Model</a> - <li><a href="15_event.html">Handling Events</a> - <li><a href="16_game.html">Project: A Platform Game</a> - <li><a href="17_canvas.html">Drawing on Canvas</a> - <li><a href="18_http.html">HTTP and Forms</a> - <li><a href="19_paint.html">Project: A Pixel Art Editor</a> + <li><a href="14_dom.html">Doküman Nesne Modeli</a> + <li><a href="15_event.html">Olayların Ele Alınması</a> + <li><a href="16_game.html">Proje Bir Platform Oyunu</a> + <li><a href="17_canvas.html">Tuval Üzerine Çizim</a> + <li><a href="18_http.html">HTTP ve Formlar</a> + <li><a href="19_paint.html">Proje Bir Piksel Sanat Editörü</a> <li> - <h3>(Part 3: Node)</h3> + <h3>(Bölüm 3: Node)</h3> <a href="20_node.html">Node.js</a> </li> - <li><a href="21_skillsharing.html">Project: Skill-Sharing Website</a> + <li><a href="21_skillsharing.html">Proje Beceri Paylaşım Sitesi</a> </ol> </div> <div id=links> - <p>A paper version of Eloquent JavaScript, including an additional - chapter, is being brought out - by <a href="http://www.nostarch.com/ejs3">No Starch Press</a>.</p> + <p>Eloquent JavaScript'in kağıt versiyonu, ek bir bölümü, <a href="https://nostarch.com/eloquent-javascript-4th-edition">No Starch Press</a> tarafından yayımlanıyor.</p> - <h2>Other pages</h2> + <h2>Diğer sayfalar</h2> <ul class="links"> - <li><a href="code">Code sandbox and exercise solutions</a></li> - <li><a href="errata.html">Errata for the paper book</a></li> - <li><a href="Eloquent_JavaScript.pdf">This book as a single PDF file</a> (& <a href="Eloquent_JavaScript_small.pdf">small version for mobile</a>)</li> - <li><a href="https://eloquentjavascript.net/Eloquent_JavaScript.epub">This book as an EPUB file</a></li> - <li><a href="https://eloquentjavascript.net/Eloquent_JavaScript.mobi">This book as a MOBI (Kindle) file</a></li> - <li><a href="https://eloquentjavascript.net/1st_edition">The first edition of the book</a></li> - <li><a href="https://eloquentjavascript.net/2nd_edition">The second edition of the book</a></li> - <li><a href="https://eloquentjavascript.net/3rd_edition">The third edition of the book</a></li> + <li><a href="https://eloquentjavascript.net/1st_edition">Kitabın ilk baskısı</a></li> + <li><a href="https://eloquentjavascript.net/2nd_edition">Kitabın ikinci baskısı</a></li> + <li><a href="https://eloquentjavascript.net/3rd_edition">Kitabın üçüncü baskısı</a></li> </ul> - <h2>Translations</h2> + <h2>Çeviriler</h2> - <h3>Fourth Edition</h3> + <h3>Dördüncü Baskı</h3> <ul class=translations> <li><a href="https://eloquent-javascript-es.vercel.app/">Español (Spanish)</a></li> </ul> - <h3>Third Edition</h3> + <h3>Üçüncü Baskı</h3> <ul class=translations> <li><a href="https://academy.hsoub.com/files/27-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D8%A8%D8%AA/">عَرَبِيّ (Arabic)</a></li> @@ -130,7 +111,7 @@ <h3>Third Edition</h3> <li><a href="https://eloquentjs-es.thedojo.mx/">Español (Spanish, partial)</a></li> </ul> - <h3>Second Edition</h3> + <h3>İkinci Baskı</h3> <ul class=translations> <li><a href="https://rabahboudia.gitbooks.io/arabic-eloquent-js/content/index.html">عَرَبِيّ‎ (Arabic)</a></li> diff --git a/img/controlflow-else.svg b/img/controlflow-else.svg deleted file mode 100644 index 4faaf6b1..00000000 --- a/img/controlflow-else.svg +++ /dev/null @@ -1,175 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> - -<svg - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="108.821" - height="206.31459" - id="svg2" - version="1.1" - inkscape:version="0.48.4 r9939" - sodipodi:docname="controlflow.svg"> - <defs - id="defs4"> - <marker - inkscape:stockid="Arrow1Send" - orient="auto" - refY="0" - refX="0" - id="Arrow1Send" - style="overflow:visible"> - <path - id="path3774" - d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" - style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" - transform="matrix(-0.2,0,0,-0.2,-1.2,0)" - inkscape:connector-curvature="0" /> - </marker> - <marker - inkscape:stockid="Arrow2Mend" - orient="auto" - refY="0" - refX="0" - id="Arrow2Mend" - style="overflow:visible"> - <path - id="path3786" - style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" - d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" - transform="scale(-0.6,-0.6)" - inkscape:connector-curvature="0" /> - </marker> - <marker - inkscape:stockid="Arrow1Mend" - orient="auto" - refY="0" - refX="0" - id="Arrow1Mend" - style="overflow:visible"> - <path - id="path3768" - d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" - style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" - transform="matrix(-0.4,0,0,-0.4,-4,0)" - inkscape:connector-curvature="0" /> - </marker> - <marker - inkscape:stockid="Arrow1Lend" - orient="auto" - refY="0" - refX="0" - id="Arrow1Lend" - style="overflow:visible"> - <path - id="path3762" - d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" - style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" - transform="matrix(-0.8,0,0,-0.8,-10,0)" - inkscape:connector-curvature="0" /> - </marker> - </defs> - <sodipodi:namedview - id="base" - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1.0" - inkscape:pageopacity="0.0" - inkscape:pageshadow="2" - inkscape:zoom="2.8" - inkscape:cx="133.86544" - inkscape:cy="94.103041" - inkscape:document-units="px" - inkscape:current-layer="layer1" - showgrid="false" - showguides="true" - inkscape:guide-bbox="true" - inkscape:window-width="1600" - inkscape:window-height="875" - inkscape:window-x="0" - inkscape:window-y="25" - inkscape:window-maximized="0" - fit-margin-top="0" - fit-margin-left="0" - fit-margin-right="0" - fit-margin-bottom="0" /> - <metadata - id="metadata7"> - <rdf:RDF> - <cc:Work - rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - <dc:title></dc:title> - </cc:Work> - </rdf:RDF> - </metadata> - <g - inkscape:label="Layer 1" - inkscape:groupmode="layer" - id="layer1" - transform="translate(-271.44205,-341.2554)"> - <path - sodipodi:nodetypes="cc" - inkscape:connector-curvature="0" - id="path4943" - d="m 313.14729,345.2554 1.01015,27.77919" - style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" /> - <path - sodipodi:nodetypes="cc" - inkscape:connector-curvature="0" - id="path5139" - d="m 322.65709,393.3243 c 43.57143,2.14286 44.46591,36.60008 47.42819,47.39307" - style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" /> - <path - style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" - d="m 315.16759,500.8189 1.01015,35.35534" - id="path5141" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cc" /> - <path - style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" - d="m 306.63306,397.25287 c 0,0 -66.25164,35.8858 -5.64249,93.4645" - id="path5159" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cc" /> - <path - sodipodi:type="arc" - style="fill:#ff0000;fill-opacity:1;stroke:none" - id="path3001" - sodipodi:cx="74.246208" - sodipodi:cy="50.755318" - sodipodi:rx="6.060915" - sodipodi:ry="6.060915" - d="m 80.307123,50.755318 c 0,3.347351 -2.713564,6.060915 -6.060915,6.060915 -3.347351,0 -6.060915,-2.713564 -6.060915,-6.060915 0,-3.347351 2.713564,-6.060915 6.060915,-6.060915 3.347351,0 6.060915,2.713564 6.060915,6.060915 z" - transform="translate(239.95593,341.76048)" /> - <path - transform="translate(299.95593,410.33191)" - d="m 80.307123,50.755318 c 0,3.347351 -2.713564,6.060915 -6.060915,6.060915 -3.347351,0 -6.060915,-2.713564 -6.060915,-6.060915 0,-3.347351 2.713564,-6.060915 6.060915,-6.060915 3.347351,0 6.060915,2.713564 6.060915,6.060915 z" - sodipodi:ry="6.060915" - sodipodi:rx="6.060915" - sodipodi:cy="50.755318" - sodipodi:cx="74.246208" - id="path3002" - style="fill:#ff0000;fill-opacity:1;stroke:none" - sodipodi:type="arc" /> - <path - style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" - d="m 365.87137,460.11002 c -16.78571,-0.35714 -26.85751,1.32164 -41.50037,27.75021" - id="path3004" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cc" /> - <path - sodipodi:nodetypes="cc" - inkscape:connector-curvature="0" - id="path3006" - d="m 371.58566,469.39573 c -3.92858,25 -28.64323,27.39307 -37.21466,29.53593" - style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" /> - </g> -</svg> diff --git a/img/controlflow-if.svg b/img/controlflow-if.svg index 618e410e..a0f793a4 100644 --- a/img/controlflow-if.svg +++ b/img/controlflow-if.svg @@ -1,155 +1,16 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> - -<svg - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="205.10103" - height="85.750778" - id="svg3283" - version="1.1" - inkscape:version="0.48.4 r9939" - sodipodi:docname="New document 11"> - <defs - id="defs3285"> - <marker - inkscape:stockid="Arrow1Send" - orient="auto" - refY="0" - refX="0" - id="Arrow1Send" - style="overflow:visible"> - <path - id="path3774" - d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" - style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" - transform="matrix(-0.2,0,0,-0.2,-1.2,0)" - inkscape:connector-curvature="0" /> - </marker> - <marker - inkscape:stockid="Arrow1Send" - orient="auto" - refY="0" - refX="0" - id="marker3266" - style="overflow:visible"> - <path - id="path3268" - d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" - style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" - transform="matrix(-0.2,0,0,-0.2,-1.2,0)" - inkscape:connector-curvature="0" /> - </marker> - <marker - inkscape:stockid="Arrow1Send" - orient="auto" - refY="0" - refX="0" - id="marker3270" - style="overflow:visible"> - <path - id="path3272" - d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" - style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" - transform="matrix(-0.2,0,0,-0.2,-1.2,0)" - inkscape:connector-curvature="0" /> - </marker> - <marker - inkscape:stockid="Arrow1Send" - orient="auto" - refY="0" - refX="0" - id="marker3274" - style="overflow:visible"> - <path - id="path3276" - d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" - style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" - transform="matrix(-0.2,0,0,-0.2,-1.2,0)" - inkscape:connector-curvature="0" /> - </marker> - </defs> - <sodipodi:namedview - id="base" - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1.0" - inkscape:pageopacity="0.0" - inkscape:pageshadow="2" - inkscape:zoom="0.35" - inkscape:cx="1288.581" - inkscape:cy="-271.41478" - inkscape:document-units="px" - inkscape:current-layer="layer1" - showgrid="false" - fit-margin-top="0" - fit-margin-left="0" - fit-margin-right="0" - fit-margin-bottom="0" - inkscape:window-width="1600" - inkscape:window-height="875" - inkscape:window-x="0" - inkscape:window-y="25" - inkscape:window-maximized="0" /> - <metadata - id="metadata3288"> - <rdf:RDF> - <cc:Work - rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - <dc:title></dc:title> - </cc:Work> - </rdf:RDF> - </metadata> - <g - inkscape:label="Layer 1" - inkscape:groupmode="layer" - id="layer1" - transform="translate(913.58095,-175.19662)"> - <g - id="g3322" - transform="matrix(0,-1,1,0,-1032.3622,-596.20924)"> - <path - style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" - d="m -815.78349,118.91917 1.01015,27.77919" - id="path4943" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cc" /> - <path - style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" - d="m -807.70227,168.41664 c 0,0 67.6802,38.3858 7.07106,95.9645" - id="path5139" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cc" /> - <path - sodipodi:nodetypes="cc" - inkscape:connector-curvature="0" - id="path5141" - d="m -813.76319,274.48267 1.01015,35.35534" - style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" /> - <path - sodipodi:nodetypes="cc" - inkscape:connector-curvature="0" - id="path5159" - d="m -820.86915,168.41664 c 0,0 -67.68021,38.3858 -7.07106,95.9645" - style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" /> - <path - transform="translate(-888.97485,115.42425)" - d="m 80.307123,50.755318 c 0,3.347351 -2.713564,6.060915 -6.060915,6.060915 -3.347351,0 -6.060915,-2.713564 -6.060915,-6.060915 0,-3.347351 2.713564,-6.060915 6.060915,-6.060915 3.347351,0 6.060915,2.713564 6.060915,6.060915 z" - sodipodi:ry="6.060915" - sodipodi:rx="6.060915" - sodipodi:cy="50.755318" - sodipodi:cx="74.246208" - id="path3001" - style="fill:#ff0000;fill-opacity:1;stroke:none" - sodipodi:type="arc" /> - </g> - </g> -</svg> +<svg xmlns="http://www.w3.org/2000/svg" width="205.101" height="85.751"> + <defs> + <marker id="a" orient="auto" overflow="visible" refX="0" refY="0"> + <path fill-rule="evenodd" stroke="#000" stroke-width=".2pt" d="m-1.2 0-1 1 3.5-1-3.5-1 1 1z" /> + </marker> + </defs> + <path fill="none" stroke="#000" stroke-width="8" marker-end="url(#a)" d="m-815.783 118.92 1.01 27.778" + transform="rotate(-90 -445.094 -326.312)" /> + <path fill="none" stroke="#000" stroke-width="8" marker-end="url(#a)" d="M-807.702 168.417s67.68 38.385 7.07 95.964" + transform="rotate(-90 -445.094 -326.312)" /> + <path fill="none" stroke="#000" stroke-width="8" marker-end="url(#a)" d="m-813.763 274.483 1.01 35.355" + transform="rotate(-90 -445.094 -326.312)" /> + <path fill="none" stroke="#000" stroke-width="8" marker-end="url(#a)" d="M-820.87 168.417s-67.68 38.385-7.07 95.964" + transform="rotate(-90 -445.094 -326.312)" /> + <path fill="red" d="M47.398 37.262a6.06 6.06 0 1 1 0 12.122 6.06 6.06 0 0 1 0-12.122z" /> +</svg> \ No newline at end of file diff --git a/img/controlflow-loop.svg b/img/controlflow-loop.svg index b4ffe3f2..290b771a 100644 --- a/img/controlflow-loop.svg +++ b/img/controlflow-loop.svg @@ -1,147 +1,15 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> - -<svg - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="206.31815" - height="72.428215" - id="svg2" - version="1.1" - inkscape:version="0.48.4 r9939" - sodipodi:docname="controlflow-loop.svg"> - <defs - id="defs4"> - <marker - inkscape:stockid="Arrow1Send" - orient="auto" - refY="0" - refX="0" - id="Arrow1Send" - style="overflow:visible"> - <path - id="path3774" - d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" - style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" - transform="matrix(-0.2,0,0,-0.2,-1.2,0)" - inkscape:connector-curvature="0" /> - </marker> - <marker - inkscape:stockid="Arrow2Mend" - orient="auto" - refY="0" - refX="0" - id="Arrow2Mend" - style="overflow:visible"> - <path - id="path3786" - style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" - d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" - transform="scale(-0.6,-0.6)" - inkscape:connector-curvature="0" /> - </marker> - <marker - inkscape:stockid="Arrow1Mend" - orient="auto" - refY="0" - refX="0" - id="Arrow1Mend" - style="overflow:visible"> - <path - id="path3768" - d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" - style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" - transform="matrix(-0.4,0,0,-0.4,-4,0)" - inkscape:connector-curvature="0" /> - </marker> - <marker - inkscape:stockid="Arrow1Lend" - orient="auto" - refY="0" - refX="0" - id="Arrow1Lend" - style="overflow:visible"> - <path - id="path3762" - d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" - style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" - transform="matrix(-0.8,0,0,-0.8,-10,0)" - inkscape:connector-curvature="0" /> - </marker> - </defs> - <sodipodi:namedview - id="base" - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1.0" - inkscape:pageopacity="0.0" - inkscape:pageshadow="2" - inkscape:zoom="2.8" - inkscape:cx="30.225462" - inkscape:cy="52.400366" - inkscape:document-units="px" - inkscape:current-layer="layer1" - showgrid="false" - showguides="true" - inkscape:guide-bbox="true" - inkscape:window-width="1600" - inkscape:window-height="875" - inkscape:window-x="0" - inkscape:window-y="25" - inkscape:window-maximized="0" - fit-margin-top="0" - fit-margin-left="0" - fit-margin-right="0" - fit-margin-bottom="0" /> - <metadata - id="metadata7"> - <rdf:RDF> - <cc:Work - rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - <dc:title /> - </cc:Work> - </rdf:RDF> - </metadata> - <g - inkscape:label="Layer 1" - inkscape:groupmode="layer" - id="layer1" - transform="translate(-376.5106,-433.43911)"> - <path - sodipodi:nodetypes="csc" - inkscape:connector-curvature="0" - id="path5161" - d="m 478.22234,451.00514 c 29.28572,23.75 27.61731,51.59627 -8.71166,51.57646 -36.44966,-0.0199 -18.10635,-25.27225 -9.3957,-39.5054" - style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" /> - <path - style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" - d="m 379.43917,445.98075 73.1512,-1.01015" - id="path3003" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cc" /> - <path - sodipodi:nodetypes="cc" - inkscape:connector-curvature="0" - id="path3005" - d="m 482.59676,443.96045 87.76125,-1.01015" - style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" /> - <path - transform="matrix(0,-1,1,0,422.09693,518.66704)" - d="m 80.307123,50.755318 c 0,3.347351 -2.713564,6.060915 -6.060915,6.060915 -3.347351,0 -6.060915,-2.713564 -6.060915,-6.060915 0,-3.347351 2.713564,-6.060915 6.060915,-6.060915 3.347351,0 6.060915,2.713564 6.060915,6.060915 z" - sodipodi:ry="6.060915" - sodipodi:rx="6.060915" - sodipodi:cy="50.755318" - sodipodi:cx="74.246208" - id="path3004" - style="fill:#ff0000;fill-opacity:1;stroke:none" - sodipodi:type="arc" /> - </g> -</svg> +<svg xmlns="http://www.w3.org/2000/svg" width="206.318" height="72.428"> + <defs> + <marker id="a" orient="auto" overflow="visible" refX="0" refY="0"> + <path fill-rule="evenodd" stroke="#000" stroke-width=".2pt" d="m-1.2 0-1 1 3.5-1-3.5-1 1 1z" /> + </marker> + </defs> + <path fill="none" stroke="#000" stroke-width="8" marker-end="url(#a)" + d="M478.222 451.005c29.286 23.75 27.618 51.596-8.711 51.577-36.45-.02-18.107-25.273-9.396-39.506" + transform="translate(-376.51 -433.44)" /> + <path fill="none" stroke="#000" stroke-width="8" marker-end="url(#a)" d="m379.44 445.98 73.15-1.01" + transform="translate(-376.51 -433.44)" /> + <path fill="none" stroke="#000" stroke-width="8" marker-end="url(#a)" d="m482.597 443.96 87.761-1.01" + transform="translate(-376.51 -433.44)" /> + <path fill="red" d="M96.342 4.92a6.06 6.06 0 1 1 0 12.123 6.06 6.06 0 0 1 0-12.122z" /> +</svg> \ No newline at end of file diff --git a/img/controlflow-nested-if.svg b/img/controlflow-nested-if.svg index f920ba22..9ab41a8a 100644 --- a/img/controlflow-nested-if.svg +++ b/img/controlflow-nested-if.svg @@ -1,175 +1,21 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> - -<svg - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="238.24316" - height="104.35892" - id="svg2" - version="1.1" - inkscape:version="0.48.4 r9939" - sodipodi:docname="controlflow-nested-else.svg"> - <defs - id="defs4"> - <marker - inkscape:stockid="Arrow1Send" - orient="auto" - refY="0" - refX="0" - id="Arrow1Send" - style="overflow:visible"> - <path - id="path3774" - d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" - style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" - transform="matrix(-0.2,0,0,-0.2,-1.2,0)" - inkscape:connector-curvature="0" /> - </marker> - <marker - inkscape:stockid="Arrow2Mend" - orient="auto" - refY="0" - refX="0" - id="Arrow2Mend" - style="overflow:visible"> - <path - id="path3786" - style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" - d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" - transform="scale(-0.6,-0.6)" - inkscape:connector-curvature="0" /> - </marker> - <marker - inkscape:stockid="Arrow1Mend" - orient="auto" - refY="0" - refX="0" - id="Arrow1Mend" - style="overflow:visible"> - <path - id="path3768" - d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" - style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" - transform="matrix(-0.4,0,0,-0.4,-4,0)" - inkscape:connector-curvature="0" /> - </marker> - <marker - inkscape:stockid="Arrow1Lend" - orient="auto" - refY="0" - refX="0" - id="Arrow1Lend" - style="overflow:visible"> - <path - id="path3762" - d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" - style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" - transform="matrix(-0.8,0,0,-0.8,-10,0)" - inkscape:connector-curvature="0" /> - </marker> - </defs> - <sodipodi:namedview - id="base" - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1.0" - inkscape:pageopacity="0.0" - inkscape:pageshadow="2" - inkscape:zoom="2.8" - inkscape:cx="182.61224" - inkscape:cy="45.356254" - inkscape:document-units="px" - inkscape:current-layer="layer1" - showgrid="false" - showguides="true" - inkscape:guide-bbox="true" - inkscape:window-width="1600" - inkscape:window-height="875" - inkscape:window-x="0" - inkscape:window-y="25" - inkscape:window-maximized="0" - fit-margin-top="0" - fit-margin-left="0" - fit-margin-right="3" - fit-margin-bottom="0" /> - <metadata - id="metadata7"> - <rdf:RDF> - <cc:Work - rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - <dc:title></dc:title> - </cc:Work> - </rdf:RDF> - </metadata> - <g - inkscape:label="Layer 1" - inkscape:groupmode="layer" - id="layer1" - transform="translate(-222.69525,-394.46429)"> - <path - sodipodi:nodetypes="cc" - inkscape:connector-curvature="0" - id="path4943" - d="m 226.69525,431.70744 27.77919,1.01015" - style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" /> - <path - sodipodi:nodetypes="cc" - inkscape:connector-curvature="0" - id="path5139" - d="m 274.76415,441.21724 c 2.14286,43.57143 36.60008,44.46591 47.39307,47.42819" - style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" /> - <path - style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" - d="m 411.18732,433.72774 35.35534,1.01015" - id="path5141" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cc" /> - <path - style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" - d="m 278.69272,425.19321 c 0,0 60.8858,-56.96593 122.75021,-4.57106" - id="path5159" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cc" /> - <path - sodipodi:type="arc" - style="fill:#ff0000;fill-opacity:1;stroke:none" - id="path3001" - sodipodi:cx="74.246208" - sodipodi:cy="50.755318" - sodipodi:rx="6.060915" - sodipodi:ry="6.060915" - d="m 80.307123,50.755318 a 6.060915,6.060915 0 1 1 -12.12183,0 6.060915,6.060915 0 1 1 12.12183,0 z" - transform="matrix(0,1,1,0,223.20033,358.51608)" /> - <path - transform="matrix(0,1,1,0,291.77176,418.51608)" - d="m 80.307123,50.755318 a 6.060915,6.060915 0 1 1 -12.12183,0 6.060915,6.060915 0 1 1 12.12183,0 z" - sodipodi:ry="6.060915" - sodipodi:rx="6.060915" - sodipodi:cy="50.755318" - sodipodi:cx="74.246208" - id="path3002" - style="fill:#ff0000;fill-opacity:1;stroke:none" - sodipodi:type="arc" /> - <path - style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" - d="m 341.54987,484.43152 c 0,0 0.96327,-38.82118 55.9645,-46.85751" - id="path3004" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cc" /> - <path - sodipodi:nodetypes="cc" - inkscape:connector-curvature="0" - id="path3006" - d="m 350.83558,490.14581 c 24.92879,-3.90484 44.71588,-30.84607 52.03593,-41.14323" - style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" /> - </g> -</svg> +<svg xmlns="http://www.w3.org/2000/svg" width="238.243" height="104.359"> + <defs> + <marker id="a" orient="auto" overflow="visible" refX="0" refY="0"> + <path fill-rule="evenodd" stroke="#000" stroke-width=".2pt" d="m-1.2 0-1 1 3.5-1-3.5-1 1 1z" /> + </marker> + </defs> + <path fill="none" stroke="#000" stroke-width="8" marker-end="url(#a)" d="m226.695 431.707 27.78 1.01" + transform="translate(-222.695 -394.464)" /> + <path fill="none" stroke="#000" stroke-width="8" marker-end="url(#a)" + d="M274.764 441.217c2.143 43.572 36.6 44.466 47.393 47.428" transform="translate(-222.695 -394.464)" /> + <path fill="none" stroke="#000" stroke-width="8" marker-end="url(#a)" d="m411.187 433.728 35.356 1.01" + transform="translate(-222.695 -394.464)" /> + <path fill="none" stroke="#000" stroke-width="8" marker-end="url(#a)" d="M278.693 425.193s60.886-56.966 122.75-4.57" + transform="translate(-222.695 -394.464)" /> + <path fill="red" + d="M51.26 44.359a6.06 6.06 0 1 1 0-12.122 6.06 6.06 0 1 1 0 12.122zM119.832 104.359a6.06 6.06 0 1 1 0-12.122 6.06 6.06 0 1 1 0 12.122z" /> + <path fill="none" stroke="#000" stroke-width="8" marker-end="url(#a)" d="M341.55 484.432s.963-38.822 55.964-46.858" + transform="translate(-222.695 -394.464)" /> + <path fill="none" stroke="#000" stroke-width="8" marker-end="url(#a)" + d="M350.836 490.146c24.928-3.905 44.715-30.846 52.036-41.143" transform="translate(-222.695 -394.464)" /> +</svg> \ No newline at end of file diff --git a/img/controlflow-straight.svg b/img/controlflow-straight.svg index 82fe554d..f94d671e 100644 --- a/img/controlflow-straight.svg +++ b/img/controlflow-straight.svg @@ -1,81 +1,9 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> - -<svg - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="204.48096" - height="19.999929" - id="svg3216" - version="1.1" - inkscape:version="0.48.4 r9939" - sodipodi:docname="New document 8"> - <defs - id="defs3218"> - <marker - inkscape:stockid="Arrow1Send" - orient="auto" - refY="0" - refX="0" - id="Arrow1Send" - style="overflow:visible"> - <path - id="path3774" - d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" - style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" - transform="matrix(-0.2,0,0,-0.2,-1.2,0)" - inkscape:connector-curvature="0" /> - </marker> - </defs> - <sodipodi:namedview - id="base" - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1.0" - inkscape:pageopacity="0.0" - inkscape:pageshadow="2" - inkscape:zoom="0.35" - inkscape:cx="156.78125" - inkscape:cy="-138.56231" - inkscape:document-units="px" - inkscape:current-layer="layer1" - showgrid="false" - fit-margin-top="0" - fit-margin-left="0" - fit-margin-right="0" - fit-margin-bottom="0" - inkscape:window-width="1600" - inkscape:window-height="875" - inkscape:window-x="0" - inkscape:window-y="25" - inkscape:window-maximized="0" /> - <metadata - id="metadata3221"> - <rdf:RDF> - <cc:Work - rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - <dc:title></dc:title> - </cc:Work> - </rdf:RDF> - </metadata> - <g - inkscape:label="Layer 1" - inkscape:groupmode="layer" - id="layer1" - transform="translate(-218.21875,-373.79994)"> - <path - style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)" - d="m 218.236,384.24914 190.41375,0" - id="path5135" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cc" /> - </g> -</svg> +<svg xmlns="http://www.w3.org/2000/svg" width="204.481" height="20"> + <defs> + <marker id="a" orient="auto" overflow="visible" refX="0" refY="0"> + <path fill-rule="evenodd" stroke="#000" stroke-width=".2pt" d="m-1.2 0-1 1 3.5-1-3.5-1 1 1z" /> + </marker> + </defs> + <path fill="none" stroke="#000" stroke-width="8" marker-end="url(#a)" d="M218.236 384.25H408.65" + transform="translate(-218.219 -373.8)" /> +</svg> \ No newline at end of file diff --git a/img/cover.jpg b/img/cover.jpg index a24f31a8..36ac9e85 100644 Binary files a/img/cover.jpg and b/img/cover.jpg differ diff --git a/pdf/book.tex b/pdf/book.tex index 673224e9..517b55cd 100644 --- a/pdf/book.tex +++ b/pdf/book.tex @@ -101,9 +101,8 @@ Péchane Sumi-e. Chapter illustrations by Madalina Tantareanu. Pixel art in Chapters 7 and 16 by Antonio Perdomo Pastor. Regular expression diagrams in Chapter 9 generated with - \href{http://regexper.com}{regexper.com} by Jeff Avallone. Village - photograph in Chapter 11 by Fabrice Creuzot. Game concept for - Chapter 16 by \href{http://lessmilk.com}{Thomas Palef}. + \href{http://regexper.com}{regexper.com} by Jeff Avallone. Game + concept for Chapter 16 by \href{http://lessmilk.com}{Thomas Palef}. \vskip 1em diff --git a/src/client/ejs.mjs b/src/client/ejs.mjs index 04220539..f7750256 100644 --- a/src/client/ejs.mjs +++ b/src/client/ejs.mjs @@ -31,7 +31,7 @@ function chapterInteraction() { let popup = document.body.appendChild(document.createElement("div")) popup.className = "popup" popup.appendChild(document.createElement("h2")).textContent = "Instructions" - popup.appendChild(document.createElement("p")).textContent = `Code on this page can be edited and run by clicking it or moving focus to it and pressing Enter. Code executed this way shares its environment with other code ran on the page, and some pre-defined code for the chapter. When inside the code editor, the following keyboard shortcuts are available.` + popup.appendChild(document.createElement("p")).textContent = `Code snippets on this page can be edited and run by clicking them or moving focus to them and pressing Enter. Executed snippets share their environment with other snippets ran on the page, and some pre-defined code for the chapter. When inside the code editor, the following keyboard shortcuts are available:` for (let [key, desc] of [ [modName + "Enter", "Run code"], [modName + "j", "Revert code"],