NODE.JS学习笔记
第一章、NODE.JS简介
node.js是一个Javascript运行环境(runtime environment),实质是对Chrome V8引擎进行了封装;node.js不是一个 JavaScript 框架,也不是浏览器端的库,node.js是一个让 JavaScript 运行在服务端的开发平台,它让 JavaScript 成为与PHP、Python、Perl、Ruby 等服务端语言平起平坐的脚本语言。
1.1 特点
- 异步IO
- 事件与回调函数
- 单线程(javascript语言的特点)
- 跨平台
1.2 node.js应用场景
1.3 node.js内置变量及含义
- __dirname 表示当前文件所在的目录的绝对路径**(路径中未包含当前文件名)**
- __filename 表示当前文件的绝对路径**(路径中包含当前文件名)**
- module.filename ==== __filename 等价
- process.cwd() 返回运行当前脚本的工作目录的路径
- process.chdir() 改变工作目录
第二章、CommonJS规范
2.1 CommonJS对模块的定义主要分为:
a.模块引用
使用require()
方法引入一个模块API;
b.模块的定义:
在模块中使用exports对象导出当前模块数据或方法;
在模块中还存在一个module对象,她代表模块自身,module对象有一个exports属性,用于数据导出;
其实exports
对象就是module.exports
的引用;exports===module.exports
c.模块的标识
其实模块的文件名,必须符合小驼峰法命名规则,使用require()
引入时使用 .
或者 ..
开头的相对路径或绝对路径,引入的可以不写文件后缀名;
重点注意:模块中的方法和变量的作用域尽在模块内部,每个模块具有独立的空间,互不干扰;
CommonJS构建的模块机制中的引入与导出是我们完全不用考虑变量
污染或者替换的问题,相比与命名空间的机制简直就是天才和菜鸟的区别;
2.2 模块加载顺序和规则
a.模块分为下面几类:
- 核心模块,如:http,fs,path等。
- .或…开始的相对路径文件模块。
- 以/开始的绝对路径文件模块。
- 非路径形式的文件模块,如自定义模块。
如果没有指明路径,那就是加载核心模块和第三方模块,否则是加载自定义模块;
无论什么模块,都是优先从缓存中加载,require()
方法对相同模块的二次加载都一律采用缓存优先的方式,这是第一优先级的,加载优先级如下:
- 缓存中的二次模块
- 核心模块
- 路径形式的文件模块
- 自定义模块
第三章、五大浏览器四大内核(扩展知识)
5.1 各常用浏览器所使用的内核
1、IE浏览器内核:Trident内核,也是俗称的IE内核;
2、Chrome浏览器内核:统称为Chromium内核或Chrome内核,以前是Webkit内核,现在是Blink内核;
3、Firefox浏览器内核:Gecko内核,俗称Firefox内核;
4、Safari浏览器内核:Webkit内核;
5、Opera浏览器内核:最初是自己的Presto内核,后来是Webkit,现在是Blink内核;
6、360浏览器、猎豹浏览器内核:IE+Chrome双内核;
7、搜狗、遨游、QQ浏览器内核:Trident(兼容模式)+Webkit(高速模式);
8、百度浏览器、世界之窗内核:IE内核;
9、2345浏览器内核:以前是IE内核,现在也是IE+Chrome双内核;
第四章、项目移植
4.1方法
将原项目包中的JSON文件拷贝到新项目包中,再将源码文件拷贝到新项目包中,最后终端中在新项目路径下执行npm install
第五章、ES6标准学
5.1 let变量声明
let
声明的变量为块级变量,只在块级作用域内起作用。
//一
let a=3;
if(1){
//块级变量以及块级作用域
let a=5;
console.log(a);//结果为5
}
console.log(a);//结果为3
//二
let a=3;
if(1){
console.log(a);//结果报错,变量声明不会升级
let a=5;
}
//三、不污染全局的window属性
var c ='hello';
let d = 'world';
window.d;//结果为undefined
window.c;//结果为hello
注:同域下,var,let声明同一变量名,会报错
-
let声明的变量不存在变量提升
-
let声明的变量不允许重复声明
-
let声明的变量存在块级作用域(前三个为let的使用规则)
-
let在循环中经常使用(使用经验)
5.2 const常量
//一、不能修改常量的值,一旦声明必须赋值
const f=1;
f=2//结果报错,给常量赋值
//二、常量如果是一个对象或者数组,对象和数组里的值是可以修改的,但对象不可赋值为其他值
const obj ={name:'李四',age:12};
obj.name='hahah';
console.log(obj.name);//结果为hahah
//常量不可修改的是指向的内存地址
5.3 模板字符
//一、用反引号``表示字符串可以增加任意的换行
var str=`haha
kasdlgjlkd
sdjkgkls`
//输出结果:
haha
kasdlgjlkd
sdjkgkls
//二、字符串中输出变量方法${变量名}
var s=1;
var b={name:2,age:4};
var f(){
return 3;
}
//模板字符
var str=`hahah=${s+3},name=${b.name},f=${f()}he
${(function(){
return 555;
})()}
heh
\${b.age}`;
console.log(str);
//结果为:
//hahah=4,name=2,f=3he
//555
//heh
//${b.age}
5.4 解构赋值
//一、变/常量解构赋值
var [a,b,c]=[1,2,3];
const [e,f]=[1,2];
console.log(e);//1
console.log(a);//1
console.log(a+b+c);//6
//二、数组解构赋值,
//字符串的解构赋值:直接将字符串看成数组
//字符串中一个字符就是一个数组元素
var[a,b]=['adfa','adg']
console.log(a);//adfa
//三、对象解构赋值
var obj={name:'lisi',age:23};
var {name,age}=obj;
console.log(name);//结果为lisi
//语法规则:对象的解构赋值必须保证属性名一一对应
var {names,age}=obj;
console.log(names);//结果报错
5.6 属性及方法的简写
//一、使用{}将一个变量名括起来,就相当于给一个对象添加一个新的键(变量名)值(变量值);
//对象中属性的简写
var foo='hhhhhh';
var b={foo};//相当于var b={foo:'hhhhhh'};
console.log(b);//结果为{foo:'hhhhhh'}
//先解构赋值
var [a,b,c]=[1,2,3];
//创建对象
var o={a,b,c};
console.log(o);//结果为{a:1,b:2,c:3}
//二、使用{}将一个函数名括起来,就相当于给一个对象添加一个新的方法;
function fun(){
console.log(this.a+this.b);
}
var a=1;
var obj={
a,
b:2,
fun
}
obj.fun();//结果为3
//运用方法——模块中方法的导出
//模块中将方法和导出分离,优化代码可读性;
var getall=function(){
}
var getone=function(){
}
//属性和方法的简写方式用在NODE。JS中使得模块可读性更强
module.exports={getall,geione};
5.7 Promise异步控制对象
5.7.1 多层使用回调函数会进入**‘回调地狱’**
//回调函数中调用其他函数,为了控制异步执行,使得几个函数顺序执行
//过多层级回调函数的嵌套会进入’回调地狱‘
var fs = require('fs');
fs.readFile('./a.txt', 'utf-8', function (err, data) {
console.log(data);
fs.readFile('./b.txt', 'utf-8', function (err, data) {
console.log(data);
fs.readFile('./c.txt', 'utf-8', function (err, data) {
console.log(data);
});
});
});
5.7.2 使用Promise异步控制对象避免’回调地狱‘
a.Promise对象的使用方法
//当前目录下有a.txt,b.txt,c.txt等多个文件
var fs = require('fs');
var fun=function(files){
//返回Promise对象,利用回调控制方法的执行顺序(异步控制)
return new Promise(function(suc,err){//suc,err是两个回调函数
fs.readFile(files,'utf-8',function(err,data){
if(err){
err(err);
}else{
suc(data);
}
})
})
};
//通过.then方法属性调用Promise中的两个回调函数
fun('./a.txt')
.then(
function(data){
console.log(data);
},
function(err){
cinsole.log(err);
}
)
b.Promise异步控制对象避免’回调地狱‘的具体实现
//当前目录下有a.txt,b.txt,c.txt等多个文件
//控制读取文件的先后顺序,避免异步执行导致的顺序混乱
var fs = require('fs');
var fun=function(files){
//返回Promise对象,利用回调控制方法的执行顺序(异步控制)
return new Promise(function(suc,err){//suc,err是两个回调函数
fs.readFile(files,'utf-8',function(err,data){
suc(data);
})
})
};
//使用链式操作方式解决嵌套形式;其中err方法缺省,不被调用
fun('./a.txt')//创建一个Promise对象
.then(function(data){
console.log(data);
//状态执行完毕,执行下一个异步函数,需要重新创建、返回一个Promise对象
return(fun('./b.txt'));//由于Promise对象有两种状态(suc,err),且状态不可逆,所以每一次异步都需要创建一个Promise对象进行管理,状态不是suc就是err
})
.then(function(data){
console.log(data);
return(fun('./c.txt'));
})
.then(function(data){
console.log(data);
})
5.8 新函数声明方式——箭头函数
- 箭头函数没有自己的this,函数体内部写的this,指向的是外层代码块的this //(箭头函数中尽量不要使用this)
- 箭头函数内部的this是定义时所在的对象,而不是使用时所在的对象并且不会改变
- 箭头函数不能用作构造函数
- 箭头函数内部不存在arguments,箭头函数体中使用的arguments其实指向的是外层函数的arguments
//一般函数表达方式
var fun1=function(s1,s2){
return s1+s2;
}
//箭头函数的使用方式
var fun2=(s1,s2)=>{
return s1+s2;
}
//无参数,()不能省略
var f=()=>{
}
//只有一个参数
var f=s=>{
return s;
}
//
var fun3=(s1,s2)=>s1+s2;//这个用法仅当函数中只有return语句时能够使用;
console.log(fun1(1,2));//结果为3
console.log(fun2(1,2));//结果为3
console.log(fun3(1,2));//结果为3
第六章 Express框架
6.1 框架基本用法
//开启服务器
const express = require('express');
const app = express();
// respond with "hello world" when a GET request is made to the homepage
app.get('/', function (req, res) {
res.send('hello world')
})
app.listen(666,function(){
console.log('success,port 666');
});
//开启外部路由
const express=require('express');
const yewu=require('./yewu');
const router=express.Router();//获取路由对象
//调用路由对象的链式操作方法,获取数据
//路由模块优化前
// router
// .get('/',function(req,res){
// yewu.getall(req,res);
// })
// .get('/getone',function(req,res){
// yewu.getall(req,res);
// });
//路由模块优化
router
.get('/',yewu.getall)//由于两个方法的形参相同,所以可以直接将yewu.getall当做回调函数;
.get('/getone',yewu.getone);
module.exports =router;//导出路由对象
6.2 模板引擎 express-art-template 和 koa-art-template
6.2.1 express-art-template使用手册
注意:
- 文件夹中必须要有public文件夹用于
Express框架
放静态资源,如CSS、JAVASCRIPT、IMG
等文件== - 文件夹中必须有views文件夹用于模块引擎存放HTML等特定文件
1. install
npm install --save art-template
npm install --save express-art-template
2. example
var express = require('express');
var app = express();
// view engine setup
app.engine('art', require('express-art-template'));
app.set('view', {
debug: process.env.NODE_ENV !== 'production'
});
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'art');
// routes
app.get('/', function (req, res) {
res.render('index.art', {
user: {
name: 'aui',
tags: ['art', 'template', 'nodejs']
}
});
});
6.2.2 koa-art-template使用手册
1. install
npm install --save art-template
npm install --save koa-art-template
2.example
const Koa = require('koa');
const render = require('koa-art-template');
const app = new Koa();
render(app, {
root: path.join(__dirname, 'view'),
extname: '.art',
debug: process.env.NODE_ENV !== 'production'
});
app.use(async function (ctx) {
await ctx.render('user');
});
app.listen(8080);
6.3 静态资源加载
//'/static':虚拟路径
//path.join :拼接路径
app.use('/static', express.static(path.join(__dirname, 'public')))
6.4 使用formidable模块实现文件上传
install
npm install formidable
example
const express=require('express');
//导入formidable表单数据解析模块
const formidable=require('formidable');
const fs=require('fs');
const app=express();
app.post('/',(req,res)=>{
var form = new formidable.IncomingForm();//初始化formidable表单对象
//使用这个方法自动实现文件上传
form.parse(req,(err,fields,files)=>{//解析表单enctype设置为multipart/form-data提交的表单数据
//将上传的文件重命名并移动到当前文件夹
fs.rename(files.imgs.path,'./'+files.imgs.name,(err)=>{
Console.log(err);
})
})
})
### 6.4 使用formidable模块实现文件上传
#### install
```shell
npm install formidable
example
const express=require('express');
//导入formidable表单数据解析模块
const formidable=require('formidable');
const fs=require('fs');
const app=express();
app.post('/',(req,res)=>{
var form = new formidable.IncomingForm();//初始化formidable表单对象
//使用这个方法自动实现文件上传
form.parse(req,(err,fields,files)=>{//解析表单enctype设置为multipart/form-data提交的表单数据
//将上传的文件重命名并移动到当前文件夹
fs.rename(files.imgs.path,'./'+files.imgs.name,(err)=>{
Console.log(err);
})
})
})