🟨 Java geliştirici için JavaScript
Java dünyasından gelen geliştiricilere yönelik ES6+, modül sistemi, HTTP istemcileri, bundling ve Jest testleri — öğren ve mülakatta net anlat.
🔎 Genel Bakış
- JS tek iş parçacıklı, event loop ve async odaklıdır (thread yerine
Promise/async/await). - Tip sistemi dinamiktir; TypeScript geçişi önerilir ama bu sayfa “Java geliştirici için yeter” JS odaklıdır.
- Modern JS → ESM modülleri, fetch API, bundler ile prod’a uygun paket.
🧠 Dil Temelleri (Java ↔ JS)
Önemli Farklar
- == vs ===:
===(strict) tercih edilir; tür dönüşümü yapmaz. - var/let/const:
varhoisting + function scope;let/constblock scope + TDZ. - this: bağlam çağrı şekline göre değişir; arrow function’lar lexical
thiskullanır. - Prototype: Sınıflar syntactic sugar; altında prototip zinciri vardır.
- Truthy/Falsy:
0,"",null,undefined,NaN,false→ falsy; diğerleri truthy.
// === kullan
console.log(0 == false); // true (kötü)
console.log(0 === false); // false (doğru yaklaşım)
// let/const
let count = 1;
const PI = 3.14; // yeniden atama yok
// Arrow this
const obj = {
val: 42,
regular(){ setTimeout(function(){ console.log(this.val); }, 0); }, // undefined
arrow(){ setTimeout(() => console.log(this.val), 0); } // 42
};
obj.regular(); obj.arrow();
✨ ES6+ Özellikleri
- Destructuring, spread/rest, template string, default param.
- Map/Set, class & static, private field
#. - Optional chaining
?., nullish coalescing??. - Promise, async/await, Promise.all/any/allSettled.
const user = { id: 1, profile: { name: "Ada" } };
const { id, profile: { name } } = user;
const full = { ...user, active: true }; // spread
function sum(...nums){ return nums.reduce((a,b) => a+b, 0); } // rest
const title = `Merhaba ${name}`;
class Counter {
#val = 0; // private field
static of(n){ const c = new Counter(); c.#val = n; return c; }
inc(){ this.#val++; return this.#val; }
}
const c = Counter.of(5).inc();
const city = user.address?.city ?? "Bilinmiyor";
📦 Modüller: ESM vs CJS
| Tür | Export | Import | Nerede |
|---|---|---|---|
| ESM | export/export default | import {...} from 'mod' | Tarayıcı & Node (modern) |
| CommonJS | module.exports | require('mod') | Node (legacy) |
// math.js (ESM)
export function add(a,b){ return a+b; }
export default class Calc { mul(a,b){ return a*b; } }
// app.js
import Calc, { add } from './math.js';
console.log(add(2,3), new Calc().mul(2,3));
// Dinamik import (code-splitting)
if(someCond){ const { heavy } = await import('./heavy.js'); heavy(); }
⚙️ Runtime & Event Loop
- Tek iş parçacığı; I/O asenkron. Microtask (Promise) → Macrotask (setTimeout).
- Node’da CommonJS/ESM karma dünyası;
"type":"module"ile ESM. - CPU-ağır işler için Web Worker / Worker Threads düşün.
console.log("A");
setTimeout(() => console.log("C"), 0);
Promise.resolve().then(() => console.log("B")); // microtask önce
// A, B, C
🌳 DOM & Eventler
querySelector,addEventListener, event delegation.- Form verisi:
FormData,URLSearchParams.
<ul id="list"></ul>
<button id="add">Ekle</button>
const list = document.querySelector("#list");
document.querySelector("#add").addEventListener("click", () => {
const li = document.createElement("li");
li.innerText = "Öğe " + (list.children.length+1);
list.appendChild(li);
});
// Delegation:
list.addEventListener("click", (e) => {
if(e.target.tagName === "LI"){ e.target.remove(); }
});
🌐 HTTP — fetch & axios
fetch (yerleşik)
async function getUser(id, { signal } = {}) {
const res = await fetch(`/api/users/${id}`, { signal, headers:{ "Accept":"application/json" }});
if(!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
}
const c = new AbortController();
setTimeout(() => c.abort(), 3000); // timeout
getUser(1, { signal: c.signal }).catch(console.error);
POST / JSON
async function saveUser(u){
const res = await fetch('/api/users', {
method:'POST',
headers:{ 'Content-Type':'application/json' },
body: JSON.stringify(u)
});
if(!res.ok) throw new Error('Save failed');
return res.json();
}
axios (kolay interceptor & timeout)
import axios from "axios";
const api = axios.create({ baseURL:'/api', timeout: 5000 });
api.interceptors.response.use(
r => r,
e => {
if(e.response?.status === 401){ /* refresh veya login yönlendirme */ }
return Promise.reject(e);
}
);
const { data } = await api.get('/users', { params:{ page:1 }});
🚦 Hata Yönetimi
async function request(promise){
try{
const res = await promise;
return [res, null];
}catch(err){
return [null, err];
}
}
// Kullanım
const [user, err] = await request(api.get('/me'));
if(err){ /* toast/log */ }
Global: window.addEventListener('unhandledrejection'), window.onerror ile loglayın.
🧰 Bundling & Build
- Vite: hızlı dev server + rollup build.
- Webpack/Rollup/esbuild: tree-shaking, code-splitting, babel.
- Tarayıcı hedefi için Babel + core-js ile polyfill.
# Vite ile sıfırdan
npm create vite@latest myapp -- --template vanilla
cd myapp
npm i
npm run dev # HMR
npm run build # dist/
ESM Native: Modern tarayıcılarda bundling’siz de çalışabilirsiniz; ancak üretimde minify/split/cache-busting için bundler önerilir.
📜 package.json & Scriptler
{
"name": "acme-frontend",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"test": "jest --runInBand",
"lint": "eslint . --ext .js,.mjs",
"format": "prettier -w ."
},
"dependencies": {
"axios": "^1.7.0"
},
"devDependencies": {
"vite": "^5.0.0",
"jest": "^29.7.0",
"@jest/globals": "^29.7.0",
"eslint": "^9.0.0",
"prettier": "^3.2.0"
}
}
🧹 ESLint & Prettier
// eslint.config.js
export default [
{ files: ["**/*.js"], languageOptions:{ ecmaVersion: "latest", sourceType:"module" },
rules: { "no-unused-vars":"warn", "eqeqeq":"error", "no-console":"off" } }
];
{
"printWidth": 100,
"singleQuote": true,
"semi": true
}
🧪 Jest Testleri
Saf Fonksiyon Testi
// sum.js
export const sum = (a,b) => a + b;
// sum.test.js
import { describe, it, expect } from "@jest/globals";
import { sum } from "./sum.js";
describe("sum", () => {
it("toplar", () => { expect(sum(2,3)).toBe(5); });
});
Async & fetch Mock
// user.test.js
import { it, expect, vi, beforeEach } from "@jest/globals";
beforeEach(() => { global.fetch = vi.fn(); });
it("kullanıcıyı getirir", async () => {
fetch.mockResolvedValueOnce(new Response(JSON.stringify({ id:1, name:"Ada" }), { status:200 }));
const res = await fetch("/api/users/1");
const data = await res.json();
expect(data.name).toBe("Ada");
});
axios Mock
import axios from "axios";
import { it, expect, vi } from "@jest/globals";
vi.mock("axios");
it("axios ile liste çeker", async () => {
axios.get.mockResolvedValueOnce({ data:[{id:1}] });
const { data } = await axios.get("/api/list");
expect(data).toHaveLength(1);
});
JSDOM ile DOM testleri: Jest 29+’da testEnvironment: "jsdom".
🧵 Spring ile Entegrasyon
- CORS: Spring’te
@CrossOriginveya global CORS konfigürasyonu. - Auth: HttpOnly cookie (CSRF korumalı) veya Bearer Token; token’ı localStorage’da saklamayın tercih.
- Tarih/Zaman: ISO-8601 (UTC) gönderin;
OffsetDateTimeile uyumlu.
// Spring JSON uyumlu client
const api = axios.create({ baseURL:"/api", withCredentials:true });
export const getOrders = (page=0) => api.get("/orders", { params:{ page }});
🛡️ Güvenlik Notları
- XSS: Kullanıcı girdisini DOM’a eklerken sanitize edin (örn. DOMPurify).
innerTexttercih edin. - CSRF: SameSite=strict/lax cookie + CSRF token;
withCredentialskullanımında dikkat. - Eval yok, 3. parti scriptlere SRI ve CSP.
❓ Mülakat Soruları & Kısa Yanıtlar
1) == ve === farkı?
== tür dönüşümü yapar; === hem tür hem değer eşitliğini ister (tercih edilir).
2) Arrow function’larda this nasıl davranır?
Lexical this; çağırıldığı yere göre değil, tanımlandığı bağlama göre belirlenir.
3) Promise vs async/await?
Aynı modeli ifade eder; async/await daha okunaklıdır, hata yakalama try/catch ile yapılır.
4) ESM ve CJS farkı?
ESM statik import (tree-shaking), CJS dinamik require; tarayıcı/modern Node ESM’i destekler.
5) fetch ile timeout nasıl?
AbortController ile istek iptal edilir; axios’ta timeout ayarı var.
6) Event loop’ta microtask/macrotask?
Promise callbackleri microtask kuyruğunda; setTimeout gibi işler macrotask’tadır.
📝 JS Cheat Sheet
// Diziler
const arr = [1,2,3];
arr.map(x => x*2).filter(x => x>=4);
// Nesneler
const o = { a:1, b:2 };
const { a, ...rest } = o; // {a:1}, rest:{b:2}
// Async
const sleep = (ms) => new Promise(r => setTimeout(r, ms));
await sleep(100);
// Hata
try { await risky(); } catch(e){ console.error(e); }
// Modül
export function fn(){}; export default class C{}
// Import
import C, { fn } from './m.js';