JavaScript第五周知识点复习

50 阅读18分钟

保护对象:保护对象的属性和方法

1、四大特性:
{

  • value: 1001, //实际保存值的地方

  • writable: true, //开关:控制着是否可以被修改 - 默认值:都为true

  • enumerable: true, //开关:控制着是否可以被for in循环遍历到 - 默认值:都为true

  • configurable: true //开关:控制着是否可以被删除 - 默认值:都为true,总开关:一旦设置为false,其他特性不可以在修改,而且它本身也是一旦设置为false,不可逆 }

      修改四大特性:
      	
      	1Object.defineProperty(对象名,"属性名",{
       			修改四大特性
      		})
      	调用一次方法只能保护一个属性的四大特性
    
      	2Object.defineProperties(对象名,{
      			"属性名":{修改四大特性},
      			...
      		})
      	至少方法只调用了一次
    
      	四大特性甚至不能防止添加
      	
    
    

三个级别

  1. 防扩展:防止添加Object.preventExtensions(obj);
  2. 密封:防止添加和删除bject.seal(obj);
  3. 冻结:防止添加和删除和修改Object.freeze(obj);

保护对象不重要:

  1. 如果你不用面向对象开发,那你也没有对象可保护
  2. 前辈们都没保护,你保护个啥
  3. 别人一般来说不可能知道你取的对象名字叫什么

四大特性,其实应该叫六大特性 - 可以帮助我们做出动态数据

Object.defineProperty(obj,"name",{
				get:()=>{
					console.log("获取数据会进行拦截");	
				},
				set:v=>{
					console.log("设置数据会进行拦截");
					v;//拦截到的新数据
					d1.innerHTML=v;
				}
			})

对象的深浅拷贝

  1. 浅拷贝
var obj1={"name":"obj1"};
var obj2=obj1;
复制代码
  1. 深拷贝
var obj1={"name":"obj1"};
var obj2={...obj1}

  1. 以后如何脱掉后端传来的数据:
    后端穿衣服:var jsonText=JSON.stringify(obj1);Node.js就是这句话,Node.js 也是js,历史上第一次一门语言可以通吃前后端;
    前端脱衣服:var jsonObj=JSON.parse(jsonText);此方法也能实现深拷贝;

3、error对象:错误

  1. 以后工作/学习的目的:
  • 快速找到错误
  • 记得要放用户
  1. 浏览器自带的4种错误类型:可以快速找到自己的错误
  • 语法错误:SyntaxError - 一定是你的符号写错了
  • 引用错误:ReferenceError - 没有创建就去使用了
  • 类型错误:TypeError - 不是你的方法,你却去使用了
  • 范围错误:RangeError - 只有一个API会碰到:num.toFixed(d);//d取值范围:0~100之间
  1. 只要发生错误,就会报错,会导致后续代码终止
  2. 错误处理:就算发生错误,我们也不希望报错,而是给出一个错误提示,让后续代码可以继续执行
    语法:
                     try{
			只放入你可能出错的代码
		}catch(err){
			发生错误后才会执行的代码
			alert(err);//err就是我们的错误提示:只不过是英文的
			alert("中文的错误提示,来提示用户");
		}

try...catch...性能非常差,几乎是所有代码里最差的,放到try中的代码效率会被降到最低;可以用分支结构代替他;

开发经验:记住一切的客户端输入/用户输入都是坏人-但是不必担心,只要做好该做的防护就不会出错

3、抛出自定义错误,只要是错误,后续代码都不会执行:throw new Error("自定义错误信息");

4、ES5;严格模式

  • 开启:"use strict"; - 写在任何一个作用域的顶部都可以
  • 作用:
  1. 禁止了全局污染,使用变量之前必须先创建变量
  2. 将静默失败升级为了错误

5、柯里化函数

               function add(a){
		return function(b){
			return function(c){
				console.log(a+b+c);
			}
		}
	}
	add(3)(5)(7)

百度/高德地图

定位:GPS 北斗 基站定位 IP定位

2、网站的定位技术都是使用的GPS,并不需要我们学习如何使用GPS,我们有现成的百度或者高德地图
3、开发者如何使用:

  1. 打开百度:搜索百度地图开放平台;
  2. 注册,登录百度账号;
  3. 拉到最下面,点击注册成为开发者;
  4. 进入控制台;
  5. 应用管理-我的应用-创建应用-实名认证-获得秘钥
  6. 找到示例文档DEMO;
  7. 复制全部代码;
  8. 查询经纬度:api.map.baidu.com/lbsapi/getp…
  9. 百度地图你看上的每一个都可以混搭在一起,但是一定要注意版本:普通版(老) 和 webGL(新),是不可以混搭的

匿名函数:没有名字的函数,两种用法

  1. 自调:只能执行一次,好处:函数中没用的变量是会自动释放的,他可以用于代替全局代码写法,两者很相似,都只会执行一次,但是自调会释放;
(function(){
console.log(1);
})();

  1. 回调:匿名函数不是自调,就是回调
elem.on事件名=function(){}
	arr.sort(function(){})
	var obj={
	"方法名":function(){}
}

一切的回调函数,都可以简化为箭头函数;

3、设计模式:不仅仅局限于前端,他是一种编辑思想,越来越复杂,对于前端要求越来越高了;

1、单列模式:也称为单体模式,保证一个类仅有用人实例对象,并且提供一个访问它的全局访问点
如何实现:最简单的单列模式:利用ES6的let不允许重复声明的特性,刚好就符合了单列的特点

let obj={
	"name":"袍哥1",
	"getName":()=>this.name,
}

不推荐:

  • 污染命名空间,容易造成变量名冲突;
  • 维护时不容易管控,会直接覆盖了;

推荐:

                      var h52301=(function(){
			let state=null;
				return function(name,age){
					this.name=name;
					this.age=age;
					if(state){
						return state;
					}
					return state=this;
				}
			})();
			
			h52301.prototype.sayHello=function(){
				console.log(this.name);
			}
			
			var llc=new h52301("兰",18);
			var yxw=new h52301("楠",19);
			
			console.log(llc);
			console.log(yxw);
			console.log(yxw==llc);

			llc.sayHello();
			yxw.sayHello();
           页面只有一个弹出框的时候使用

2、发布订阅模式

                       let obj={};
			//创建订阅者
			function on(id,fn){
				if(!obj[id]){//判断有没有此id(有没有这个人),没有我就创建了一个空数组
					obj[id]=[];
				}
				obj[id].push(fn);
			}
			on("老袍",(msg)=>{console.log("小兰来了",msg)});
			on("老袍",(msg)=>{console.log("小尹来了",msg)});
			on("老袍",(msg)=>{console.log("小张来了",msg)});
			on("老袍",(msg)=>{console.log("小李来了",msg)});
			on("老袍",(msg)=>{console.log("小赵来了",msg)});
			console.log(obj);//{"老袍":[fn,fn,fn,fn,fn]}
			
			//发布者的操作
			function emit(id,msg){
				obj[id].forEach(fn=>fn(msg));//obj["老袍"].forEach
			}
			btn.onclick=()=>{
				emit("老袍","一支");
			}

4、事件轮询:js其实是单线程引用,代码必然是从上向下,一步一步的执行,,如果某一块代码非常耗时,可能会导致整个页面卡住,尤其是把js放到head中,会看到页面是一块白板

1、宏任务:不会再卡住我们的单线程应用,可以让后续代码先走,我们慢慢跟着来,但是问题在于,多个宏任务同时存在,到底谁先执行谁后执行,分不清

2、计时器:setInterval和setTimeout 3、Ajax

2、微任务:ES6提供的Promise对象 - 可以控制异步代码,依然是异步代码,但是可以控制执行的顺序了

                     function ajax1(resolve){
				setTimeout(()=>{
					console.log(1);
					resolve();
				},Math.random()*5000);
			}
			
			function ajax2(){
				return new Promise(resolve=>{
					setTimeout(()=>{
						console.log(2);
						resolve();
					},Math.random()*5000);
				})
			}
			
			function ajax3(){
				return new Promise(resolve=>{
					setTimeout(()=>{
						console.log(3);
						resolve();
					},Math.random()*5000);
				})
			}
			
			new Promise(ajax1).then(ajax2).then(ajax3);//promise的回调函数提供了一个形参函数,可以用于放行
			console.log("后续代码");

NOde.js概述:不是js,但是语法和JavaScript非常相似

做的功能绝对不是特效!做的事和服务器端其他语言是一致(和数据库进行交互,成为了一个前端到数据库的中间桥梁)

目的:

  1. 使用代码搭建一个服务器&文件系统(服务器文件可以放在任何位置,但是不在你的电脑里,你可以根据网址来访问到我的东西)
  2. Node.js如何沟通前端和数据库
  3. 全栈:图书管理系统(HTML+CSS+JS+Node+Mongo)

4、Node.js安装:node-v18.15.0-x64.msi - 一路往下点,哪里点不动了,就把哪里勾上,千万不要取消任何东西 版本:16年初(0.12) 16年中(4.xx) 16年末(6.xx) - 更新速度快,意味着:发展迅速,有前景,其实也没有多大的变化,更新的最多的是提升了性能
检查你安装成功没有:打开cmd输入:node -v - 查看版本号,如果有版本号代表你已经安装成功!
其实你安装的这个node.js就是一个运行环境而已!我们书写“js”不再需要浏览器了,因为根本写的就是不是js,而是node.js,只不过语法和js非常相似

5、Node.js如何运行:3种
1、交互模式 - 临时测试,打开cmd输入:node回车,就可以开始敲你的"js"代码

2、脚本/文件模式 - 正式开发中
1、先创建xx.js,里面书写自己的代码
2、打开cmd输入:node 文件的绝对路径
3、编辑器越来越强大了:安装插件,前提:至少两个方式能够成功,才可以安装插件
vscode - code runner:对着文件出右键,第一个选项就是code runner,或者 右上角有一个开始按钮

6、Node.js知识: js和node的区别
相同点:都可以使用一切的ECMAScript的东西包括一切的API都可以使用,在服务器端不存在任何浏览器,所以不必担心兼容问题
不同点:
1、JavaScript:DOM+BOM - 做特效
2、Node.js:虽然没有DOM+BOM,但是他却又10万以上+的模块等待我们学习

模块(module):每一个xx.js文件,都可以称之为是一个模块
1、模块化开发:如果以一个网站来说,我们可以按功能分为很多模块:商家模块、商品模块、促销模块、用户模块、产品模块....
分工合作:将每个模块交给对应的人,完成,最后再由【主模块】进行引入
1、每一个模块都有一个操作,可以用于公开/暴露自己的成员,exports:Node.js自带的一个预定义变量,可以直接使用,是一个对象,放在此对象里面的东西,就是允许公开的东西
语法:

exports.属性名=属性值;
module.exports={
 属性名:属性值,
	...
		   }

错误导出法:
	exports={
	name:"袍哥",
	age:18,
	hobby:"学习"
    }

2、每一个模块(主模块)都有一个操作,可以用于导入/引入其他模块
require:Node.js自带的一个预定义变量,可以直接使用,是一个函数,函数中需要书写出引入模块的路径
语法:var x=require("./文件名")

笔试题:exports和module.exports有什么区别?
1、语法,写法,用法不同
2、都是用于公开暴露自己的成员的
但是exports={},写法是错误的,其实Node.js底层有一句话:exports=module.exports,其实真正做公开功能的是module.exports,如果你使用,exports={};//你创建了一个新的空对象,把module.exports,所以不再具有公开的功能

2、模块的分类:

  • 官方模块 - 今日目标,大概有二十几个,但是重要的其实只有几个
  • 第三方模块 - 多到数不清出,提供了很多官方模块没有的东西,有一个网址npm可以去下载 - 明天我们在学习
  • 自定义模块

Node.js最大的特点:

  • 快、非常快 - 以前最快的是php,js的速度是php的十六倍
  • 为什么快:
  1. 因为官方提供的东西少,甚至连数据库的操作API都没有提供的
  2. 使用了chrome浏览器的v8引擎

3、官方模块:不需要下载,在你安装node.js环境的时候就已经带上了,但是某的模块可以需要引入,某的模块可能不需要引入:
1、Global模块:不需要引入的,可以直接使用

提供了: 1、五个预定义变量,可以直接使用

  1. filename - 获取当前文件完整的绝对路径
  2. dirname - 获取当前文件绝对路径,不包含文件的名字,何时:vscode某的同学可能不支持node.js上书写相对路径,只能写绝对路径 - 等我们学习了文件系统
  3. exports - 空对象,可以用于公开暴露自己的成员
  4. require - 函数,可以用于导入其他模块
  5. module - 指代当前模块本身,甚至包含着以上4个操作

2、定时器(周期性、一次性、瞬间定时器):定时器不是当初的js,只不过用法和当初一模一样
3、console也不是当初的console,只不过用法和当初一模一样

2、querystring模块:解析查询字符串,使其变成一个对象,可以获取到前端传到后端的消息

  • 需要引入:var qs = require('querystring');
  • 作用:解析url查询字符串部分的功能
  • var obj=qs.parse("查询字符串");
  • 想要获得前端传来的每一个部分:obj.键名;
  • 垃圾:如果前端传来的是一个完整的url网址,他就解析不了了!

url模块 - 今日小重点

  • 需要引入:var url = require('url');
  • 作用:提供了解析url各个部分的功能
  • var objUrl=url.parse("网址",true);//支持第二参数,是一个布尔值,默认为false,一旦设置为true,自动使用querystring模块的parse方法去解析查询字符串部分 真正的重点:
  1. 查询字符串:objUrl.query.键名; - 前端form表单提交传到后端的东西
  2. 路由/文件相对路径/请求地址:objUrl.pathname - 判断路由的不同,去读取不同的HTML发送给我们的用户看

4、Buffer模块:缓冲区,可以将数据变成一个16进制的数字,你可以理解为是Node.js中的一种新的数据类型,但是我们绝对不会手动使用,因为我们一眼看不懂,但是后面的一些API可能会导致我们被动都到Buffer,但是你也别怕,因为Node.js中大部分的API,是支持Buffer

5、fs模块 - 大重点 需要引入:var fs = require('fs');

异步读取文件:

fs.readFile("文件路径",(err,buf)=>{
buf->读取到的内容
 })

异步写入文件:

fs.writeFile("文件路径","新内容"/buf,()=>{
console.log("写入完毕后,要做什么,必须放在这里面");
 })//会替换掉原来的东西

异步追加文件:

fs.appendFile("文件路径","新内容"/buf,()=>{
console.log("写入完毕后,要做什么,必须放在这里面");
})//会替换掉原来的东西

强调:只有异步才能更完美的发挥Node.js的特点(快)

NOde.js 官方模块

6、http模块 - 超级重点:搭建服务器
引入了http(搭建服务器)、url(区分开路由和请求消息)、fs(读取文件响应给用户看)

var http=require("http");
var url=require("url");
var fs=require("fs");

创建服务器应用:var app=http.createServer();
为其绑定监听端口:app.listen(80);
/为其绑定请求事件:http:请求 - 响应模式,必须要有一个请求,才有一个响应

app.on("request",(req,res)=>{
req:request(请求)对象,他有一个属性叫做req.url,看了一获取到前端传到后端的路由和请求消息,但是路由和请求消息是融为一体的,不方便我们获取某个部分,所以我们引入了url,进行解析,分开两部分
	var objUrl=url.parse(req.url,true);
	//保存路由
	var router=objUrl.pathname;
	if(router=="/" || router=="/index.html"){//判断路由的不同,读取不同的页面给用户看
		//res:response(响应)对象,他有一个方法:res.end(响应的内容) - 可以响应给前端想要的东西
		fs.readFile("./public/html/index.html",(err,buf)=>{
			res.end(buf);//res.end只能用一次
		})
	}
})

扩展:字符串有一个API:math
var rs=str.match(reg);和indexOf几乎一致,但是支持正则,我们不关心为多少,只关心为不为null

强调:一切的src和href都是一个请求都是一个路由,这个请求就需要后端来解析,根据不同的请求响应不同的内容

完成了:
1、使用代码搭建服务器&文件系统

2、模块(每个.js文件)的分类

  1. 官方模块:不需要下载,再安装Node.js环境的时候就已经自带了,但是有的模块需要引入:require("模块名");
  2. 第三方模块
  3. 自定义模块:自己书写的xx.js:require("./模块名");

自定义模块:分为2大类

  1. 文件模块:创建xx.js去公开需要公开的内容,主模块要引入,必须写为require("./模块名");
  2. 目录模块:3种用法
  • 比如创建m1的文件夹,在其中创建index.js的文件,去公开需要公开的内容,主模块要引入,必须写为require("./m1");
  • 比如创建m2的文件夹,在其中创建xx.js的文件,,去公开需要公开的内容,主模块要引入,必须写为require("./m2");必须再创建一个package.json的配置文件,写入:{"main":"xx.js"}
  • 创建一个文件夹必须名为:node_modules,再在其中创建出m3文件夹,在其中创建index.js的文件,去公开需要公开的内容,主模块要引入,必须写为require("m3");

其实真实开发中,我们程序员用的最多的是文件模块,目录模块的第三种方式其实根本不是给人用的(第三方模块下载后会自动创建此文件夹)

3、如何下载第三方模块:
npm工具:Node Package Manager:Node.js的模块/包管理器,专门用于管理第三方模块的,作用:下载、更新、删除、维护包之间的依赖关系
打开网址:npm官网www.npmjs.com/
搜索你需要用到的模块:尽量用带有完全符合标签的那个包,或者是 第一个包:

  1. 打开cmd:检查npm是否安装成功:npm -v
  2. 在你的项目之中,再打开cmd
  3. 下载:npm i 包名
  4. 更新:npm up 包名
  5. 删除:npm un 包名

mongo就是基于json的数据库,json就是JavaScript Object Notation
1、安装&启动:

  • 解压我提供的mongodb-win32-x86_64-2008plus-ssl-3.6.11.zip文件
  • 打开bin文件夹,里面有:mongo.exe(客户端) 和 mongod.exe(服务器端)
  • 如何启动:在bin文件夹中打开cmd:输入:.\mongod.exe --dbpath=你想要保存的绝对文件夹路径; - 服务器开启成功,而且那个文件夹就保存着你以后要存储的所有的数据,不要关闭mongo服务器的cmd,再打开一个cmd:输入:.\mongo.exe - 在上一个命令行可以查看我们是否连接成功 - 客户端开启成功

2、mongo的语法:都是在客户端cmd输入 1、数据库的操作 1、查询所有数据库:show dbs 2、创建/切换数据库:没有就创建,有了就切换:use 数据库名称 3、查看当前选中的数据库:db 4、创建数据表:db.createCollection("表名") - 无限,一定要先创建数据表后,我们才能查看到自己创建的数据库 5、删除数据库:db.dropDatabase(); - 一旦删除不能恢复,不推荐,因为要坐牢

2、数据表的操作

  1. 创建数据表:db.createCollection("表名",{size:5242880,capped:true,max:5000}) - 最大存储空间为5mb,最多存储500个,意味着这个数据表做了限制,不推荐
  2. 查看目前所有的数据表:db.getCollectionNames();
  3. 删除数据表:db.表名.drop();

3、数据的操作 1、增:db.表名.save({键值对,...}) - 一次只能插入一条数据,db.表名.save([{},{},{},....]) - 一次插入多条数据

2、删:db.表名.remove({}) - 不推荐,删除数据库中所有的数据
db.表名.remove({name:"小波"}) - 会删除数据库中name:"任小波"的所有数据

3、改:db.表名.update({条件},{set:{新内容}});
举例:db.表名.update({name:"小波"},{set:{pwd:"123123"}});

4、查:db.表名.find(); - 找所有

  • db.表名.find({pwd:"666666"}); - 找到所有的密码为666666的数据
  • db.表名.find({},{name:1,pwd:1}) - 找到所有的数据,但是只返回name和pwd
  • db.表名.find().sort({age:1}) - 按照age升序排列,-1为降序排列
  • db.表名.find({age:{$gte:18}}) - 拿到所有age大于等于18的数据
  • db.表名.find({name:/正则/}) - 甚至可以用正则(模糊查询)
  • db.表名.find().skip(5).limit(5) - 跳过前5条,再拿5条,理解为5-10条数据(第几个分页条显示第几条数据-第几条数据)
  • db.表名.find().count() - 获取到此表有多少条数据(做出分页条)

3、安装mongoDBCompass软件:图形化界面,直观、好看、方便 - 仅仅只用于给我们方便查看

4、Node.js操作mongoDB:

  1. 安装第三方模块:mongoose
  2. 使用步骤:
  • 引入:const mongoose = require('mongoose');
  • 连接数据库:mongoose.connect("mongodb://127.0.0.1/数据库名称");
  • 创建出一个新的数据表的同时,设置数据类型的控制,防止用户乱输
                       const UserSchema=mongoose.Schema({
				age: Number,
				pwd: String,
				email: String,
				vip: String,
				name: String,
			})
			//		模型名    类型限制     
			var User=mongoose.model("User",UserSchema,"数据表名
                        ");

4、增:

                    var x=new User({//仅仅只是创建出了一个x对象,并没有放入到数据库之中
				age: "20",
				pwd: "123123",
				email: "dy@qq.com",
				vip: "0",
				name: "dy",
			})

			x.save((err)=>{
				console.log("新增成功后要干什么");
			})

5、删:

User.remove/deleteOne/deleteMany({条件},(err)=>{// - 作者不推荐remove在mongoose之中使用
console.log("删除成功后要干什么");
	})


6、改:


			User.update/updateOne/updateMany({条件},{新内容},(err)=>{// - 作者不推荐update在mongoose之中使用
				console.log("修改成功后要干什么");
			})

7、查:

User.find({条件},(err,result)=>{
                          result就是你的查找到的结果
			})

目前:前端能传到后端的技术,只有一个:form表单,action属性可以随便自定义一个路由名称,后端解析此路由就可以通过objUrl.query.键名得到想要的部分