1.js数据类型,新增数据类型set,map的用法与数据结构,weakmap,weakset
(1条消息) js的数据类型、堆栈存储、多数据类型计算_star@星空的博客-CSDN博客
- 最重要的区别是,WeakMap 不会阻止在没有对键的引用时对键进行垃圾收集。
1、WeakMap只接受对象作为key,如果设置其他类型的数据作为key,会报错。
2、WeakMap的key所引用的对象都是弱引用,只要对象的其他引用被删除,垃圾回收机制就会释放该对象占用的内存,从而避免内存泄漏。
3、由于WeakMap的成员随时可能被垃圾回收机制回收,成员的数量不稳定,所以没有size属性。
4、没有clear()方法/map有
5、不能遍历/map有forEach,keys,entries
2.object.keys;Symbol 作为属性名
js遍历对象篇(一)-for...in和Object.keys - 掘金 (juejin.cn)
- 返回一个所有元素为字符串的数组,其元素来自给定的
object上面可直接枚举的属性。这些属性的顺序与手动遍历该对象属性时的一致。 - 如果你想获取一个对象的所有属性,甚至包括不可枚举的,请查看
Object.getOwnPropertyNames。 - 在 ES5 里,如果此方法的参数不是对象(而是一个原始值),那么它会抛出
TypeError。 在 ES2015 中,非对象的参数将被强制转换为一个对象。 - js中原型属性一般是不可枚举的,而自定义的属性一般是可枚举的可以通过
propertylsEnumerable()方法判断该属性是否可枚举 - !!!Symbol 作为属性名,遍历对象的时候,该属性不会出现在
for...in、for...of循环中,也不会被Object.keys()、Object.getOwnPropertyNames()(包括不可枚举属性)、JSON.stringify()返回 Object.getOwnPropertySymbols()在给定对象自身上找到的所有 Symbol 属性的数组,可获取自身所有Symbol属性,包括不可枚举的Symbol属性Reflect.ownKeys()方法返回一个由目标对象自身的属性键组成的数组。它的返回值相等于Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))
枚举:1. 对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行为。
3.定义函数常用的方式
- 命名函数/自定义函数/函数声明
- 函数表达式/匿名函数
- new Function(){} 区别:函数声明会在预解析的时候进行函数提升 (14条消息) Javascript定义一个函数_js定义一个函数_Tarafireworks的博客-CSDN博客
4. DOM事件的绑定与优化??
(3条消息) js中事件委托_star@星空的博客-CSDN博客 绑定很多的点击事件,删除所有点击事件,内存
- 事件代理/事件委托:指将事件统一绑定给元素的共同的祖先元素,这样当后代元素上的事件触发时,会一直冒泡到祖先元素,从而通过祖先元素的响应函数来处理事件。
- 事件委派是利用了冒泡,通过委派可以减少事件绑定的次数,提高程序的性能
- 实现方法:
- 这样我们就可以做到很多个a链接上的点击事件都添加到父元素div上。
- 当然还要排除掉不参加事件委托的子元素。/选择参加的元素
- 应用场景:vue
- 我们经常遇到vue中
v-for一个列表,列表的每一项都绑定了@click处理事件。我们都知道绑定这么多监听,从性能方面来说是不太好的。那我们我们可以通过把每个item的click事件委托给父元素的形式来实现。
- 我们经常遇到vue中
- 解绑事件
- 传统方式删除事件
eventTarget.onclick = null; - 方法监听注册方式删除(addEventListener注册的事件删除)
eventTarget.removeEventListener(type, listener[, useCapture]) - attachEvent注册的事件删除
eventTarget.detachEvent(‘onclick’, fn);(3条消息) 删除事件(解绑事件)(三种方式)_嘘禁止想象~的博客-CSDN博客_删除事件
- 传统方式删除事件
5. 水平垂直居中
- flex布局
.wp {
display: flex;
justify-content: center;
align-items: center;
}
- absolute+transfrom:translate
- absolute+定位全为0+margin:auto;
- 行内元素
.father {
text-align:center;
}
.son {
vertical-align:middle;
line-height:inherit;
}
6.单页面应用,后端数据变化后,主动通知前端????
(3条消息) 新手入门:websocket_一只BOY猿的博客-CSDN博客_websocket
- 后端通知前端:(服务端定时推送)WebSocket
webSocket(一) 浅析 - 掘金 (juejin.cn)
- 建立在tcp协议上,与http兼容性良好;
- 纯事件驱动,一旦连接建立,通过监听事件可以处理到来的数据和改变的连接状态;一旦连接建立,通过监听事件可以处理到来的数据和改变的连接状态
- 没有同源限制
- 不用频繁创建及销毁 TCP 请求,减少网络带宽资源的占用,同时也节省服务器资源;
- 无超时处理
- 前端轮询后端:
- 短轮询:短轮询(Polling)的实现思路就是浏览器端每隔几秒钟向服务器端发送http请求,服务端在收到请求后,不论是否有数据更新,都直接进行响应。在服务端响应完成,就会关闭这个Tcp连接(非常消耗资源)
- 长轮询:客户端发送请求后服务器端不会立即返回数据,服务器端会阻塞请求连接不会立即断开,直到服务器端有数据更新或者是连接超时才返回,客户端才再次发出请求新建连接、如此反复从而获取最新数据。(有数据、连接超时后,服务端才会返回) webSocket(二) 短轮询、长轮询、Websocket、sse - 掘金 (juejin.cn)
7.js垃圾回收机制
(3条消息) 一文彻底搞懂js垃圾回收和内存泄露_star@星空的博客-CSDN博客 垃圾收集器会定期(周期性)找出那些不在继续使用的变量,然后释放其内存。但是这个过程不是实时的,因为其开销比较大并且GC时停止响应其他操作,所以垃圾回收器会按照固定的时间间隔周期性的执行。
- 只有函数内的变量才可能被回收
- 标记清除
- js中最常用的垃圾回收方式就是标记清除。当变量进入环境时,例如,在函数中声明一个变量,就将这个变量标记为“进入环境”。从逻辑上讲,永远不能释放进入环境的变量所占用的内存,因为只要执行流进入相应的环境,就可能会用到它们。而当变量离开环境时,则将其标记为“离开环境”。
- 垃圾回收器在运行的时候会给存储在内存中的所有变量都加上标记(当然,可以使用任何标记方式)。然后,它会去掉环境中的变量以及被环境中的变量引用的变量的标记(闭包)。而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。最后,垃圾回收器完成内存清除工作,销毁那些带标记的值并回收它们所占用的内存空间。
- 引用计数
- 引用计数的含义是跟踪记录每个值被引用的次数。当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是1。如果同一个值又被赋给另一个变量,则该值的引用次数加 1。相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值的引用次数减 1。当这个值的引用次数变成 0 时,则说明没有办法再访问这个值了,因而就可以将其占用的内存空间回收回来。这样,当垃圾回收器下次再运行时,它就会释放那些引用次数为 0 的值所占用的内存。
function test() {
var a = {}; // a指向对象的引用次数为1
var b = a; // a指向对象的引用次数加1,为2
var c = a; // a指向对象的引用次数再加1,为3
var b = {}; // a指向对象的引用次数减1,为2
}
内存泄漏
- 不再用到的内存,没有及时释放,就叫做内存泄漏(memory leak)。
vue中的内存泄漏
- mounted/created 钩子中使用js绑定了DOM/BOM,第三方库的初始化,就要在beforeDestroy中解绑,销毁;
- 组件中使用了setInterval,就要在beforeDestroy中销毁;
js中的内存泄漏
- 循环引用::一个DOM对象被一个Javascript对象引用,与此同时又引用同一个或其它的Javascript对象,这个DOM对象可能会引发内存泄露。这个DOM对象的引用将不会在脚本停止的时候被垃圾回收器回收。要想破坏循环引用,引用DOM元素的对象或DOM对象的引用需要被赋值为null。
- 闭包
- DOM泄漏:当原有的DOM被移除时,子结点引用没有被移除则无法回收。、
- 定时器:定时器setInterval或者setTimeout在不需要使用的时候,没有被clear,导致定时器的回调函数及其内部依赖的变量都不能被回收,这就会造成内存泄漏。 解决方式:当不需要interval或者timeout的时候,调用clearInterval或者clearTimeout
8.跨域?新方法
(3条消息) 如何实现跨域?_star@星空的博客-CSDN博客_如何跨域
- jsonp :只能针对get
- cors
res.header('Access-Control-Allow-Origin', 'http://example.com'); - Nginx
- 反向代理:即所有客户端的请求都必须先经过的处理,nginx作为代理服务器再讲请求转发给node或者java服务,这样就规避了同源策略。
juejin.cn/post/708265… 【nginx】
聊聊代理服务器的那些事 - 掘金 (juejin.cn)
- 正向代理代理客户端请求,隐藏真实的客户端
- 反向代理代理服务器请求,隐藏真实的服务器
- 反向代理:即所有客户端的请求都必须先经过的处理,nginx作为代理服务器再讲请求转发给node或者java服务,这样就规避了同源策略。
juejin.cn/post/708265… 【nginx】
聊聊代理服务器的那些事 - 掘金 (juejin.cn)
9.vue2响应式,Object.defineProperty()???
1.Object.defineProperty()
看笔记或者文档 Object.defineProperty() - JavaScript | MDN (mozilla.org)
Object.defineProperty()方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。Object.defineProperty(obj, prop, descriptor)要定义的对象,属性,描述- descriptor对象:value,enumberable,writable,configurable,get(),set()
vue2响应式原理
看笔记
- 监视data中所有层次的数据
- 对象新增属性,直接检测不到,需要用
vm.$set(obj,prop,value)Vue.set() - 数组:包裹数组更新元素的方法;返回新数组,代替旧数组
-
实现原理:
-
对象类型:通过
Object.defineProperty()对属性的读取、修改进行拦截(数据劫持)。 -
数组类型:通过重写更新数组的一系列方法来实现拦截。(对数组的变更方法进行了包裹)。
Object.defineProperty(data, 'count', { get () {}, set () {} })
-
-
存在问题(数据改变了,vue2监听不到):
- 新增属性、删除属性, 界面不会更新。(数据会改变,vue2监听不到,页面无变化。
用this.$set(对象,"属性",值)/Vue.ser()解决。 用this.$delete()) - 直接通过下标修改数组, 界面不会自动更新。`this.$set(对象,"属性",值)/arr.split()等改变数组的
- 新增属性、删除属性, 界面不会更新。(数据会改变,vue2监听不到,页面无变化。
vue3 响应式,proxy
// 模拟vue2响应式
//`window 身上的内置函数 Proxy`
// person是被代理的对象
const p = new Proxy(person,{
// target 是源对象,这里是传入的person
// prop 读取修改的是那个属性
get (target, prop) {},//读取
set (target, prop, value){},//添加、修改
// value 新增/修改属性的值
deleteProperty (target, prop){} //删除
// delet p.name //delete删除一个属性,会有一个返回值
})
const p = new Proxy(person,{})
// 打在p身,痛在person身
new Proxy(data, {
// 拦截读取属性值
get (target, prop) {
return Reflect.get(target, prop)
},
//target 源对象, prop 被读取n的属性
// 拦截设置属性值或**添加**新属性
set (target, prop, value) {
return Reflect.set(target, prop, value)
},
// 拦截删除属性
deleteProperty (target, prop) {
return Reflect.deleteProperty(target, prop)
}
})
proxy.name = 'tom'
实现原理: (Proxy,Reflect都是window上的)
- 通过Proxy(代理): 拦截对象中任意属性的变化, 包括:属性值的读写、属性的添加、属性的删除等。
- 通过Reflect(反射): 对源对象的属性进行操作。===>可以提高代码的健壮性
- Reflect.defineProperty(),可以重复定义属性不会报错,但会返回一个false值。
- Object.defineProperty()定义重名属性,代码会直接报错,代码会挂掉
- MDN文档中描述的Proxy与Reflect:
11.webpack 更改配置???
- vue.config.js 配置proxy跨域
12.防抖节流
1.防抖
防抖:前面的所有的触发都被取消,最后一次执行在规定的时间之后才会触发%%也就是说如果连续快速的触发,只会执行最后一次%%
<body>
<button id="debounce">防抖</button>
<script>
// 防抖
/* 函数防抖是指在事件被触发 n 秒后再执行回调,如果在这 n 秒内事件又被触发,则重新计时。这可以使用在一些点击请求的事件上,避免因为用户的多次点击向后端发送多次请求。 */
function debounce(fn, wait) {
let timer = null;
return function () {
let context = this,
args = arguments;
if (timer) {
clearTimeout(timer);
//清空timer
timer = null;
} else {
timer = setTimeout(() => {
// 用apply改变this走向
fn.apply(context, args);
}, wait);
}
};
}
// 防抖测试
document.querySelector("#debounce").onclick = debounce(() => {
console.log("debounce");
}, 2000);
</script>
2.节流
节流:在规定的间隔时间范围内不会重复触发回调,只有大于这个时间间隔才会触发回调,把频繁触发变为少量触发
<body>
<button id="throttle">节流</button>
<script>
// 节流
/* 函数节流是指规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。节流可以使用在 scroll 函数的事件监听上,通过事件节流来降低事件调用的频率。 */
function throttle(fn, delay) {
let curTime = Date.now();
// Date.now() 方法返回自 1970 年 1 月 1 日 00:00:00 (UTC) 到当前时间的毫秒数。
return function () {
let nowTime = Date.now(),
context = this,
args = arguments;
// 如果两次时间间隔超过了指定时间,则执行函数
if (nowTime - curTime >= delay) {
fn.apply(context, args);
curTime = Date.now();
}
// !只有触发成功了才会更新时间
};
}
// 节流测试
document.querySelector("#throttle").onclick = throttle(() => {
console.log("throttle");
}, 2000);
</script>
D:\我的学习\前端\基础算法\手撕\02防抖节流.html
- 防抖与节流的原理,通过JS实现【闭包 + 延迟器】