珠峰培训

node入门(二)核心API(三)

作者:

2015-11-24 16:21:21

142

概述

Buffer对象是Node.js用来处理二进制数据的一个接口。JavaScript比较擅长处理Unicode数据,对于处理二进制格式的数据(比如TCP数据流),就不太擅长。Buffer对象就是为了解决这个问题而提供的。该对象也是一个构造函数,它的实例代表了V8引擎分配的一段内存,基本上是一个数组,成员都为整数值。

Buffer是Node原生提供的全局对象,可以直接使用,不需要require('buffer')。

Buffer对象与字符串的互相转换,需要指定编码格式。目前,Buffer对象支持以下编码格式。

  • ascii
  • utf8
  • utf16le:UTF-16的小头编码,支持大于U+10000的四字节字符。
  • ucs2:utf16le的别名。
  • base64
  • hex:将每个字节转为两个十六进制字符。

V8引擎将Buffer对象占用的内存,解释为一个整数数组,而不是二进制数组。所以,new Uint32Array(new Buffer([1,2,3,4])),生成的Uint32Array数组是一个4个成员的Uint32Array数组,而不是只有单个成员([0x1020304]或者[0x4030201])的。

注意,这时类型化数组所对应的内存是从Buffer对象拷贝的,而不是共享的。类型化数组的buffer属性,保留指向原Buffer对象的指针。

类型化数组的操作,与Buffer对象的操作基本上是兼容的,只有轻微的差异。比如,类型化数组的slice方法返回原内存的拷贝,而Buffer对象的slice方法创造原内存的一个视图(view)。

Buffer构造函数

Buffer作为构造函数,可以用new命令生成一个实例,它可以接受多种形式的参数。

javascript
// 参数是整数,指定分配多少个字节内存
var hello = new Buffer(5);

// 参数是数组,数组成员必须是整数值
var hello = new Buffer([0x48, 0x65, 0x6c, 0x6c, 0x6f]);
hello.toString() // 'Hello'

// 参数是字符串(默认为utf8编码)
var hello = new Buffer('Hello');

// 参数是字符串(不省略编码)
var hello = new Buffer('Hello', 'utf8');

// 参数是另一个Buffer实例,等同于拷贝后者
var hello1 = new Buffer('Hello');
var hello2 = new Buffer(hello1);

类的方法

Buffer.isEncoding()

Buffer.isEncoding方法返回一个布尔值,表示Buffer实例是否为指定编码。

javascript
Buffer.isEncoding('utf8')

Buffer.isBuffer()

Buffer.isBuffer方法接受一个对象作为参数,返回一个布尔值,表示该对象是否为Buffer实例。

javascript
Buffer.isBuffer(Date) // false

Buffer.byteLength()

Buffer.byteLength方法返回字符串实际占据的字节长度,默认编码方式为utf8。

javascript
Buffer.byteLength('Hello', 'utf8') // 5

Buffer.concat()

Buffer.concat方法将一组Buffer对象合并为一个Buffer对象。

javascript
var i1 = new Buffer('Hello');
var i2 = new Buffer(' ');
var i3 = new Buffer('World');
Buffer.concat([i1, i2, i3]).toString()
// 'Hello World'

需要注意的是,如果Buffer.concat的参数数组只有一个成员,就直接返回该成员。如果有多个成员,就返回一个多个成员合并的新Buffer对象。

Buffer.concat方法还可以接受第二个参数,指定合并后Buffer对象的总长度。

javascript
var i1 = new Buffer('Hello');
var i2 = new Buffer(' ');
var i3 = new Buffer('World');
Buffer.concat([i1, i2, i3], 10).toString()
// 'Hello World'

省略第二个参数时,Node内部会计算出这个值,然后再据此进行合并运算。因此,显式提供这个参数,能提供运行速度。

实例属性

length

length属性返回Buffer对象所占据的内存长度。注意,这个值与Buffer对象的内容无关。

javascript
buf = new Buffer(1234);
buf.length // 1234

buf.write("some string", 0, "ascii");
buf.length // 1234

上面代码中,不管写入什么内容,length属性总是返回Buffer对象的空间长度。如果想知道一个字符串所占据的字节长度,可以将其传入Buffer.byteLength方法。

length属性是可写的,但是这会导致未定义的行为,不建议使用。如果想修改Buffer对象的长度,建议使用slice方法返回一个新的Buffer对象。

实例方法

write()

write方法可以向指定的Buffer对象写入数据。它的第一个参数是所写入的内容,第二个参数(可省略)是所写入的起始位置(从0开始),第三个参数(可省略)是编码方式,默认为utf8。

javascript
var buf = new Buffer(5);
buf.write('He');
buf.write('l', 2);
buf.write('lo', 3);
console.log(buf.toString());
// "Hello"

slice()

slice方法返回一个按照指定位置、从原对象切割出来的Buffer实例。它的两个参数分别为切割的起始位置和终止位置。

javascript
var buf = new Buffer('just some data');
var chunk = buf.slice(4, 9);
chunk.toString()
// "some"

toString()

toString方法将Buffer对象,按照指定编码(默认为utf8)转为字符串。

javascript
var hello = new Buffer('Hello');
hello // <Buffer 48 65 6c 6c 6f>
hello.toString() // "Hello"

toString方法可以只返回指定位置内存的内容,它的第二个参数表示起始位置,第三个参数表示终止位置,两者都是从0开始计算。

javascript
var buf = new Buffer('just some data');
console.log(buf.toString('ascii', 4, 9));
// "some"

toJSON()

toJSON方法将Buffer实例转为JSON对象。如果JSON.stringify方法调用Buffer实例,默认会先调用toJSON方法。

javascript
var buf = new Buffer('test');
var json = JSON.stringify(buf);
json // '[116,101,115,116]'

var copy = new Buffer(JSON.parse(json));
copy // <Buffer 74 65 73 74>

Node.js 全局对象

global表示Node所在的全局环境,类似于浏览器的window对象,它及其所有属性都可以在程序的任何地方访问。 需要注意的是,如果在浏览器中声明一个全局变量,实际上是声明了一个全局对象的属性,比如var name = "zfpx"; 等同于设置window.name = "zfpx". 在模块文件中,声明var name = "zfpx";,该变量不是global对象的属性,global.name等于undefined。 这是因为模块的全局变量都是该模块私有的变量,其他模块无法取到。

在 Node.js 我们可以直接访问到 global 的属性,而不需要先通过require引入。

全局变量

global 最根本的作用是作为全局变量的宿主。 满足以下条件的变量是全局变量:

  • 全局对象的属性; global.name="zfpx"
  • 隐式定义的变量(未定义直接赋值的变量)。 name="zfpx"

当你定义一个全局变量时,这个变量同时也会成为全局对象的属性,反之亦然。 注意:永远要使用var定义变量以避免引入全局变量,因为全局变量会污染命名空间,提高代码的耦合风险。

setTimeout(cb, ms)

setTimeout(cb, ms) 全局函数在指定的毫秒(ms)数后执行指定函数(cb)。:setTimeout() 只执行一次指定函数。返回一个代表定时器的句柄。

 function printHello(){
    console.log( "Hello, zfpx!");
 }
 // 两秒后执行以上函数
 setTimeout(printHello, 2000);

clearTimeout(t)

clearTimeout( t ) 全局函数用于停止一个之前通过 setTimeout() 创建的定时器。 参数 t 是通过 setTimeout() 函数创建的计算器。

function printHello(){
   console.log( "Hello, zfpx!");
}
// 两秒后执行以上函数
var t = setTimeout(printHello, 2000);

// 清除定时器
clearTimeout(t);

setInterval(cb, ms)

setInterval(cb, ms) 全局函数在指定的毫秒(ms)数后执行指定函数(cb)。 返回一个代表定时器的句柄。可以使用 clearInterval(t) 函数来清除定时器。 setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。

function printHello(){
   console.log( "Hello, World!");
}
// 两秒后执行以上函数
setInterval(printHello, 2000);

Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! …… 以上程序每隔两秒就会输出一次"Hello, World!",且会永久执行下去,直到你按下 ctrl + c 按钮。

伪全局变量

还有一些对象实际上是模块内部的局部变量,指向的对象根据模块不同而不同,但是所有模块都适用,可以看作是伪全局变量, 主要为__filename,__dirname,module, module.exports, exports等。

__filename

注意此属性并不是全局对象的属性,而只是node在我们注入模块的参数,可以在模块内直接使用. _filename 表示当前正在执行的脚本的文件名。它将输出文件所在位置的绝对路径

 // 输出全局变量 __filename 的值
 console.log( __filename );

__dirname

注意此属性并不是全局对象的属性,而只是node为我们注入模块的参数,可以在模块内直接使用. __dirname 表示当前执行脚本所在的目录。

// 输出全局变量 __dirname 的值
console.log( __dirname );

module

代表当前模块本身

exports

模块的导出对象