1. 模块化

常用模块化规范

CommonJS + nodejs

AMD(Asynchronous Module Definition) + RequireJS

CMD(Common Module Definition) + SeaJS

UMD

ECMAScript 2015 Module

CMD规范seajs

1seajs的基础语法:

引入sea.js插件包

创建一个test.js文件,在其中写如下代码:

define(function( require , exports , module ) {

module.exports.name = ” Tom”

module模块对象exports对外接口对象(向外暴露数据的方法),name是添加在module模型对象上的属性

console.log(module.exports === exports) 此处打印结果为true

也就是exports可以相当于module.exports来使用,但值得注意的是,exports并不是module.exports本身,只是给exports这个变量赋值为module.exports,实现机制类似于:var exports = module.exports

})

创建一个main.js文件,在其中写如下代码:

define(function( require , exports , module ) {

console.log("hello world")

console.log(require(‘./test’))

通过require( )方法,将需要获取数据的文件路径传递进去,如果该文件向外暴露了数据,此处即可获取该数据 { name: “Tom” },如果没有暴露数据,此处打印结果为空对象{ }require无视流程控制语句,只要写了就会加载

})

再在页面中创建一个<script>标签,写上seajs.use("./js/main");即上述main.js文件的路径,该文件的.js后缀名写不写都可以,便可执行上述文件中的代码

2)使用seajs加载第三方插件的兼容写法:(以Zepto为例)

在Zepto的js文件中,找到定义Zepto的位置:window.Zepto = Zepto

在这行代码下面添加define函数的兼容写法:

if( typeof define === ‘function’ &&define.cmd ){

此处全局判断,文件中是否加载了seajs,因为seajsdefine函数默认添加了cmd属性,如果加载了seajs才引入define函数暴露Zepto,这样可以避免在没有引入seajs时,直接引入Zepto会找不到define方法

define(function( require , exports , module ) {

module.exports = Zepto;

}

}

2. nodejs 浅析(node:节点)

nodejs基本介绍(在服务器端使用JavaScript

(1)JavaScript运行时,构建在chrome V8引擎之上

(2)是一个JavaScript运行环境

(3)event-driven 事件驱动

(4)non-blocking I/O model 非阻塞I/O模型

(5)包括npm开源库生态系统

REPL(Read-eval-print-loop):交互式解析器环境

(1)REPL的常用命令:

进入node,即进入了REPL环境,在命令窗口输入node

退出:输入.exit或者连续按ctrl+c两次

点击tab可以打印出Node.js中的所有对象

点击向上/向下可以查看历史命令

.save filename保存输入的命令

.load filename加载文件

在REPL环境下,可以用_代替上一次表达式的结果

(2)REPL中执行js代码文件

在命令窗口输入node ./nodetest.js  (需要打开的文件路径)

(3)终端/控制台(命令窗口)基础通用命令

dir 查看目录中的所有文件

cd 切换目录   切盘符直接输d:即可

cls clear screen 清理控制台显示内容

模块作用域

nodejs本身是模块化的,具备类似seajs中的moduleexportsrequire使用方法也基本相同,只是不需要写在define中,直接写在js文件内即可,再在需要加载输出内容的文件中使用require请求数据即可

例如:

在test.js文件中写:

module.exports.name = { name: ”Tom” }

global.obj = { name: ”Jack” }      globalnode提供的类似window的全局对象

在nodetest.js文件中写:

console.log( require(‘./test’).name );   require中传入的内容是模块标识,如果是引用同级文件,必须加上./否则会认为是引用的核心模块

console.log(global.obj);

在控制台输出:node nodetest.js  输出结果为{ name: ”Tom” }  { name: ”Jack” }

次案例中,moduleexportsrequire的意义与seajs中基本一致,称为伪全局对象,即在自身模块中有全局效果,每个模块都有这几个对象,用法与seajs中相同,需要注意的是global是node提供的一个全局对象,可以在全局中获取数据,但是存在冲突的可能性,不推荐使用

node模块中还包含__filename(双下划线)__dirname(双下划线)两个变量,

__filename当前文件模块的绝对路径,包含当前文件的文件名和后缀

__dirname当前文件所属的绝对路径,不包含当前文件的文件名和后缀

全局函数(异步执行函数)

setTimeout( )、clearTimeout( )、setInterval( )、clearInterval( )

setImmediate( )、clearImmediate( )

例如:setTimeout( function(){

console.log(“异步执行”);

})   即使不传入时间参数,里面的内容也会最后执行,起到异步的作用

commonJS规范(为JavaScript在后台功能实现定义的API规范nodejs遵循这个规范

规范特征:

(1)每个单独的文件都是一个模块

(2)所有的代码都在自身的模块作用域中运行,不会污染全局作用域

(3)所有模块的对外接口都是module.exports对象

(4)require方法用于加载需要调用数据的模块文件

(5)模块可以多吃加载,但只会在首次加载时运行,并将运行结果进行缓存,以后再加载时,就直接读取缓存结果

(6)模块加载的顺序,按照其在代码中出现的顺序进行,边加载,边执行

模块加载

(1) require查找规则

1 ) 首先判断标识符是纯字符串还是相对路径

2 ) 如果是纯字符串:表示核心模块 或者 第三方模块(包)

3 ) 如果是第三方包:package.json中指定的优先级大于index.js

4 ) 如果是相对路径,且有扩展名(.js.html等):直接去找对应的文件即可

5 ) 如果是相对路径,没有扩展名,例如require(‘./test’):,有优先级:test.js > test.json > test.node

6 ) 如果在当前node_modules找不到:返回上一级目录找

7 ) 最好使用require(‘path’)模块控制路径,如果直接加载路径,正/、反\有时会产生分歧,产生无法加载文件的现象

(2) 核心模块(node提供的模块)具体功能查看文档

a ) fs模块(文件操作)

require(‘fs’).readFile(‘./readme.md’ , function(err , data)){

console.log(data);  读取传入的文件,以二进制的十六进制形式输出

console.log(data.toString())   以可视文件形式输出

}

b ) os模块(系统操作)

…….等等

(2) 加载第三方模块

a ) 库加载示例:underscore库加载

使用npm安装underscore库,然后再加载

加载:require(‘./node_module/underscore/underscore.js’)

或者不用写路径直接写模块名:require(‘underscore’)

实现原理是,node在node_module目录下找到underscore文件夹,查看里面的package.json文件,加载这个json文件里面的main属性(指定该包的入口)下的文件路径,这个路径是相对于该package.json文件而言的,也可根据自己需求修改路径

b ) 自定义库加载

同理可以按照underscore的思路,将自定义库放在node_module目录下,再在自定义库中创建一个package.json文件,指定main属性的路径到需要加载的文件,最后再require(自定义name’),即可实现加载

(如果package.json文件中没有main字段,require方法会查找包目录下的index.js , index.json , index.node作为默认入口)

c ) node中只需在根目录创建唯一node_module目录

如果当前目录没有node_module目录,node会自动查找上级目录,如果上级也没有,会查找上上级目录,类似JS中函数作用域链,这样带来的好处是,只需要在根目录下创建唯一node_module目录即可,不需要在创建的每个子目录下都创建node_module目录,提高库管理的效率。

引入库只需执行require(name’)即可

文件操作("fs”

(1)编码(字符串与二进制0101…)转换

a ) node中支持的编码类型(不包含gbk:支持中文的编码规则)

  ascii     早期的编码规则,只支持英文

  utf8     支持不同国家语言的编码规则

  utf16le

  base64

  binary

  hex

b ) Buffer对象

Buffer是内存中的一个缓冲区,或者说是内存中的一个数据块

var buf = new Buffer(2)  创建2个字节的数据块

buf.write(“a”在上述2字节空间中,用第一个字节写a

buf.toString()  将16进制显示的Buffer对象转换为字符串显示

Buffer.concat( [buf1 , buf2 , buf3 , ……] ) Buffer拼接,传入一个Buffer对象的数组

……等等 (参考官方文档)

c ) 解决node中不支持的编码类型

引入插件包:iconv – lite  具体使用方法查看官方文档

简单示例:

var fs = require('fs');

var iconv = require('iconv-lite');

var data = iconv.encode('这是一段中文', 'gbk');

fs.writeFile('./test.txt', data, function(err) {

if (err) throw err;

});

fs.readFile('./test.txt', function(err, data) {

if (err) throw err;

console.log(data);  ------  <Buffer d5 e2 ca c7 d2 bb b6 ce d6 d0 ce c4>

二进制数据(Buffer类型的对象)

var str = iconv.decode(data, 'gbk');

console.log(str);  ------  “这是一段中文”

})

(2)同步和异步文件调用

a ) 同步操作:阻塞I/O操作(input/output)输入/输出端口

1 ) 会立即执行,阻塞I/O

2 ) 以同步编码的方式接受返回值

3 ) 针对同步I/O必须使用try – catch 捕获异常

4 ) 编程思路简单,易于操作

5 ) node中的文件操作(fs)API,带sync的都表示同步

b ) 异步操作:非阻塞I/O操作

1 ) 不会立即执行,会先把任务添加到事件队列,再依次执行

2 ) 必须通过回调函数的方式接收异步操作的返回值

3 ) 通过回调函数中的参数err对象,判断是否有错误

4 ) 相对于同步操作而言,编程思路复杂,不容易操作

(3)fs文件操作相关API简单示例(查看官方文档)

读文件  readFilereadFileSync

写文件  writeFilewriteFileSync

监视文件  watchFile

查看文件相关信息  stat

……等等

(4)可读流、可写流

a ) 可读流

创建可读流对象:var readStream = require(‘fs’).createReadStream(‘srcRead’)

通过可读流对象,可以监听文件读取过程,读取过程是通过chunk对象,一点一点进行读取,chunk即是每次读取的文件的大小,读取示例如下:

读取文件的总字节数:

var totalSize = require(‘fs’).statSync(‘srcRead’).size

开始监听文件过程读取:

readStream.on(‘data’ , function(chunk){

chunk是一个Buffer对象,具备length属性,length是字节的长度

由于每次只能读取chunk.length长度的字节,记录总共读取到的文件的大小:

curSize += chunk.length

通过curSize/ totalSize,可以获得已经读取的文件的百分比

})

读取结束时触发end事件:

readStream.on(‘end’, function(){

console.log(“读取结束”)

}

b ) 可写流

创建可读流对象:var writeStream = require(‘fs’).createWriteStream(‘srcWrite’)

写入数据:writeStream.write(datadata可以是字符串也可以是变量,如果将可读流中的chunk对象,传入可写流方法,可实现大文件的复制

关闭可写流:writeStream.end( )

c ) pipe(管道方法)

创建可读流、可写流对象:

var readStream = require(‘fs’).createReadStream(‘srcRead’)

var writeStream = require(‘fs’).createWriteStream(‘srcWrite’)

可读流具有pipe方法,可直接写入可写流中:

readStream.pipe(writeStream)

网络编程

(1)OSI(Open System Interconnection)开放系统互联模型,将网络通信的工作分为7

应用层:HTTP、SMTP、IMAP等

表示层:加密、解密等

会话层:通信连接、维持会话

传输层:TCP、UDP

网络层:IP

链路层:网络特有的链路接口

物理层:网络物理硬件

(2)网络操作(net

服务器端代码示例:

var net = require('net');

创建一个网络服务器:

var server = net.createServer();

监听服务器的连接请求,设置请求处理回调函数,只要客户端连接成功就会触发connect连接事件,将当前连接的客户端封装成一个socket对象(双向数据流)

server.on('connection', function(socket) {

console.log('客户端连接');

设置客户端连接:首先启动window的Talnet客户端功能,然后在命令窗口输入telnet 127.0.0.1 3000即可看到客户端的信息,此处为”hello”

console.log('当前客户端IP地址:'+socket.remoteAddress)

console.log('当前客户端port端口号:'+socket.remotePort)

socket.write('hello client');

socket.on('data', function(data) {

console.log(data.toString())

})

})

开启服务器,并分配一个端口号进行监听,此处分配端口号3000

server.listen(3000, function() {

console.log("server is running")

console.log("please visit 127.0.0.1:3000")

});

客户端代码示例:

var net = require('net');

var client = net.createConnection(3000, '127.0.0.1');

client.on('connect', function() {    创建客户端与服务器的连接

console.log('connect success');

})

client.on('data', function(data) {   data是服务器中socket.write写入的数据

var data = data.toString();

console.log(data);

if (data == "hello client") {

client.write('hello server');   向服务器中写入数据

}

})

(3)http协议基本概念

客户端浏览器、服务器连接的简单图示:(以百度为例)

利用curl查看请求和响应报文: >表示请求报文、<表示响应报文

下载curl后,配置好环境变量后即可在CMD终端中查看报文

具体命令:curl www.baidu.com –v

三次握手

* Rebuilt URL to: www.baidu.com/

* Trying 115.239.211.112...

* TCP_NODELAY set

* Connected to www.baidu.com (115.239.211.112) port 80 (#0)

下述部分是请求报文

> GET / HTTP/1.1    请求首行:请求方法+请求路径+HTTP协议版本

> Host: www.baidu.com

> User-Agent: curl/7.53.1    键值对,包含当前客户端信息

> Accept: */*

> 回车换行

下述部分是响应报文

< HTTP/1.1 200 OK

< Server: bfe/1.0.8.18

< Date: Wed, 01 Mar 2017 02:01:40 GMT

< Content-Type: text/html

< Content-Length: 2381

< Last-Modified: Mon, 23 Jan 2017 13:28:28 GMT

< Connection: Keep-Alive

< ETag: "588604fc-94d"

< Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform

< Pragma: no-cache

< Set-Cookie: BDORZ=27315; max-age=86400; domain=.baidu.com; path=/

< Accept-Ranges: bytes

回车换行

<!DOCTYPE html>   响应体(index.html中的内容)

<!--STATUS OK--><html>

……

(4)node中的http模块

示例代码如下:

var http = require('http');

通过npm安装moment插件,可以获取当前时间

var moment = require('moment');

var fs = require('fs');

var server = http.createServer();  创建http服务器

server.on('request', function(request, response) {

两个参数request表示请求报文解析成的对象,response表示客户端对象与net中的socket基本相同

var url = request.url;   requesturl属性,如果没有值,默认为/

if (url == "/") {

fs.readFile(require('path').join(__dirname, 'test.html'), 'utf8', function(err, data) {

 response.writeHead(200, {  设置文件类型,可以写text/plain表示任意类型

'Content-Type': 'text/html;charset=utf-8'

})

response.write('当前服务器最新时间是:' + moment().format('YYYY-MM-DD hh:mm:ss'))

response.end(data);  设置响应结束后的内容,此处渲染test.html

})

}

加载静态资源:

例如其他的cssjs文件,或者img图片,需要再次发送请求,以css为例,如果test.html页面中有<link rel="stylesheet" href="/css/test.css">则还需在node中加载该文件

else if (url == "/css/test.css") {

fs.readFile(require('path').join(__dirname, 'test.html'), 'utf8', function(err, data) {

 response.writeHead(200, {  设置文件类型为css

'Content-Type': 'text/css;charset=utf-8'

})

response.end(data);  设置响应结束后的内容,此处渲染test.css

})

}

如果有大量静态资源需要加载,这样重复写else if的方法显然不合适,此时可以通过npm安装mime插件,根据url路径判断Content-Type,方法如下:

var mime = require('mime');

var url = request.url;

var statciPath = require('path').join(__dirname, url)  获取静态资源的路径

fs.readFile(statciPath, 'utf8', function(err, data) {

if(err){ return response.end(‘404 Not Found’) }   如果资源有错误,报错

(通过mime中的lookup方法获取资源的Content-Type

var contentType = mime.lookup(statciPath)

 response.writeHead(200, {

'Content-Type': contentType

})

response.end(data);

})

})

server.listen(3000, '127.0.0.1', function() {   设置端口号为3000

console.log('请访问:127.0.0.1')

})

(5)安装formidable插件可以对文件上传等操作进行管理

查考文档:https://www.npmjs.com/package/formidable

Nodejs 基础知识 浅析的更多相关文章

  1. 前端知识体系-NodeJS相关】NodeJS基础知识全面总结

    NodeJS基础知识 1. Node的全局对象和全局变量 1.1 全局对象:所有模块都可以调用的 global:表示Node所在的全局环境,类似于浏览器的window对象. process:该对象表示 ...

  2. Ajax基础知识 浅析(含php基础语法知识)

    1.php基础语法    后缀名为.php的文件 (1) echo   向页面中输入字符串  <?php    所有php相关代码都要写在<?php ?>这个标签之中 echo &q ...

  3. nodejs基础知识查缺补漏

    1. 单线程.异步I/O.对比php nodejs是单线程的,但是是异步I/O,对于高并发时,它也能够快速的处理请求,100万个请求也可以承担,但是缺点是非常的耗内存,但是我们可以加大内存, 所以能用 ...

  4. NodeJs 基础知识

    1.网站 http://nodejs.cn/ 下载最新NodeJs并且安装2. 你可以输入一个新命令“node”.使用该“node”命令有两种不同的方法.第一种不带任何参数,将打开一个交互式Shell ...

  5. 21.Nodejs基础知识(下)——2019年12月16日

    2019年10月04日16:56:23 7. 模块 7.1 暴露一个类,字段 var bar = require("./bar.js"); var msg = "你好&q ...

  6. 20.Nodejs基础知识(上)——2019年12月16日

    2019年12月16日18:58:55 2019年10月04日12:20:59 1. nodejs简介 Node.js是一个让JavaScript运行在服务器端的开发平台,它让JavaScript的触 ...

  7. ES6(ECMAScript2015) 基础知识 浅析

    1.块级作用域(let) { let fruit = “apple”; } console.log(fruit) 会报错,因为{ }大括号包含的区域为块级作用域,let在其中申明的变量只能在该块中生效 ...

  8. Echarts 基础知识浅析

    1. 引入Echarts Echarts是基于canvas的数据可视化产品,由百度公司推出 参考官方文档,引入教程示例即可,注意有两种引入方式: (1)直接引入 (2)模块化引入 2. 基本API使用 ...

  9. Angular1 基础知识 浅析(含锚点)

    1.angular:前端js框架  https://angularjs.org ① SPA单页应用程序 通过ajax从后台获取数据,动态渲染页面,不出现白屏,提高效率,节省流量 (1)锚点值 锚点:是 ...

随机推荐

  1. 【Effective c++ 读书笔记】条款01 视 C++ 为一个语言联邦

    一开始,C++只是 C 加上一些面向对象的特性.C++最初的名称 C with Classes 也反映了这个血缘关系. 但是,现在,当这个语言逐渐成熟,它变得更活跃更无拘束,更大胆冒险,开始接受不同于 ...

  2. php性能优化 --- laravel 性能优化

    1.laravel官方提供了一些优化(laravel 5.* 版本): (1).关闭debug,修改 .env 的  APP_DEBUG=false    (2).  sudo php artisan ...

  3. 关于sql server 2008 r2 展开时报错:参数名:viewInfo ( Microsoft SqlServer Management SqlStudio Explorer )解决思路

    今天安装了sql server 2008 R2,安装成功之后我打开软件登陆都没问题,但是一展开选项就弹出错误提示框: 参数名:viewInfo 不能为空 (Microsoft SqlServer Ma ...

  4. mybatis中@Param用法

    用注解来简化xml配置的时候,@Param注解的作用是给参数命名,参数命名后就能根据名字得到参数值,正确的将参数传入sql语句中 我们先来看Mapper接口中的@Select方法 package Ma ...

  5. poj 2674 线性世界 弹性碰撞

    弹性碰撞的题目一般都是指碰到就会掉转方向的一类题目,这里我们可以忽略掉头,仅仅看成擦肩而过,交换名字等等 题意:一条线上N只蚂蚁,每只蚂蚁速度固定,方向和坐标不同,碰头后掉头,求最后掉下去那只蚂蚁的名 ...

  6. PHP.26-TP框架商城应用实例-后台3-商品修改、删除

    商品修改{修改页一般与添加页有百分之九十的相似度} create($_POST,Model::MODEL_UPDATE):系统内置的数据操作包括Model::MODEL_INSERT(或者1)和Mod ...

  7. [bzoj2733]永无乡&&[bzoj3545]Peaks

    并不敢说完全会了线段树合并,只是至少知道原理写法了...还是太菜了,每天被大佬吊锤qwq 我看到的几道线段树合并都是权值线段树的合并.这个算法适用范围应该只是01线段树的. 这两道算入门题了吧... ...

  8. POJ 3461 Oulipo(字符串hash)

    题目链接 字符串hash判断字符串是否相等. code #include<cstdio> #include<algorithm> #include<cstring> ...

  9. 被relativeLayout的grivate center 折腾死了

    <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=&q ...

  10. 什么是App加壳,以及App加壳的利与弊

    非著名程序员涩郎 非著名程序员,字耿左直右,号涩郎,爱搞机,爱编程,是爬行在移动互联网中的一名码匠!个人微信号:loonggg,微博:涩郎,专注于移动互联网的开发和研究,本号致力于分享IT技术和程序猿 ...