From 764d53851c1b0dbb93f61280cb12a03f0cc5a092 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96=2E=20F=2E=20K=C3=BCc=C3=BCk=20-=20Polyca=20Games?= <85259815+polycaman@users.noreply.github.com> Date: Sat, 18 Oct 2025 01:12:04 +0000 Subject: [PATCH 1/3] Translated most parts --- .../01-proxy/01-error-nonexisting/solution.md | 4 +- .../01-proxy/01-error-nonexisting/task.md | 15 +- .../01-proxy/02-array-negative/solution.md | 4 +- .../01-proxy/02-array-negative/task.md | 22 +- .../01-proxy/03-observable/solution.md | 18 +- .../99-js-misc/01-proxy/03-observable/task.md | 17 +- 1-js/99-js-misc/01-proxy/article.md | 225 +++++++++--------- 7 files changed, 154 insertions(+), 151 deletions(-) diff --git a/1-js/99-js-misc/01-proxy/01-error-nonexisting/solution.md b/1-js/99-js-misc/01-proxy/01-error-nonexisting/solution.md index 099664a1d..70e6c8c57 100644 --- a/1-js/99-js-misc/01-proxy/01-error-nonexisting/solution.md +++ b/1-js/99-js-misc/01-proxy/01-error-nonexisting/solution.md @@ -10,7 +10,7 @@ function wrap(target) { if (prop in target) { return Reflect.get(target, prop, receiver); } else { - throw new ReferenceError(`Property doesn't exist: "${prop}"`) + throw new ReferenceError(`Özellik yok: "${prop}"`) } } }); @@ -19,5 +19,5 @@ function wrap(target) { user = wrap(user); alert(user.name); // John -alert(user.age); // Error: Property doesn't exist +alert(user.age); // Hata: Özellik yok ``` diff --git a/1-js/99-js-misc/01-proxy/01-error-nonexisting/task.md b/1-js/99-js-misc/01-proxy/01-error-nonexisting/task.md index 0b8b35720..4871bd130 100644 --- a/1-js/99-js-misc/01-proxy/01-error-nonexisting/task.md +++ b/1-js/99-js-misc/01-proxy/01-error-nonexisting/task.md @@ -1,13 +1,12 @@ -# Error on reading non-existant property +# Mevcut olmayan özelliği okuma hatası -Create a proxy that throws an error for an attempt to read of a non-existant property. +Mevcut olmayan bir özelliği okumaya çalışıldığında hata fırlatan bir proxy oluşturun. -That can help to detect programming mistakes early. +Bu, programlama hatalarını erken tespit etmeye yardımcı olabilir. -Write a function `wrap(target)` that takes an object `target` and return a proxy instead with that functionality. - -That's how it should work: +Bir nesne `target` alan ve bu işlevselliğe sahip bir proxy döndüren `wrap(target)` fonksiyonunu yazın. +Şöyle çalışmalı: ```js let user = { @@ -17,7 +16,7 @@ let user = { function wrap(target) { return new Proxy(target, { *!* - /* your code */ + /* kodunuz */ */!* }); } @@ -26,6 +25,6 @@ user = wrap(user); alert(user.name); // John *!* -alert(user.age); // Error: Property doesn't exist +alert(user.age); // Hata: Özellik yok */!* ``` diff --git a/1-js/99-js-misc/01-proxy/02-array-negative/solution.md b/1-js/99-js-misc/01-proxy/02-array-negative/solution.md index 207205501..8bd4c7229 100644 --- a/1-js/99-js-misc/01-proxy/02-array-negative/solution.md +++ b/1-js/99-js-misc/01-proxy/02-array-negative/solution.md @@ -5,8 +5,8 @@ let array = [1, 2, 3]; array = new Proxy(array, { get(target, prop, receiver) { if (prop < 0) { - // even if we access it like arr[1] - // prop is a string, so need to convert it to number + // buna arr[1] gibi erişsek bile + // prop bir yazıdır(string), o zaman onu bir numaraya(number) çevirmeliyiz prop = +prop + target.length; } return Reflect.get(target, prop, receiver); diff --git a/1-js/99-js-misc/01-proxy/02-array-negative/task.md b/1-js/99-js-misc/01-proxy/02-array-negative/task.md index 6663b6f59..a7aa6e7e7 100644 --- a/1-js/99-js-misc/01-proxy/02-array-negative/task.md +++ b/1-js/99-js-misc/01-proxy/02-array-negative/task.md @@ -1,33 +1,33 @@ -# Accessing array[-1] +# array[-1]'e Erişmek -In some languages, we can access array elements using negative indexes, counted from the end. +Bazı dillerde, dizi elemanlarına sondan sayılarak negatif indekslerle erişebiliriz. -Like this: +Şöyle: ```js let array = [1, 2, 3]; -array[-1]; // 3, the last element -array[-2]; // 2, one step from the end -array[-3]; // 1, two steps from the end +array[-1]; // 3, son eleman +array[-2]; // 2, sondan bir önceki eleman +array[-3]; // 1, sondan iki önceki eleman ``` -In other words, `array[-N]` is the same as `array[array.length - N]`. +Başka bir deyişle, `array[-N]` ifadesi `array[array.length - N]` ile aynıdır. -Create a proxy to implement that behavior. +Bu davranışı uygulamak için bir proxy oluşturun. -That's how it should work: +Şöyle çalışmalı: ```js let array = [1, 2, 3]; array = new Proxy(array, { - /* your code */ + /* kodunuz */ }); alert( array[-1] ); // 3 alert( array[-2] ); // 2 -// Other array functionality should be kept "as is" +// Geri kalan dizi(array) özelliği "olduğu gibi" kalmalıdır ``` diff --git a/1-js/99-js-misc/01-proxy/03-observable/solution.md b/1-js/99-js-misc/01-proxy/03-observable/solution.md index dcb4f2a79..7a8d06afd 100644 --- a/1-js/99-js-misc/01-proxy/03-observable/solution.md +++ b/1-js/99-js-misc/01-proxy/03-observable/solution.md @@ -1,26 +1,26 @@ -The solution consists of two parts: +Çözüm iki bölümden oluşur: -1. Whenever `.observe(handler)` is called, we need to remember the handler somewhere, to be able to call it later. We can store it right in the object, using our symbol as the key. -2. We need a proxy with `set` trap to call handlers in case of any change. +1. `.observe(handler)` çağrıldığında, handler'ı daha sonra çağırabilmek için bir yerde saklamamız gerekir. Bunu, sembolümüzü anahtar olarak kullanarak doğrudan nesnede saklayabiliriz. +2. Herhangi bir değişiklik durumunda handler'ları çağırmak için `set` tuzağına sahip bir proxy'ye ihtiyacımız var. ```js run let handlers = Symbol('handlers'); function makeObservable(target) { - // 1. Initialize handlers store + // 1. Handler'ları saklamak için alanı başlat target[handlers] = []; - // Store the handler function in array for future calls + // Handler fonksiyonunu ileride çağırmak için diziye ekle target.observe = function(handler) { this[handlers].push(handler); }; - // 2. Create a proxy to handle changes + // 2. Değişiklikleri yakalamak için bir proxy oluştur return new Proxy(target, { set(target, property, value, receiver) { - let success = Reflect.set(...arguments); // forward the operation to object - if (success) { // if there were no error while setting the property - // call all handlers + let success = Reflect.set(...arguments); // İşlemi nesneye ilet + if (success) { // Özellik atanırken hata yoksa + // Tüm handler'ları çağır target[handlers].forEach(handler => handler(property, value)); } return success; diff --git a/1-js/99-js-misc/01-proxy/03-observable/task.md b/1-js/99-js-misc/01-proxy/03-observable/task.md index 6220104c8..f0b4cc5e7 100644 --- a/1-js/99-js-misc/01-proxy/03-observable/task.md +++ b/1-js/99-js-misc/01-proxy/03-observable/task.md @@ -1,13 +1,13 @@ -# Observable +# Gözlemlenebilir (Observable) -Create a function `makeObservable(target)` that "makes the object observable" by returning a proxy. +Bir nesneyi "gözlemlenebilir" yapan ve bir proxy döndüren `makeObservable(target)` fonksiyonunu oluşturun. -Here's how it should work: +Şöyle çalışmalı: ```js run function makeObservable(target) { - /* your code */ + /* kodunuz */ } let user = {}; @@ -20,10 +20,9 @@ user.observe((key, value) => { user.name = "John"; // alerts: SET name=John ``` -In other words, an object returned by `makeObservable` has the method `observe(handler)`. +Başka bir deyişle, `makeObservable` tarafından döndürülen nesnede `observe(handler)` metodu bulunur. -Whenever a property changes, `handler(key, value)` is called with the name and value o the property. +Bir özelliğin değeri değiştiğinde, ilgili özelliğin adı ve değeri ile `handler(key, value)` çağrılır. - -P.S. In this task, please handle only writing to a property. Other operations can be implemented in a similar way. -P.P.S. You might want to introduce a global variable or a global structure to store handlers. That's fine here. In real life, such function lives in a module, that has its own global scope. +Not: Bu görevde yalnızca bir özelliğe değer atamayı (yazmayı) ele alın. Diğer işlemler benzer şekilde uygulanabilir. +Ek Not: Handler'ları saklamak için global bir değişken veya global bir yapı kullanabilirsiniz. Burada bu uygundur. Gerçek hayatta, böyle bir fonksiyon kendi global kapsamına sahip bir modülde yaşar. diff --git a/1-js/99-js-misc/01-proxy/article.md b/1-js/99-js-misc/01-proxy/article.md index 05632bdfb..53610dce3 100644 --- a/1-js/99-js-misc/01-proxy/article.md +++ b/1-js/99-js-misc/01-proxy/article.md @@ -1,107 +1,109 @@ -# Proxy and Reflect +# Proxy ve Reflect -A *proxy* wraps another object and intercepts operations, like reading/writing properties and others, optionally handling them on its own, or transparently allowing the object to handle them. +Bir *proxy* (vekil), başka bir nesneyi sarmalar ve özellik okuma/yazma gibi işlemleri engeller (intercept eder). Bu işlemleri kendisi yönetebilir veya şeffaf bir şekilde hedef nesnenin yönetmesine izin verebilir. -Proxies are used in many libraries and some browser frameworks. We'll see many practical applications in this chapter. +Proxy’ler birçok kütüphanede ve bazı tarayıcı framework’lerinde kullanılır. Bu bölümde birçok pratik kullanım örneği göreceğiz. -The syntax: +Sözdizimi: ```js let proxy = new Proxy(target, handler) ``` -- `target` -- is an object to wrap, can be anything, including functions. -- `handler` -- an object with "traps": methods that intercept operations., e.g. `get` for reading a property, `set` for writing a property, etc. +- `target` -- sarmalanacak nesne; fonksiyonlar da dahil olmak üzere herhangi bir şey olabilir. +- `handler` -- işlemleri yakalayan (“trap” adı verilen) metotları içeren bir nesnedir. Örneğin, bir özelliği okumak için `get`, bir özelliğe yazmak için `set` gibi. -For operations on `proxy`, if there's a corresponding trap in `handler`, then it runs, and the proxy has a chance to handle it, otherwise the operation is performed on `target`. +`proxy` üzerinde bir işlem yapılırsa, `handler` içinde o işleme karşılık gelen bir trap varsa, o çalıştırılır; yoksa işlem `target`üzerinde gerçekleştirilir. -As a starting example, let's create a proxy without any traps: +Basit bir örnek olarak, hiç trap içermeyen bir proxy oluşturalım: ```js run let target = {}; -let proxy = new Proxy(target, {}); // empty handler +let proxy = new Proxy(target, {}); // boş handler -proxy.test = 5; // writing to proxy (1) -alert(target.test); // 5, the property appeared in target! +proxy.test = 5; // proxy’ye yazma (1) +alert(target.test); // 5, özellik target üzerinde belirdi! -alert(proxy.test); // 5, we can read it from proxy too (2) +alert(proxy.test); // 5, proxy’den de okuyabiliyoruz (2) -for(let key in proxy) alert(key); // test, iteration works (3) +for(let key in proxy) alert(key); // test, döngü çalışıyor (3) ``` -As there are no traps, all operations on `proxy` are forwarded to `target`. +Hiç trap olmadığından, `proxy` üzerindeki tüm işlemler `target`’a yönlendirilir. -1. A writing operation `proxy.test=` sets the value on `target`. -2. A reading operation `proxy.test` returns the value from `target`. -3. Iteration over `proxy` returns values from `target`. +1. `proxy.test=` yazma işlemi, değeri `target` üzerine yazar. +2. `proxy.test` okuma işlemi, değeri `target`’tan döndürür. +3. `proxy` üzerinde döngü yapmak, `target`’taki değerleri döndürür. -As we can see, without any traps, `proxy` is a transparent wrapper around `target`. +Gördüğümüz gibi, trap olmadan `proxy`, `target` üzerinde şeffaf bir sarmalayıcı gibi davranır. ![](proxy.svg) -The proxy is a special "exotic object". It doesn't have "own" properties. With an empty handler it transparently forwards operations to `target`. +Proxy, özel bir “egzotik nesnedir”. Kendi özellikleri yoktur. Boş bir handler ile, işlemleri tamamen `target`’a yönlendirir. -If we want any magic, we should add traps. +Eğer sihirli bir davranış istiyorsak, trap’ler eklememiz gerekir. -There's a list of internal object operations in the [Proxy specification](https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots). A proxy can intercept any of these, we just need to add a handler method. +[Proxy spesifikasyonu](https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots)’nda tanımlanmış bir dizi dahili nesne işlemi vardır. Bir proxy, bunlardan herhangi birini yakalayabilir; bunun için handler’a karşılık gelen metodu eklememiz yeterlidir. -In the table below: -- **Internal Method** is the specification-specific name for the operation. For example, `[[Get]]` is the name of the internal, specification-only method of reading a property. The specification describes how this is done at the very lowest level. -- **Handler Method** is a method name that we should add to proxy `handler` to trap the operation and perform custom actions. +Aşağıdaki tabloda: +- **İçsel Metot(Internal Method)** Spesifikasyondaki dahili işlemin adıdır. Örneğin, `[[Get]]` bir özelliği okuma işlemidir. +- **Handler Metodu(Handler Method)** `handler`’a eklememiz gereken metot adıdır; bu metot işlemi yakalar ve özel bir davranış tanımlar. -| Internal Method | Handler Method | Traps... | +| İçsel Metot | Handler Metodu | Yakalanan İşlem(Traps)... | |-----------------|----------------|-------------| -| `[[Get]]` | `get` | reading a property | -| `[[Set]]` | `set` | writing to a property | -| `[[HasProperty]]` | `has` | `in` operator | -| `[[Delete]]` | `deleteProperty` | `delete` operator | -| `[[Call]]` | `apply` | function call | -| `[[Construct]]` | `construct` | `new` operator | +| `[[Get]]` | `get` | özelliği okuma | +| `[[Set]]` | `set` | özelliğe yazma | +| `[[HasProperty]]` | `has` | `in` operatörü | +| `[[Delete]]` | `deleteProperty` | `delete` operatörü | +| `[[Call]]` | `apply` | fonksiyon çağrısı | +| `[[Construct]]` | `construct` | `new` operatörü | | `[[GetPrototypeOf]]` | `getPrototypeOf` | [Object.getPrototypeOf](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf) | | `[[SetPrototypeOf]]` | `setPrototypeOf` | [Object.setPrototypeOf](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf) | | `[[IsExtensible]]` | `isExtensible` | [Object.isExtensible](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible) | | `[[PreventExtensions]]` | `preventExtensions` | [Object.preventExtensions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/preventExtensions) | | `[[GetOwnProperty]]` | `getOwnPropertyDescriptor` | [Object.getOwnPropertyDescriptor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor) | | `[[DefineOwnProperty]]` | `defineProperty` | [Object.defineProperty](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty), [Object.defineProperties](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperties) | -| `[[OwnPropertyKeys]]` | `ownKeys` | [Object.keys](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys), [Object.getOwnPropertyNames](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames), [Object.getOwnPropertySymbols](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertySymbols), iteration keys | +| `[[OwnPropertyKeys]]` | `ownKeys` | [Object.keys](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys), [Object.getOwnPropertyNames](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames), [Object.getOwnPropertySymbols](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertySymbols), yineleme anahtarları | ```warn header="Invariants" -JavaScript enforces some invariants -- conditions that must be fulfilled by internal methods and traps. +JavaScript, bazı değişmez kuralları zorunlu kılar — bu kurallar, içsel metotlar ve trap’lerin belirli koşulları yerine getirmesini sağlar. -Most of them are for return values: -- `[[Set]]` must return `true` if the value was written successfully, otherwise `false`. -- `[[Delete]]` must return `true` if the value was deleted successfully, otherwise `false`. -- ...and so on, we'll see more in examples below. +Çoğu, dönüş değerleriyle ilgilidir: +- `[[Set]]` başarılıysa `true`, değilse `false` döndürmelidir. +- `[[Delete]]` başarılıysa `true`, değilse `false` döndürmelidir. +- …ve benzerleri; aşağıda örneklerde göreceğiz. -There are some other invariants, like: -- `[[GetPrototypeOf]]`, applied to the proxy object must return the same value as `[[GetPrototypeOf]]` applied to the proxy object's target object. +Bazı diğer kurallar: +- `[[GetPrototypeOf]]` çağrıldığında, proxy nesnesinin prototipi, hedef nesneninkiyle aynı olmalıdır. -In other words, reading prototype of a `proxy` must always return the prototype of the target object. The `getPrototypeOf` trap may intercept this operation, but it must follow this rule, not do something crazy. +Yani, bir `proxy`’nin prototipini okuduğumuzda, her zaman hedef nesnenin prototipini döndürmelidir. `getPrototypeOf` trap bu işlemi yakalayabilir ama bu kurala uymalıdır. + +Bu değişmez kurallar, dilin tutarlı ve doğru çalışmasını sağlar. Tüm liste [spesifikasyonda](https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots) bulunur; genellikle sıradışı bir şey yapmadığınız sürece ihlal etmezsiniz. -Invariants ensure correct and consistent behavior of language features. The full invariants list is in [the specification](https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots), you probably won't violate them, if not doing something weird. ``` -Let's see how that works on practical examples. +Haydi bunun pratik örneklerde nasıl çalıştığına bakalım. + +## "get" tuzağı ile varsayılan değer -## Default value with "get" trap +En yaygın trap’ler özellik okuma/yazma içindir. -The most common traps are for reading/writing properties. +Okumayı yakalamak için, `handler` içinde `get(target, property, receiver)` adlı bir metot bulunmalıdır. -To intercept the reading, the `handler` should have a method `get(target, property, receiver)`. +Bir özellik okunduğunda tetiklenir: -It triggers when a property is read: +- `target` -- hedef nesnedir; `new Proxy`’ye ilk argüman olarak verilen nesne, +- `property` -- özellik adı, +- `receiver` -- eğer özellik bir getter ise, o kodda `this` olarak kullanılacak nesnedir. Genellikle bu `proxy` nesnesinin kendisidir (veya proxy’den miras alıyorsak ondan türeyen nesne). -- `target` -- is the target object, the one passed as the first argument to `new Proxy`, -- `property` -- property name, -- `receiver` -- if the property is a getter, then `receiver` is the object that's going to be used as `this` in that code. Usually that's the `proxy` object itself (or an object that inherits from it, if we inherit from proxy). +Bir nesne için varsayılan değerleri uygulamak üzere `get`’i kullanalım. -Let's use `get` to implement default values for an object. +Örneğin, sayısal bir dizinin var olmayan indeksler için `undefined` yerine `0` döndürmesini istiyoruz. -For instance, we'd like a numeric array to return `0` for non-existant values instead of `undefined`. +Bunu, okumayı yakalayan ve öyle bir özellik yoksa varsayılan değer döndüren bir proxy ile saralım: -Let's wrap it into a proxy that traps reading and returns the default value if there's no such property: ```js run let numbers = [0, 1, 2]; @@ -111,20 +113,20 @@ numbers = new Proxy(numbers, { if (prop in target) { return target[prop]; } else { - return 0; // default value + return 0; // varsayılan değer } } }); *!* alert( numbers[1] ); // 1 -alert( numbers[123] ); // 0 (no such value) +alert( numbers[123] ); // 0 (böyle bir değer yok) */!* ``` -The approach is generic. We can use `Proxy` to implement any logic for "default" values. +Bu yaklaşım geneldir. "Varsayılan" değer mantığını `Proxy` ile istediğimiz gibi kurabiliriz. -Imagine, we have a dictionary with phrases along with translations: +Diyelim ki elimizde ifadeler ve onların çevirilerinden oluşan bir sözlük var: ```js run let dictionary = { @@ -136,9 +138,9 @@ alert( dictionary['Hello'] ); // Hola alert( dictionary['Welcome'] ); // undefined ``` -Right now, if there's no phrase, reading from `dictionary` returns `undefined`. But in practice, leaving a phrase non-translated is usually better than `undefined`. So let's make a non-translated phrase the default value instead of `undefined`. +Şu anda, bir ifade yoksa `dictionary`’den okumak `undefined` döndürüyor. Ama pratikte, çevrilmemiş bir ifadeyi olduğu gibi bırakmak çoğu zaman `undefined`’dan daha iyidir. O hâlde, `undefined` yerine varsayılan değerin çevrilmemiş ifadenin kendisi olmasını sağlayalım. -To achieve that, we'll wrap `dictionary` in a proxy that intercepts reading operations: +Bunu başarmak için, okumayı yakalayan bir proxy ile`dictionary`’yi saracağız: ```js run let dictionary = { @@ -148,59 +150,59 @@ let dictionary = { dictionary = new Proxy(dictionary, { *!* - get(target, phrase) { // intercept reading a property from dictionary + get(target, phrase) { // dictionary’den bir özellik okunmasını yakala */!* - if (phrase in target) { // if we have it in the dictionary - return target[phrase]; // return the translation + if (phrase in target) { // sözlükte varsa + return target[phrase]; // çeviriyi döndür } else { - // otherwise, return the non-translated phrase + // yoksa, çevrilmemiş ifadeyi döndür return phrase; } } }); -// Look up arbitrary phrases in the dictionary! -// At worst, they are not translated. +// Sözlükte rastgele ifadeleri ara! +// En kötü ihtimalle çevrilmemiş olarak dönerler. alert( dictionary['Hello'] ); // Hola *!* -alert( dictionary['Welcome to Proxy']); // Welcome to Proxy (no translation) +alert( dictionary['Welcome to Proxy']); // Welcome to Proxy (çeviri yok) */!* ``` -````smart header="Proxy should be used instead of `target` everywhere" -Please note how the proxy overwrites the variable: +````smart header="Proxy, her yerde `target` yerine kullanılmalıdır" +Proxy’nin değişkenin üzerine nasıl yazdığına dikkat edin: ```js dictionary = new Proxy(dictionary, ...); numbers = new Proxy(numbers, ...); ``` -The proxy should totally replace the target object everywhere. No one should ever reference the target object after it got proxied. Otherwise it's easy to mess up. +Proxy, hedef nesnenin yerini her yerde tamamen almalıdır. Bir nesne proxylenmişse, sonrasında kimse hedef nesneye doğrudan referans vermemelidir. Aksi takdirde işler kolayca karışır. ```` -## Validation with "set" trap +## "set" tuzağı ile doğrulama (Validation) -Now let's intercept writing as well. +Şimdi yazma işlemlerini de yakalayalım. -Let's say we want a numeric array. If a value of another type is added, there should be an error. +Diyelim ki yalnızca sayılardan oluşan bir dizi istiyoruz. Eğer farklı türde bir değer eklenirse, bir hata fırlatılmalı. -The `set` trap triggers when a property is written: `set(target, property, value, receiver)` +`set` tuzağı (trap), bir özellik yazıldığında tetiklenir: `set(target, property, value, receiver)` -- `target` -- is the target object, the one passed as the first argument to `new Proxy`, -- `property` -- property name, -- `value` -- property value, -- `receiver` -- same as in `get` trap, only matters if the property is a setter. +- `target` -- hedef nesnedir; `new Proxy`’ye ilk argüman olarak verilen nesne, +- `property` -- özellik adı, +- `value` -- özellik değeri, +- `receiver` -- `get` tuzağındakiyle aynıdır; yalnızca özellik bir setter ise önemlidir. -The `set` trap should return `true` if setting is successful, and `false` otherwise (leads to `TypeError`). +`set` tuzağı, işlem başarılıysa `true`, başarısızsa `false` döndürmelidir (aksi hâlde `TypeError` oluşur). -Let's use it to validate new values: +Yeni değerleri doğrulamak için bunu kullanalım: ```js run let numbers = []; numbers = new Proxy(numbers, { // (*) *!* - set(target, prop, val) { // to intercept property writing + set(target, prop, val) { // özelliğe yazmayı yakala */!* if (typeof val == 'number') { target[prop] = val; @@ -219,28 +221,31 @@ alert("Length is: " + numbers.length); // 2 numbers.push("test"); // TypeError ('set' on proxy returned false) */!* -alert("This line is never reached (error in the line above)"); +alert("Bu satıra asla ulaşılmaz (yukarıdaki satırda hata var)"); ``` -Please note: the built-in functionality of arrays is still working! The `length` property auto-increases when values are added. Our proxy doesn't break anything. +Dikkat ederseniz, dizinin yerleşik işlevleri hâlâ çalışıyor! +Yeni değerler eklendiğinde `length` özelliği otomatik olarak artıyor. Proxy’miz hiçbir şeyi bozmadı. -Also, we don't have to override value-adding array methods like `push` and `unshift`, and so on! Internally, they use `[[Set]]` operation, that's intercepted by the proxy. +Ayrıca`push`, `unshift` gibi değer ekleyen metotları da yeniden tanımlamamız gerekmedi. +Çünkü bunlar dahili olarak `[[Set]]` işlemini kullanırlar ve bu işlem proxy tarafından yakalanır. -So the code is clean and concise. +Kod bu sayede hem temiz hem de kısa olur. -```warn header="Don't forget to return `true`" -As said above, there are invariants to be held. +```warn header="`true` döndürmeyi unutmayın" +Yukarıda belirtildiği gibi, bazı değişmez kurallar (invariant) vardır. -For `set`, it must return `true` for a successful write. +`set` işlemi başarılıysa `true` döndürmelidir. -If it returns a falsy value (or doesn't return anything), that triggers `TypeError`. +Eğer yanlış (falsy) bir değer döndürülürse (veya hiç değer döndürülmezse), bu `TypeError` hatasına neden olur. ``` -## Protected properties with "deleteProperty" and "ownKeys" +## "deleteProperty" ve "ownKeys" ile korunan özellikler -There's a widespread convention that properties and methods prefixed by an underscore `_` are internal. They shouldn't be accessible from outside the object. +Yaygın bir konvansiyona göre, `_` (alt çizgi) ile başlayan özellikler ve metotlar içseldir. +Bu tür özelliklere nesnenin dışından erişilmemelidir. -Technically, that's possible though: +Teknik olarak erişmek mümkündür: ```js run let user = { @@ -251,15 +256,15 @@ let user = { alert(user._password); // secret ``` -Let's use proxies to prevent any access to properties starting with `_`. +Şimdi `_` ile başlayan özelliklere erişimi engellemek için proxy kullanalım. -We'll need the traps: -- `get` to throw an error when reading, -- `set` to throw an error when writing, -- `deleteProperty` to throw an error when deleting, -- `ownKeys` to skip properties starting with `_` when iterating over an object or using `Object.keys()` +Bunun için şu tuzaklara ihtiyacımız var: +- `get` okuma sırasında hata fırlatmak için, +- `set` yazma sırasında hata fırlatmak için, +- `deleteProperty` silme sırasında hata fırlatmak için, +- `ownKeys` `_` ile başlayan özellikleri `for...in` döngüsü veya `Object.keys()` gibi işlemlerden gizlemek için. -Here's the code: +Kod şu şekilde olur: ```js run let user = { @@ -272,53 +277,53 @@ user = new Proxy(user, { get(target, prop) { */!* if (prop.startsWith('_')) { - throw new Error("Access denied"); + throw new Error("Erişim reddedildi"); } let value = target[prop]; return (typeof value === 'function') ? value.bind(target) : value; // (*) }, *!* - set(target, prop, val) { // to intercept property writing + set(target, prop, val) { // yazma işlemini yakala */!* if (prop.startsWith('_')) { - throw new Error("Access denied"); + throw new Error("Erişim reddedildi"); } else { target[prop] = val; } }, *!* - deleteProperty(target, prop) { // to intercept property deletion + deleteProperty(target, prop) { // silme işlemini yakala */!* if (prop.startsWith('_')) { - throw new Error("Access denied"); + throw new Error("Erişim reddedildi"); } else { delete target[prop]; return true; } }, *!* - ownKeys(target) { // to intercept property list + ownKeys(target) { // özellik listesini yakala */!* return Object.keys(target).filter(key => !key.startsWith('_')); } }); -// "get" doesn't allow to read _password +// "get" -> _password okunamaz try { - alert(user._password); // Error: Access denied + alert(user._password); // Hata: Erişim reddedildi } catch(e) { alert(e.message); } -// "set" doesn't allow to write _password +// "set" -> _password yazılamaz try { - user._password = "test"; // Error: Access denied + user._password = "test"; // Hata: Erişim reddedildi } catch(e) { alert(e.message); } -// "deleteProperty" doesn't allow to delete _password +// "deleteProperty" -> _password silinemez try { - delete user._password; // Error: Access denied + delete user._password; // Hata: Erişim reddedildi } catch(e) { alert(e.message); } -// "ownKeys" filters out _password +// "ownKeys" -> _password filtrelenir for(let key in user) alert(key); // name ``` From 7d8dd3aaf4ebd231e769cc51825ea2677e12376a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96=2E=20F=2E=20K=C3=BCc=C3=BCk=20-=20Polyca=20Games?= <85259815+polycaman@users.noreply.github.com> Date: Sat, 18 Oct 2025 09:48:24 +0000 Subject: [PATCH 2/3] translated the remaining of the article.md file --- 1-js/99-js-misc/01-proxy/article.md | 293 +++++++++++++++------------- 1 file changed, 159 insertions(+), 134 deletions(-) diff --git a/1-js/99-js-misc/01-proxy/article.md b/1-js/99-js-misc/01-proxy/article.md index 53610dce3..ee037ace6 100644 --- a/1-js/99-js-misc/01-proxy/article.md +++ b/1-js/99-js-misc/01-proxy/article.md @@ -327,7 +327,7 @@ try { for(let key in user) alert(key); // name ``` -Please note the important detail in `get` trap, in the line `(*)`: +Lütfen `get` tuzağındaki, `(*)` satırındaki önemli detaya dikkat edin: ```js get(target, prop) { @@ -339,36 +339,36 @@ get(target, prop) { } ``` -If an object method is called, such as `user.checkPassword()`, it must be able to access `_password`: +Bir nesne metodu çağrıldığında, örneğin `user.checkPassword()`, bu metodun `_password`’a erişebilmesi gerekir: ```js user = { // ... checkPassword(value) { - // object method must be able to read _password + // nesne metodu _password'ı okuyabilmeli return value === this._password; } } ``` -Normally, `user.checkPassword()` call gets proxied `user` as `this` (the object before dot becomes `this`), so when it tries to access `this._password`, the property protection kicks in and throws an error. So we bind it to `target` in the line `(*)`. Then all operations from that function directly reference the object, without any property protection. +Normalde, `user.checkPassword()` çağrısında `this` olarak proxylanmış `user` geçer (noktadan önceki nesne `this` olur). Bu yüzden metod `this._password`’a erişmeye çalıştığında, özellik koruması devreye girer ve hata fırlatır. İşte bu nedenle `(*)` satırında metodu `target`’a bağlarız (`bind`). Böylece o fonksiyon içindeki tüm işlemler doğrudan orijinal nesneye yapılır ve özellik korumasına takılmaz. -That solution is not ideal, as the method may pass the unproxied object somewhere else, and then we'll get messed up: where's the original object, and where's the proxied one. +Bu çözüm ideal değildir; çünkü metot, proxylanmamış nesneyi başka bir yere aktarabilir ve sonrasında işler karışabilir: Orijinal nesne nerede, proxy nerede? -As an object may be proxied multiple times (multiple proxies may add different "tweaks" to the object), weird bugs may follow. +Bir nesne birden fazla kez proxylanabilir (farklı proxy’ler nesneye farklı “ince ayarlar” ekleyebilir), bu da garip hatalara yol açabilir. -So, for complex objects with methods such proxy shouldn't be used. +Dolayısıyla, metotları olan karmaşık nesneler için bu tür bir proxy kullanımı önerilmez. ```smart header="Private properties of a class" -Modern JavaScript engines natively support private properties in classes, prefixed with `#`. They are described in the chapter . No proxies required. +Modern JavaScript motorları, `#` ile başlayan sınıf içi özel özellikleri yerel olarak destekler. Bunlar bölümünde anlatılmıştır. Proxy gerekmez. -Such properties have their own issues though. In particular, they are not inherited. +Ancak bu özelliklerin de kendine özgü sorunları vardır. Özellikle, kalıtılmazlar. ``` -## "In range" with "has" trap +## "has" tuzağı ile "in range" (aralıkta mı?) denetimi -Let's say we have a range object: +Bir aralık (range) nesnemiz olduğunu varsayalım: ```js let range = { @@ -377,14 +377,14 @@ let range = { }; ``` -We'd like to use "in" operator to check that a number is in `range`. +Bir sayının `range` içinde olup olmadığını denetlemek için "in" operatörünü kullanmak istiyoruz. -The "has" trap intercepts "in" calls: `has(target, property)` +"has" tuzağı, "in" çağrılarını yakalar: `has(target, property)` -- `target` -- is the target object, passed as the first argument to `new Proxy`, -- `property` -- property name +- `target` -- `new Proxy`’ye ilk argüman olarak geçirilen hedef nesne,, +- `property` -- özellik adı -Here's the demo: +Örnek: ```js run let range = { @@ -406,28 +406,28 @@ alert(50 in range); // false */!* ``` -A nice syntactic sugar, isn't it? +Güzel bir sözdizim şekeri, değil mi? -## Wrapping functions: "apply" +## Fonksiyonları sarmalamak: "apply" -We can wrap a proxy around a function as well. +Bir fonksiyonun etrafına da proxy sarabiliriz. -The `apply(target, thisArg, args)` trap handles calling a proxy as function: +`apply(target, thisArg, args)` tuzağı, proxy’nin fonksiyon gibi çağrılmasını yakalar: -- `target` is the target object, -- `thisArg` is the value of `this`. -- `args` is a list of arguments. +- `target` hedef nesne (fonksiyon), +- `thisArg` çağrıda kullanılacak `this` değeri, +- `args` argümanların listesi. -For example, let's recall `delay(f, ms)` decorator, that we did in the chapter . +Örneğin, bölümünde yaptığımız `delay(f, ms)` dekoratörünü hatırlayalım. -In that chapter we did it without proxies. A call to `delay(f, ms)` would return a function that forwards all calls to `f` after `ms` milliseconds. +Orada proxy kullanmadan yapmıştık. `delay(f, ms)` çağrısı, tüm çağrıları `ms` milisaniye sonra `f`’e ileten bir fonksiyon döndürüyordu. -Here's the function-based implementation: +Fonksiyon-tabanlı uygulama: ```js run -// no proxies, just a function wrapper +// proxy yok, sadece bir sarmalayıcı fonksiyon function delay(f, ms) { - // return a wrapper that passes the call to f after the timeout + // timeout sonrası çağrıyı f'ye ileten bir sarmalayıcı döndür return function() { // (*) setTimeout(() => f.apply(this, arguments), ms); }; @@ -437,15 +437,15 @@ function sayHi(user) { alert(`Hello, ${user}!`); } -// now calls to sayHi will be delayed for 3 seconds +// artık sayHi çağrıları 3 saniye gecikmeli sayHi = delay(sayHi, 3000); -sayHi("John"); // Hello, John! (after 3 seconds) +sayHi("John"); // Hello, John! (3 saniye sonra) ``` -As you can see, that mostly works. The wrapper function `(*)` performs the call after the timeout. +Gördüğünüz gibi, çoğunlukla çalışıyor. `(*)` satırındaki sarmalayıcı fonksiyon, çağrıyı bekleme süresinden sonra gerçekleştiriyor. -But a wrapper function does not forward property read/write operations or anything else. So if we have a property on the original function, we can't access it after wrapping: +Ama sarmalayıcı fonksiyon, özellik okuma/yazma gibi diğer işlemleri iletmez. Dolayısıyla, orijinal fonksiyonun bir özelliği varsa, sarmalamadan sonra ona erişemeyiz: ```js run function delay(f, ms) { @@ -459,20 +459,20 @@ function sayHi(user) { } *!* -alert(sayHi.length); // 1 (function length is the arguments count) +alert(sayHi.length); // 1 (function length argüman sayısıdır) */!* sayHi = delay(sayHi, 3000); *!* -alert(sayHi.length); // 0 (wrapper has no arguments) +alert(sayHi.length); // 0 (sarmalayıcının argümanı yok) */!* ``` -`Proxy` is much more powerful, as it forwards everything to the target object. +`Proxy` çok daha güçlüdür; çünkü her şeyi hedef nesneye iletir. -Let's use `Proxy` instead of a wrapping function: +Sarmalayıcı fonksiyon yerine `Proxy` kullanalım: ```js run function delay(f, ms) { @@ -490,25 +490,27 @@ function sayHi(user) { sayHi = delay(sayHi, 3000); *!* -alert(sayHi.length); // 1 (*) proxy forwards "get length" operation to the target +alert(sayHi.length); // 1 (*) proxy "length" okuma işlemini hedefe iletir */!* -sayHi("John"); // Hello, John! (after 3 seconds) +sayHi("John"); // Hello, John! (3 saniye sonra) ``` -The result is the same, but now not only calls, but all operations on the proxy are forwarded to the original function. So `sayHi.length` is returned correctly after the wrapping in the line `(*)`. +Sonuç aynı, ancak artık yalnızca çağrılar değil, proxy üzerindeki tüm işlemler de orijinal fonksiyona iletiliyor. Bu nedenle `(*)` satırında sarmalamadan sonra `sayHi.length` doğru şekilde döndü. -We've got a "richer" wrapper. +Böylece daha “zengin” bir sarmalayıcı elde etmiş olduk. -There exist other traps, but probably you've already got the idea. +Başka trap’ler de var, fakat sanırım artık mantığı anladınız. ## Reflect -The `Reflect` API was designed to work in tandem with `Proxy`. +`Reflect` API’si, `Proxy` ile birlikte çalışmak üzere tasarlanmıştır. -For every internal object operation that can be trapped, there's a `Reflect` method. It has the same name and arguments as the trap, and can be used to forward the operation to an object. +Yakalanabilecek (trap’lenebilecek) her dahili nesne işlemi için bir `Reflect` metodu vardır. +Bu metodun adı ve parametreleri, ilgili trap ile aynıdır ve işlemi hedef nesneye iletmek için kullanılabilir. -For example: + +Örneğin: ```js run let user = { @@ -534,14 +536,14 @@ let name = user.name; // GET name user.name = "Pete"; // SET name TO Pete ``` -- `Reflect.get` gets the property, like `target[prop]` that we used before. -- `Reflect.set` sets the property, like `target[prop] = value`, and also ensures the correct return value. +- `Reflect.get`, tıpkı `target[prop]` gibi özelliği okur. +- `Reflect.set`, tıpkı `target[prop] = value` gibi özelliği yazar, ayrıca doğru dönüş değerini de garanti eder. -In most cases, we can do the same thing without `Reflect`. But we may miss some peculiar aspects. +Çoğu durumda `Reflect` kullanmadan da aynı işi yapabiliriz, ancak bazı ince detayları kaçırabiliriz. -Consider the following example, it doesn't use `Reflect` and doesn't work right. +Aşağıdaki örneğe bakalım; `Reflect` kullanılmamış ve yanlış sonuç veriyor: -We have a proxied user object and inherit from it, then use a getter: +Bir user nesnesini proxy’liyoruz, sonra ondan kalıtım alıp bir getter kullanıyoruz: ```js run let user = { @@ -564,27 +566,27 @@ let admin = { }; *!* -// Expected: Admin +// Beklenen: Admin alert(admin.name); // Guest (?!?) */!* ``` -As you can see, the result is incorrect! The `admin.name` is expected to be `"Admin"`, not `"Guest"`! Without the proxy, it would be `"Admin"`, looks like the proxying "broke" our object. +Gördüğünüz gibi sonuç hatalı! `admin.name` değerinin `"Admin"` olması gerekirken `"Guest"` döndü. Proxy olmadan `"Admin"` olacaktı; proxyleme nesneyi “bozmuş” gibi görünüyor. ![](proxy-inherit.svg) -Why this happens? That's easy to understand if we explore what's going on during the call in the last line of the code. +Peki neden? Son satırdaki çağrının ne yaptığına bakalım: -1. There's no `name` property in `admin`, so `admin.name` call goes to `admin` prototype. -2. The prototype is the proxy, so its `get` trap intercepts the attempt to read `name`. -3. In the line `(*)` it returns `target[prop]`, but what is the `target`? - - The `target`, the first argument of `get`, is always the object passed to `new Proxy`, the original `user`. - - So, `target[prop]` invokes the getter `name` with `this=target=user`. - - Hence the result is `"Guest"`. +1. `admin` içinde `name` özelliği yok, bu yüzden çağrı `admin`’in prototipine gider. +2. Prototip bir proxy olduğu için, `get` tuzağı `name` okuma girişimini yakalar. +3. `(*)` satırında `target[prop]` döndürülür, peki `target` nedir? + - `target`, `get`’in ilk parametresidir ve her zaman `new Proxy`’ye verilen orijinal nesnedir(`user`). + - Dolayısıyla, `target[prop]` getter `name`’i `this=target=user` olarak çağırır. + - Bu yüzden sonuç `"Guest"` olur. -How to fix it? That's what the `receiver`, the third argument of `get` is for! It holds the correct `this`. We just need to call `Reflect.get` to pass it on. +Bunu nasıl düzeltiriz? İşte bu noktada üçüncü parametre olan `receiver` devreye girer! `receiver`, doğru `this` değerini tutar. Sadece `Reflect.get`’i çağırarak bu değeri aktarabiliriz. -Here's the correct variant: +Doğru çözüm şöyle olur: ```js run let user = { @@ -613,9 +615,9 @@ alert(admin.name); // Admin */!* ``` -Now the `receiver` holding the correct `this` is passed to getter by `Reflect.get` in the line `(*)`, so it works correctly. +Artık `receiver`, doğru `this` değerini tutarak getter’a `Reflect.get` aracılığıyla (`(*)` satırında) aktarılır ve her şey düzgün çalışır. -We could also write the trap as: +Ayrıca tuzağı şu şekilde de yazabilirdik: ```js get(target, prop, receiver) { @@ -623,27 +625,30 @@ get(target, prop, receiver) { } ``` -`Reflect` calls are named exactly the same way as traps and accept the same arguments. They were specifically designed this way. +`Reflect` çağrıları, tuzaklarla birebir aynı isimlere ve argümanlara sahiptir. +Bu özellikle böyle tasarlanmıştır. -So, `return Reflect...` provides a safe no-brainer to forward the operation and make sure we don't forget anything related to that. +Dolayısıyla `return Reflect...` şeklinde bir çağrı, işlemi güvenli bir şekilde iletmenin ve hiçbir detayı unutmamanın en kolay yoludur. -## Proxy limitations +## Proxy Sınırlamaları -Proxies are a great way to alter or tweak the behavior of the existing objects, including built-in ones, such as arrays. +Proxy’ler, var olan nesnelerin (hatta yerleşik olanların, örn. diziler) davranışlarını değiştirmek veya özelleştirmek için mükemmel bir araçtır. -Still, it's not perfect. There are limitations. +Yine de, bazı sınırlamaları vardır. -### Built-in objects: Internal slots +### Yerleşik Nesneler: İçsel Slotlar (Internal Slots) -Many built-in objects, for example `Map`, `Set`, `Date`, `Promise` and others make use of so-called "internal slots". +Birçok yerleşik nesne, örneğin `Map`, `Set`, `Date`, `Promise` ve benzerleri, “içsel slot” (internal slot) denen yapıları kullanır. -These are like properties, but reserved for internal purposes. Built-in methods access them directly, not via `[[Get]]/[[Set]]` internal methods. So `Proxy` can't intercept that. +Bunlar özelliklere benzer, ancak dahili amaçlar için ayrılmıştır. +Yerleşik metotlar bu slotlara doğrudan erişir, `[[Get]]/[[Set]]` gibi içsel metotları kullanmazlar. Bu yüzden `Proxy` bunları yakalayamaz. -Who cares? They are internal anyway! +“Eee ne olmuş, sonuçta dahili yapılar!” diyebilirsiniz. -Well, here's the issue. After such built-in object gets proxied, the proxy doesn't have these internal slots, so built-in methods will fail. +Ama sorun şudur: +Böyle bir yerleşik nesne proxylenirse, proxy bu içsel slotlara sahip olmaz ve dolayısıyla yerleşik metotlar çalışmaz. -For example: +Örneğin: ```js run let map = new Map(); @@ -651,15 +656,15 @@ let map = new Map(); let proxy = new Proxy(map, {}); *!* -proxy.set('test', 1); // Error +proxy.set('test', 1); // Hata */!* ``` -An attempt to set a value into a proxied `Map` fails, for the reason related to its [internal implementation](https://tc39.es/ecma262/#sec-map.prototype.set). +Bir `Map` üzerinde `set` çağırmak başarısız olur; çünkü bu davranış [içsel implementasyona](https://tc39.es/ecma262/#sec-map.prototype.set) bağlıdır. -Internally, a `Map` stores all data in its `[[MapData]]` internal slot. The proxy doesn't have such slot. The `set` method tries to access `this.[[MapData]]` internal property, but because `this=proxy`, can't find it in `proxy` and just fails. +Dahili olarak bir `Map`, tüm verilerini `[[MapData]]` adlı içsel slotta saklar. Proxy’de böyle bir slot yoktur. `set` metodu `this.[[MapData]]`’ya erişmeye çalışır; ancak `this=proxy` olduğu için bulamaz ve hata verir. -Fortunately, there's a way to fix it: +Neyse ki bunu düzeltmenin bir yolu var: ```js run let map = new Map(); @@ -674,24 +679,24 @@ let proxy = new Proxy(map, { }); proxy.set('test', 1); -alert(proxy.get('test')); // 1 (works!) +alert(proxy.get('test')); // 1 (çalışıyor!) ``` -Now it works fine, because `get` trap binds function properties, such as `map.set`, to the target object (`map`) itself. +Şimdi düzgün çalışıyor, çünkü `get` tuzağı fonksiyon özellikleri (`map.set` gibi), hedef nesneye (`map`) bağlıyor. -Unlike the previous example, the value of `this` inside `proxy.set(...)` will be not `proxy`, but the original `map`. So when the internal implementation of `set` tries to access `this.[[MapData]]` internal slot, it succeeds. +Böylece `proxy.set(...)` içindeki `this` artık `proxy` değil, orijinal `map` olur. Dolayısıyla `set` metodu `this.[[MapData]]` slotuna erişmeye çalıştığında başarılı olur. -```smart header="`Array` has no internal slots" -A notable exception: built-in `Array` doesn't use internal slots. That's for historical reasons, as it appeared so long ago. +```smart header="`Array`'in içsel slotları yoktur" +Belirgin bir istisna: yerleşik `Array` içsel slotlar kullanmaz. Bu tarihsel bir sebepten dolayıdır, çok eski bir yapı olduğundan. -So there's no such problem when proxying an array. +Bu nedenle, dizileri proxy’lemek bu tür bir soruna yol açmaz. ``` -### Private fields +### Özel Alanlar (Private Fields) -The similar thing happens with private class fields. +Benzer bir durum, sınıflardaki özel (private) alanlarda da görülür. -For example, `getName()` method accesses the private `#name` property and breaks after proxying: +Örneğin, `getName()` metodu özel `#name` alanına erişir, ancak proxy uygulandıktan sonra bozulur: ```js run class User { @@ -711,11 +716,12 @@ alert(user.getName()); // Error */!* ``` -The reason is that private fields are implemented using internal slots. JavaScript does not use `[[Get]]/[[Set]]` when accessing them. +Bunun nedeni, özel alanların (private fields) dahili slotlar (internal slots) kullanılarak uygulanmasıdır. +JavaScript, bunlara erişirken `[[Get]]` veya `[[Set]]` mekanizmalarını kullanmaz. -In the call `user.getName()` the value of `this` is the proxied user, and it doesn't have the slot with private fields. +`user.getName()` çağrısında, `this` değeri proxylanmış kullanıcı nesnesidir ve bu nesnede özel alanların bulunduğu slot yoktur. -Once again, the solution with binding the method makes it work: +Daha önceki örneklerde olduğu gibi, metodu hedef nesneye bağlayarak (`bind`) bu durumu düzeltebiliriz: ```js run class User { @@ -738,13 +744,15 @@ user = new Proxy(user, { alert(user.getName()); // Guest ``` -That said, the solution has drawbacks, explained previously: it exposes the original object to the method, potentially allowing it to be passed further and breaking other proxied functionality. +Ancak bu çözümün daha önce açıkladığımız bir dezavantajı var: +Metot, orijinal nesneye doğrudan erişim kazanır ve onu başka bir yere aktarabilir. +Bu da diğer proxy işlevselliklerini bozabilir. ### Proxy != target -Proxy and the original object are different objects. That's natural, right? +Proxy ve orijinal nesne farklı nesnelerdir. Bu oldukça doğaldır, değil mi? -So if we store the original object somewhere, and then proxy it, then things might break: +Yani bir nesneyi bir yerde saklayıp daha sonra proxy’larsak, bazı şeyler bozulabilir: ```js run let allUsers = new Set(); @@ -767,34 +775,40 @@ alert(allUsers.has(user)); // false */!* ``` -As we can see, after proxying we can't find `user` in the set `allUsers`, because the proxy is a different object. +Gördüğünüz gibi, proxylamadan sonra `user`, `allUsers` kümesinde bulunamıyor çünkü proxy farklı bir nesne. -```warn header="Proxies can't intercept a strict equality test `===`" -Proxies can intercept many operators, such as `new` (with `construct`), `in` (with `has`), `delete` (with `deleteProperty`) and so on. +```warn header="Proxy'ler sıkı eşitlik testini `===` yakalayamaz" +Proxy’ler `new` (-> `construct`), `in` (-> `has`), `delete` (-> `deleteProperty`) gibi birçok işlemi yakalayabilir. -But there's no way to intercept a strict equality test for objects. An object is strictly equal to itself only, and no other value. +Ancak, nesneler için sıkı eşitlik testi (`===`) yakalanamaz. +Bir nesne yalnızca kendisine eşittir; başka hiçbir şeye değil. -So all operations and built-in classes that compare objects for equality will differentiate between the object and the proxy. No transparent replacement here. +Bu nedenle, nesneleri karşılaştıran tüm işlemler ve yerleşik sınıflar, nesne ile proxy arasında ayrım yapar. +Yani proxy’ler tam anlamıyla “şeffaf” bir yedek olamaz. ``` -## Revocable proxies +## Geri Alınabilir Proxy’ler (Revocable Proxies) + +*Revocable proxy*, yani “geri alınabilir proxy”, devre dışı bırakılabilen bir proxy türüdür. -A *revocable* proxy is a proxy that can be disabled. +Diyelim ki bir kaynağımız var ve istediğimiz anda bu kaynağa erişimi kapatmak istiyoruz. -Let's say we have a resource, and would like to close access to it any moment. +Bunu, herhangi bir trap eklemeden bir “revocable proxy” ile sarmalayabiliriz. +Bu proxy işlemleri hedef nesneye iletir, ancak ayrıca onu devre dışı bırakmak için özel bir fonksiyon sağlar. -What we can do is to wrap it into a revocable proxy, without any traps. Such proxy will forward operations to object, and we also get a special method to disable it. -The syntax is: +Sözdizimi şöyledir: ```js let {proxy, revoke} = Proxy.revocable(target, handler) ``` -The call returns an object with the `proxy` and `revoke` function to disable it. +Bu çağrı, iki özellik döndürür: +- `proxy` vekil nesne, +- `revoke` bu proxy’yi devre dışı bırakmak için kullanılan fonksiyon. -Here's an example: +Örnek: ```js run let object = { @@ -803,19 +817,21 @@ let object = { let {proxy, revoke} = Proxy.revocable(object, {}); -// pass the proxy somewhere instead of object... +// nesne yerine proxy’yi bir yere aktarabiliriz... alert(proxy.data); // Valuable data -// later in our code +// kodun ilerleyen bir kısmında revoke(); -// the proxy isn't working any more (revoked) -alert(proxy.data); // Error +// proxy artık çalışmaz (devre dışı) +alert(proxy.data); // Hata ``` -A call to `revoke()` removes all internal references to the target object from the proxy, so they are no more connected. The target object can be garbage-collected after that. +`revoke()` çağrısı, proxy’nin hedef nesneyle olan tüm dahili bağlantılarını kaldırır. +Böylece artık birbirleriyle ilişkili değildirler. +Bu noktadan sonra hedef nesne, çöp toplayıcı (garbage collector) tarafından silinebilir. -We can also store `revoke` in a `WeakMap`, to be able to easily find it by the proxy: +Ayrıca `revoke` fonksiyonunu bir `WeakMap` içinde saklayarak, proxy üzerinden kolayca bulabiliriz: ```js run @@ -831,52 +847,61 @@ let {proxy, revoke} = Proxy.revocable(object, {}); revokes.set(proxy, revoke); -// ..later in our code.. +// ...kodun ilerleyen kısmında... revoke = revokes.get(proxy); revoke(); -alert(proxy.data); // Error (revoked) +alert(proxy.data); // Hata (revoked) ``` -The benefit of such approach is that we don't have to carry `revoke` around. We can get it from the map by `proxy` when needeed. +Bu yaklaşımın avantajı, `revoke` fonksiyonunu her yere taşımak zorunda olmamamızdır. +Proxy üzerinden `WeakMap` aracılığıyla gerektiğinde erişebiliriz. -Using `WeakMap` instead of `Map` here, because it should not block garbage collection. If a proxy object becomes "unreachable" (e.g. no variable references it any more), `WeakMap` allows it to be wiped from memory (we don't need its revoke in that case). +Burada `Map` yerine `WeakMap` kullanmamızın nedeni, çöp toplamayı engellememesidir. +Eğer bir proxy nesnesine artık erişilmiyorsa (örneğin hiçbir değişken onu tutmuyorsa), `WeakMap` onun bellekten silinmesine izin verir. Çünkü artık `revoke` fonksiyonuna da ihtiyacımız yoktur. -## References +## Referanslar -- Specification: [Proxy](https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots). +- Spesifikasyon: [Proxy](https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots). - MDN: [Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy). -## Summary +## Özet -`Proxy` is a wrapper around an object, that forwards operations to the object, optionally trapping some of them. +`Proxy`, bir nesnenin etrafını saran ve işlemleri o nesneye yönlendiren (ve istenirse bazılarını yakalayan) bir yapıdır. -It can wrap any kind of object, including classes and functions. +Her tür nesneyi, sınıflar ve fonksiyonlar dahil, sarmalayabilir. -The syntax is: +Sözdizimi: ```js let proxy = new Proxy(target, { - /* traps */ + /* tuzaklar */ }); ``` -...Then we should use `proxy` everywhere instead of `target`. A proxy doesn't have its own properties or methods. It traps an operation if the trap is provided or forwards it to `target` object. +...Bundan sonra `target` yerine her yerde `proxy` kullanılmalıdır. Bir proxy’nin kendi özellikleri veya metotları yoktur. +Bir işlem, uygun bir trap tanımlanmışsa yakalanır; yoksa hedef nesneye (`target`) iletilir. + +Yakalanabilecek işlemler şunlardır: +- Özellik okuma (`get`), yazma (`set`), silme (`deleteProperty`), hatta var olmayan bir özellik bile. +- Fonksiyon çağrıları: `new` ile (`construct` tuzağı), `new` olmadan (`apply` tuzağı). +- Daha birçok işlem (tam liste makalenin başında ve [MDN dokümentasyonunda](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) yer alır). -We can trap: -- Reading (`get`), writing (`set`), deleting (`deleteProperty`) a property (even a non-existing one). -- Calling functions with `new` (`construct` trap) and without `new` (`apply` trap) -- Many other operations (the full list is at the beginning of the article and in the [docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy)). +Bu sayede: +- “Sanal” (virtual) özellikler ve metotlar oluşturabiliriz, +- Varsayılan değerler tanımlayabiliriz, +- Gözlemlenebilir (observable) nesneler oluşturabiliriz, +- Fonksiyon dekoratörleri (decorators) yazabiliriz, +ve çok daha fazlasını yapabiliriz. -That allows us to create "virtual" properties and methods, implement default values, observable objects, function decorators and so much more. -We can also wrap an object multiple times in different proxies, decorating it with various aspects of functionality. +Bir nesneyi farklı `Proxy` katmanlarıyla birden fazla kez sarmalayabiliriz. Her biri farklı bir işlevsellik ekleyebilir. -The [Reflect](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect) API is designed to complement [Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy). For any `Proxy` trap, there's a `Reflect` call with same arguments. We should use those to forward calls to target objects. +[Reflect](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect) API'si [Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy)’yi tamamlamak üzere tasarlanmıştır. Her `Proxy` tuzağı için aynı argümanları alan bir `Reflect` çağrısı bulunur. Bu çağrılar, işlemleri hedef nesneye güvenli bir şekilde iletmek için kullanılmalıdır. -Proxies have some limitations: +Proxy’lerin bazı sınırlamaları vardır: -- Built-in objects have "internal slots", access to those can't be proxied. See the workaround above. -- The same holds true for private class fields, as they are internally implemented using slots. So proxied method calls must have the target object as `this` to access them. -- Object equality tests `===` can't be intercepted. -- Performance: benchmarks depend on an engine, but generally accessing a property using a simplest proxy takes a few times longer. In practice that only matters for some "bottleneck" objects though. +- Yerleşik nesneler, "içsel slot" (internal slot) adı verilen alanlara sahiptir; bunlara erişim proxy ile yakalanamaz. (Yukarıda çözüm örneği verilmiştir.) +- Aynı durum özel (private) sınıf alanları için de geçerlidir; bunlar da slot’lar aracılığıyla uygulanır. Bu nedenle proxylanmış metod çağrıları, bu alanlara erişebilmek için `this` değerinin hedef nesne olması gerekir. +- Nesne eşitlik testi (`===`) yakalanamaz. +- Performans: Proxy üzerinden özellik erişimi genellikle birkaç kat daha yavaştır. Ancak pratikte bu fark yalnızca dar boğaz oluşturan nesnelerde hissedilir. From ef000218deb513119eba1960d2995fa9a2375cc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96=2E=20F=2E=20K=C3=BCc=C3=BCk=20-=20Polyca=20Games?= <85259815+polycaman@users.noreply.github.com> Date: Sat, 18 Oct 2025 09:54:07 +0000 Subject: [PATCH 3/3] small fixes --- 1-js/99-js-misc/01-proxy/article.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/1-js/99-js-misc/01-proxy/article.md b/1-js/99-js-misc/01-proxy/article.md index ee037ace6..178037efa 100644 --- a/1-js/99-js-misc/01-proxy/article.md +++ b/1-js/99-js-misc/01-proxy/article.md @@ -67,8 +67,8 @@ Aşağıdaki tabloda: | `[[DefineOwnProperty]]` | `defineProperty` | [Object.defineProperty](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty), [Object.defineProperties](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperties) | | `[[OwnPropertyKeys]]` | `ownKeys` | [Object.keys](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys), [Object.getOwnPropertyNames](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames), [Object.getOwnPropertySymbols](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertySymbols), yineleme anahtarları | -```warn header="Invariants" -JavaScript, bazı değişmez kuralları zorunlu kılar — bu kurallar, içsel metotlar ve trap’lerin belirli koşulları yerine getirmesini sağlar. +```warn header="Değişmez kurallar (Invariants)" +JavaScript, bazı değişmez kuralları zorunlu kılar. Bu kurallar, içsel metotlar ve trap’lerin belirli koşulları yerine getirmesini sağlar. Çoğu, dönüş değerleriyle ilgilidir: - `[[Set]]` başarılıysa `true`, değilse `false` döndürmelidir. @@ -359,7 +359,7 @@ Bir nesne birden fazla kez proxylanabilir (farklı proxy’ler nesneye farklı Dolayısıyla, metotları olan karmaşık nesneler için bu tür bir proxy kullanımı önerilmez. -```smart header="Private properties of a class" +```smart header="Bir sınıfın özel (private) özellikleri" Modern JavaScript motorları, `#` ile başlayan sınıf içi özel özellikleri yerel olarak destekler. Bunlar bölümünde anlatılmıştır. Proxy gerekmez. Ancak bu özelliklerin de kendine özgü sorunları vardır. Özellikle, kalıtılmazlar.