NodeJS初探

运行


运行方式:

> node .\test.js

 

模块


CommonJS是模块化的标准,NodeJS是CommonJS的实现。

在Node中,一个JS文件就是一个模块。

模块分为“核心模块”和“文件模块”两大类:

       核心模块:由node引擎提供的模块

       文件模块:由用户自己创建的模块

引入其它模块规则:

       核心模块引入:require()函数中直接写模块名

       文件模块引入:绝对路径引入时,require()函数中写模块绝对路径;相对路径引入时,require()函数中写模块相对路径(须以‘./’或‘../’开头)

require ("modulepath");

// 上面只是引入了模块,但要使用模块内的内容,肯定得拿到对应模块的模块对象
// 下面语句展示了require()函数返回的模块对象,并通过模块对象去引用模块内容
var md_fs = require ("fs");
// 注意:文件模块引入时,若是引用相对路径,须以 ‘./’ 或 ‘../’ 开头
var md_md1 = require("./module1.js");

 

每个JS文件中的JS代码都是独立运行在一个作用域中,而不是全局作用域。

  • 模块内声明全局变量:去掉 var

        m = 1; //作用域是全局

        var n = 2; //作用域是模块内

  • Node中有一个全局对象global,声明的全局变量或方法都被管理在global里。
  • 每个模块里的代码实际上都是包装在函数中运行的,通过console.log(arguments);可查看。

        arguments有一个callee属性,保存的是当前执行的函数对象。

        执行console.log(arguments.callee + "");可以将当前运行的函数(模块)内容打印出来。

        在函数执行时,同时传递了5个实参:

            exports   - 对象,用于将变量或方法暴露到模块外

            require   - 函数,用来引入外部的模块

            module   - 代表当前模块本身,exports就是module的属性。(所以在导出时,既可以使用exports,也可以使用module.exports)

                              -- 使用exports例子:

                                     exports.属性 = 属性值;

                                     exports.方法 = 函数;

                              -- 使用module.exports例子:

                                     module.exports.属性 = 属性值;

                                     module.exports.方法 = 函数;

                                     module.exports = {

                                                 属性 = 属性值;

                                                 ...

                                                 方法 = 函数;

                                                 ...

                                     };

            __filename   - 当前模块的完整路径

            __dirname   - 当前模块所处文件夹

所以一个模块中的变量和函数在其它模块中无法直接访问。

下面举例演示:

/// module1.js
console.log("i am modul.1");
var x = 10;
var y = 20;

/// test.js
var md1 = require("./module1.js");
console.log(md1);
console.log(md1.x);
console.log("********************")

运行结果:

i am modul.1
{}
undefined
********************

为解决作用域问题,引入了exports。可以将需要暴露给外部的变量或方法设置为exports属性。

/// module1.js
console.log("i am modul.1");
var x = 10;
var y = 20;
exports.x = "i am x in module.1";
exports.fn = function(){

};
exports.divide = function(a, b) {
    return a / b;
};


/// test.js
var md1 = require("./module1.js");
console.log(md1);
console.log(md1.x);
console.log(md1.divide(10, 2));
console.log("********************")

运行结果:

i am modul.1
{ x: 'i am x in module.1', fn: [Function (anonymous)] }
i am x in module.1
5
********************

注意:上边module1.js中,var xexports.x是两个完全不同的变量。

           总之,需要对外开放的变量或方法,使用exports进行修饰;而不需要对外开放只限于模块内使用的还是使用var声明。

 

npm


npm简介

       npm(Node package manager),是帮助Node完成第三方模块的发布、安装、依赖等的包管理器。就好比Node的软件管家。

npm指令

  • npm    :帮助说明
  • npm version    :查看npm所有模块版本
  • npm -v    :查看npm版本
  • npm search [packagename]    :搜索模块包
  • npm install [packagename]    :在当前目录安装包
  • npm install [packagename] --save    :将包下载到项目根目录下的node_modules内,并添加在依赖文件package.json中的dependencies属性下。(?但新版本的npm似乎默认自动加了--save)
  • npm install [packagename] -g    :在全局模式安装包(npm安装路径)
  • npm remove [packagename]    :删除(/卸载)一个模块包
  • npm init    :在当前目录下初始化package.json
  • npm install [filepath]    :从本地安装包
  • npm install [packagename] -registry=address    :从镜像源安装包
  • npm config set registry address    :设置镜像源

 

Buffer


Buffer结构和操作方法都跟数组很像,但性能优于数组,是专门用于存储二进制数据的数据结构。Buffer的元素(内存中的一个Byte)显示时为16进制的两位数。

Buffer中的内存实际并不是通过JavaScript分配的,而是在底层通过C++申请,底层申请的内存空间是地址连续的。

Buffer的大小一旦确定,则不能更改。

// 创建一个Buffer,同时申请10Byte的内存空间
var buf3 = Buffer.alloc(10);
console.log(buf3, ":", buf3.length);
// 通过索引操作buf中的元素
buf3[0] = 88; //直接赋值十进制元素
buf3[1] = 255; //一个字节占8位,范围为00000000 ~ 11111111。十进制255对应的二进制为11111111,对应十六进制为ff
buf3[2] = 256; //十进制256对应的二进制为100000000,而buffer一个元素最大占8位,故只会取后八位00000000,对应十六进制为00
buf3[3] = 0xaa;
buf3[10] = 88; //buffer申请的内存空间为10Byte,最大索引位为9。给第10号索引位赋值为无效操作
console.log(buf3, ":", buf3.length);

/// 运行结果
<Buffer 00 00 00 00 00 00 00 00 00 00> : 10
<Buffer 58 ff 00 aa 00 00 00 00 00 00> : 10

// ---------------------------------------------------

var str1 = "Hello gaoxing";
var str2 = "Hello 高兴";
var buf1 = Buffer.from(str1); //将字符串转换为buffer
var buf2 = Buffer.from(str2);
console.log(str1, ":", str1.length); //字符串的长度
console.log(str2, ":", str2.length);
console.log(buf1, ":", buf1.length); //buffer占用内存的大小
console.log(buf2, ":", buf2.length);
console.log(buf2.toString()); //将缓冲区内数据转换成字符串

/// 运行结果
Hello gaoxing : 13
Hello 高兴 : 8
<Buffer 48 65 6c 6c 6f 20 67 61 6f 78 69 6e 67> : 13
<Buffer 48 65 6c 6c 6f 20 e9 ab 98 e5 85 b4> : 12
Hello 高兴

 

 

fs模块


// fs - 文件系统
var md_fs = require("fs");

// 检测文件是否存在
var bExists = md_fs.existsSync("hello.txt");
console.log(bExists);

// 同步操作
var fd = md_fs.openSync("./hello.txt", "w");
md_fs.writeSync(fd, "今天下雨了!");
md_fs.closeSync(fd);


// 异步操作
md_fs.open("hello.txt", "w", function(err, fd) {
    if (!err) {
        console.log("file open ok.");
        md_fs.write(fd, "异步方式写入文件~", function(err) {
            if (!err) {
                console.log("file write ok.")
            }

            md_fs.close(fd, function(err) {
                if (!err) {
                    console.log("file close ok.")
                }
            });
        });
    } else {
        console.log("file open failed!", err);
    }
});



// --------------------------
/// 简单文件写入
// asynchronous
md_fs.writeFile("hello.txt", "这是简单文件写入~", function(err) {
    if (!err) {
        console.log("simple write file by asynchronous ok.");
    } else {
        console.log("simple write file by asynchronous failed!");
    }
});
md_fs.readFile("hello.txt", function(err, data) {
    if (!err) {
        console.log(data.toString());
    }
});

// synchronize
md_fs.writeFileSync("hello.txt", "这是简单文件写入~");




// --------------------------
/// 流式文件写入
//同步、异步、简单文件的写入都不适合大文件的写入,性能较差,还容易导致内存溢出。
var ws = md_fs.createWriteStream("hello.txt");
ws.once("open", function() { //绑定一个一次性的事件
    console.log("stream is open")
});
ws.once("close", function() {
    console.log("stream is close")
});

ws.write("流式写入文件内容1");
ws.write("流式写入文件内容2");
ws.write("流式写入文件内容3");
//ws.close(); //这种方式可能导致流还没写完就关闭了流式句柄
ws.end(); //这种方式能正常的等流写完了再关闭流式句柄


// 流式文件读取也适合于大文件
// 创建一个可读流
var rs = md_fs.createReadStream("hello.txt");
rs.once("open", function() {
    console.log("read stream open");
});
rs.once("close", function() {
    console.log("read stream close");
});

// 如果要读取一个可读流中的数据,必须要为可读流绑定一个data事件,待data事件绑定完毕,会自动开始读取数据
rs.on("data", function(data) { //注意:对于大文件会分为多次读取,每次读取上限是65536字节
    console.log(data);
});




// --------------------------
/// 下面演示如何将一个可读流和可写流串起来(通过管道)
var rs = md_fs.createReadStream("hello.txt");
rs.once("open", function() {
    console.log("read stream open");
});
rs.once("close", function() {
    console.log("read stream close");
});

var ws = md_fs.createWriteStream("hello1.txt");
ws.once("open", function() { 
    console.log("write stream open")
});
ws.once("close", function() {
    console.log("write stream close")
});
rs.pipe(ws); //通过管道流式读写完后会自动关闭流句柄


 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值