Heim >Web-Frontend >js-Tutorial >Clean Code: JavaScript-Unveränderlichkeit, Kernkonzepte und Tools

Clean Code: JavaScript-Unveränderlichkeit, Kernkonzepte und Tools

Susan Sarandon
Susan SarandonOriginal
2025-01-17 20:33:15527Durchsuche

Clean Code: JavaScript immutability, core concepts and tools

Was ist Mutation?

Mutation bezieht sich auf die direkte Änderung eines vorhandenen Werts. In JavaScript können Objekte und Arrays standardmäßig geändert (mutiert) werden:

<code class="language-javascript">// 变异示例
const user = { name: 'Alice' };
user.name = 'Bob';           // 变异对象属性

const numbers = [1, 2, 3];
numbers.push(4);             // 变异数组
numbers[0] = 0;              // 变异数组元素</code>

Diese Mutationen können zu schwer zu findenden Fehlern führen, insbesondere in großen Anwendungen.

Warum sollten Mutationen vermieden werden?

Sehen wir uns ein einfaches Beispiel an:

<code class="language-javascript">// 使用变异的代码
const cart = {
  items: [],
  total: 0
};

function addProduct(cart, product) {
  cart.items.push(product);
  cart.total += product.price;
}

// 使用示例
const myCart = cart;
addProduct(myCart, { id: 1, name: "Laptop", price: 999 });
// 直接更改 myCart
console.log(cart === myCart); // true,两个变量指向同一个对象</code>

Mutationsproblem:

  1. Gemeinsame Referenzen: Verschiedene Teile des Codes können dasselbe Objekt ändern, ohne dass andere Teile davon erfahren.
  2. Nebenwirkungen: Änderungen wirken sich auf andere Funktionen aus, die dasselbe Objekt verwenden.
  3. Schwer zu debuggen: Es kann nicht nachvollzogen werden, welcher Teil des Codes das Objekt geändert hat.
  4. Komplexe Tests: Mutationen erschweren das Schreiben von Unit-Tests.

Lösung: Unveränderlichkeitsprogrammierung

Die Unveränderlichkeitsmethode erstellt für jede Änderung eine neue Kopie des Objekts:

<code class="language-javascript">// 不变性代码
function addProduct(cart, product) {
  // 创建一个新对象,而不更改原始对象
  return {
    items: [...cart.items, product],
    total: cart.total + product.price
  };
}

// 使用示例
const initialCart = { items: [], total: 0 };
const newCart = addProduct(initialCart, { id: 1, name: "Laptop", price: 999 });

console.log(initialCart); // { items: [], total: 0 }
console.log(newCart);     // { items: [{...}], total: 999 }
console.log(initialCart === newCart); // false,它们是不同的对象</code>

Vorteile dieses Ansatzes:

  1. Vorhersehbarkeit: Jede Funktion gibt einen neuen Zustand zurück, keine versteckten Nebenwirkungen.
  2. Änderungsverfolgung: Jede Änderung erstellt ein neues Objekt, das nachverfolgt werden kann.
  3. Einfach zu testen: Funktionen sind reine Funktionen und einfacher zu testen.
  4. Besseres Debugging: Kann den Status vor und nach Änderungen vergleichen.

Moderne Unveränderlichkeitstools

Immer: Einfacher Schreibstil

Immer ermöglicht es Ihnen, Code zu schreiben, der wie normaler JavaScript-Code aussieht, aber unveränderte Ergebnisse liefert:

<code class="language-javascript">import produce from 'immer';

const initialCart = {
  items: [],
  total: 0,
  customer: {
    name: 'Alice',
    preferences: {
      notifications: true
    }
  }
};

// 不使用 Immer(冗长的方法)
const updatedCart = {
  ...initialCart,
  items: [...initialCart.items, { id: 1, name: "Laptop", price: 999 }],
  total: initialCart.total + 999,
  customer: {
    ...initialCart.customer,
    preferences: {
      ...initialCart.customer.preferences,
      notifications: false
    }
  }
};

// 使用 Immer(简单的方法)
const updatedCartImmer = produce(initialCart, draft => {
  draft.items.push({ id: 1, name: "Laptop", price: 999 });
  draft.total += 999;
  draft.customer.preferences.notifications = false;
});</code>

Vorteile von Immer:

  • Vertraute Syntax: Schreiben Sie Code wie gewohnt.
  • Keine neue API zu erlernen: Verwenden Sie reguläre JavaScript-Objekte und -Arrays.
  • Schnell: Kopieren Sie nur die geänderten Teile.
  • Automatische Änderungserkennung: Verfolgen Sie Änderungen und erstellen Sie nur bei Bedarf neue Referenzen.
  • Funktioniert gut mit TypeScript: Alle Typinformationen bleiben erhalten.

Immutable.js: effiziente Datenstruktur

Immutable.js bietet Datenstrukturen, die auf Unveränderlichkeit ausgelegt sind:

<code class="language-javascript">import { Map, List } from 'immutable';

// 创建不变的数据结构
const cartState = Map({
  items: List([]),
  total: 0
});

// 添加一个项目
const newCart = cartState
  .updateIn(
    ['items'],
    items => items.push(Map({
      id: 1,
      name: "Laptop",
      price: 999
    }))
  )
  .update('total', total => total + 999);

// Immutable.js 方法始终返回新实例
console.log(cartState.getIn(['items']).size); // 0
console.log(newCart.getIn(['items']).size);   // 1

// 轻松比较
console.log(cartState.equals(newCart)); // false

// 转换回常规 JavaScript
const cartJS = newCart.toJS();</code>

Vorteile von Immutable.js:

  • Die Verwendung unveränderlicher Datenstrukturen ist schnell.
  • Umfangreiche API für die Arbeit mit Daten.
  • Speichereffizienter Datenaustausch.
  • Verwenden Sie equal() für eine einfache Gleichheitsprüfung.
  • Verhindern Sie versehentliche Änderungen.

ESLints unveränderliche Konfiguration

ESLint kann dabei helfen, unveränderliche Codierungspraktiken durch spezifische Regeln durchzusetzen:

<code class="language-javascript">// .eslintrc.js
module.exports = {
  plugins: ['functional'],
  rules: {
    'functional/immutable-data': 'error',
    'functional/no-let': 'error',
    'functional/prefer-readonly-type': 'error'
  }
};</code>

Diese Regeln werden:

  • Verhindern Sie direkte Datenmutationen.
  • Fördern Sie die Verwendung von const anstelle von let.
  • Es wird empfohlen, in TypeScript schreibgeschützte Typen zu verwenden.

TypeScript und Unveränderlichkeit

TypeScript hilft durch sein Typsystem, Unveränderlichkeit zu erzwingen:

<code class="language-typescript">// 购物车的不变类型
type Product = {
  readonly id: number;
  readonly name: string;
  readonly price: number;
};

type Cart = {
  readonly items: ReadonlyArray<Product>;
  readonly total: number;
};

// TypeScript 防止变异
const cart: Cart = {
  items: [],
  total: 0
};

// 编译错误:items 是只读的
cart.items.push({ id: 1, name: "Laptop", price: 999 });

// 函数必须创建一个新的购物车
function addProduct(cart: Cart, product: Product): Cart {
  return {
    items: [...cart.items, product],
    total: cart.total + product.price
  };
}

// TypeScript 确保原始对象不会更改
const newCart = addProduct(cart, { id: 1, name: "Laptop", price: 999 });</code>

Schreibgeschützter Modifikator für TypeScript:

  • schreibgeschützt: Attributänderungen verhindern.
  • ReadonlyArray: Array-Änderungen verhindern.
  • Schreibgeschützt: Macht alle Eigenschaften schreibgeschützt.

Diese Typen werden zur Kompilierzeit überprüft und helfen so, Fehler frühzeitig zu erkennen.

Fazit

Unveränderlichkeit macht Ihren Code vorhersehbarer und wartbarer. Es ist zwar etwas gewöhnungsbedürftig, aber die Vorteile in Bezug auf Zuverlässigkeit und Wartbarkeit sind es wert.

Das obige ist der detaillierte Inhalt vonClean Code: JavaScript-Unveränderlichkeit, Kernkonzepte und Tools. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn