Nodejs基础

Nodejs.day1

01-nodejs入门


1.1-什么是nodejs

  • 1.Node.js官网地址:https://nodejs.org/en/

  • 中文网站:http://nodejs.cn/api/

  • 2.Node是一个构建Chrome V8引擎之上的一个Javascript 运行环境

    • Node一个运行环境,作用是让js拥有开发服务端的功能
  • 3…Node中的NPM是世界上最大的开源库生态系统(类似于github)

    • NMP官网:https://www.npmjs.com

1.2-Node.js环境安装

  • 1.确认电脑是否安装Node环境

    • 打开终端,输入 node -v,如果能看到版本号则说明当前电脑已经安装Node环境,如果提示Node不是内部或外部命令,则表示未安装

      一旦安装了node,则会自动一并安装`npm[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f3tyT12I-1599793552966)(C:/Users/86188/AppData/Roaming/Typora/typora-user-images/1599028279378.png)]

1.3-服务端js与客户端js区别

    1. 前端js三个部分组成
      • ECMAScript :确定js的语法规范
      • DOM :js动态操作网页内容
      • BOM :js动态操作浏览窗口
  • ​ 2.服务端nodejs 只有一个部分 ECMAScript
    • nodejs可以使用 : 比那里 数据类型 运算符 分支循环
    • nodejs不能使用 : document,window
    • 因为服务端是没有界面的
      • 在nodejs中使用dom和bom的api程序会报错

02.-ES6语法

2.1-变量声明let与const

/* 
    学习目标: 了解let与const声明变量特点
        ES6学习技巧:对比法
    
    学习路线:
        1. 介绍ES5声明变量var特点
            * a. 有变量提升--->编译器会将var声明提升到当前作业与最顶端
            * b. 没有块级作用域 (块级作用域:大括号里面的变量都是局部的)
        2. 介绍ES6声明变量let与const特点
            * a. 没有变量提升 : 一定要先声明后使用
            * b. 有块级作用域 : 只要是大括号里面声明的变量,都是局部
        3. 介绍let与const区别
            * a. let :变量。 可以重新赋值
            * b. const :常量。 不可以重新赋值,只能在声明的时候唯一赋值一次

*/

/* 1.介绍ES5声明变量var特点 */

// 1.1 有变量提升
// var num; 编译器会将var声明提升到当前作用域最顶端
console.log(num);
var num = 10;

// 1.2 没有块级作用域 (块级作用域:大括号里面的变量都是局部的)
if(1){
     
    // var在大括号里面声明的还是全局的
    var num = 20;
}
console.log(num);

/* 2.介绍ES6声明变量let与const特点 */

// 2.1 没有变量提升
// console.log(num1);
// let num1 = 10;

// 2.2 有块级作用域

if(1){
     
    let num2 = 20;
    console.log(num2);
}
// console.log(num2);

/* 3.介绍let与const区别 */
// 3.1 let :变量(可以重新赋值)  和var一样
let a = 10;
console.log(a);

a = 100;
console.log(a);

// 3.2 const : 常量(不可重新赋值) 只能声明的时候赋值一次
const b = 800;
console.log(b);

2.2-结构赋值

/* 
    1.学习目标: 对象的解构赋值
        解构赋值 : 变量赋值的简写形式

    2.对比法学习
        2.1 取出对象的属性  赋值给  变量
            let {name,age,sex} = obj;
        2.2 取出变量的值   赋值给 对象的属性
            let obj = {name,age,sex}
        2.3 解构赋值语法默认值
            let {name,age=18,sex} = obj;
*/

/* 1. 取出对象的属性  赋值给  变量 */

//1.1 复习 以前ES5写法
let obj = {
     
    name:'张三',
    age:20,
    sex:'男'
};

// let name = obj.name 
// let age = obj.age 
// let sex = obj.sex
console.log(name,age,sex);

// 1.1 复习 一起ES6写法

let obj1 = {
     
    name:'张三',
    age:20,
    sex:'男'
};

// let name = obj.name 
// let age = obj.age 
// let sex = obj.sex
let {
     age,name,sex} = obj1
console.log(name,age,sex);

/* 2.2 取出变量的值   赋值给 对象的属性 */

let name = '李四';
let age = 22;
let sex = '女';

// ES5 写法
let obj2 = {
     
    name:name,
    age:age,
    sex:sex
}

console.log(obj2);

// ES6 写法
let obj = {
     
    name, // === name:name
    age,
    sex,
    satHi:function(){
     console.log(11111);},
    eat(){
       // === eat:function(){}
        console.log(22222);
    }
}

console.log(obj2);

//3 解构赋值语法默认值
let obj3 = {
     
    name:'王五',
    sex:'男',
    age:0
};

// let name = obj.name;
// let sex = obj.sex;

/* 
    (1)声明变量 let age
    (2)检查obj有没有属性要age,有则赋值。没有则赋默认值
        if(obj.age != undefined) { 
            age = obj.age
        } else {
            age = 18
        }
 */

     let {
     name,sex,age} = obj3;

 console.log(name,sex,age);

2.3-数组解构

/* 数组解构赋值 */
let arr = [10,20,30]

/* 解构数组 */
// let n1 = arr[0]
// let n2 = arr[1]
// let n3 = arr[2]
// let n4 = arr[3]

let [n1,n2,n3,n4=100] =arr;

console.log(n1,n2,n3,n4);

2.4-函数解构与默认参数

/* 
    学习目标 :函数的结构赋值与函数默认参数

    学习路线 :
        1.复习函数传参本质: 实参给形参
        2.函数解构赋值
        3.函数默认参数
*/

// 1. 复习函数传参本质:实参给形参赋值

// ES5接收参数:let obj = {name:'张三',age:20}
// ES6接收参数:let{name,age,sex="男"} = {name:'张三',age:20}
// function fn ({name,age,sex="男"}){
     
//     //ES5 :
//     // console.log(obj); 
//     // let name = obj.name;
//     // let age = obj.age;
//     console.log(name,age,sex);
// }

// let preson = { name:'张三',age:20};
// fn(preson); 

// 2.函数默认参数
function fn1(a=10,b=20){
     
    // ES5 : 逻辑或短路
    // a = a || 10;
    // b = b || 20;
    console.log(a,b);
}
fn1(100,200);
fn1();
fn1(5)

2.5-箭头函数

/* 
    1. 学习目标:箭头函数
        *就是function函数的间歇形式
        *(1)将function替换成箭头
        *(2)将形参小括号移到箭头的=>的左边
        * let fn = () => {}

    2. 学习目标
        2.1 一般用法
        2.2 其他用法
            * a. 如果函数只有一个形参,则可以省略形参小括号
            * b. 如果函数只有一行,则可以省略函数体的大括号(此时必须要省略return
*/

// 1. ES5声明函数:function

// 无参无返回
let fn = ()=>{
     
    console.log('5555');
}
fn();

// 有参有返回
let fn1 = (a,b)=>{
     
    return a+b;
}
let res = fn1(10,20);
console.log(res);

// 2.其他用法

// 2.1 如果函数只有一个形参,则可以省略小括号
let fn2 = a=>{
      return a*2};
let res2 = fn2(100);
console.log(res2);

// 2.2 如果函数体只有一行代码,则可以省略大括号(此时必须省略return)
let fn3 = a =>a*2;
let res3 =fn3(500);
console.log(res3);

2.6-模板字符串

/* 

学习目标: 模板字符串
学习技巧: 对比法

1. 复习ES5学习的字符串特点:一切以 单引号 '' 或 双引号 "" 引起了的内容
    1.1 不能字符串里面取变量的值:需要使用连接符
    1.2 不能识别字符串格式 : 需要使用转义符

2. ES6新增 模板字符串:一切以反引号引起来的内容 ` `
    2.1 可以去变量的值: ${变量名}
    1.2 可以识别字符串格式
*/

// 1.复习ES5学习的字符串特点

// 1.1 不能在字符串中去变量的值 :只能使用字符串连接符 + 
// 1.2 不能识别字符串本身格式 : 需要使用转义符
let name ="保健";

let str1 = '我爱\n'
+ name;
console.log(str1);

//2.ES6新增 模板字符串:一切以反引号引起来的内容 ` `
// 2.1 可以去变量的值:${变量名}
// 2.2 支持字符串格式

let name2 = '学生';
let str2 = `我爱
${
       name2}`;

console.log(str2);

2.7-拓展运算符

/* 

    1.拓展运算符(展开运算符) : ...
    2.作用 :变量对象一种简写形式(类似于for-in循环)
    3.应用场景:
        a. 连接数组
        b. 求最大/最小值
        c. 一行代码实现数组去重
*/

// 1. 基本用法
let car = {
     
    pinpai:'特斯拉',
    price:888888
};

let hourse = {
     
    address : '深圳湾一号'
}

let person = {
     
    name: '维克多',
    age:26,
    ...car,
    ...hourse
}

console.log(person);

// 2.应用场景

// 2.1 连接数组

let arr1 = [10,20,30]
let arr2 = [40,50,60]

// 之前:concat
let arr3 = arr1.concat(arr2);  //连接arr1 和 arr2
arr3.push(70,80,90);  //连接之后,继续添加元素
console.log(arr3);

// ES6展开运算符
let arr4 = [...arr1,...arr2,70,80,90];
console.log(arr4);

// 2.2 求数组最大值/最小值

let arr = [23,45,11,23,45,88,66,11,88,66];

// 之前:擂台思想、 Math.max.apply()
let max = Math.max.apply(Math,arr);
console.log(max); 

// ES6展开运算符
let min = Math.min(...arr);
console.log(min);

2.8-数据类型

/* 
    1.新增数据类型(集合): Set
        * 与数组几乎一致,惟一的区别是不支持重复元素(相当于是无法存储重复元素)

*/

// 声明Set : new Set(数组)
let set = new Set([10,20,30,66,77,30,20,77,10])
console.log(set);

// set一般不会单独使用,只是为了去掉重复数组元素。将set转成数组
let arr =[...set];
console.log(arr);

// 应用场景:数组去重
let arr1 = [21,54,67,88,54,21,67];
// 最简单的一行代码实现数组去重
let newArr = [...new Set(arr1)];
console.log(newArr);

03-babel网站:ES6转ES5

  • babel官网地址:https://www.babeljs.cn/repl
    • babel作用:把ES6语法转成ES5语法
    • 由于ES6是js的最新语法,所以有的老版本浏览器不支持。这个网站可以查询ES6支持哪些浏览器:https://www.caniuse.com/#search=es6

Nodejs.day2

01-fs文件读写

1.1-readFile读取文件

​ 1.前端框架使用流程

​ *导包 (下载) :得到一个对象,存储框架中的API

​ *拥抱 : 调用对象方法

​ 2.后端nodejs模块使用流程

​ *导包 :得到一个对象,存储框架中的API

​ *用包 :调用对象方法

fs.readFile('./data/c.txt','utf-8',(err,data)=>{
     
    if(err){
     
        console.log(err);
        // 抛出异常,throw的作用就是让node程勋终止运行,方便调试
        throw err;
    }else{
     
        console.log(data);
    }
})

console.log('111');

1.2-writefile写入文件

//1. 导入模块
const fs =  require('fs');
//2. 使用模块
/**
* @description: 写入文件
* @param {string} path : 文件路径
* @param {string} data : 要写入的数据
* @param {string} option : 文件编码 自动根据数据识别,一般不用传
* @param {function} callback : 写入回调 (err)=>{ err:错误信息 }
* @return: 
*/
fs.writeFile('./data/b.txt','临渊羡鱼不如退而结网',err=>{
     
    if( err ){
     
        throw err;
    }else{
     
        console.log('写入成功');
    }
});

1-3-同步异步

/* 学习目标:   同步与异步区别 
    1. 编译器执行代码流程
        1.1 从上往下解析代码
        1.2 判断代码是同步还是异步
            同步  :立即执行
            异步  :不执行,放入一个事件队列池 (EventLoop)
        1.3 当页面所有的同步执行完毕之后,才会执行事件队列池中的代码
    
    2. 同步与异步区别
        2.1 API不同 :异步有回调函数,同步一般没有
                * 前端有两个API是异步 : 定时器 和 ajax
        2.2 执行顺序不同 : 同步有序且优先执行, 异步是无序执行
        2.3 性能不同 : 异步性能高(不阻塞线程),同步阻塞线程
*/

// nodejs中所有的api默认都是异步的,如果希望拥抱就会后面加上Sync即可
/*异步特点 
    1. 有回调函数
    2. 无序执行
    3. 不阻塞线程 : 性能高
*/
fs.readFile('./data/c.txt','utf8',(err,data)=>{
     
    console.log('11111');  
})

/* 同步特点
    1. 没有回调
    2. 有序
    3. 阻塞线程:性能低
*/
let data = fs.readFileSync('./data/c.txt','utf8');
console.log('7');

02-path路径

2-1.相对路径与绝对路径

//1.导入文件模块
const fs = require('fs');
//2.读取文件
/*a.注意点: node中的相对路径: ./ 不是相对于当前文件所在路径,而是相对于执行node命名的文件夹路径
	在服务端开发中,一般不要使用相对路径,而使用绝对路径
		b.解决方案:在nodejs中,每一个js文件都有两个全局属性,它可以帮助我们获取到文件的绝对路径
		__filename:当前js文件所在目录的绝对路径
		__dirname:当前js文件的绝对路径
*/
console.log(_dirname);
console.log(_filename);
/* 2.如果想要获取当前文件夹下其他文件绝对路径,可以使用 __dirname属性来拼接 */
var path = __dirname + '/aaa.txt';
console.log(path);

fs.readFile(path,'utf-8',(err,data)=>{
     
    if(err){
     
        console.log(err);
        //抛出异常,throw的作用就是让node程序终止运行,方便调试
        throw err;
    }else{
     
        console.log(data);
    };
});

2-2.path模块介绍

/* 
    1. 前端相对路径 ./ 与nodejs后端 相对路径  ./ 区别
        1.1 前端相对路径   ./ :   相对于当前文件 所在的文件夹   (固定的)
        1.2 nodejs相对路径 ./ :   相对于 执行node命令 所在的文件夹 (不固定)
    
    2. nodejs中文件路径一般不适应相对路径,使用绝对路径
        * 在node中,每一个js文件都有两个默认的全局变量
        * __dirname :当前js文件所在的文件夹绝对路径
        * __filename : 当前js文件本身的绝对路径

    3. path模块作用: 拼接文件路径
        作用和自己拼接差不多,但是容错率更高
        * 自动识别当前操作系统的磁盘分隔符,会自动添加
        * 接错功能 :如果磁盘疯符写错了,path模块会自动纠正
*/
//1.导入模块
//(1)参数: 模块路径  (2)返回值: 对象 , 存储模块所有的api
const fs = require('fs');

//2.使用模块
fs.readFile( aPath ,'utf-8',function(err,data){
     
    if(err)throw err;

    console.log(data);
});

03-http服务器

3-1-搭建服务器

//1.导入模块
const http = require('http');

//2.创建服务器
let server = http.createServer((req,res)=>{
     
    //req : 请求对象。 负责获取客户端的请求信息   res : 响应对象。 负责响应客户端数据的
    console.log(req.url);
     //了解即可: url中的中文会被进行urlencode转码
     console.log(decodeURI(req.url));
});

//3.开启服务器
server.listen(3000,()=>{
     
    console.log('服务器开启成功');
});

Nodejs.day3

01-nodejs搭建服务器

01-1-搭建静态服务器

/* nodejs搭建静态资源服务器

1. 浏览器中所有的外部资源路径,都会变成网络请求

*/

// 1. 导入模块
const http = request('http');
const fs = require('fs');
const path = require('path');


//2.创建服务器
let server = http.createServer((req,res)=>{
     
     // (1)请求:req
     console.log(req.url);

     // (2)处理
     if (req.url == '/') {
     
          // 读取html文件响应返回
          fs.readFile(path.join(__dirname,'www','index.html'),'utf8',(err,data)=>{
     
               if(err) throw err;
               // (3)响应:res
               res.end(data);
          });
     }else if (req.url == '/resource/css/index.css'){
     
          fs.readFile( path.join(__dirname,'www','resource','css','index.css'),(err,data)=>{
     
               if(err) throw err;
                //(3)响应:res
               res.end(data);
           });
     }else if( req.url == '/resource/images/01.gif'){
     
          fs.readFile( path.join(__dirname,'www','resource','images','01.gif'),(err,data)=>{
     
              if(err) throw err;
               //(3)响应:res
              res.end(data);
          });
      }else if( req.url == '/resource/images/01.jpg'){
     
          fs.readFile( path.join(__dirname,'www','resource','images','01.jpg'),(err,data)=>{
     
              if(err) throw err;
               //(3)响应:res
              res.end(data);
          });
      }else if( req.url == '/resource/video.mp4'){
     
          fs.readFile( path.join(__dirname,'www','resource','video.mp4'),(err,data)=>{
     
              if(err) throw err;
               //(3)响应:res
              res.end(data);
          });
      }else{
     //错误路径
          res.end('404 not found');
      }

});

//3.开启服务器
server.listen(3000,()=>{
     
     console.log('服务器开启成功');
});
/* nodejs搭建静态资源服务器

1. 浏览器中的所有外部资源路径,都会变成网络请求

2. 一般静态资源(css文件,图片,音视频)使用 url路径拼接的方式来处理

*/

//1.导入模块
const http = require('http');
const fs = require('fs');
const path = require('path');

//2.创建服务器
let server = http.createServer((req,res)=>{
     
     // (1)请求:red
     console.log(req.url);

     // (2)处理
     if( req.url == '/' ){
     
          //读取html文件响应返回
          fs.readFile( path.join(__dirname,'www','index.html'),(err,data)=>{
     
              if(err) throw err;
               //(3)响应:res
              res.end(data);
          });
      }else if( req.url.indexOf('/resource') == 0  ){
     
          fs.readFile( path.join(__dirname,'www',req.url),(err,data)=>{
     
              if(err) throw err;
               //(3)响应:res
              res.end(data);
          });
      }else{
     //错误路径
          res.end('404 not found');
      }
});

//3.开启服务器
server.listen(3000,()=>{
     
     console.log('服务器开启成功');
});
  • 1.html中所有外部资源路径都会变成网络请求
    • 服务器需要根据请求路径响应返回对应的文件
  • 2.静态资源(图片、文件、音视频)一般使用路径拼接的方式来处理
    • 服务短板可以直接拼接url来响应对应资源,简化代码

02-nodejs接收get请求与post请求

02-1-nodejs接收get参数

/* 
学习目标:nodejs接受get请求参数
     1. 前端发送get请求:直接在url后面拼接 url?key1=value&key2=val2

     2. nodejs接受get请求参数
          2.1 导入url模块
          2.2 调用parse()方法解析参数: url.parse( req.url,true)
          2.3 获取解析好的query属性: get参数
*/

//1.导入模块
const http = require('http');

const url = require('url');

//2.创建服务器
let server = http.createServer((req,res)=>{
     
     // (1)get请求采纳数直接在url后面拼接
     console.log(req.url);
     // (2)get参数解析原理是 字符串切割
     // 第一个参数:要切割的url字符串 
     // 第二个参数:布尔类型  默认false:query不处理   true:query处理成对象
     let obj = url.parse(req.url,true);
     console.log(obj);

     let {
     query} = obj;
     let query = obj.query
     console.log(query);

     // 响应返回参数:告诉客户端解析成功 (js对象需要转json对象才可以响应返回)
     res.end(JSON.stringify(query));
});

//3.开启服务器
server.listen(3000,()=>{
     
     console.log('服务器开启成功');
});

02-2-nodejs接收post参数

/* 
学习目标:nodejs接受post请求参数

     1. 前端发送post
          1.1 需要设置请求头
          1.2 请求头中发送: xhr.send(key=value)

     2. nodejs接受post参数
          2.1 给red注册data事件 (接收数据包)
          2.2 给red注册end事件  (数据包接受完毕)
          2.3 在end方法中使用querystring模块解析body
*/

// 1. 导入模块
//1.导入模块
const http = require('http');

// 解析get请求参数
const url = require('url');
// 解析post请求参数
const querystring = require('querystring');

//2.创建服务器
let server = http.createServer((req,res)=>{
     
     console.log(req.url);

     /* (1)给req注册data事件
          客户点每发送一个数据包,这个事件就会车发一次 (触发多次)
     */
     let postData = '';
     req.on('data',function (chunk){
     
          postData += chunk;
     })

     /* (2)给req注册end事件
          客户端每一次post所有的数据包发送完毕会执行一次
     */
    req.on('end',function (){
     
         /* (3)处置post参数:使用querystring模块切割 请求体 */
         console.log(postData);
         let body = querystring.parse(postData);
         console.log(body);

          // 响应给客户端
          res.end(JSON.stringify(body))
    })
});

//3.开启服务器
server.listen(3000,()=>{
     
     console.log('服务器开启成功');
});

02-3-get与post区别

get与post区别

  • 位置不同:
    • get是在url后面拼接(请求行)
    • post是在请求体中发送(请求体)
  • 大小不同: 一般文件上传接口都是post
    • get发送数据有大小限制(一般1MB)
    • post发送数据没有大小限制
  • 速度不同:
    • get速度比post快
  • 安全性不同:一般登录注册都是post
    • post比get安全

03-Express框架

03-1框架介绍

  • Express官网:
    • http://www.expressjs.com.cn/
    • http://expressjs.com/
    • 多去官网文档查看API,多进行尝试,熟能生巧
  • 三大核心功能
      1. 托管静态资源
        1. nodejs实现静态服务器功能在express中只需一行代码
      2. 路由
        1. Express自带路由功能,Node服务端开发变得极其简单
        2. Express支持链式语法,可以让代码看起来更加简洁
      3. 中间件
        1. Express最为核心的技术和思想,万物皆中间件
        2. 中间件虽然理解起来有点困难,但是使用起来非常方便,类似于jquery的插件一样,由于jquery库自身的功能无法满足开发需求,所以通过插件来拓展功能

03-2响应数据

/*学习目标: express响应客户端数据 
    (1)响应普通文本 :  res.send('字符串')
    (2)响应json对象 :  res.send( js对象 )
    (3)响应html文件 :  res.sendFile( 文件绝对路径 )

(1)express框架本质不是修改原生代码,而是在原生的基础上添加方法 (给req和res原型添加成员)
(2)在express中你可以使用一切node原生语法
*/

//1.导入模块----相当于http
const express = require('express');

//2.创建服务器
let app = express();

//3.路由(接口文档) : 一个请求对应一个函数
app.get('/',(req,res)=>{
     
    //响应普通文本

    //原生node语法
    // res.end('这是首页');
    //express语法
    res.send('这是首页');

});

app.get('/login',(req,res)=>{
     
    //响应json : 底层会自动将js对象转成json格式字符串
    res.send({
     
        name:'班长',
        age:40
    });
});

app.get('/list',(req,res)=>{
     
    //响应html文件: 文件绝对路径
    res.sendFile( `${
       __dirname}/list.html`);
});

app.use((req,res)=>{
     
    //自定义404处理结果
    res.end('404');
})

//4.开启服务器
app.listen(3000,()=>{
     
    console.log('服务器开启成功');   
});

03-3-静态资源

//1.导入模块
const express = require('express');

//2.创建服务器
let app = express();

//3.托管静态资源
/* 
(1)如果请求路径为/ , express会自动读取www下面index.html响应返回
(2)如果请求路径是以www中文件夹开头,express会自动根据url拼接路径返回
*/
app.use(express.static('www'));

//4.写路由(接口文档)


//5.开启服务器
app.listen(3000,()=>{
     
    console.log('服务器开启成功');
    
})

03-4-get与post参数

//1.导入模块
const express = require('express');

//2.创建服务器
let app = express();

//3.托管静态资源
app.use(express.static('www'));

//4.配置中间件(jq的插件) : 本质都是给req或者res原型添加成员

//4.1 body-parser中间件 : 解析post参数
//(1)导入中间件
const bodyParser = require('body-parser');
//(2)使用中间件 : 给req添加body属性,存储解析好的post参数
app.use(bodyParser.urlencoded({
      extended: false }));

//5.写路由(接口文档)

/*接收get请求参数 
    req.query
*/
app.get('/hero/list',(req,res)=>{
     
    console.log( req.url );

    //获取get请求参数 : express会自动帮我们解析get参数并且添加到req的原型query属性中
    console.log( req.query );
    

    res.send( req.query )
    
});

/*接收post请求参数 
    (1)使用body-parser插件
    (2)req.body
*/
app.post('/hero/add',(req,res)=>{
     
    console.log( req.url );
    
    console.log( req.body );
    res.send( req.body )
});


//6.开启服务器
app.listen(3000,()=>{
     
    console.log('服务器开启成功');
})

04-第三方模块使用流程

适合所有第三方模块

  • 官网:https://www.npmjs.com/
  • 按照官方文档要求安装模块`npm install 模块名
  • 复制粘贴官网代码(别人作者提前写好的)

04-1-爬虫实战

  • crawler爬取网页
/* 
第三方模块使用流程

    1. 初始化项目 : npm init -y
        *** 注意点:文件夹不能有中文
        * 生成 package.json文件 : 记录整个项目使用了那些第三方模块以及对应的版本号
    
    2. 装包(下载): npm install 模块名
        * 生成 package-lock.json文件 :记录每一个包的下载地址 
            * 提高下一次更新速度,类似于浏览器收藏夹功能
        * 生成node_modules文件夹 :  第三方模块资源文件
            *  类似于前端的libs,专门存放第三方模块资源的
    
    3. 用包 : 官网文档CV
*/


//1.导入爬虫模块
var Crawler = require("crawler");
//2.创建爬虫对象 
var c = new Crawler({
     
    maxConnections : 10,
    // This will be called for each crawled page
    callback : function (error, res, done) {
     
        if(error){
     
            console.log(error);
        }else{
     

            //爬虫成功回调

            //将爬取到的网页DOM树赋值给jq的$ (目的:使用jq的语法来操作DOM树)
            var $ = res.$;
            // $ is Cheerio by default
            //a lean implementation of core jQuery designed specifically for the server
            // console.log($("html").text());
            // console.log(  $('#jSearchHeroDiv>li').html() );
            console.log( $('html').text() );
            
        }
        done();
    }
});

//3.开始爬虫
// Queue just one URL, with default callback
c.queue('https://mc.163.com/index.html');
  • crawler爬取文件
ar Crawler = require("crawler");
var fs = require('fs');
 
var c = new Crawler({
     
    encoding:null,
    jQuery:false,// set false to suppress warning message.
    callback:function(err, res, done){
     
        if(err){
     
            console.error(err.stack);
        }else{
     
            //将爬取好的文件通过fs模块写入文件
            fs.createWriteStream(res.options.filename).write(res.body);
        }
        
        done();
    }
});
 
//绝大多数网站,都有反爬机制。只有小众网站没有
//浏览器可以下载,但是服务端爬虫无效。反爬:检测你这个请求是通过浏览器发出来,还是服务端(解决方案:让服务端伪装成浏览器来发这个请求)
c.queue({
     
    url:"http://upos-hz-mirrorks3u.acgvideo.com/upgcxcode/75/11/112251175/112251175-1-6.mp4?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfq99M=&uipk=5&nbs=1&deadline=1571396695&gen=playurl&os=ks3u&oi=2005998532&trid=a4c624adafe64ababb2a851334eaf87eh&platform=html5&upsig=2a29cd105837278e3b4c92181fe3eb59&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform&mid=0",
    filename:"./video/11111.mp4",//写入文件名 默认在根目录
    headers:{
     'User-Agent': 'requests'}//让服务端伪装成客户端
});

Nodejs.day4

01-初始化npm

node指令 作用
npm init -y 初始化
npm i express 搭建nodejs服务器
npm i body-parser 解析post请求
nodemon + 当前文件名 自动刷新
npm i xpress-fileupload 处理文件上传
npm i mysql-ithm 操作mysql数据库
  • express-fileupload文件上传中间件:npm i xpress-fileupload
    • 官网地址:https://github.com/richardgirges/express-fileupload
  • express-fileupload使用流程
    • (1)装包:npm i xpress-fileupload
    • (2)配置中间件:查阅文档example
      • 导包:const* fileUpload = require('express-fileupload');
      • 使用中间件:app.use(fileUpload());
    • (3)接受用户上传文件

02-项目思路、流程

02-1-初始化

  • 1.初始化npm:npm init -y
  • 2.安装模块:
    • express:npm i express
    • body-parser:npm i body-parser
  • 3.使用模块

02-2-项目流程

  • (1)导入模块
  • (2)创建服务器
  • (3)托管静态资源
    • 只要请求路径是以www文件夹里面的文件开头,express就会自动拼接路径返回
      • app.use(express.static('www'));
    • 只要请求路径是 / 。 express会自动读取(打开)www里面的首页index.html 返回
      • 托管服务器的static文件:存储用户图像
      • app.use(express.static(‘static’));
  • (4)配置中间件
  • (5)写路由(接口文档)
  • (6)开启服务器

02-3-nodejs处理流程

  • 请求
  • 处理
  • 响应

03-CORS跨域

  • 1.跨域 :是一个固定格式报错。(没有之一)

    • Access to XMLHttpRequest at ‘服务器url地址’ from origin ‘null’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QXsW9KHq-1599793552989)(Nodejs课程笔记/day04.assets/1571856567565.png)]
  • 2.什么是跨域?

    • ajax请求地址 与 当前页面地址 不同源 称为跨域
      • (1)ajax :浏览器只有是有ajax发送请求才会出现跨域。 href属性与scr属性不会出现跨域
      • (2)接口地址:ajax请求的url
      • (3)当前页面地址 : window.location.href
      • (4)不同源 :两个网址的 协议 || id || 端口号 不一致
  • 3.同源策略 :协议 和 id 和 端口号 一致

    • 协议:http,https,file
    • id:域名
    • 端口号:3000, 4399
  • 4.浏览器同源策略存在的理由

    • 保证电脑安全 : 当你在一个页面,使用ajax向不同源的 地址发送请求。浏览器会认为是向两个不同的服务器发送请求。浏览器为了了保证你的安全,就会拦截你的请求
  • 5.如何解决跨域限制

    第一种 :CORS

    ​ 目前的主流方案,也是最简单的方案

    ​ 简单快捷,后台只需一行代码,跟前端没有任何关系

    第二种:JSONP

    ​ 面试专用,前端需要写代码


    工作原理: 服务器 在返回响应报文的时候,在响应头中 设置一个允许的header

    res.setHeader('Access-Control-Allow-Origin', '*');

app.use((req, res, next) => {
     //任何请求都会进入这个use中间件
  res.setHeader('Access-Control-Allow-Origin', '*')//设置响应头
  next()//执行下一个中间件
})

express有一个自带的中间件cors,它的作用是自动给每一个res设置默认请求头

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ef59Tn3S-1599793552994)(Nodejs课程笔记/day04.assets/1571858796482.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XqgEG2b7-1599793553004)(Nodejs课程笔记/day04.assets/1571858867308.png)]今日易错点:

  • 图片路径写错 书写注意图片路径要和服务器地址一样
  • 单词书写有误,记得细心检查

Nodejs.day4

01-MySQL数据库使用

01-1-MySQL数据库介绍

  • 什么是数据库
    • 存储数据的文件夹
  • 数据库使用 ---- 增删改查
  • 安装mysql数据库软件
    • 安装phpstudy软件自带mysql数据库

02MySQL语法

  • 学习网址: https://www.w3school.com.cn/sql/index.asp

02-1增删查改语句

1. 增删改查的意思
  • 增:新增记录 insert
  • 删:删除记录 delete
  • 查:查询记录 select
  • 改:修改记录 update

02-2 增加—insert语句

  • 新增数据 用法

    **insert into 表名(字段名) value(值)**

02-3 删除—delete语句

  • 删除数据

    delete from 表名

02-4 查询—select语句

  • 查询数据

    select 字段 from 表名

  • 查询所有字段

    select * from 表名

02-5 修改—update语句

  • 修改数据

    update 表名 set 字段 = 新值

  • 指定条件修改

    update student set name = “黑马一哥’ where id = 3

03-扩展知识

03-1 通配符—模糊查询

%为通配符,一般搭配like关键字使用

03-2 以什么开头

查询所有字段以关键字开头的数据

select * from 表名 where 字段 like 关键字%

03-3 以什么结尾

查询所有字段以关键字结尾的数据

select * from 表名 where 字段 like %关键字

03-4 包含什么内容

查询所有字段包含关键字的数据

select * from 表名 where 字段 like %关键字%

03-5 或者条件

使用or关键字

-- 找到student表中age小于10,或者age大于100的数据
select *from student where age < 10 or age > 100;

今日易错点

  • 粗心,依旧会有单词错误
  • 文件创建错误,每次写代码前先坚持是否准备好

Nodejs.day5

01-客户端代码

首页—index

  • 注意点:

    • 编辑按钮:使用window.location.href给编辑页面传id

      window.location.href='./update.html?id={ { v.id }}'

    • 删除按钮:

      • 用自定义属性设置id存储英雄id
      • 删除按钮是动态生成,需要进行委托事件
<!-- 模板引擎一 :英雄列表 -->
<script id="hero_list" type="text/html">
    {
     {
      each heros v }}
      <tr>
      <td> {
     {
      v.name }} </td>
      <td> <img src="{
     { v.skill }}" width="100px" height="100px"> </td>
      <td><img src="{
     { v.icon }}" width="72px" height="72px"></td>
      <td class="manager">
        <button  class="btn btn-success" onclick="location.href='./update.html?id={
     { v.id }}'">编辑</button>
        <button id={
     {
      v.id }} class="btn btn-danger">删除</button>
      </td>
      </tr>
    {
     {
      /each  }}
  </script>

<script>
  // 入口函数  : 等页面加载完毕后执行
  $(function () {
     
    /* 查询英雄详情 */
    $('#searchBtn').click(function (e) {
     
      e.preventDefault();
      $.ajax({
     
        url: 'http://127.0.0.1:3000/hero/list',
        type: 'get',
        dataType: 'json',
        data: {
      search: $('#search').val() },
        success: function (backData) {
     
          $('#heroListBody').html(template('hero_list', backData))
        }
      });
    })

    /* ajax查询列表 */
    $('#searchBtn').click();

    /* 删除英雄 */
    $('tbody').on('click', '.btn-danger', function () {
     
      $.ajax({
     
        url: 'http://127.0.0.1:3000/hero/delete',
        type: 'post',
        dataType: 'json',
        data: {
      id: $(this).attr('id') },
        success: function (backData) {
     
          if (backData.code == 200) {
     
            alert('删除成功');
            window.location.reload();
          } else {
     
            alert(backData.msg);
          }
        }
      });
    })

  })

</script>

编辑—update

<script>
        // 入口函数
        $(function(){
     
            /* 1. 获取上个页面的信息 */
            let id = window.location.href.split('=')[1];
            console.log(id);

            /* 2. 查询英雄详情 */
            $.ajax({
     
                url:'http://127.0.0.1:3000/hero/info',
                type:'get',
                dataType:'json',
                data:{
     id},
                success: function(backData){
     
                    console.log(backData);
                    $('#name').val(backData.data.name);
                    $('#skill').val(backData.data.skill);
                    $('#iconImg').attr('src',backData.data.icon);
                    console.log(backData.data.icon);
                }
            });

            /* 2. ajax发送请求 */
            //1.给file表单元素注册onchange事件
            $('#icon').change(function () {
     
                //1.2 获取用户选择的图片
                let file = this.files[0];
                //1.3 将文件转为src路径
                let url = URL.createObjectURL(file);
                //1.4 将url路径赋值给img标签的src
                $('#iconImg').attr('src', url);
            });

            /* 3. 文件上传 */
            $('.btn-success').on('click',function(e){
     
                //禁用表单默认提交事件
                e.preventDefault();
                //创建FormData对象:参数是表单dom对象
                let fd = new FormData($('form')[0])
                
                fd.append('id',id)
                $.ajax({
     
                    url:'http://127.0.0.1:3000/hero/update',
                    type:'post',
                    dataType:'json',
                    data:fd,
                    contentType: false,
                    processData: false,
                    success: function(backData){
     
                        console.log(backData);
                        if (backData.code == 200) {
     
                            alert('编辑成功');
                            window.location.href = './index.html'
                        }else{
     
                            alert('编辑失败');
                        }
                    }
                });
            });
        })
    </script>

新增—insert

<script>
  //  入口函数
  $(function(){
     
     /* 2. ajax发送请求 */
            //1.给file表单元素注册onchange事件
            $('#icon').change(function () {
     
                //1.2 获取用户选择的图片
                let file = this.files[0];
                //1.3 将文件转为src路径
                let url = URL.createObjectURL(file);
                //1.4 将url路径赋值给img标签的src
                $('#iconImg').attr('src', url);
            });

            /* 3. 文件上传 */
            $('.btn-insert').on('click',function(e){
     
                //禁用表单默认提交事件
                e.preventDefault();
                //创建FormData对象:参数是表单dom对象
                let fd = new FormData($('form')[0])
                $.ajax({
     
                    url:'http://127.0.0.1:3000/hero/add',
                    type:'post',
                    dataType:'json',
                    data:fd,
                    contentType: false,
                    processData: false,
                    success: function(backData){
     
                        console.log(backData);
                        if (backData.code == 200) {
     
                            alert('新增成功');
                            window.location.href = './index.html'
                        }else{
     
                            alert('新增失败');
                        }
                    }
                });
            });
  })
</script>

02-验证码功能

  • 验证码功能思路
    • 1.服务端生成一个二进制验证码 图片文件与对应的 验证码文本
    • 2.服务端声明全局变量存储验证码文本(文本答案)
    • 3.客服端img标签发起网络请求,服务端响应验证码图片
    • 4.客户端提交注册数据,服务端处理
  • svg-captcha第三方模块:https://www.npmjs.com/search?q=svg-captcha

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yZIr1AcW-1599793553007)(课程资料/上课资料–imgs/验证码node安装与使用.png)]

验证码工作流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vDe9HOgC-1599793553009)(课程资料/上课资料–imgs/验证码工作流程.png)]

验证码–服务端

/* svg 验证码模块 */
const svgCaptcha = require('svg-captcha');
let captchaText = '';  // 声明全局变量存储验证码文本

/* 5.6 验证码 */
app.get('/captcha', (req, res) => {
     
   // 1.请求
   console.log(req.url);
   // 2.1 生成图片 + 文本
   var captcha = svgCaptcha.create({
     
      size: 4,
      noise: 2,
      color: true,
      // background:'#d1c'
   });
   // 2.2 文本 :服务器自己存起来 (答案)
   captchaText = captcha.text;
   // 2.3 图片:响应返回浏览器
   res.type('svg');
   res.status(200).send(captcha.data);
})

客户端—register.html

  • img标签src属性请求图片,服务器响应之后img标签会自动加载图片
<img class="code" src="http://127.0.0.1:3000/captcha" alt="">

03-加密功能(md5加密与加盐技术)

  • 客户端点击提交的时候对密码进行md5加密 (使用前端第三方包 md5.min.js)
  • 服务端接收密文保存到数据库
    • 密码明文只存在于用户填写的表单input中
    • 网络传输和服务器都只存储密文
      • 防止http请求被攻击导致密码泄露
      • 防止数据库被攻击导致密码泄露
    • 下次用户登录,使用相同加密方式对登录密码加密,然后与后台服务器进行匹配看是否一致

客户端—register.html

	
<script src="./libs/md5.min.js">script>
  • 官方文档:http://jquery.cuishifeng.cn/serialize.html
  • $(form表单).serialize()new FormData(form表单区别)
    • serialize() : 用来传输文本数据的(自己一个个拼接麻烦,这是简写)
    • FormData() : 用来传输文件数据的(如果要上传文件,就用formdata

Nodejs.day7

01-Promise

1.1Promise介绍 :解决 回调地狱

  • ES6教程传送门:http://es6.ruanyifeng.com/#docs/promise

  • Promise 是一个构造函数,用于创建Promise对象

    • Promise对象:可以理解为一个处理异步操作的容器,针对异步操作
  • Promise作用:解决回调地狱

    • 回调地狱 :异步回调,层层嵌套
/*  为什么要学Promise? 

1.Promise作用 :解决回调地狱问题
	回调地狱 :异步回调 层层嵌套

*/

// 需求: 一次读取文件 a.txt , b.txt , c.txt , d.txt 这三个文件内容
cons fs = require('fs');
// (1)不能直接按照顺序写,因为异步操作是无序的

// (2)解决方案 :在回调函数中嵌套执行
// 弊端 :形参回调地狱(异步回调 层层嵌套,麻烦不方便维护)
//读取文件a
fs.readFile('/data/a.txt','utf8',(err,data)=>{
     
    if(err){
     
        throw err;
    }else{
     
        console.log(data);
        //读取文件b
        fs.readFile('/data/b.txt','utf8',(err,data)=>{
     
            if(err){
     
                throw err;
            }else{
     
                console.log(data)
                //读取文件c
                fs.readFile('/data/c.txt','utf8',(err,data)=>{
     
                    if(err){
     
                        throw err;
                    }else{
     
                        console.log(data);
                        //读取文件d
                        fs.readFile('/data/d.txt','utf8',(err,data)=>{
     
                            if(err){
     
                                throw err;
                            }else{
     
                                console.log(data)
                            }
                        })
                    }
                })
            }
        })
    }
})

1.2Promise使用

使用流程 Promise是一个后遭函数,用于创建promise实例

  • 创建Promise实例对象
    • let p = new Promise((resolve,reject)=>{ //异步操作 })
  • 调用实例对象的then方法处理异步操作结果
    • p.then(data=>{ //处理成功数据 },err=>{ //处理失败数据 })
/*
1.Promise是一个构造函数,返回一个Promise对象
2.使用流程
	(1)实例化Promise对象 :将异步操作放入Promise中
	(2)调用then()方法:处理异步操作结果
*/

const fs = require('fs');
/* 
参数 :回调函数(resolve,reject)=>{ //异步操作 }
	resolve : 完成回调
	reject :失败回调
*/

let p = new Promise( (resolve,reject)=>{
     
    //异步操作:读取文件a
    fs.readFile(`${
       __dirname}/data/a.txt`,'utf8',(err,data)=>{
     
        if(!err){
      //成功 
            // (1)resolve: 执行then方法里面的第一个函数
            reslove(data);
        }else{
      // 失败
            // (2)reject: 执行then方法里的第二个函数
            reject(err);
        }
    })
} )

//调用promise实例的then方法
//第一个参数:成功的回调
//第二个参数:失败的回调
p.then(data=>{
     
    console.log(data);
},err=>{
     
    console.log(err)
})

1.3Promise原理

promise本质不是修改异步的顺序(异步永远是无序的),而是通过控制异步结果的顺序,从而实现异步代码有序执行

/* 
1.Promise注意点及原理:
     1.1 Promise对象有三种状态
          * pending(进行中)
          * fulfilled(已成功)
          * rejected(已失败)
     1.2 Promise状态改变只有两种情况
          * 从pending(进行中)变为fulfilled(成功)
          * 从pending(进行中)变为rejected(失败)
     1.3 注意 :Promise对象在创建的时候,里面的异步就会立即执行
          ***** 不要在创建promise的时候回处理异步结果,应该调用resolve()或reject()交给then()方法来处理

     1.4 promise解决回调地狱 :在上一个promise的then方法中返回下一个promise实例对象

     1.5 坤哥个人总结 :promise本质不是修改异步的顺序(异步永远是无序的),而是通过控制异步结果的顺序,从而实现异步代码有序执行
     
*/

const fs = require('fs');
//(1)创建三个异步操作 promise

//读取文件a
let p1 = new Promise((resolve,reject)=>{
     
    // 读文件
    fs.readFile('./data/a.txt','utf8',(err,data)=>{
     
        if(!err){
     // 成功
            resolve(data);
        }else{
     // 失败
            reject(err);
        }
    })
})

let p2 = new Promise((resolve,reject)=>{
     
    if(!err){
     // 成功
            resolve(data);
    }else{
     // 失败
            reject(err);
    }
})

let p3 = new Promise((resolve, reject) => {
     
    //异步操作: 读取文件a
    fs.readFile(`${
       __dirname}/data/c.txt`, 'utf8', (err, data) => {
     
        if (!err) {
     //成功
            resolve(data);

        } else {
     //失败
            reject(err);
        }
    });
});

let p4 = new Promise((resolve, reject) => {
     
    //异步操作: 读取文件a
    fs.readFile(`${
       __dirname}/data/d.txt`, 'utf8', (err, data) => {
     
        if (!err) {
     //成功
            resolve(data);

        } else {
     //失败
            reject(err);
        }
    });
});

//(2)调用promise实例的then方法
//第一个参数:成功的回调
//第二个参数:失败的回调
p1.then(data=>{
     
    console.log(data);
    return p2; //在第一个promise的then方法中返回第二个promise对象
})
    .then(data=>{
      //p2的then
    console.log(data);
    return p3;
})
    .then(data=>{
     
    console.loh(data);
    return p4;
})
    .then(data=>{
     
    console.log(data);
})

1.4Promise函数封装

const fs = require('fs);
                   
//1.封装一个函数 :根据文件名生成 文件读取的promise
function createPromise(filename){
     
    return new Promise((resolve,reject)=>{
     
        fs.readFile(`${
       __dirname}/data/${
       filename}.txt`,'utf8',(err,data)=>{
     
            if(!err){
     
                resolve(data);
            }else{
     
                reject(err);
            }
        })
    })
}

let p1 = createPromise('a')
let p2 = createPromise('b')
let p3 = createPromise('c')
let p4 = createPromise('d')

//2.解决希求:先读a,读完a后读b,一次读取
p1.then(data=>{
     
    console.log(data);
    return p2;
}) 
    .then(data=>{
     
    console.log(data);
    return p3;
})
    .then(data=>{
     
    console.log(data)
    return p3;
})
    .then(data=>{
     
    console.log(data)
})

1.5Promise对象的catch方法

  • catch() : 捕捉then方法中的错误err
const fs = require("fs");

/* promise实例对象的catch方法: 用于捕获异步操作的错误信息 */

//1.封装一个函数 :根据文件名生成 文件读取的promise
function createPromise(filename){
     
    return new Promise((resolve,reject)=>{
     
        fs.readFile(`${
       __dirname}/data/${
       filename}.txt`,'utf8',(err,data)=>{
     
            if(!err){
     
                resolve(data);
            }else{
     
                reject(err);
            }
        })
    })
}

//2.解决需求:要先读a,读完a后读b
p1.then(data=>{
     
    console.log(data);
    return p2;
}) 
    .then(data=>{
     
    console.log(data);
    return p3;
})
    .then(data=>{
     
    console.log(data)
    return p3;
})
    .then(data=>{
     
    console.log(data)
})
    .catch(err=>{
     
    //catch :上面任何一个then出错了都会进入这个方法
    console.log(err);
})

1.6Promise对象的all()方法

  • all() : 将多个promise对象放入数组中合并成一个promise
  • 所有异步全部执行完毕才会执行then方法
const fs = require('fs');

//Promise是一个构造函数,用于创建promise实例

//封装一个创建promise的函数
function createPromise(filename){
     
    return new Promise((resolve,reject)=>{
     
        fs.readFile(`${
       __dirname}/data/${
       filename}.txt`, 'utf8', (err, data) => {
     
            if (!err) {
     //成功
                resolve(data);
    
            } else {
     //失败
                reject(err);
            }
        });
    });
};

let p1 = createPromise('a');
let p2 = createPromise('b');
let p3 = createPromise('c');
let p4 = createPromise('d');

// Promise.all([p1,p2,p3,p4]) : 多个promise合成一个
let pArr = Promise.all([p1,p2,p3,p4])
// (2)调用promise实例的then方法
pArr.then(data=>{
     
    //执行时机:pAll中所有的promise全部都完成才会执行then
    // data : 数组。 数组中每一个元素就是每一个promise的结果
    console.log(data)
})

1.7Promise对象的rece()方法

  • race() : 将多个Promise合并成一个Promise
  • 任何一个异步 执行完毕就会执行then方法
const fs = require('fs');

// Promise是一个构造函数,用于创建promise实例

// 封装一个创建promise的函数
function createPromise(filename){
     
     return new Promise((resolve,reject)=>{
     
         fs.readFile(`${
       __dirname}/data/${
       filename}.txt`, 'utf8', (err, data) => {
     
             if (!err) {
     //成功
                 resolve(data);
     
             } else {
     //失败
                 reject(err);
             }
         });
     });
 };
 
 let p1 = createPromise('a');
 let p2 = createPromise('b');
 let p3 = createPromise('c');
 let p4 = createPromise('d');

//Promise.all([p1,p2,p3,p4]) : 多个promise合成一个
 let pArr = Promise.race([p1,p2,p3,p4]);

//(2)调用promise实例的then方法
pArr.then(data =>{
     
    //执行时机 : pAll中任何一个promise完成就会执行then
    //data : 每一个执行的promise的结果
    console.log(data)
})

02-js难点面试题

2.1箭头函数this指向

  • 箭头函数中没有this:这意味着 call() apply() bind()无法修改箭头函数中的this

  • 箭头函数中的this指向:访问上一个作用域的this

    
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Documenttitle>
    head>
    <body>
        <script>
    	/* ES6箭头函数中的this
        (1)箭头函数中没有this :这意味着call() apply() bind() 无法修改箭头函数中的this
        (2)箭头函数中的this指向 :访问上一个作用域的this
        
        2.学习路线 : 对比法
                2.1 function函数中的this : 谁 ‘调用’ 我, 我就指向谁
                    * 跟你怎么声明没关系,取决于调用 (变化的)
                    普通函数 : this指向window
                    对象方法 : this指向对象
                    构造函数 : this指向new创建的对象
                2.2 箭头函数中的this : 谁 '声明' 我,我就指向谁
                    * 跟你怎么调用没关系,取决于声明 (不变的)
    	*/
            // 1.全局函数:window
            let fn = () =>{
            
                console.log(this);
            }
            
            fn();//window
            fn.call({
             a:11 });//window 箭头函数中的this无法修改,因为箭头函数没有this
            
            // 2. 对象方法:window (因为对象无法开辟作用域,obj所在作用域还是window)
            let obj ={
            
                sayHi:()=>{
            
                    console.log('学习使我快乐')
                    console.log(this);
                }
            };
            obj.sayHi();//window
            
            // 3.局部函数
            var person ={
            
                play:function(){
            
                    console.log('paly中的this');
                    console.log(this);//person
                    
                    //在局部作用域声明一个箭头函数
                    let fn2 = () =>{
            
                        console.log('fn2在一级链中被声明,我的this就是一级链的this')
                        console.log(this);//person
                    }
                fn2();
                }
            };
            person.paly();
        script>
    body>
    html>
    

2.2数组降维

  • 数组降维:把一个二维数组变成一维数组

<html lang="en">
<head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <title>Documenttitle>
head>
<body>
     <script>
          /* 
          二维数组 :数组每一个元素都是一个数组
          */
         let arr = [['a','b','c'],['d','e','f'],['g','h','i']];

         console.log(arr);

          // 降维
          // 方式一:数组的concat()拼接数组
          // let newArr = [];
          // for(let i = 0;i < arr.length;i++) {
      
          //      newArr = newArr.concat(arr[i]);
          // };
          // console.log(newArr);

          // 方式二:使用ES6的拓展运算符
          let newArr = [];
          for(let i = 0;i < arr.length;i++) {
      
               newArr.push(...arr[i]);
          };
          console.log(newArr);
     script>
body>
html>

2.3数组升维


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Documenttitle>
head>
<body>
    <script>
        /* 
        升维 :一维数组生成二维
        */
        let arr = [
            {
                type: '电子产品',
                name: 'iPhone',
                price: 8888
            },
            {
                type: '家具',
                name: '桌子',
                price: 100
            },
            {
                type: '食品',
                name: '瓜子',
                price: 10
            },
            {
                type: '家具',
                name: '椅子',
                price: 380
            }, {
                type: '电子产品',
                name: '小米手机',
                price: 1380
            }, {
                type: '食品',
                name: '辣条',
                price: 5
            }, {
                type: '食品',
                name: '咖啡',
                price: 50
            }
        ];
        
        let newArr = []; //升维之后的数组
        let obj = {}; //记录一维数组种类
        
        for(let i = 0; i

你可能感兴趣的:(node.js)