2.9 דסטרקצ׳רינג וספרד פתרון
פתרון - דסטרקצ'רינג וספרד
תרגיל 1 - דסטרקצ'רינג בסיסי
// 1. first three colors
const colors = ["red", "green", "blue", "yellow", "purple"];
const [red, green, blue] = colors;
console.log(red, green, blue); // "red" "green" "blue"
// 2. second and fourth elements
const numbers = [10, 20, 30, 40, 50];
const [, second, , fourth] = numbers;
console.log(second, fourth); // 20 40
// 3. name, age, email from object
const user = { name: "Alice", age: 25, email: "alice@test.com", city: "Tel Aviv" };
const { name, age, email } = user;
console.log(name, age, email); // "Alice" 25 "alice@test.com"
// 4. name with age default
const partialUser = { name: "Bob" };
const { name: pName, age: pAge = 18 } = partialUser;
console.log(pName, pAge); // "Bob" 18
// 5. rename name to userName
const profile = { name: "Charlie", role: "admin" };
const { name: userName } = profile;
console.log(userName); // "Charlie"
// 6. swap variables
let x = 100;
let y = 200;
[x, y] = [y, x];
console.log(x, y); // 200 100
תרגיל 2 - דסטרקצ'רינג מקונן
// 1. city and country from nested object
const company = {
name: "TechCorp",
address: {
street: "Herzl 10",
city: "Tel Aviv",
country: "Israel"
}
};
const { address: { city, country } } = company;
console.log(city, country); // "Tel Aviv" "Israel"
// 2. student data
const student = {
name: "Alice",
grades: [95, 88, 72],
info: {
city: "Haifa",
school: "Tech High"
}
};
const { name: studentName, grades: [firstGrade], info: { city: studentCity } } = student;
console.log(studentName, firstGrade, studentCity); // "Alice" 95 "Haifa"
// 3. API response
const response = {
status: 200,
data: {
users: [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" }
],
total: 2
}
};
const { status, data: { users: [{ name: firstName }], total } } = response;
console.log(status, firstName, total); // 200 "Alice" 2
תרגיל 3 - Rest ו-Spread עם מערכים
// 1. first and rest
const fruits = ["apple", "banana", "cherry", "date", "elderberry"];
const [first, ...rest] = fruits;
console.log(first); // "apple"
console.log(rest); // ["banana", "cherry", "date", "elderberry"]
// 2. combine three arrays
const a = [1, 2];
const b = [3, 4];
const c = [5, 6];
const combined = [...a, ...b, ...c];
console.log(combined); // [1, 2, 3, 4, 5, 6]
// 3. copy with elements at start and end
const original = [2, 3, 4];
const extended = [1, ...original, 5];
console.log(extended); // [1, 2, 3, 4, 5]
// 4. removeAt
function removeAt(arr, index) {
return [...arr.slice(0, index), ...arr.slice(index + 1)];
}
console.log(removeAt([1, 2, 3, 4, 5], 2)); // [1, 2, 4, 5]
תרגיל 4 - Rest ו-Spread עם אובייקטים
// 1. copy with additional property
const person = { name: "Alice", age: 25 };
const personWithCity = { ...person, city: "Tel Aviv" };
console.log(personWithCity);
// { name: "Alice", age: 25, city: "Tel Aviv" }
// 2. remove property using rest
const user = { name: "Alice", password: "secret", email: "alice@test.com" };
const { password, ...safeUser } = user;
console.log(safeUser); // { name: "Alice", email: "alice@test.com" }
// 3. merge with user overriding defaults
const defaults = { theme: "light", language: "en", fontSize: 14 };
const userPrefs = { theme: "dark", fontSize: 18 };
const settings = { ...defaults, ...userPrefs };
console.log(settings);
// { theme: "dark", language: "en", fontSize: 18 }
// 4. updateObject function
function updateObject(obj, updates) {
return { ...obj, ...updates };
}
const updated = updateObject(
{ name: "Alice", age: 25, city: "Tel Aviv" },
{ age: 26, email: "alice@test.com" }
);
console.log(updated);
// { name: "Alice", age: 26, city: "Tel Aviv", email: "alice@test.com" }
תרגיל 5 - דסטרקצ'רינג בפונקציות
// 1. getFullName
function getFullName({ firstName, lastName }) {
return `${firstName} ${lastName}`;
}
console.log(getFullName({ firstName: "Alice", lastName: "Smith" }));
// "Alice Smith"
// 2. calculateArea
function calculateArea({ width, height, unit = "cm" }) {
return `${width * height} ${unit}^2`;
}
console.log(calculateArea({ width: 10, height: 5 })); // "50 cm^2"
console.log(calculateArea({ width: 3, height: 4, unit: "m" })); // "12 m^2"
// 3. createUser
function createUser({ name, age = 18, role = "user", ...rest }) {
return {
name,
age,
role,
extra: rest
};
}
console.log(createUser({ name: "Alice", email: "alice@test.com", active: true }));
// { name: "Alice", age: 18, role: "user", extra: { email: "alice@test.com", active: true } }
// 4. printScores
function printScores(name, ...scores) {
const average = scores.reduce((sum, s) => sum + s, 0) / scores.length;
console.log(`${name}'s average: ${average}`);
}
printScores("Alice", 90, 85, 92, 88);
// "Alice's average: 88.75"
תרגיל 6 - Shallow vs Deep Copy
// 1. shallow copy problem
const original = {
name: "Alice",
scores: [90, 85, 92],
address: { city: "Tel Aviv" }
};
const shallowCopy = { ...original };
shallowCopy.name = "Bob"; // doesn't affect original
shallowCopy.scores[0] = 100; // DOES affect original!
shallowCopy.address.city = "Haifa"; // DOES affect original!
console.log(original.name); // "Alice" - OK
console.log(original.scores[0]); // 100 - changed!
console.log(original.address.city); // "Haifa" - changed!
// 2. deep copy with structuredClone
const original2 = {
name: "Alice",
scores: [90, 85, 92],
address: { city: "Tel Aviv" }
};
const deepCopy = structuredClone(original2);
deepCopy.scores[0] = 100;
deepCopy.address.city = "Haifa";
console.log(original2.scores[0]); // 90 - not affected!
console.log(original2.address.city); // "Tel Aviv" - not affected!
// 3. JSON.parse/stringify limitations
const testObj = {
name: "Alice",
greet: function() { return "hi"; }, // function
value: undefined, // undefined
date: new Date("2024-01-01") // Date object
};
const jsonCopy = JSON.parse(JSON.stringify(testObj));
console.log(jsonCopy);
// {
// name: "Alice",
// // greet is GONE (functions are not serializable)
// // value is GONE (undefined is not serializable)
// date: "2024-01-01T00:00:00.000Z" // converted to string!
// }
תרגיל 7 - דפוסים מעשיים
// 1. mergeConfig
function mergeConfig(...configs) {
return configs.reduce((merged, config) => ({ ...merged, ...config }), {});
}
console.log(mergeConfig(
{ host: "localhost", port: 3000 },
{ port: 8080, debug: true },
{ debug: false, timeout: 5000 }
));
// { host: "localhost", port: 8080, debug: false, timeout: 5000 }
// 2. pluck
function pluck(arr, key) {
return arr.map((item) => item[key]);
}
const users = [
{ name: "Alice", age: 25 },
{ name: "Bob", age: 30 },
{ name: "Charlie", age: 35 }
];
console.log(pluck(users, "name")); // ["Alice", "Bob", "Charlie"]
// alternative with destructuring:
function pluck2(arr, key) {
return arr.map(({ [key]: value }) => value);
}
// 3. immutableUpdate
function immutableUpdate(obj, path, value) {
if (path.length === 0) return value;
const [first, ...rest] = path;
return {
...obj,
[first]: rest.length === 0
? value
: immutableUpdate(obj[first], rest, value)
};
}
const state = {
user: {
name: "Alice",
address: { city: "Tel Aviv" }
}
};
const newState = immutableUpdate(state, ["user", "address", "city"], "Haifa");
console.log(newState);
// { user: { name: "Alice", address: { city: "Haifa" } } }
console.log(state.user.address.city); // "Tel Aviv" - original unchanged
תרגיל 8 - תרגיל מסכם
const employees = [
{ id: 1, name: "Alice", department: "Engineering", salary: 15000, skills: ["JavaScript", "React"] },
{ id: 2, name: "Bob", department: "Design", salary: 12000, skills: ["Figma", "CSS"] },
{ id: 3, name: "Charlie", department: "Engineering", salary: 18000, skills: ["Python", "Node.js"] },
{ id: 4, name: "Diana", department: "Marketing", salary: 11000, skills: ["SEO", "Analytics"] },
{ id: 5, name: "Eve", department: "Engineering", salary: 16000, skills: ["JavaScript", "TypeScript"] }
];
// 1. destructure first employee
const [{ name: firstName, department: firstDept }] = employees;
console.log(firstName, firstDept); // "Alice" "Engineering"
// 2. add bonus (immutable)
const withBonus = employees.map((emp) => ({
...emp,
bonus: emp.salary * 0.1
}));
console.log(withBonus[0]);
// { id: 1, name: "Alice", ..., salary: 15000, ..., bonus: 1500 }
console.log(employees[0].bonus); // undefined - original unchanged
// 3. engineer names with destructuring
function getEngineerNames(employees) {
return employees
.filter(({ department }) => department === "Engineering")
.map(({ name }) => name);
}
console.log(getEngineerNames(employees)); // ["Alice", "Charlie", "Eve"]
// 4. add skill (immutable)
function addSkill(employees, employeeId, newSkill) {
return employees.map((emp) => {
if (emp.id !== employeeId) return emp;
return {
...emp,
skills: [...emp.skills, newSkill]
};
});
}
const updated = addSkill(employees, 1, "TypeScript");
console.log(updated[0].skills); // ["JavaScript", "React", "TypeScript"]
console.log(employees[0].skills); // ["JavaScript", "React"] - original unchanged
// 5. transfer employee (immutable)
function transferEmployee(employees, employeeId, newDepartment, salaryChange) {
return employees.map((emp) => {
if (emp.id !== employeeId) return emp;
return {
...emp,
department: newDepartment,
salary: emp.salary + salaryChange
};
});
}
const transferred = transferEmployee(employees, 2, "Engineering", 3000);
console.log(transferred[1]);
// { id: 2, name: "Bob", department: "Engineering", salary: 15000, skills: [...] }
console.log(employees[1].department); // "Design" - original unchanged
// 6. summary
function getSummary(employees) {
const allSkills = [...new Set(employees.flatMap(({ skills }) => skills))];
const avgSalary = employees.reduce((sum, { salary }) => sum + salary, 0) / employees.length;
const byDepartment = employees.reduce((groups, emp) => {
const { department } = emp;
if (!groups[department]) groups[department] = [];
groups[department].push(emp.name);
return groups;
}, {});
return {
allSkills,
avgSalary,
byDepartment
};
}
console.log(getSummary(employees));
// {
// allSkills: ["JavaScript", "React", "Figma", "CSS", "Python", "Node.js", "SEO", "Analytics", "TypeScript"],
// avgSalary: 14400,
// byDepartment: {
// Engineering: ["Alice", "Charlie", "Eve"],
// Design: ["Bob"],
// Marketing: ["Diana"]
// }
// }