Node.js开发者必须熟悉的四个JavaScript概念

简介: 版权声明:本文为博主chszs的原创文章,未经博主允许不得转载。 https://blog.csdn.net/chszs/article/details/50054087 Node.js开发者必须熟悉的四个JavaScript概念作者:chszs,未经博主允许不得转载。
版权声明:本文为博主chszs的原创文章,未经博主允许不得转载。 https://blog.csdn.net/chszs/article/details/50054087

Node.js开发者必须熟悉的四个JavaScript概念

作者:chszs,未经博主允许不得转载。经许可的转载需注明作者和博客主页:http://blog.csdn.net/chszs

Node.js是一个服务器端的开发框架,它基于Google Chrome的V8 JavaScript引擎构建。尽管Node.js自身是使用C++开发的,但是它使用JavaScript作为其应用语言。
Node.js有四个概念对于初学者非常重要,应该理解并掌握它们。如下:

一、非阻塞或异步I/O

由于Node.js是一个服务器端框架,因此它的主要工作之一就是处理来自浏览器的请求。在传统的I/O系统中,只有先前请求的响应返回来后,新的请求才能发出。这也就是为什么称之为阻塞I/O的通信。服务器阻塞了下一个到来的请求,然后处理当前的请求,直到请求处理完成,发出响应,再解除下一个到来的请求的阻塞。

Node.js不遵循上面的阻塞I/O通信原则。如果一个请求需要的处理时间较长,Node.js会把请求发送到事件循环中,然后在调用栈上处理下一个请求。一旦事件循环中的请求完成了处理,它会通知Node.js,Node.js会返回响应给浏览器。下面可以看一个例子:

1、阻塞式I/O

// 餐桌1,获取订单1
var order1 = orderBlocking(['Coke', 'Iced Tea']);
// 服务订单1
serveOrder(order1);
// 一旦订单服务完成,服务员去另一张餐桌
// 餐桌2,订单2
var order2 = orderBlocking(['Coke', 'Water']);
// 服务订单2
serveOrder(order2);
// 一旦订单服务完成,服务员去另一张餐桌
// 餐桌3,订单3
var order3 = orderBlocking(['Iced Tea', 'Water']);
// 服务订单3
serveOrder(order3);
// 一旦订单服务完成,服务员去另一张餐桌

上面的例子中,服务员在第一个餐桌获得订单,然后向订单提供服务,服务完成后,服务员立刻移动到下一张餐桌获得订单。订单是按时间顺序进行处理的,服务器仅仅是服务于订单和阻塞其它的订单。

2、非阻塞式I/O

// 在餐桌1取走交付的订单并移动到下一个餐桌
orderNonBlocking(['Coke', 'Iced Tea'], function(drinks){
  return serveOrder(drinks);
});
// 在餐桌2取走交付的订单并移动到下一个餐桌
orderNonBlocking(['Beer', 'Whiskey'], function(drinks){
  return serveOrder(drinks);
});
//在餐桌3取走交付的订单并移动到下一个餐桌
orderNonBlocking(['Hamburger', 'Pizza'], function(food){
  return serveOrder(food);
});

在上面的例子中,服务员去获取订单并通知厨师,再去下一个餐桌。在第一个订单被处理期间,服务员移动到下一个餐桌去获取订单,服务员不阻塞订单。

二、原型

在JavaScript中,原型即Prototype,是一个比较复杂的概念。Node.js使用了原型的地方很多,因此每一个JavaScript开发者都应该熟悉这个概念。

像Java、C++等编程语言都实现了典型的继承,这有助于代码的重用。首先构建一个基类(作为对象的蓝图),然后从这个类创建对象或扩展这个类。

但是JavaScript语言没有这样的概念。首先在JavaScript中创建一个对象,然后扩展这个对象或者从这个对象中创建新的对象。这就是所谓的原型继承,它通过原型来实现。

每一个JavaScript对象都链接到一个原型对象,并且可以从原型对象中继承其属性。原型有点类似于面向对象语言中的类,但实际上是不同的,它们自身都是对象。每一个对象都链接到Object.prototype,它是JavaScript预定义的对象。

如果你在通过obj.propName或obj[‘propName’]来查看属性时,这个对象有没有这样的属性,可以通过obj.hasOwnProperty(‘propName’)来检查,JavaScript的运行时会查看原型对象中是否有这个属性。如果原型对象没有这样的属性,然后再依次检查此对象本身有没有这样的属性(有可能对象继承了几级),直到匹配到此属性。如果整个属性链都没有这样的属性,那么就会返回未定义的值。

用例子来说明这一点:

if (typeof Object.create !== 'function') {
    Object.create = function (o) {
        var F = function () {};
        F.prototype = o;
        return new F();
    };
var otherPerson = Object.create(person);

当创建了一个新对象时,你可以选择这个对象的原型。在上面的代码中,我们增加了一个Object函数的create方法。create方法创建了一个新对象,并且使用了另一个对象作为它的原型,并作为参数传递到新对象。

当我们修改了新对象,它的原型还保留原样,不受影响。但是如果我们要修改原型对象,那么就会影响到所有基于此原型对象的对象。

原型是一个很复杂的概念,需要继续深入。

三、模块

如果你熟悉Java语言的包Package概念,那么你会理解Node.js的模块这个概念,两者没什么不同。模块是简单的JavaScript文件,它包含了特定目的的代码。模块模式(Module Pattern)用于简化代码的组织和导航。要使用模块的属性,你必须在JavaScript中require导入它,与Java语言中的import导入相同。

Node.js中有两者类型的模块:

1、核心模块(Core Module)

核心模块包含了预编译到Node.js的库。核心模块的模板是向开发者提供经常出现和重复的代码片段,如果没有这些,那么开发者会陷入这些大量重复且冗长无趣的工作中。常见的核心模块包括:HTTP模块、URL模块、EVENTS模块、文件系统模块等。

2、用户定义的模块(User Defined Module)

用户定义的模块是开发者为了特定功能自己实现的模块。通常是核心模块不能满足所需的功能时开发的。用户定义的模块同样需要require导入。如果是核心模块,require导入只需传入模块名,而对于用户定义的模块,require导入还需要传入文件系统的路径。

比如:

// 导入核心模块
var http = require('http);
// 导入用户定义的模块
var something = require('./folder1/folder2/folder3/something.js');

四、回调

在JavaScript语言中,函数被认为是第一级的对象。这意味着开发者可以把函数当作是常规对象那样,做所有的操作。可以把函数赋值给一个变量,还可以把函数作为参数传递给方法,还可以把函数作为对象的属性,甚至可以从函数返回函数。

回调是JavaScript语言中的一种匿名函数,它可以作为参数传递给另一个函数,还可以在随后的函数执行中执行回调函数或返回回调函数。这是回调函数广泛使用的编程范式。

把回调函数作为参数传递给另一个函数时,我们只需传递函数定义,也即,我们无需知道回调函数什么时候得以执行。这完全取决于调用函数的机制,故以回调命名。回调函数是Node.js的非阻塞通信和异步处理的基础。

setTimeout(function() {
    console.log("world");
}, 2000)
console.log("hello");

这是最简单的回调函数的例子之一,我们把匿名函数当作参数传递给setTimeout函数,而匿名函数仅仅是在控制台输出日志“world”。由于这只是函数定义,我们并不知道它什么时候得以执行,执行取决于setTimeout函数的2000毫秒后输出。

故第二个日志语句先在控制台输出“hello”,然后等两秒后再输出回调函数定义的日志“world”。

// output
hello
world

理解以上四个概念有助于深入Node.js。

目录
相关文章
|
6天前
|
存储 JavaScript 前端开发
webSocket+Node+Js实现在线聊天(包含所有代码)
文章介绍了如何使用WebSocket、Node.js和JavaScript实现在线聊天功能,包括完整的前端和后端代码示例。
31 0
|
8天前
|
JavaScript 前端开发 开发工具
五子棋小游戏(JS+Node+Websocket)可分房间对战
本文介绍了通过JS、Node和WebSocket实现的五子棋游戏,支持多人在线对战和观战功能。
20 1
五子棋小游戏(JS+Node+Websocket)可分房间对战
|
20天前
|
自然语言处理 JavaScript 前端开发
探索JavaScript中的闭包:从基础概念到实际应用
本文深入探讨了JavaScript中闭包的概念,从定义、作用域链和实际应用等方面进行了详细阐述。通过生动的比喻和实例代码,帮助读者理解闭包在函数执行上下文中的重要性,以及如何在实际开发中有效利用闭包解决复杂问题。同时,文章也指出了过度使用闭包可能导致的潜在问题,并给出了相应的优化建议。
|
2月前
|
JSON JavaScript 前端开发
JS的无限可能: 前端 精妙DOM技巧至Node.js的服务端
JS的无限可能: 前端 精妙DOM技巧至Node.js的服务端
|
2月前
|
JavaScript 前端开发
js bom的概念
js bom的概念
29 1
|
2月前
|
Java 数据库连接 数据库
从零到精通:揭秘 Hibernate 构建持久层服务的全过程,你离数据持久化大师还有多远?
【8月更文挑战第31天】本文详细介绍了如何从零开始使用 Hibernate 构建一个持久层服务。首先,通过在 Maven 项目中添加必要的依赖,确保项目具备使用 Hibernate 的条件。接着,配置 `hibernate.cfg.xml` 文件以连接 MySQL 数据库,并设置了基本属性。然后定义了一个简单的 `User` 实体类及其映射关系。此外,还创建了一个 `HibernateUtil` 工具类来管理 `SessionFactory`。
28 0
|
2月前
|
JavaScript 前端开发 测试技术
Vue.js开发者必看!Vue Test Utils携手端到端测试,打造无懈可击的应用体验,引领前端测试新风尚!
【8月更文挑战第30天】随着Vue.js的普及,构建可靠的Vue应用至关重要。测试不仅能确保应用质量,还能提升开发效率。Vue Test Utils作为官方测试库,方便进行单元测试,而结合端到端(E2E)测试,则能构建全面的测试体系,保障应用稳定性。本文将带你深入了解如何使用Vue Test Utils进行单元测试,通过具体示例展示如何测试组件行为;并通过Cypress进行E2E测试,确保整个应用流程的正确性。无论是单元测试还是E2E测试,都能显著提高Vue应用的质量,让你更加自信地交付高质量的应用。
45 0
|
2月前
|
JavaScript 开发者 UED
Vue.js组件库大对决:Element UI与Vuetify,开发者的罗密欧与朱丽叶!
【8月更文挑战第30天】Element UI和Vuetify是Vue.js开发中的热门组件库,前者简洁高效,后者遵循Material Design,国际化程度高。两者均提供丰富的组件支持,但Vuetify组件更多样,设计更灵活;Element UI在性能和中文支持上更优。文档方面,Element UI更直观易懂,而Vuetify配置灵活但学习成本稍高。选择时需综合考虑项目需求、团队背景及设计风格,以达到最佳开发效果。
96 0
|
2月前
|
JavaScript 前端开发 API
全栈开发革命来临!Vue.js与Node.js联手,打造前后端无缝对接的奇迹之作!
【8月更文挑战第30天】在Web开发领域,前后端分离与协作至关重要。Vue.js以其轻量级和易用性深受前端开发者喜爱,而Node.js则以高性能和事件驱动特性在后端领域崭露头角。二者结合开启了全栈开发新篇章,通过RESTful API或GraphQL实现高效稳定通信。本文以示例说明如何使用Vue.js和Node.js构建全栈应用,从前端Vue组件到后端Express服务器,展示了数据获取与展示的全过程。这种组合提供了一种高效简洁的全栈开发方案,使开发者能更专注于业务逻辑实现。
67 0
|
2月前
|
缓存 JavaScript 前端开发
Vue.js与JavaScript性能优化终极揭秘:掌握这些技巧,让你的Web应用飞一般地流畅!
【8月更文挑战第30天】随着前端应用复杂度的增加,性能优化变得至关重要。本文深入探讨了如何利用Vue.js和JavaScript实现高效的应用性能。主要内容包括:优化组件设计以减少不必要的渲染,采用异步组件与懒加载技术加速应用启动,利用虚拟滚动和分页处理大数据集,改进Vuex使用方式以及合理运用浏览器缓存等策略。通过具体示例和最佳实践,帮助开发者充分挖掘Vue.js潜力,打造高性能的前端应用。
48 0
下一篇
无影云桌面