לדלג לתוכן

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"]
//   }
// }