Node.js是建立在Chrome强劲的V8 JavaScript引擎上的服务器端框架。虽然最初是用C++编写的,但是应用程序通过JavaScript运行。
下面这4个基本概念是你想要掌握node.js所必需的。我会尽可能长话短说向大家介绍它们。
1.非阻塞或异步I/O由于Node.js是一种服务器端框架,所以它的一个主要工作就是处理浏览器请求。在传统的I/O系统中,当前请求只有当先前请求的响应(HTML页面)已到达才会发出。这就是为什么它被称为阻塞I/O。服务器阻塞其他请求是为了处理当前的请求,而这会导致浏览器的等待。
Node.js不遵循I/O的这个原则。如果一个请求需要花费较长时间,那么Node.js会发送请求到事件循环(event loop)中,并继续在调用栈(call stack)中处理下一个请求。一旦未决请求完成处理,它就会告诉Node.js,并将响应渲染在浏览器上。
用一个虚拟的例子来理解这一点:
阻塞I / O
// take order for table 1 and wait... var order1 = orderBlocking(['Coke', 'Iced Tea']); // once order is ready, take order back to table. serveOrder(order1); // once order is delivered, move on to another table. // take order for table 2 and wait... var order2 = orderBlocking(['Coke', 'Water']); // once order is ready, take order back to table. serveOrder(order2); // once order is delivered, move on to another table. // take order for table 3 and wait... var order3 = orderBlocking(['Iced Tea', 'Water']); // once order is ready, take order back to table. serveOrder(order3); // once order is delivered, move on to another table.
在这个餐厅例子中,服务员给出菜单,等待订单完成,然后再回到餐桌根据菜单上菜。在当前客户点菜时,服务员就在旁边等待,不接受其他客户的菜单。
非阻塞I / O
// take order for table 1 and move on... orderNonBlocking(['Coke', 'Iced Tea'], function(drinks){ return serveOrder(drinks); }); // take order for table 2 and move on... orderNonBlocking(['Beer', 'Whiskey'], function(drinks){ return serveOrder(drinks); }); // take order for table 3 and move on... orderNonBlocking(['Hamburger', 'Pizza'], function(food){ return serveOrder(food); });
在这个例子中,服务员获得菜单,并告知厨师,然后返回取另一份菜单。在完成第一个菜单进程中,他既按照顺序给当前顾客上菜,也接受来自其他客户的点单。服务员不会因为阻塞来自于其他客户的点菜而浪费时间。
2.原型原型是JavaScript的一个复杂概念。不过因为在Node.js中你要多次用到原型,所以每个JavaScript开发人员都必须了解这个概念。
在实现经典继承的语言中,例如Java,或C ++,对于以代码重用为目的的语言,你首先必须写一个类,然后从该类创建对象或扩展该类。但是,在JavaScript中不存在类的概念。首先在JavaScript中创建一个对象,然后从这个对象中增加自己的对象,或创建新的对象。这就是所谓的原型传承和通过原型的实现。
每个JavaScript对象被链接到一个来自于它可以继承属性的原型对象。原型类似其他OO语言中的类,但不同的是,它们本身也是对象。每一个对象都链接到Object.prototype,而Object.prototype自带JavaScript预定义。
如果你通过obj.propName或 obj['propName'] 查找属性,而对象并不具有可通过 obj.hasOwnProperty(‘propName')被检查的属性,那么JavaScript的运行时会在其原型对象中查找属性。如果原型对象也没有这样的属性,那么依次检查它的原型,直到找到匹配,或者到达Object.prototype。如果该属性不存在原型链,那么它会导致一个未定义的值。
通过下面的示例代码来理解这个概念:
if (typeof Object.create !== 'function') { Object.create = function (o) { var F = function () {}; F.prototype = o; return new F(); }; var otherPerson = Object.create(person);
当你创建一个新对象的时候,你必须选择一个应该是它的原型的对象。这里,我们添加了一个方法到Object function。该方法创建了一个使用另一个对象作为其原型的新对象,而原型作为参数传递给它。
当我们改变新对象的时候,它的原型不受影响。但是,当我们进行改变原型对象的时候,这些变化在所有基于该原型的对象上可见。
原型是一个复杂的概念。我将在另一篇文章中详细说明。
3.模块如果你曾经接触过Java中的包,那么Node.js中的模块也没有什么不同。如果没有,那么也不用担心。模块是包含特定目的代码的简单的JavaScript文件。模块模式用来使你的代码易于导航和使用。要使用模块属性,你需要在JavaScript文件中需求它,很像在Java类中导入包。
node.js中有两种类型的模块。
核心模块——这些模块是用Node.js库预编译过的。核心模块的目的是提供开发者经常发生和重复的代码段,这些代码段如果不可用的话,会导致开发者陷入不得不一次又一次地写相同代码的处境。一些常见的核心模块是HTTP,URL,EVENTS,FILE SYSTEM,等等。