const dayOfYear = (date) =>
Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24);
dayOfYear(new Date('2023,01,01'));
效果
实现
将RGB颜色灰度化(基于光感加权平均)
const gray = (r,g,b) =>0.2126*r+0.7152*g+0.0722*b;
gray(50,100,150);
const pick=(obj,...props)=>Object.fromEntries(Object.entries(obj).filter(([k])=>props.includes(k)))
pick({a:1,b:2,c:3},'a','b')//{a: 1, b: 2}
Object.fromEntries扩展应用
fromEntries可以用来对象过滤,Map 转 Object,url的search参数转换
const randomColor=()=>'#'+Math.floor(Math.random()*0xffffff).toString(16).padEnd(6,'0')
//padEnd填充字符0,向前方补充至6位
const randomString=()=>Math.random().toString(36).slice(2)
//36进制由0-9,A-Z组成,toString(36)即转换成36进制的字符串,一般都是为了生成不重复的随机数才调用。
//.slice(2)是去掉0.
const removeTag=(fragment)=>new DOMParser().parseFromString(fragment,'text/html').body.textContent||''
removeTag('DOMParser')
监听copy事件,禁用默认行为
如果想复制但是复制不了可以用这个
上面实现是小问题,主要是下面扩展
因为有框选的属性存在,所以Object.prototype.toString.call后面那一段会改
function promiseLike(value){
return value!==null&&(typeof value==='object' ||typeof value==='function')&&(typeof value.then==='function')
}
所有promise都是promise A+规范的实现,jQuery的$.ajax也是
?根据规范,promise A+是一个对象或函数,且value不等于null
function isOdd(value){
return value%2===1 || value%2===-1
}
需要考虑数是任意值时,做什么处理,
比方说假如这个数是负数,用欧几里得的求余法,即
a % b = a - b * p
//p为a/b的整数部分
第三方库highlight.js,最好手动告诉这一块代码是什么语言
分析原理↓
给代码最外部元素设置两个样式hls和根据不同语言带的css(如language-css),
然后里面递归替换
value就可以直接插入
promise嵌套多重,则需要平级展开,链式.then
??
https://blog.csdn.net/yun_master/article/details/115015113
假如有朝一日需要自己实现表单,最好使用@submit提交,button上写明type=“submit”
console去除工具terser
浏览器指纹,全世界很难找出两个完全一样的设备环境(ip,浏览器版本,浏览器语言偏好,时区),通过这些信息生成哈希值,尽管无痕没有任何登录,他也能知道是谁
应用是,个性化广告,防刷频
读取用户文件指纹,用fingerprintjs
1、移动端键盘弹出类型inputmode
2、视频预览图片
<video src="" poster="图片地址"></video>
3、multiple,文件多选,下拉多选
4、accesskey,按下b可以聚焦
<input type="text" accesskey="b">
4、tableindex,按下tab的切换顺序
<input type="text" tabindex="3">
<input type="text" tabindex="2">
<input type="text" tabindex="1">
rel后的总共有
async
defer
preload
prefetch
prerender
preconnect
前两个是附着在script元素上的
遇到script暂停解析,通过另一个网络线程,去远程获取js文件,再去执行js,完成同步代码后,继续解析dom。主线程会有空窗期。一般js写在body元素末尾,保证dom解析完后执行js,现在有两个更好的办法:
遇到script,去远程获取js文件,不会暂停解析
1、async
这个不一定dom全部加载完成
2、defer
有点像DOMContentLoaded,主线程把dom元素全部解析完成后,再去运行js。这个一定是dom完成了
async和defer发生时间是在DOMContentLoaded之前
<script type="module">
他的资源提示符默认就是defer
——————
link元素上的资源提示符,preload和prefetch
<link rel="preload">
async和defer是拿资源并且要执行,preload和prefetch是拿资源但是不执行,可以拿任何资源js css和图片
1、preload
不会阻塞dom解析,会有缓存,优先级很高,这个资源马上会用到,发出的网络请求时间很早
2、prefetch
优先级低,会在空闲的时候去取
其他页面用到的,preload,自身页面用到的prefetch,闲着也是闲着
Main表示渲染主线程
一个方格就是一个任务,红色三角表示卡顿
纵向是调用栈
package.json
"build": "vue-cli-service build --mode prod --report"
1、cdn优化,使用cdn服务器,跨项目的共享同一个js,js一般设置缓存。用户访问第一个项目,缓存一下,第二个项目就不用重新加载js
生产环境引入cdn写法
生产环境不参入打包的写法
externals
2、core.js体积也很大,是因为项目里有babel,对项目进行向下降级,es5向下
生成两套打包,一套针对高级浏览器,一套针对低级IE浏览器
红框加上后会进行两次打包,
高版本的打包里部分script上有nomodule属性,直接不加载
低版本 type="module"不认识,不加载,低版本不认识nomodule,忽略,从而去加载
在package.json根本没有导入的库,可以直接import
1、A依赖B库,A库升级,B库也莫名其妙升级
2、依赖丢失,开发依赖有,生产依赖没有
幻影依赖的原因:
1、node_module是树结构,如上图红圈所示,本来一个就结束的依赖,树状结构必须两个
2、所以后来出现了yarn
node js有个查询报的流程,比方说,紫色依赖深绿和深蓝,它的代码在require或者import时,在自身目录找不到,它就会往上找,但是这样还是有幻影依赖,因此有了pnpm
3、pnpm
虽然是树状,但是通过链接的方式
pnpm为什么能够不占磁盘空间?硬链接和软链接
我们的文件数据都存在磁盘上,创建了文件,分配了个磁盘空间,这个文件是个指针指向磁盘空间,通过文件A创建硬链接,生成文件B,因为是硬链接,所以,B同A,A文件没了不会影响B
软链接类似快捷方式,B指向的是文件A,A文件没了影响B
<style>
body{
background: url(https://i.loli.net/2019/11/17/GAYyzeKsiWjP5qO.jpg) no-repeat;
}
.box {
width: 100px;
height: 100px;
}
</style>
<button id="start-button">取色</button>
<div class="box"></div>
<script>
const btn = document.querySelector('button')
const box = document.querySelector('.box')
btn.onclick = async () => {
if (!window.EyeDropper) {
box.textContent = 'Your browser does not support the EyeDropper API';
return;
}
const dropper = new EyeDropper()
try {
const result = await dropper.open()
console.log(result)
box.style.backgroundColor = box.textContent = result.sRGBHex;
} catch (e) {
console.log('user canceled')//按了esc
}
}
</script>
p*5>lorem1
https://picsum.photos/
https://picsum.photos/200/300,随机生成300宽200高图片
https://picsum.photos/200/300?r=1,加参数则生成不同图片
设置cookie的时候会去设置一个SameSite属性
它的作用就是限制跨站请求,img、iframe、Ajax,假如img之前浏览过相关网站,很有可能就有对应的cookie,没有sameSite就会默认发送其他iframe、Ajax的cookie,会造成CSRF攻击
请求的地址和页面地址不一样,就需要用到SameSite,会对请求做出限制,限制cookie发还是不发
同站不受sameSite限制,第五个是公共后缀问题
具体是怎么限制的呢?
SameSite为none时,在set-cookie时候,cookie必须为secure(https)传输,否则无效,会造成CSRF攻击
SameSite为Lax时,宽松,会阻止所有的跨站请求,阻止发送cookie,但对超链接放行
SameSite为Strict时,会阻止所有的跨站请求,阻止发送cookie,
因为就算重定向到了新的网站,但是上一个网站的cookie还是发送到新网站了。如果新网站是恶意网站,它就可以利用这个正确的cookie伪造用户身份。
数据埋点是为了监控服务的,监控用户行为,收集各种报错信息
三种服务监控:错误监控、性能监控(白屏FP、卡顿、FCP、LCS)、行为监控
https://zhuanlan.zhihu.com/p/265948624
网络传输给监控中心,可能会有预警
阿里云的ARMS,神策,sentry
数据埋点分为侵入(技术代价大)和非侵入(我们对接的浙政钉专有钉钉都是非侵入)
缩写 | 全称 | 描述 |
---|---|---|
R | Response | 在100ms内响应用户的操作。虽说是100ms,但预算只有50ms,因为浏览器内部还有很多工作需要预留时间。 |
A | Animation | 在使用动画时,需要保证有60FPS,换算下来也就是16ms处理1帧(1000ms/60FPS)才不会让用户感觉到卡顿。同样的,浏览器大概需要花费6ms来渲染1帧,因此只有10ms以内的时间。 |
I | Idle | 预留空闲时间,最大化利用空闲时间,以便于可以在50ms内响应用户的操作。 |
L | Load | 3g网络的情况下,首次加载需要在5s之内加载网站并可以让用户进行交互。而在后续的加载中,则是2s。 |
https://web.dev/fcp/
列了部分指标
名称 | 描述 |
---|---|
FCP | 首次内容加载时间 |
LCP | 最大内容绘制时间 |
CLS | 累计偏移 |
TBT | 总阻塞时间 |
i18n国际化,internationalization
L10n本地化,localization
g11n全球化,globalization
不仅仅是翻译,
1、文字表达,大陆区是程序,台湾是程式,繁体简体
2、数字表达,货币书写,每三个空一格,我们是每四个空一格
3、敏感词
4、配色
5、布局,部分国家从右到左,确认和取消按钮
6、单击双击
7、落后国家,电脑屏幕小,布局、交互都有区别
等等…
获取地域信息,可以从http头里的accept-lang,或者是h5里面的navigator.language
vuei18n工具
静态资源路径配置
publicPath: ‘/admin’,//是加在部署地址后的。协议域名端口+/rxlz+资源地址css/js
路由路径配置,加在路由地址前
base: “/admin”,
一个应用程序,运行过程中一定需要内存,但是运行完这块内存不需要了,需要垃圾回收机制,
但是问题是,根本没有垃圾回收器这种东西去回收内存,
它无法理解哪一块代码需要,哪一块代码不需要,
垃圾回收器的范围<垃圾,所以会有多余的内存
垃圾回收不掉,内存泄漏
算法
1、引用计数(会导致垃圾回收器的范围更小,所以不怎么用)
2、标记清除,(新生代/旧生代,星历图)
跟内存泄露有关的闭包,原因就是它无法理解是否还需要这个变量
DNS解析过程耗费时间,有本地缓存
解析DNS会打断解析HTML
异步DNS解析,不在主线程解析
//在head里面尽早写明
<link rel="dns-prefetch" href="https://www.baidu.com">
后面nodejs没看懂
https://www.douyin.com/user/self?modal_id=7233335691046980921&showTab=favorite_collection
老版私有字段,包括Vue也是这么写
es6 Symbol
新版的私有字段,加#
a.#abc会报错
行为验证码验证是要放在服务器端而不是客户端,因为有OCR识别,所以验证码升级
google/recaptcha
现在点击验证码会把人工识别结果作为AI训练的工作集
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 500px;
height: 300px;
margin: 10px auto;
overflow: hidden;
position: relative;
}
.container .carousel img {
width: 500px;
height: 300px;
}
.carousel {
width: 100%;
height: 100%;
display: flex;
/* transition: all .5s; */
}
.indicator {
position: absolute;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
display: flex;
z-index: 2;
}
.indicator span {
width: 20px;
height: 20px;
border: 2px solid #ccc;
margin: 0 3px;
border-radius: 50%;
cursor: pointer;
}
.indicator .active {
background-color: #fff;
border-color: #fff;
}
.arrow {
width: 100%;
height: 100%;
padding: 0 20px;
position: absolute;
top: 0;
left: 0;
display: flex;
align-items: center;
justify-content: space-between;
}
.arrow img {
width: 30px;
height: 30px;
cursor: pointer;
}
</style>
<body>
<!-- -->
<div class="container" onmouseout="outClick()" onmouseover="οnmοuseοver()">
<div class="carousel">
<div class="item">
<img src="https://picsum.photos/300/200?r=1" alt="">
</div>
<div class="item">
<img src="https://picsum.photos/300/200?r=2" alt="">
</div>
<div class="item">
<img src="https://picsum.photos/300/200?r=3" alt="">
</div>
<div class="item">
<img src="https://picsum.photos/300/200?r=4" alt="">
</div>
<div class="item">
<img src="https://picsum.photos/300/200?r=5" alt="">
</div>
<div class="item">
<img src="https://picsum.photos/300/200?r=6" alt="">
</div>
</div>
<div class="indicator">
<span class="active"></span>
<span></span>
<span></span>
<span></span>
</div>
<div class="arrow">
<img src="./left.png" alt="" class="arrow-left">
<img src="./right.png" alt="" class="arrow-right">
</div>
</div>
<script>
// 定义一个当前选中第几张图片的index(默认选中第一个)
let currIndex=0
// 定义一个定时器对象
let interObj=null
// 获取相关元素
let doms={
arrowLeft:document.querySelector('.arrow-left'),//左箭头
arrowRight:document.querySelector('.arrow-right'),//右箭头
indicator:document.querySelectorAll('.indicator span'),//所有的指示器按钮
carousel:document.querySelector('.carousel'),//轮播图容器
}
// 初始化轮播图
function init(){
// 将第一张图片实行定位使其脱离文档流,并且使相对轮播图容器其往左移动一张图片的单位
document.querySelectorAll('.carousel .item')[0].style.transform='translateX(-100%)';
document.querySelectorAll('.carousel .item')[0].style.position='absolute';
}
init()
// 定义轮播图滚动的方法,并接收当前处于第几张图片的参数
function moveTo(index){
// 进行轮播图容器位置移动
doms.carousel.style.transform=`translateX(-${index}00%)`
//添加过渡 /* transition: all .5s; */
doms.carousel.style.transition='all .5s'
// 去除前一个选中的指示点
let active=document.querySelector('.active')
active.classList.remove('active')
// 添加当前选中的指示器
doms.indicator[index].classList.add('active')
currIndex=index
}
// 对指示器添加点击方法
doms.indicator.forEach((item,index)=>{
item.onclick=function(){
moveTo(index)
}
})
// 定义向左滚动的方法
function leftNext(){
// 先判断当前选中的是否是处于0这个位置
if(currIndex==0){
// 将轮播图容器迅速至于最后一张图的位置
doms.carousel.style.transform=`translateX(-${doms.indicator.length}00%)`
// 去除过渡
doms.carousel.style.transition='none'
// 由于快速的更新css样式,浏览器来不及渲染,所以需要强制使浏览器进行渲染
// 强制渲染
// 只要读取元素的尺寸,位置就会导致浏览器的回流,这一回流就会重新渲染
doms.carousel.clientHeight;
moveTo(doms.indicator.length-1)
}else{
moveTo(currIndex-1)
}
}
// 定义向右滚动的方法
function rightNext(){
// 先判断当前选中的是否是处于最后的位置
if(currIndex==doms.indicator.length-1){
// 将轮播图容器迅速至于第一张的位置
doms.carousel.style.transform=`translateX(100%)`
// 去除过渡
doms.carousel.style.transition='none'
// 由于快速的更新css样式,浏览器来不及渲染,所以需要强制使浏览器进行渲染
// 强制渲染
// 只要读取元素的尺寸,位置就会导致浏览器的回流,这一回流就会重新渲染
doms.carousel.clientHeight;
moveTo(0)
}else{
moveTo(currIndex+1)
}
}
// 给左右箭头添加点击事件
doms.arrowLeft.onclick=leftNext
doms.arrowRight.onclick=rightNext
// 定义自动轮播的方法
function pollingInt(){
interObj=setInterval(()=>{
rightNext()
},2000)
}
pollingInt()
// 鼠标移出,打开定时器
function outClick(){
pollingInt()
}
// 鼠标移入,清楚定时器
function οnmοuseοver(){
clearInterval(interObj)
}
</script>
</body>
</html>
//在ES6里面用类语法,整个代码是在严格模式下
"use strict";
//在类里,只能通过new Example来调用,不能通过Example('abc')来调用
function Example(name){
if(!(this inctance Example)){//this是构造函数的实例
throw new TypeError(`Class constructor Example cannot be invoked without 'new'`)
}
this.name=name
}
//Example.prototype.func=function(){//类里面的方法func不能被枚举,
// console.log(this.name)
//}
Object.defineProperty(Example.prototype.func,'func',{
value:()=>{
if(!(this inctance Example)){//不可通过new调用,看this指向,正常情况下指向构造函数的实例
throw new TypeError(`is not a constructor`)
}
console.log(this.name)
},
enumerable:false//不能被枚举
})
Example(‘abc’)直接调用报错
枚举差异,类里面的方法func不能被枚举
在类里面不能↓
class MyPromise{
constructor(executor){
const resolve=()=>{}
const reject=()=>{}
executor(resolve,reject)
}
resolve(){//放在原型链上是不太合适的。this会有问题
}
}
const p=new Promise((resolve,reject)=>{//要启动promise,就是启动任务,就是这个函数,即执行器,这一块同步
resolve(1)
})
align-self独自
order排序
flex-flow: column wrap
align-content整体
flex-wrap:wrap-reverse
已知三种
1、Object.prototype.toString.call()
function(arr){
return Object.prototype.toString.call(arr)==='[object Array]'
}
现在判断会有缺陷,该obj返回true
const obj={
[Symbol.toStringTag]:'Array'
}
2、arr instanceof Array
判断对象原型链上有没有array的原型
优点是可以对原型链上的,精准判断类型
class A extends Array{}
const obj=new A()
obj instanceof Array//true
缺点是
①改变对象原型为数组原型
const obj={}
Object.setPrototypeOf(obj,Array.prototype)//改变对象原型,true
②iframe
iframe会在页面生成独立的一套documents还有window
const Array1=window.array;
const iframe=document.querySelector('iframe')
const Array2=iframe.contentWindow.Array
Array1===Array2//false
//会导致
const arr =new Array2()
//arr instanceof Array//false,因为读的是window里面的Array而不是iframe里的Array
数组是一个特殊存储结构的对象
3、Array.isArray
判断有没有经过Array的构造函数
字段分为
1、标准字段,npm或者node官方能识别的字段
main字段会影响node模块的查找,导入一个包的时候,无论是使用import导入还是require导入(第44点),他会找到文件夹里的package.json,然后找到main字段,读取到底用的是哪个模块
标准字段,开发完的发布文件/文件夹
会影响到npm上的搜索结果
作者、证书、bug反馈
影响一个npm展示插件主页的地方
2、非标准字段,开发者自行扩展的字段
module是非标字段,webpack rollup这些构建工具会读,往往需要树摇,假如它们读main,有可能会读到一个已经被降级的代码(es6转es5),并不是esmodule,不利于树摇优化,有没有支持ESmodule的一个文件,假如有就会去读这个文件去树摇优化
给ts使用的非标字段,可以读到包里的类型定义文件
buildOptions是第三方插件,比如Vue,自定义的非标字段,会影响到rollup打包的参数,formats,表示打包的时候要打包成两种格式
给构建工具看的,标识包里面的副作用
单纯提供信息,展示仓库,仓库目录
模块查找有两种方式,一种是classic,一种是node
node模块查找分四种:
1、文件查找
./或者…/或者/,进入文件查找,假如文件不存在,自动补上.js再去搜索,然后是补上.json再去搜索,假如都没有进入第二步
2、文件夹查找
查找package.json文件,看文件配置有没有main,看main写的文件能否找到,假如失败,直接查找index.js,或者index.json
3、内置模块
先查看是不是内置模块,fs、path、http等,require(‘fs’)
4、第三方模块
require(‘a’)
会从node_module里去找,假如有就去看a有没有,假如没有就会往上级去找,又会进入1和2的循环
1、原生
图片本身就支持渐进式
jpg图片,本身就支持多个帧,第一帧是比较小的内容,第二帧是清晰的内容,
即使做成渐进式,文件大小不会增加多少
1)兼容性问题,有些浏览器不支持
2)没有图片源
2、封装
传子组件一张清晰一张模糊
子组件↓
两次打印都是2、2,为什么?
浏览器做的小处理,为了节省内存空间,不会吧对象所有内容展示出来,而是折叠展示,第一次点击的时候才会去计算
假如收起来,再进行++,再展开又是加完后的数了,假如再收起来,结果就不变了,后面复用了
结论是,调试用断点
原数组会变化,函数式编程环境我们不希望变化,数据不可变
原数组不变
除此之外还有toSorted、toReversed、toSpliced
字符串当成js来执行
1、eval
同步代码,当前作用域,先2再sync
2、setTimeOut
setTimeOut(code,0)
异步,全局作用域,先sync再1
3、创建script元素
同步,全局作用域,先1再sync,额外标签
4、创建function
创建了这个函数的函数体
同步,全局作用域,先1再sync,这个和3一样,更好一点
之前没有ES2023的时候,思路都是创建副本
const sorted1 = arr.slice().sort();
const sorted2 = [...arr].sort();
const sorted3 = Array.from(arr).sort();
2020年
::focus-with,能非常方便处理获取焦点状态, 当元素本身或其后代获得焦点时,:focus-within伪类的元素就会有效。
:has
需求是,span元素后的兄弟元素带有自定义属性data-required才打*
::first-letter,首字母下沉
::selection,选中文字后的样式
:where简化css重复代码,:has和:is
此文必看醍醐灌顶,部分属性在scope里无法作用是因为并没有 data-v-xxx
这样的随机属性
https://blog.csdn.net/qq_43624878/article/details/127045426