ES6:
//ES6:
//全局中的this是一个空对象,指向window,函数中的this是global
/*let声明的变量不允许重复(在一个块级区域内)*/
//1.数组的解读
//解构的目标=解构的源
// let ary=[1,2,3,4,[5,6]];
// // let [a,b,c,d,[e,f]]=ary;
// // console.log(e,f);//5,6
// let [g,...k]=ary;
// console.log(g,k);
// let [h,,...j]=ary;
// console.log(h,j);
// //合并数组
// let x=100,y=200;
// let ary2=[x,y];
// console.log(ary2);//[100,200]
// //改变原先的值
// let v=300,m=400;
// [v,m]=[m,v];
// console.log(v,m);//400,300
// //2.字符串解构解读
// //如果其中某一项没有可以用解构赋值的方式 (例子:d=90)
// //特别注意的地方:let声明如果有相同的会报错某解析错误
// let str='abc';
// let [a,b,c,d=90]=str;
// console.log(a,b,c,d);//a b c 90
// //3.对象的解构解读
// let obj={
// n:100,
// m:200,
// t:[1,2]
// }
// // let {n,m:m2,z=500,t:[f,q]}=obj;//解构名必须一致;
// //解构名也可以重新起个别的名(m:m2)然后调用
// // console.log(n,m2,z,f,q);//100 200 500 1 2
// //解构赋值也可以通过扩展符号接收
// let {n,...e}=obj;
// console.log(n,e);/*100
// {m: 200, t: Array(2)}
// m: 200
// t: (2) [1, 2]
// __proto__: Object */
//.给对象调换一下解构
// let a={
// x:100,
// y:200
// }
// a={x,y}={x:200,y:100};
// console.log(x,y);//200 100
// //4.模板字符串``
// //好处可以相互嵌套多个标签
// //5.includes
// //includes()方法就是为了简化indexof()的判断
// //因为indexof()方法返回的是包含字符串的位置,如果==-1的话,那也就是不包含这个字符串
// //includes()方法返回的是布尔值 false或true
// //测试str.includes('测试')?console.log(true):console.log(false);
// //includes相当于截取字符串的位置,返回的是布尔类型的值
// //也类似于some 、every、节省了不用去循环
// let ary3=[1,23,3];
// let s=ary3.includes(23);
// console.log(s);//true
// let str="abc";
// let s2=str.includes('d');
// console.log(s2);//false 如果有就返回true没有就false
//5.箭头函数
//箭头函数注意事项
/*
1.this取决于上级作用域,而不是调用
2,箭头函数不用new关键字
3.箭头函数不可以使用arguments获的参数列表,可以使用rest参数代替
引入了rest参数(形式:...变量名),参数放入数组中
let f00=(...param=>{
console.log(param);
})
foo(12,56);
*/
//箭头函数例子:rest代替参数列表
// let foo=(...a)=>{//...在箭头函数中rest代替参数列表接收箭头函数
// console.log(a);//1 2 3 4
// }
// foo(1,2,3,4);
//6.引入class(类)这个概念,通过class关键字可以定义类
//通过class关键字定义类,必须使用constructor来定义this(和使用this,否则就报错)
// class Fn{//
// constructor(){//函数接收this上的
// this.n=10;
// this.m=20;//接收this
// }
// //获取原型上的继承(例子:如下方法)
// sum(){
// console.log('我是公共的sum内容')
// }
// }
// let f=new Fn();
// console.log(f.n,f.m);//10 20
// f.sum();//调取:我是公共的sum内容
//7.模块化:es6的模块化分为导出(export)与导入(import)两个模块
//export default导出对象包含多个/export一个一个的导出
//8.promise本身是同步的
//promise先预定之后再去执行这些方法
//promise用来异步操作,是构造函数,参数为then(失败和成功的执行)和catch(捕获失败的执行)后需要执行的方法
//then()可以有两个函数一个成功,一个catch的失败,
//catch()只能捕获上一级then的失败的状态
//all:全部(调多个异步接口都成功才会成功,否则就catch失败状态)
//race:比赛(多个异步同时执行哪个快就执行哪个)
//有三种状态:从pending到成功 从pending到失败 catch捕获到失败
//本身是一个类,可以用new出来一个promise
//解决了回调地狱和来回嵌套的问题。
//9.Object.assign:是合并对象,把多个对象合并到第一个对象上
let obj1={n:1},
obj2={m:2},
obj3={k:3};
Object.assign(obj1,obj2,obj3);
console.log(obj1);//会自动合并到第一个对象上//{n: 1, m: 2, k: 3}
//10.generator yield 函数
function* name(){
yield console.log('执行1');//执行1
yield console.log('执行2');//执行2
function h(){
console.log('执行函数h');//执行函数h
}
yield h();//调用函数
}
let s=name();
//next:代表执行下一项
s.next();
s.next();
s.next();
//11.Symbol唯一值
//2个变量交换值
let a=1,b=2;
[b,a]=[a,b];
console.log(a,b);//2 1
//js设计模式有哪几种?:发布订阅设计模式和单例设计模式和工厂设计模式
JS面向对象:
//面向对象的理解:
//(封装、继承、多态、属于后台的面向对象)
//1.js的面向对象:Object Oriented Programming 简称OOP
/*
常用的编程思想有2种:
1.面向对象编程:js、java、PHP、python、c#.....
2.面向过程编程:c
-js本身就是基于面向对象的编程语言,具备它自己的编程思想
-面向对象编程需要我们掌握对象,类,实例的概念
面向对象:万物皆对象
类:对象的细分
实例:类中具体的一个事物
举个例子说明上面三个词:自然界是个大环境,包含万物,把这些万物
按照特征区分了很多种类,包含人类、动物类、植物类...
我们要学习人类这一类别,就会拿出具体的一个人来研究,学习了这个人
有什么特征,就知道了其他人也拥有相同的特征了,这个具体的人就是人类中的实例
回归js中
js也有很多的东西。把这些东西分成很多类,我们学习其中一个类,就先拿出这一类中的一个具体实例来
研究。学习了一个实例具有的属性和方法,就知道了其他实例也会拥有相同的属性和方法
例如:学习数组,就先var ary=[1,2,3];研究这个数组有什么方法和属性,就知道其他数组也有同样的方法
和属性,每一个ary数组就是Array数组类的一个实例,这个实例就是我们要操作的对象
面向对象要有类,实例这些东西,js中有哪些类?
1.自定义类:new 出它的实例
2.内置类:Number、String、Boolean、Function、Array...
每一个实例都有自己的所属类,包括每一个元素都有自己的所属类
1,2,3,4...每一个数字都是Number类的一个实例
var ary=[1,2,3],var ary2=[]...每一个数组都是Array类的一个实例
总结:js本身就是面向对象开发的,他提供了很多内置类,我们操作js就是操作这些类的实例
所以每一个内置类的实例,都是我们要操作的对象,操作js本身就是面向对象编程。
后台的面向对象有封装、继承、多态性的特性,js中面向对象可以实现函数的封装,多种继承的方式
但是没有多态一说,如果非要说多态,可以把给一个函数中传递不同的参数,会实现不同的效果
勉强说成多态。
*/
JS同步和异步:
/*
js中的同步和异步?
浏览器是多线程的,js是单线程的
1.js为什么是单线程的?
因为浏览器只分配了一个线程给js
单线程:同一时间,只能执行一个任务,同一时间,只能放一件事,同一时间只能放一件事情
去主栈中运行
多线程的浏览器体现在哪里?
浏览器打开一个页面,就是开启了一个进程,
进程大线程小:一个进程中又包含了多个线程,例如在浏览器中打开一个html页面(有去加载html的,有去加载css的...)
浏览器加载一个html页面:
当去加载html的时候,浏览器分配一个线程加载html结构,分配其他线程去加载对应的资源文件,最后再分配一个线程去
自上而下执行js文件(所以有的时候,js文件加head中运行的时候,dom元素获取不到)
2.js为什么没有设计成单线程的?
假如有2个方法,a方法改变了xxx变量的内容,同时b方法也改变了xxx变量的内容,同时进行,按照哪个执行
3.js的同步编程:在一个线程上(主栈、主任务队列),同一时间,只能做一件事情,当前事情完成
才能进行下一事情、
先把一个任务进栈执行,执行完出栈,再把下一个任务进栈,上一个任务出栈...
进栈出栈的过程
4.js的同步编程:首先它不是同时执行
主栈上执行任务的时候,发现这个任务是异步任务的操作的时候,会把它移出主栈,放到等待任务队列中,
(浏览器会再分配一个线程,来监听等待任务队列中的任务是否达到指定的运行时间),而对于事件监听,
就是监听是否被触发了
如果主栈执行完,监听者会把到达时间的任务重新放到主栈中执行,执行完成后,主栈就空闲下来了
再去拿异步任务队列中去拿最先到达时间的任务,到主栈中运行...
4-1:js中的异步操作:
定时器,事件绑定,回调函数,ajax,promise(async/await),process.nextTick
node中的fs异步的I/O操作
所有js中的异步编程仅仅是根据异步机制来管控任务的执行顺序,不存在同时执行两个任务一说
扩展:
console.time('s');//记录执行的开始时间
console.timeEnd('s');//记录执行的结束时间
定时器的最小等待时间:谷歌 4ms
如果主栈的任务执行的时间超过了等待任务,也要等待主栈中的任务执行完成,才能去执行等待中的任务
等待任务队列中,谁先到达时间,就把谁先执行,微任务除外
如果同时达到时间的,先放的先执行
宏任务,微任务:
等待队列中的任务:分为宏任务和微任务,先执行微任务,在执行宏任务
Promise的then
Promise(async/await)
*/
//1.例子:
// setTimeout(()=>{
// console.log(1);//
// },1000);
// console.time('a');
// for(let i=0;i<10;i++){
// }
// console.timeEnd('a');
// console.log(2);//同步
// setTimeout(()=>{
// console.log(3);//定时器到时间执行
// },0)
//执行顺序a:: 0.010986328125 ms 2 3 1
//2.例子:
// let p=new Promise((s,j)=>{//promise第一个函数代表成功,第二个代表失败
// console.log(4);//2.同步
// setTimeout(()=>{
// console.log(5);
// },1000)
// s();//任务队列
// })
// p.then(()=>{
// console.log(6);//3.任务队列执行微任务
// },()=>{
// console.log(7);
// })
//1例子.和2例子.同时执行时运行结果:
//执行顺序 a: 0.02099609375 ms 2 4 6 3 1 5
/*
同步执行,再异步执行:又分为(微任务和宏任务),先执行微任务再执行宏任务
异步分为以下几种:
1.Promise.then是微任务,async和awaity也是微任务
2.定时器是宏任务
3.ajax
*/
//1.1例子:
// function a(){
// return new Promise((resolve,reject)=>{
// //方法执行必须调用后才会执行:例如resolve成功和失败reject
// setTimeout(()=>{
// console.log(9);
// resolve();
// },1000);
// })
// }
// function b(){
// a();//异步
// console.log(8);
// }
// b();
//执行顺序 8 9
//1.2例子:改变执行顺序为9 8的操作如下
function a(){
return new Promise((resolve,reject)=>{
//方法执行必须调用后才会执行:例如resolve成功和失败reject
setTimeout(()=>{
console.log(9);
resolve();
},1000);
})
}
//异步:ajax
async function b(){//同时使用async await搭配使用才会改变
await a();//解析为await执行完成后其它才会执行(await会把下边的执行加入到异步队列中,直到await执行完再执行异步队列任务)
console.log(8);
}
b();
/*
说一说事件循环(event loop)过程?
1.js执行的时候会判断当前代码是同步还是异步,同步就进入同步消息队列中立即执行
异步就推进异步消息队列中等待执行
2.当所有同步任务执行完毕后,主线程空闲下来就会去到异步消息队列中
看是否有异步任务达到可执行条件的,就将其移到主栈中去执行(先微任务再宏任务以及队列先进先出机制)
上面操作循环就形成了事件循环(event loop)
(例子:主栈空闲时,当两个队列同时有任务时,谁先进来就执行谁)
*/
闭包的作用:
/*
闭包的作用,优点和缺点。
闭包:是js的一个重要机制。通过函数执行形成一个不销毁的私有作用域,保护和保存里面的私有变量不受外界的干扰
保护:之前项目中,现实功能的时候,防止和别人的变量名冲突,就是把功能代码封装到一个闭包中
保护起来,防止全局变量的污染
保存:循环的事件绑定的时候,此时的用到它索引的时候有可能变成全局的了,用闭包形成一个不销毁的作用域
把每次的索引都保存了起来,后面使用的时候直接拿出来用
缺点:真是项目为了保证js性能,堆栈内存的性能优化,应该尽可能的减少闭包的使用,不销毁的堆栈内存是
消耗性能的
//闭包的表现形式 :
//柯理化函数
function fn(){//形成的作用域不销毁
return function(){
}
}//调用外面的函数的返回的都是return的函数
//惰性函数=>单例模式
var untis=(function(){//自执行函数执行,形成一个不销毁的作用域,返回了一个对象
return{
}
})()
*/
DOM重绘和回流:
/*
dom的重绘和回流
1.html加载时发生了什么?
浏览器会把html解析成DOM数,把css解析成cssom树,DOM和CSSOM合并就产生了
渲染树(Render Tree)有了render three,浏览器根据render tree节点绘制
到页面上
2.回流:
DOM树和CSSOM树结合后的render tree后,将可见Dom节点以及它对应的样式结合起来
可是我们还需要计算它们在设备视口(viewport)内的确切位置和大小,这个计算的阶段就是回流
width、height、bottom、left、top
3.重绘:
通过构造render tree和回流阶段,我们知道了那些节点是可见的,以及可见节点的样式
和具体的几何信息(位置、大小),那么我们就可以将render tree的每个节点都
转换为屏幕上的实际像素,这个阶段就叫做重绘节点
例如background-color、color、outline等(改变一些样式就是重绘)
注:重绘不一定会引起回流,回流一定引起重绘,任何对render tree中元素的操作都会引起回流
或重绘
4.什么操作会引起重绘、回流
1.页面一开始渲染的时候
2.添加或删除可见的dom元素
3.元素的位置发生变化
4.元素的尺寸发生变化(包括外边距、内边框、边框大小、高度和宽度等)
5.内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代
6.用户操作浏览器的窗口尺寸变化(因为回流是根据视口的大小来计算元素的位置和大小的)
5.如何减少回流、重绘
1).浏览器的优化机制
现代的浏览器都是很聪明的,由于每次重排都会造成额外的计算消耗
因此大多数浏览器都会通过队列化修改并批量执行来优化重排过程。浏览器
会将修改操作放入到队列里,直到过了一段时间或者操作达到了一个阀值(界限),才清空队列
但是,当你获取布局信息的操作的时候,会强制队列刷新
比如当你访问以下属性或者使用以下方法:
offsetTop、offsetLeft、offsetWidth、offsetHeight
scrollTop、scrollLeft、scrollWidth、scrollHeight
clientTop、clientLeft、clientWidth、clientHeight
以上属性和方法都需要返回最新的布局信息,因此浏览器不得不清空队列
触发回流重绘来返回正确的值。
因此,我们在修改样式的时候,最好避免使用上面列出属性,他们都会刷新渲染
队列。
2)尽可能的减少回流和重绘
1.尽可能在DOM树的最末端改变class
原因:回流可以自上而下,或者自下而上的回流的信息传递给周围的节点的,但可以减少其影响。
尽可能在Dom树的里面改变class,可以限制了回流的范围,使其影响尽可能少的节点
总结就是减少了回流的影响范围
2.避免设置多层内联样式,改成使用外部类统一修改
原因:通过style属性设置样式,每个dom元素都会造成回流
样式应该合并在一个外部类,这样当该元素的class属性可被操控时仅会产生一次回流
3).动画效果应用到position属性为absolute或flex的元素上
原因:脱离文档流,减少回流的render tree的规模
*/
原型和原型链:
/*
原型和原型链?
1.每一个函数都天生自带一个prototype属性(原型),它的值是个对象类型的,作用是储存供给它的
实例使用的属性和方法
2.每个prototype上都有一个constuctor属性,指向当前函数本身
3.每个对象天生自带一个_proto_的属性,指向它的所属类prototype(原型)
4.所有的内置类的基类都是object对象
原型链:当操作一个对象属性或者方法的时候,首先会找私有的,有就使用,私有的没有
会通过_proto_属性,找它所属类原型(prototype)中的公共的方法和属性,一直找到基类object位置,
这种一级级向上查找的机制叫做原型链机制
*/