Node.js 因其在后端利用 JavaScript 的能力而迅速成为构建 Web 应用程序和系统软件的标准。 Express 等流行框架和 Webpack 等工具有助于其广泛使用。尽管存在 Deno 和 Bun 等竞争对手,Node 仍然是领先的服务器端 JavaScript 平台。
JavaScript 的多范式性质允许各种编程风格,但它也带来了范围和对象突变等风险。缺乏尾部调用优化使得大型递归迭代变得危险,并且 Node 的单线程架构需要异步代码来提高效率。尽管面临挑战,但遵循 JavaScript 中的关键概念和最佳实践可以帮助 Node.js 开发人员编写可扩展且高效的代码。
1。 JavaScript 闭包
JavaScript 中的闭包是一个内部函数,即使在外部函数返回控制权之后,它也可以访问其外部函数的作用域。闭包使内部函数的变量成为私有的。 函数式编程已经流行起来,使得闭包成为 Node 开发者工具包的重要组成部分。这是 JavaScript 中闭包的一个简单示例:
2. JavaScript 原型
每个 JavaScript 函数都有一个原型属性,用于附加属性和方法。该属性不可枚举。它允许开发人员将方法或成员函数附加到其对象。 JavaScript 仅通过prototype 属性支持继承。对于继承的对象,prototype 属性指向该对象的父对象。将方法附加到函数的常见方法是使用原型,如下所示:
尽管现代 JavaScript 具有相当复杂的类支持,但它仍然使用底层的原型系统。这是该语言大部分灵活性的来源。
3.使用哈希名称定义私有属性
过去,使用下划线作为变量前缀的约定用于指示变量应该是私有的。然而,这只是一个建议,并不是平台强制的限制。现代 JavaScript 为类提供了 hashtag 私有成员和方法:
私有哈希名称是 JavaScript 中一个较新且非常受欢迎的功能!最新的 Node 版本和浏览器都支持它,并且 Chrome 开发工具允许您直接访问私有变量以方便。
4。使用闭包定义私有属性
有时您会看到另一种解决 JavaScript 原型系统中缺乏私有属性的方法是使用闭包。现代 JavaScript 允许您使用主题标签前缀定义私有属性,如上面的示例所示。然而,这对于 JavaScript 原型系统不起作用。另外,这是您在代码中经常发现的一个技巧,了解它在做什么很重要。
使用闭包定义私有属性可以让您模拟私有变量。需要访问私有属性的成员函数应该在对象本身上定义。以下是使用闭包创建私有属性的语法:
5。 JavaScript 模块
曾几何时,JavaScript 没有模块系统,开发人员设计了一个聪明的技巧(称为模块模式)来装配一些可以工作的东西。随着 JavaScript 的发展,它产生了两个而不是一个模块系统:CommonJS include 语法和 ES6 require 语法。
Node 传统上使用 CommonJS,而浏览器则使用 ES6。然而,Node 的最新版本(最近几年)也支持 ES6。现在的趋势是使用 ES6 模块,有一天我们将只使用一种模块语法来跨 JavaScript 使用。 ES6 看起来像这样(我们导出默认模块然后导入它):
您仍然会看到 CommonJS,并且有时需要使用它来导入模块。以下是使用 CommonJS 导出然后导入默认模块的方式:
6。错误处理
无论您使用什么语言或环境,错误处理都是必不可少且不可避免的。节点也不例外。处理错误有三种基本方法:try/catch 块、抛出新错误和 on() 处理程序。
带有 try/catch 的块是在出现问题时捕获错误的可靠方法:
在这种情况下,我们使用console.error将错误记录到控制台。您可以选择抛出错误,将其传递给下一个处理程序。请注意,这会破坏代码流的执行;也就是说,当前执行停止,堆栈上的下一个错误处理程序接管:
现代 JavaScript 在其 Error 对象上提供了很多有用的属性,包括 Error.stack 用于查看堆栈跟踪。在上面的示例中,我们使用构造函数参数设置 Error.message 属性和 Error.cause。
您会发现错误的另一个地方是异步代码块,您可以在其中使用 .then() 处理正常结果。在这种情况下,您可以使用 on(‘error’) 处理程序或 onerror 事件,具体取决于 Promise 如何返回错误。有时,API 会返回一个错误对象作为第二个返回值和正常值。 (如果您在异步调用上使用await,则可以将其包装在try/catch中以处理任何错误。)这是处理异步错误的简单示例:
无论如何,永远不要吞下错误! 我不会在这里展示,因为有人可能会复制并粘贴它。基本上,如果您发现错误然后不执行任何操作,您的程序将默默地继续运行,而没有任何明显的迹象表明出现了问题。逻辑将被打破,你将不得不思考,直到你发现你的 catch 块中什么都没有。 (请注意,提供 finally{} 块而不使用 catch 块将导致您的错误被吞没。)
7. JavaScript 柯里化
柯里化是一种使函数更加灵活的方法。使用柯里化函数,您可以传递函数期望的所有参数并获取结果,也可以仅传递参数的子集并接收返回的函数,该函数等待其余参数。这是一个简单的咖喱示例:
原始柯里化函数可以通过在一组单独的括号中依次传递每个参数来直接调用:
这是一项有趣的技术,它允许您创建函数工厂,其中外部函数允许您部分配置内部函数。例如,您还可以使用上面的柯里化函数,如下所示:
在实际使用中,当您需要创建许多根据某些参数而变化的函数时,这个想法会很有帮助。
8。 JavaScript 应用、调用和绑定方法
虽然我们不是每天都会使用它们,但了解一下 call、apply 和 bind 方法是有好处的。在这里,我们正在处理一些严重的语言灵活性问题。从本质上讲,这些方法允许您指定 this 关键字解析的内容。
在所有三个函数中,第一个参数始终是您想要赋予函数的 this 值或上下文。
三者中,call是最简单的。这与在指定其上下文时调用函数相同。这是一个例子:
请注意,apply 与 call 几乎相同。唯一的区别是您将参数作为数组传递,而不是单独传递。数组在 JavaScript 中更容易操作,为使用函数提供了更多可能性。这是使用 apply 和 call 的示例:
bind 方法允许您将参数传递给函数而不调用它。返回一个新函数,其参数限制在任何其他参数之前。这是一个例子:
9。 JavaScript 记忆
记忆化是一种优化技术,它通过存储昂贵操作的结果并在同一组输入再次出现时返回缓存的结果来加速函数执行。 JavaScript 对象的行为类似于关联数组,因此可以轻松地在 JavaScript 中实现记忆化。以下是将递归阶乘函数转换为记忆阶乘函数的方法:
10. JavaScript IIFE
立即调用函数表达式(IIFE)是创建后立即执行的函数。它与任何事件或异步执行没有任何联系。您可以定义 IIFE,如下所示:
第一对括号 function(){...} 将括号内的代码转换为表达式。第二对括号调用表达式生成的函数。 IIFE 也可以描述为自调用匿名函数。它最常见的用法是限制通过 var 创建的变量的范围或封装上下文以避免名称冲突。
还有一些情况,您需要使用 await 调用函数,但您不在异步函数块内。这种情况有时会发生在您想要直接执行并作为模块导入的文件中。您可以将这样的函数调用包装在 IIFE 块中,如下所示:
11。有用的参数特征
虽然 JavaScript 不支持方法重载(因为它可以处理函数上的任意参数计数),但它确实有几个强大的工具来处理参数。其一,您可以定义一个具有默认值的函数或方法:
您还可以一次接受并处理所有参数,这样您就可以处理传入的任意数量的参数。这使用 rest 运算符将所有参数收集到一个数组中:
如果您确实需要处理不同的参数配置,您可以随时检查它们:
另外,请记住 JavaScript 包含一个内置参数数组。每个函数或方法都会自动为您提供 arguments 变量,保存传递给调用的所有参数。
结论
当您熟悉 Node 时,您会发现有很多方法可以解决几乎所有问题。正确的方法并不总是显而易见的。有时,针对特定情况有多种有效方法。了解许多可用选项会有所帮助。
这里讨论的 10 个 JavaScript 概念是每个 Node 开发人员都将从中受益的基础知识。但它们只是冰山一角。 JavaScript 是一种强大而复杂的语言。使用它的次数越多,您就会越了解 JavaScript 到底有多么庞大,以及您可以用它做多少事情。
免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。
Copyright© 2022 湘ICP备2022001581号-3