首页 web前端 js教程 现代 JavaScript 最佳实践 - 第 2 部分

现代 JavaScript 最佳实践 - 第 2 部分

Dec 08, 2024 pm 04:09 PM

Mejores Prácticas en JavaScript Moderno - Parte 2

在本文的第一部分中,我们探讨了现代 JavaScript 的基础知识以及一些基本的最佳实践,以开始编写更清晰、更高效的代码。但作为开发者,我们知道总是有更多东西需要学习和改进。

8. 可选链接 (?.)

在处理对象或嵌套结构时,我们有时需要在尝试访问属性之前检查它是否存在。 可选链接运算符 (?.) 是一个强大的工具,可以简化此任务,避免 null 或未定义值的属性访问错误。

为什么它有用?

想象一下您有一个复杂的对象结构,并且您不确定其中是否存在某些属性。如果没有可选链接,您将必须在每个步骤进行手动检查,这可能会使您的代码更长且可读性较差。使用 ?. 运算符,您可以安全地访问属性并在任何中间属性不存在时获取未定义的值。

基本示例

const producto = {};
const impuesto = producto?.precio?.impuesto;
console.log(impuesto); // undefined
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

在这种情况下,由于产品没有价格属性,因此可选链返回未定义而不是生成错误。

具有更复杂对象的示例

假设您有一个具有不同属性的产品列表,其中一些可能为空或未定义:

const productos = [
  { nombre: 'Laptop', detalles: { precio: 1000 } },
  { nombre: 'Teléfono', detalles: null },
  { nombre: 'Tablet', detalles: { precio: 500, impuesto: 50 } }
];

// Acceso seguro a la propiedad 'impuesto' de cada producto
productos.forEach(producto => {
  const impuesto = producto?.detalles?.impuesto;
  console.log(impuesto); // undefined, null o el valor real
});
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

在此示例中,可选链允许我们在尝试访问product.details.tax时避免错误,即使详细信息为空或不存在。

它如何改进您的代码?

  • 避免对空或未定义属性的访问错误。
  • 简化代码,使安全检查更清晰、更具可读性。
  • 允许您处理不确定或不完整的数据,这在处理来自 API 或数据库的响应时非常常见。

奖励:可选的函数链接

可选链也可以与函数一起使用,当您的函数可能未在对象上定义时,这非常有用:

const usuario = { nombre: 'Juan', obtenerEdad: null };
const edad = usuario.obtenerEdad?.();
console.log(edad); // undefined
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

这里,getAge函数是未定义的(它为空),但它不会抛出错误,它只是返回未定义。

9. 使用 async/await 进行异步处理

当您在 JavaScript 中使用异步操作时,例如从 API 获取数据或读取文件,async/await 语法可能是您最好的朋友。 async/await 不是使用 .then() 和 .catch() 中的 Promise,而是允许您以更清晰、更易读的方式编写异步代码,类似于我们编写同步代码的方式。

为什么使用异步/等待?

  • 简单性和可读性:您可以避免阅读和维护变得复杂的“承诺链”。
  • 更直观的错误处理:使用try/catch处理错误比使用.catch()更清晰。
  • 更精确的控制:允许在函数中的任何地方使用await,从而更容易控制更复杂的异步流程。

基本使用示例:

假设我们正在使用一个返回数据的 API。使用 async/await 而不是 .then() 使流程更容易遵循:

const producto = {};
const impuesto = producto?.precio?.impuesto;
console.log(impuesto); // undefined
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

实际示例:从 API 获取数据并将其显示在 UI 中

假设您有一个网页,您需要在其中显示来自 API 的用户信息。以下是如何使用 async/await 获取数据并将其呈现到界面的示例:

const productos = [
  { nombre: 'Laptop', detalles: { precio: 1000 } },
  { nombre: 'Teléfono', detalles: null },
  { nombre: 'Tablet', detalles: { precio: 500, impuesto: 50 } }
];

// Acceso seguro a la propiedad 'impuesto' de cada producto
productos.forEach(producto => {
  const impuesto = producto?.detalles?.impuesto;
  console.log(impuesto); // undefined, null o el valor real
});
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

对象.values()

返回一个包含对象属性的所有值的数组。当您只需要值而不需要键时,这是完美的。

示例:

const usuario = { nombre: 'Juan', obtenerEdad: null };
const edad = usuario.obtenerEdad?.();
console.log(edad); // undefined
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

对象.entries()

这是最通用的方法。返回一个数组的数组,其中每个子数组包含一个键及其对应的值。如果您想在一次操作中同时使用键和值,这非常有用。

示例:

async function obtenerDatos() {
  try {
    const respuesta = await fetch('https://api.ejemplo.com/datos');
    if (!respuesta.ok) {
      throw new Error('Error al obtener los datos');
    }
    const datos = await respuesta.json();
    console.log(datos);
  } catch (error) {
    console.error('Error:', error.message);
  }
}
登录后复制
登录后复制
登录后复制

奖励:使用 for...of 进行迭代

您是否知道可以将这些方法与 for...of 结合起来使您的代码更加简洁?这是使用 Object.entries() 的示例:

示例:

// Función para obtener y mostrar los datos de usuarios
async function obtenerUsuarios() {
  try {
    const respuesta = await fetch('https://api.ejemplo.com/usuarios');
    if (!respuesta.ok) {
      throw new Error('No se pudieron cargar los usuarios');
    }
    const usuarios = await respuesta.json();
    mostrarUsuariosEnUI(usuarios);
  } catch (error) {
    console.error('Hubo un problema con la carga de los usuarios:', error);
    alert('Error al cargar los usuarios. Intenta más tarde.');
  }
}

// Función para renderizar usuarios en el HTML
function mostrarUsuariosEnUI(usuarios) {
  const contenedor = document.getElementById('contenedor-usuarios');
  contenedor.innerHTML = usuarios.map(usuario => `
    <div>



<h3>
  
  
  ¿Qué mejoramos con async/await?
</h3>

<ol>
<li>
<strong>Manejo claro de errores:</strong> Usamos try/catch para capturar cualquier error que pueda ocurrir durante la obtención de datos, ya sea un problema con la red o con la API.</li>
<li>
<strong>Código más legible:</strong> La estructura de await hace que el flujo del código se lea de manera secuencial, como si fuera código sincrónico.</li>
<li>
<strong>Evita el anidamiento:</strong> Con async/await puedes evitar los callbacks anidados (el famoso "callback hell") y las promesas encadenadas.</li>
</ol>

<p>Usar async/await no solo mejora la calidad de tu código, sino que también hace que sea mucho más fácil depurar y mantener proyectos a largo plazo. ¡Es una herramienta poderosa que deberías incorporar siempre que trabajes con asincronía en JavaScript!</p>

<h2>
  
  
  10. Métodos modernos para objetos
</h2>

<p>Cuando trabajamos con objetos en JavaScript, es común que necesitemos iterar sobre las claves y los valores, o incluso extraer solo las claves o valores. Los métodos modernos como Object.entries(), Object.values() y Object.keys() hacen que estas tareas sean mucho más fáciles y legibles.</p>

<h3>
  
  
  Object.keys()
</h3>

<p>Este método devuelve un array con todas las claves de un objeto. Es útil cuando solo necesitas acceder a las claves y no a los valores.</p>

<p><strong>Ejemplo:</strong><br>
</p>

<pre class="brush:php;toolbar:false">const obj = { a: 1, b: 2, c: 3 };
const claves = Object.keys(obj);
console.log(claves); // ["a", "b", "c"]
登录后复制

这种方法更干净、更容易阅读,特别是当您处理大型或复杂的对象时。

11.使用Map作为非原始键

当需要将值与非字符串或符号的键关联时,请使用Map。它更加健壮,并且保持了键的类型和顺序。

示例:

const producto = {};
const impuesto = producto?.precio?.impuesto;
console.log(impuesto); // undefined
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

12.使用Symbol作为唯一键

符号是一项 JavaScript 功能,允许您创建唯一且不可变的键,当我们需要确保值不会被意外覆盖或访问时,符号是一个强大的工具。符号无法通过 Object.keys()、for...in 或 JSON.stringify() 等方法访问,这使得它们非常适合私有或“隐藏”值。

为什么要使用符号?

当我们使用文本字符串等键创建对象的属性时,可以轻松操作或覆盖它们。然而,即使我们创建同名的符号,符号也能确保每个键都是唯一的。此外,符号不会出现在对象属性枚举中。

基本示例:

const productos = [
  { nombre: 'Laptop', detalles: { precio: 1000 } },
  { nombre: 'Teléfono', detalles: null },
  { nombre: 'Tablet', detalles: { precio: 500, impuesto: 50 } }
];

// Acceso seguro a la propiedad 'impuesto' de cada producto
productos.forEach(producto => {
  const impuesto = producto?.detalles?.impuesto;
  console.log(impuesto); // undefined, null o el valor real
});
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

在此示例中,hiddenKey 键是唯一的,尽管我们代码的另一部分可以创建另一个 Symbol('hidden'),但它会完全不同,并且不会影响存储在 obj 中的值。

高级示例:将 Symbol 与 Object.defineProperty 组合

您甚至可以将 Symbol 与 Object.defineProperty 一起使用,以更受控制的方式向对象添加属性,确保属性是不可枚举的。

const usuario = { nombre: 'Juan', obtenerEdad: null };
const edad = usuario.obtenerEdad?.();
console.log(edad); // undefined
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

在此示例中,secretKey 不会出现在对象的键枚举中,这使其成为不应意外访问或修改的“私有”值的理想选择。

注意事项:

  • 符号对于避免属性名称冲突非常有用,尤其是在使用第三方库或 API 时。
  • 虽然符号并不是严格意义上的“私有”,但它们不可按常规方式访问的事实有助于保护数据的完整性。
  • 请注意,Symbol 无法序列化为 JSON,因此如果需要传输数据,请务必正确处理 Symbol 属性。

13. 小心 JSON 和大数字

在 JavaScript 中,处理大量数字可能是一个真正的挑战。 Number 数据类型在准确表示整数方面存在限制:最大安全整数值为 9007199254740991(也称为 Number.MAX_SAFE_INTEGER)。如果您尝试使用大于此值的数字,则可能会失去精度,这可能会导致应用程序出现错误。

例如,假设您从外部 API 收到大量数字:

async function obtenerDatos() {
  try {
    const respuesta = await fetch('https://api.ejemplo.com/datos');
    if (!respuesta.ok) {
      throw new Error('Error al obtener los datos');
    }
    const datos = await respuesta.json();
    console.log(datos);
  } catch (error) {
    console.error('Error:', error.message);
  }
}
登录后复制
登录后复制
登录后复制

如您所见,数字 9007199254740999 被错误地转换为 9007199254741000。如果该数字对您的应用程序至关重要(例如唯一标识符或财务金额),这可能会出现问题。

如何避免这个问题?

一个简单而优雅的解决方案是使用 ECMAScript 2020 中引入的 BigInt 数据类型。BigInt 可以处理更大的数字而不会损失精度。但是,JSON 本身并不处理 BigInt,因此您需要在序列化数字时将其转换为字符串,然后在反序列化时将它们转换回来。

以下是如何做到这一点的示例:

使用 BigInt 和 JSON.stringify 的解决方案

const producto = {};
const impuesto = producto?.precio?.impuesto;
console.log(impuesto); // undefined
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

通过使用这种方法,您可以保持大量数据的准确性,而不会丢失重要数据。当您再次需要该数字时,只需将其转换回 BigInt:

const productos = [
  { nombre: 'Laptop', detalles: { precio: 1000 } },
  { nombre: 'Teléfono', detalles: null },
  { nombre: 'Tablet', detalles: { precio: 500, impuesto: 50 } }
];

// Acceso seguro a la propiedad 'impuesto' de cada producto
productos.forEach(producto => {
  const impuesto = producto?.detalles?.impuesto;
  console.log(impuesto); // undefined, null o el valor real
});
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

其他策略

如果您不想使用 BigInt 或者考虑性能,另一种策略是简单地将大数字视为 JSON 中的字符串。这避免了精度问题,但代价是必须在代码中进行转换。

示例:

const usuario = { nombre: 'Juan', obtenerEdad: null };
const edad = usuario.obtenerEdad?.();
console.log(edad); // undefined
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

为什么它很重要?

正确处理大数不仅对于计算的准确性至关重要,而且对于维护数据完整性也至关重要。当您使用您无法完全控制的第三方 API 或系统时,这一点尤其重要。错误解释的数字可能会导致应用程序失败,或更糟糕的是,可能会导致至关重要的数据错误,例如金融交易或数据库中唯一标识符的处理。

记住:不要忽略精度限制。虽然这看起来像是一个小细节,但应用程序可能会以意想不到的方式失败,并且代价高昂。

14. 显式处理 if 语句中的表达式

在 JavaScript 中,if 语句隐式将表达式转换为“真”或“假”值,如果不考虑此行为,可能会导致意外结果。尽管这种行为有时很有用,但建议在比较中明确,以避免细微的错误并提高代码的可读性。

“真”或“假”是什么意思?

  • “Falsy” 指的是在条件表达式中求值时被视为等同于 false 的值。示例:0、“”(空字符串)、null、未定义、NaN。
  • “Truthy” 是所有非 falsy 的值,即不是上述之一的任何值。示例:0 以外的任何数字、任何非空字符串、对象等

隐式示例(可能会给出意想不到的结果)

const producto = {};
const impuesto = producto?.precio?.impuesto;
console.log(impuesto); // undefined
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

在上面的例子中,条件没有被执行,因为 0 被认为是“假”。然而,当使用更复杂的值时,这种行为可能很难检测到。

明确的示例(更好的可读性)

const productos = [
  { nombre: 'Laptop', detalles: { precio: 1000 } },
  { nombre: 'Teléfono', detalles: null },
  { nombre: 'Tablet', detalles: { precio: 500, impuesto: 50 } }
];

// Acceso seguro a la propiedad 'impuesto' de cada producto
productos.forEach(producto => {
  const impuesto = producto?.detalles?.impuesto;
  console.log(impuesto); // undefined, null o el valor real
});
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

提示:每当您处理可能为 false 的值(例如 0、null、false 或“”)时,最好在比较中明确。这样您就可以确保逻辑按照您的期望执行,而不是因为隐式类型强制行为。

另一个值不明确的例子

假设您有一个可以为 null 的对象、一个空数组 [] 或一个空对象 {}。如果你这样做:

const usuario = { nombre: 'Juan', obtenerEdad: null };
const edad = usuario.obtenerEdad?.();
console.log(edad); // undefined
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

虽然 [] (空数组)是一个有效且真实的对象,但如果您不完全理解其行为,它可能会在将来导致混乱。与其依赖隐式强制转换,最好进行更显式的比较,例如:

async function obtenerDatos() {
  try {
    const respuesta = await fetch('https://api.ejemplo.com/datos');
    if (!respuesta.ok) {
      throw new Error('Error al obtener los datos');
    }
    const datos = await respuesta.json();
    console.log(datos);
  } catch (error) {
    console.error('Error:', error.message);
  }
}
登录后复制
登录后复制
登录后复制

为什么它很重要?

通过显式定义条件,可以降低 JavaScript 自动强制导致错误的风险。这种方法使您的代码更清晰、更易读、更可预测。此外,它还提高了可维护性,因为其他人(或将来的你自己)将能够快速理解逻辑,而不必记住 JavaScript 中虚假值的隐式行为。

15. 尽可能使用严​​格相等(===)

JavaScript 最令人困惑的行为之一来自非严格相等运算符 (==)。该运算符执行所谓的类型强制,这意味着它在比较值之前尝试将它们转换为通用类型。这可能会产生出乎意料的结果并且非常难以调试。

例如:

const producto = {};
const impuesto = producto?.precio?.impuesto;
console.log(impuesto); // undefined
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

这是一种在你开发过程中会让你发疯的事情。 == 运算符将 [] (空数组)与 ![] 进行比较(结果为 false,因为 [] 被视为 true 值,而 ![] 将其转换为 false)。然而,根据 JavaScript 的内部强制规则,这是一个有效的结果,尽管乍一看没有意义。

为什么会发生这种情况?

JavaScript 在比较之前将比较的双方转换为通用类型。在这种情况下,与 ![] 的布尔值相比,空数组 [] 变为 false。这种类型的强制是一个明显的例子,说明了错误的发生是多么微妙和难以识别。

提示:始终使用严格相等

为了避免这些问题,只要有可能,您应该使用严格相等 (===)。不同之处在于这个 运算符不执行类型强制 。这意味着它严格比较变量的值和类型。

const productos = [
  { nombre: 'Laptop', detalles: { precio: 1000 } },
  { nombre: 'Teléfono', detalles: null },
  { nombre: 'Tablet', detalles: { precio: 500, impuesto: 50 } }
];

// Acceso seguro a la propiedad 'impuesto' de cada producto
productos.forEach(producto => {
  const impuesto = producto?.detalles?.impuesto;
  console.log(impuesto); // undefined, null o el valor real
});
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

更典型的例子

以下是一些更常见的示例,说明非严格相等 (==) 可能会出现问题:

const usuario = { nombre: 'Juan', obtenerEdad: null };
const edad = usuario.obtenerEdad?.();
console.log(edad); // undefined
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

为什么使用 === 很重要?

  • 预测和可靠性: 使用 === 可以让您进行更可预测的比较,而不会出现意外或类型转换。
  • 避免难以检测的错误:当您的代码开始变得更大、更复杂时,与类型强制相关的错误可能很难发现和调试。
  • 提高代码可读性:当您看到显式比较时,其他开发人员(或将来的您自己)更容易理解您的代码,而不会产生隐式转换的混乱。

以上是现代 JavaScript 最佳实践 - 第 2 部分的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

<🎜>:泡泡胶模拟器无穷大 - 如何获取和使用皇家钥匙
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系统,解释
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆树的耳语 - 如何解锁抓钩
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

Java教程
1667
14
CakePHP 教程
1426
52
Laravel 教程
1328
25
PHP教程
1273
29
C# 教程
1255
24
JavaScript引擎:比较实施 JavaScript引擎:比较实施 Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和执行JavaScript代码时,效果会有所不同,因为每个引擎的实现原理和优化策略各有差异。1.词法分析:将源码转换为词法单元。2.语法分析:生成抽象语法树。3.优化和编译:通过JIT编译器生成机器码。4.执行:运行机器码。V8引擎通过即时编译和隐藏类优化,SpiderMonkey使用类型推断系统,导致在相同代码上的性能表现不同。

Python vs. JavaScript:学习曲线和易用性 Python vs. JavaScript:学习曲线和易用性 Apr 16, 2025 am 12:12 AM

Python更适合初学者,学习曲线平缓,语法简洁;JavaScript适合前端开发,学习曲线较陡,语法灵活。1.Python语法直观,适用于数据科学和后端开发。2.JavaScript灵活,广泛用于前端和服务器端编程。

从C/C到JavaScript:所有工作方式 从C/C到JavaScript:所有工作方式 Apr 14, 2025 am 12:05 AM

从C/C 转向JavaScript需要适应动态类型、垃圾回收和异步编程等特点。1)C/C 是静态类型语言,需手动管理内存,而JavaScript是动态类型,垃圾回收自动处理。2)C/C 需编译成机器码,JavaScript则为解释型语言。3)JavaScript引入闭包、原型链和Promise等概念,增强了灵活性和异步编程能力。

JavaScript和Web:核心功能和用例 JavaScript和Web:核心功能和用例 Apr 18, 2025 am 12:19 AM

JavaScript在Web开发中的主要用途包括客户端交互、表单验证和异步通信。1)通过DOM操作实现动态内容更新和用户交互;2)在用户提交数据前进行客户端验证,提高用户体验;3)通过AJAX技术实现与服务器的无刷新通信。

JavaScript在行动中:现实世界中的示例和项目 JavaScript在行动中:现实世界中的示例和项目 Apr 19, 2025 am 12:13 AM

JavaScript在现实世界中的应用包括前端和后端开发。1)通过构建TODO列表应用展示前端应用,涉及DOM操作和事件处理。2)通过Node.js和Express构建RESTfulAPI展示后端应用。

了解JavaScript引擎:实施详细信息 了解JavaScript引擎:实施详细信息 Apr 17, 2025 am 12:05 AM

理解JavaScript引擎内部工作原理对开发者重要,因为它能帮助编写更高效的代码并理解性能瓶颈和优化策略。1)引擎的工作流程包括解析、编译和执行三个阶段;2)执行过程中,引擎会进行动态优化,如内联缓存和隐藏类;3)最佳实践包括避免全局变量、优化循环、使用const和let,以及避免过度使用闭包。

Python vs. JavaScript:社区,图书馆和资源 Python vs. JavaScript:社区,图书馆和资源 Apr 15, 2025 am 12:16 AM

Python和JavaScript在社区、库和资源方面的对比各有优劣。1)Python社区友好,适合初学者,但前端开发资源不如JavaScript丰富。2)Python在数据科学和机器学习库方面强大,JavaScript则在前端开发库和框架上更胜一筹。3)两者的学习资源都丰富,但Python适合从官方文档开始,JavaScript则以MDNWebDocs为佳。选择应基于项目需求和个人兴趣。

Python vs. JavaScript:开发环境和工具 Python vs. JavaScript:开发环境和工具 Apr 26, 2025 am 12:09 AM

Python和JavaScript在开发环境上的选择都很重要。1)Python的开发环境包括PyCharm、JupyterNotebook和Anaconda,适合数据科学和快速原型开发。2)JavaScript的开发环境包括Node.js、VSCode和Webpack,适用于前端和后端开发。根据项目需求选择合适的工具可以提高开发效率和项目成功率。

See all articles