length
单页面应用,局部刷新,不利于SEO,速度快,url是哈希模式
服务端渲染,用于SEO
每次返回一个新的函数,就不带上一个函数的参数,也不用储存桑一个函数,复杂度O(1),不会造成栈溢出
实现方法就是在末尾调用自身,在调用的函数内部执行新的形参
可以通过多种数据结构来实现,数组是以一种哈希映射的方式存储的。
需要注意的是:原始类型的数据放在栈中,对象的数据放在堆中,而数组是特殊的对象
Array.from()方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)。
sort()
commonJS和ES Module,主要从用于哪里,用的语法去解释
commonjs的特点:同步/运行时加载,磁盘读取速度快
ES module:在编译就确定了输入输出
遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。用于for…of遍历
Generator
Generator 函数有多种理解角度。语法上,首先可以把它理解成,Generator 函数是一个状态机,封装了多个内部状态。
执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。
形式上,Generator 函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是“产出”)。
async await是Generator的语法糖
理解弱引用和强引用,就要不要手动回收
Map的键可以是任意类型,WeakMap只接受对象作为键,不接受其它类型的值作为键
Map的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键;WeakMap的键是弱引用,键所指向的对象是可以被垃圾回收,此时键是无效的。
Map可以被遍历,WeakMap不能被遍历
controller.abort(),比如过了多久我就取消请求
地址有没有共享
存在浅拷贝的obj.assign、arr.slice()、arr.concat()、扩展运算符复制
从键值对、访问,赋值、删除、获取长度、迭代、去述说
键值对:object只能用字符串当键,map各种类型的值都可以当键
访问:object通过.访问,map通过get()访问
赋值:object通过.键去赋值,map通过set()赋值
删除:object通过delete操作符删除或者=nll,map通过delete()删除
大小:object通过keys()转换成数组再计算,map通过size()即可
迭代:map拥有迭代器
npm2 是通过嵌套的方式管理 node_modules 的,会有同样的依赖复制多次的问题。
npm3+ 和 yarn 是通过铺平的扁平化的方式来管理 node_modules,解决了嵌套方式的部分问题,但是引入了幽灵依赖的问题,并且同名的包只会提升一个版本的,其余的版本依然会复制多次。
什么是幽灵依赖?
最主要的一个问题是幽灵依赖,也就是你明明没有声明在 dependencies 里的依赖,但在代码里却可以 require 进来。
这个也很容易理解,因为都铺平了嘛,那依赖的依赖也是可以找到的。
但是这样是有隐患的,因为没有显式依赖,万一有一天别的包不依赖这个包了,那你的代码也就不能跑了,因为你依赖这个包,但是现在不会被安装了。
这就是幽灵依赖的问题。
Fast, disk space efficient package manager
pnpm 则是用了另一种方式,不再是复制了,而是都从全局 store 硬连接到 node_modules/.pnpm,然后之间通过软链接来组织依赖关系。
这样不但节省磁盘空间,也没有幽灵依赖问题,安装速度还快,从机制上来说完胜 npm 和 yarn。
主要围绕npm2嵌套,复制多次依赖,npm3和yarn扁平化,但带来幽灵依赖,pnpm则节省磁盘空间,安装速度快,因为包从全局硬连接到.pnpm,然后软连接到依赖
1、首先,在浏览器地址栏中输入url
2、浏览器先查看浏览器缓存-系统缓存-路由器缓存,如果缓存中有,会直接在屏幕中显示页面内容。若没有,则跳到第三步操作。
3、在发送http请求前,需要域名解析(DNS解析),解析获取相应的IP地址。
4、浏览器向服务器发起tcp连接,与浏览器建立tcp三次握手。
5、握手成功后,浏览器向服务器发送http请求,请求数据包。
6、服务器处理收到的请求,将数据返回至浏览器
7、浏览器收到HTTP响应
8、读取页面内容,浏览器渲染,解析html源码
9、生成Dom树、解析css样式、js交互,渲染显示页面
浏览器下载HTML后,首先解析头部代码,进行样式表下载,然后继续向下解析HTML代码,构建DOM树,同时进行样式下载。当DOM树构建完成后,立即开始构造CSSOM树。理想情况下,样式表下载速度够快,DOM树和CSSOM树进入一个并行的过程,当两棵树构建完毕,构建渲染树,然后进行绘制。
Tips:浏览器安全解析策略对解析HTML造成的影响:
当解析HTML时遇到内联JS代码,会阻塞DOM树的构建,会先执行完JS代码;当CSS样式文件没有下载完成时,浏览器解析HTML遇到了内联JS代码,此时,浏览器暂停JS脚本执行,暂停HTML解析。直到CSS文件下载完成,完成CSSOM树构建,重新恢复原来的解析。
JavaScript 会阻塞 DOM 生成,而样式文件又会阻塞 JavaScript 的执行,所以在实际的工程中需要重点关注 JavaScript 文件和样式表文件,使用不当会影响到页面性能的。
针对DNS Lookup环节,我们可以针对性的进行DNS解析优化。
多花点钱吧
服务端的处理优化,是一个非常庞大的话题,会涉及到如Redis缓存、数据库存储优化或是系统内的各种中间件以及Gzip压缩等…
根据浏览器对页面的下载、解析、渲染过程,可以考虑一下的优化处理:
因为JavaScript 会阻塞 DOM 生成,而样式文件又会阻塞 JavaScript 的执行,所以在实际的工程中需要重点关注 JavaScript 文件和样式表文件,使用不当会影响到页面性能的
通过js设置点击一次后按钮在一段时间内不可点击,一是使用setTimeout,二是使用按钮的disabled属性
伪随机数
①JS 通过navigator.userAgent
属性拿到这个字符串,只要里面包含mobi
、android
、iphone
等关键字,就可以认定是移动设备。
②window.screen
对象返回用户设备的屏幕信息,该对象的width
属性是屏幕宽度(单位为像素)
③第三种方法是侦测屏幕方向,手机屏幕可以随时改变方向(横屏或竖屏),桌面设备做不到。
window.orientation
属性用于获取屏幕的当前方向,只有移动设备才有这个属性,桌面设备会返回undefined
。
④第四种方法是,手机浏览器的 DOM 元素可以通过ontouchstart
属性,为touch
事件指定监听函数。桌面设备没有这个属性。
⑤css媒体查询
结合参数是一样的,但是用途不一样去述说
参数:array.map(function(currentValue,index,arr), thisValue)
用途上:map返回的是数值处理后并且和原数组长度相同的新数组,filer返回的是数值不变但长度不同的新数组
map用来返回一个处理后的新数组,foreach不会返回数据,一般用来处理数据
window.pageYOffset、window.scrollY
通过for循环多次执行包含异步任务的函数,即for+await,通过generator的next()方法
pending(进行中)、fulfilled(已成功)、rejected(已失败)
Promise.all
需要传入一个数组,数组中的元素都是 Promise
对象。当这些对象都执行成功时,则 all 对应的 promise 也成功,且执行 then 中的成功回调。如果有一个失败了,则 all 对应的 promise
失败,且失败时只能获得第一个失败 Promise
的数据。
Promise.allSettled()
方法返回一个在所有给定的 promise 都已经 fulfilled 或 rejected 后的 promise,并带有一个对象数组,每个对象表示对应的 promise 结果。
1.解析HTML结构
2.加载外部脚本和样式表文件
3.解析并执行脚本代码
4.构造HTML DOM模型 //ready
5.加载图片等外部文件
6.页面加载完毕 //load
这个顺序要记
$(window).load()
必须等到页面内包括图片的所有元素加载完毕后才能执行(比如图片和媒体资源,它们的加载速度远慢于DOM的加载速度)加载完成之后才执行。$(window).load
不能同时编写多个,如果有多个$(window).load()
,那么只有最后一个$(window).load()
里面的函数或者代码才会执行,之前的$(window).load()
都将被覆盖。$(document).ready()
是DOM结构绘制完毕后就执行,不必等到加载完毕。但这并不代表页面的所有数据已经全部加载完成,一些大的图片有会在建立DOM树之后很长一段时间才行加载完成。$(document).ready()
可以同时编写多个,并且都可以得到执行。脚本会阻塞页面的渲染,所有放在body底部最好,此时dom树已渲染完成
一是ES6的Array.from()方法,二是for循环将arguments内的内容复制到新数组,三是用rest参数转换
实现思路:使用map过滤,如果是rejected的就return一个错误值,如果是resolve就原值,返回后的数组再进入all的then方法,继而继续执行
var p1 = new Promise((resolve, reject) => { resolve(‘p1’); });
var p2 = new Promise((resolve, reject) => { resolve(‘p2’); });
var p3 = new Promise((resolve, reject) => { reject(‘p3’); });
Promise.all([p1, p2, p3].map(p => p.catch(e => ‘出错后返回的值’ ))) .then(values => { console.log(values); }).catch(err => { console.log(err); })
把函数内的代码移出本次执行,等到下一轮事件轮询时再检查,如果时间到了就执行,否则继续等待
事件轮询的工作是监听调用堆栈,并确定调用堆栈是否为空。如果调用堆栈是空的,它将检查消息队列,看看是否有任何挂起的回调等待执行。
在这种情况下,消息队列包含一个回调,此时调用堆栈为空。因此,事件轮询将回调推到堆栈的顶部。
ES6引入了任务队列的概念,任务队列是 JS
中的 promise
所使用的。消息队列和任务队列的区别在于,任务队列的优先级高于消息队列,这意味着任务队列中的promise
作业将在消息队列中的回调之前执行
for循环、forEach、for…in、for…of、map、filter
更方便进行代码的检查,可以结合webpack等工具的tree-shaking“树摇”减少代码体积,提升系统性能
new.target
属性允许你检测函数或构造方法是否是通过new运算符被调用的。
在通过new运算符被初始化的函数或构造方法中,new.target
返回一个指向构造方法或函数的引用。在普通的函数调用中,new.target
的值是undefined。
typeof、instanceof、constructor、Array.isArray(),需要联想他们之间的区别
typeof在判断原始类型时,typeof null
会等于object
。而且对于对象(Object)、数组(Array)来说,都会转换成object
。
instanceof
是通过原型链来判断的,但是对于对象来说,Array
也会被转换成Object
,而且也不能区分基本类型string
和boolean
。
constructor 判断方法跟instanceof相似,但是constructor检测Object与instanceof不一样,constructor还可以处理基本数据类型的检测,不仅仅是对象类型。
Array.isArray() 用于确定传递的值是否是一个 Array。如果对象是 Array ,则返回true,否则为false。
转换为数组,比如用扩展运算符,用map等等
需要补充的是:Arguments 对象的 callee 属性,通过它可以调用函数自身。
改变this的指向,数组传参变为一般传参
bind()方法主要就是将函数绑定到某个对象
设置为0即跟随系统默认,其销毁与Session销毁时间相同,即都在浏览器关闭后的特定时间删除。
CSS3
可以做到自然降级,而JS
则需要撰写额外代码CSS
实现稍微复杂一点动画,最后CSS
代码都会变得非常笨重css3
动画丰富,有些动画效果,比如曲线运动,冲击闪烁,视差滚动效果,只有js
动画才能完成CSS3
有兼容性问题,而JS
大多时候没有兼容性问题CSS
动画JavaScript
在浏览器的主线程中运行,而主线程中还有其它需要运行的JavaScript
脚本、样式计算、布局、绘制任务等,对其干扰导致线程可能出现阻塞,从而造成丢帧的情况transition
属性animation
属性canvas
绘制动画animate
函数e.target
:触发事件的元素e.currentTarget
:绑定事件的元素push()
方法接收任意数量的参数,并将它们添加到数组末尾,返回数组的最新长度,会影响原数组
unshift()
unshift()在数组开头添加任意多个值,然后返回新的数组长度,会影响原数组
splice()
传入三个参数,分别是开始位置、0(要删除的元素数量)、插入的元素,返回空数组,会影响原数组
concat()
首先会创建一个当前数组的副本,然后再把它的参数添加到副本末尾,最后返回这个新构建的数组,不会影响原始数组
pop()
pop()
方法用于删除数组的最后一项,同时减少数组的 length
值,返回被删除的项,会影响原数组
shift()
shift()
方法用于删除数组的第一项,同时减少数组的 length
值,返回被删除的项,会影响原数组
splice()
传入两个参数,分别是开始位置,删除元素的数量,返回包含删除元素的数组,会影响原数组
slice()
slice() 用于创建一个包含原有数组中一个或多个元素的新数组,不会影响原始数组
还是用splice()
indexOf()
返回要查找的元素在数组中的位置,如果没找到则返回-1
includes()
返回要查找的元素在数组中的位置,找到返回true
,否则false
find()
返回第一个匹配的元素
reverse()
顾名思义,将数组元素方向排列
sort()
sort()方法接受一个比较函数,用于判断哪个值应该排在前面
join() 方法接收一个参数,即字符串分隔符,返回包含所有项的字符串
some()
对数组每一项都运行传入的函数,如果有一项函数返回 true ,则这个方法返回 true
every()
对数组每一项都运行传入的函数,如果对每一项函数都返回 true ,则这个方法返回 true
forEach()
对数组每一项都运行传入的函数,没有返回值
filter()
对数组每一项都运行传入的函数,函数返回 true
的项会组成数组之后返回
map()
对数组每一项都运行传入的函数,返回由每次函数调用的结果构成的数组
Array.isArray()、instanceid、constructor、Object.prototype.toString.call
我们可以使用 instanceof
检测某个对象是不是另一个对象的实例,例如 new Person() instanceof Person --> true
new
来调用构造函数,会生成一个新对象,并且把这个新对象绑定为调用函数的 this
。this
指向 window
,严格模式指向 undefined
使用 new
调用函数和普通调用函数最大的区别在于函数内部 this
指向不同: new
调用后 this
指向实例,普通调用则会指向 window
。
instanceof
可以检测某个对象是不是另一个对象的实例。如果为 new
调用, this
指向实例,this instanceof 构造函数 返回值为 true
,普通调用返回值为 false
。
《ECMAScript 6 入门》中讲到: ES6
为 new
命令引入了一个 new.target
属性,该属性一般用在构造函数之中,返回 new
命令作用于的那个构造函数。如果构造函数不是通过 new
命令或 Reflect.construct()
调用的,new.target
会返回 undefined
,因此这个属性可以用来确定构造函数是怎么调用的。
节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效
防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时
实现:setTimeout
loading="lazy"
生命周期上:
存储数据大小:
http请求:
协议+域名+端口都一样就要同源,跨域使用CORS
HEAD
、GET
、POST
,三者之一我只会localStorage和WebSocket
“事件委托”即是把原本需要绑定在子元素的响应事件委托给父元素,让父元素担当事件监听的职务。
一个父元素有很多子元素,每个子元素都绑定了同样的函数,那我们就可以把这个函数绑定在父元素上,在点击子元素的时候冒泡到父元素执行,就是一个简单的事件委托
promise.all出现reject即输出异常的信息,但fullfild的信息也消失了,promise.allSettled不会造成信息丢失
for…in 循环主要是为了遍历对象而生,不适用于遍历数组;for…of 循环可以用来遍历数组、类数组对象,字符串、Set、Map 以及 Generator 对象。
null是空对象,undefined是未定义
原生具备 Iterator 接口的数据结构如下。
Array、Map、Set、String、TypedArray、函数的 arguments 对象、NodeList 对象
就可以用for…of循环
一个数据结构只要部署了Symbol.iterator属性,就被视为具有 iterator 接口,就可以用for…of循环遍历它的成员。也就是说,for…of循环内部调用的是数据结构的Symbol.iterator方法。
for…of循环可以使用的范围包括数组、Set 和 Map 结构、某些类似数组的对象(比如arguments对象、DOM NodeList 对象)、后文的 Generator 对象,以及字符串。