学习es5
开始学习 es5 核心知识
- '珠峰高级工程师'参考这里的项目:https://gitee.com/wangluoshihuang/webgaoji (opens new window)
- js 的 6 种继承方式优缺点:
- new 一个对象的时候发生了什么? (opens new window)
- JS 的 history 和 location 用法;react 路由的 history 对象的插件 history 的使用介绍
- 为了查看页面是直接从服务器上载入还是从缓存中读取,你可以使用 PageTransitionEvent 对象的 persisted 属性来判断。 如果页面从浏览器的缓存中读取该属性返回 ture,否则返回 false 。
- 参考:https://www.runoob.com/jsref/event-onpagehide.html
- 参考:https://developer.mozilla.org/zh-CN/docs/Web/API/PageTransitionEvent
- console 的使用:
- console.dir(XXX):可以打印出一个对象的所有属性。
- 面向对象的里的“多态”
- 多态:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。
- https://www.cnblogs.com/aaronchu/p/6169843.html
- 面向对像编程基本概念:
数组和对象的关系
哈希表和关联型数组
- 在一些编程语言中,通常会存在两种不同的数组形式:
一般性数组,也叫作索引型数组或者枚举型数组(通常以数字为键);
关联型数组,也叫作哈希表或者字典(通常以字符串为键)。
在 JavaScript 中,我们会用数组来表示索引型数组,而用对象来表示关联型数组。因此,如果我们想在 JavaScript 中使用哈希表,就要用到对象。
- 所以我们可以通过以下两种方式来访问对象的属性:方括号表示法,如 hero['occupation']; 点号表示法,如 hero.occupation。
postmessage 的使用:页面间通讯使用
- https://mp.weixin.qq.com/s/EZ7mf6kT5fNApXMSJpkV9A
- postMessage - 跨域消息传递:https://blog.csdn.net/huangpb123/article/details/83692019
- 文章截图在https://gitee.com/wangluoshihuang/static_article/tree/master/JS 里的 postMessage 的使用
h5 原生拖拽: - 讲解:https://juejin.cn/post/7075918201359433758
问题处理:
- h5 原生拖拽不能触发 drop 事件问题:
- 需要给目标元素至少绑定 dragOver 以及 drop 事件;并且都要执行 evente.preventDefault();
- dragOver 执行阻止默认事件,是为了防止 drop 事件不触发。
- drop 执行阻止默认事件,是为了防止浏览器打开文件。
- 当前前面事件处理好后,drop 事件里打印 event.dataTransfer.files 始终为空
- 实际上是有值的。我们使用 console.dir()打印就会发现有值(实际上通过 event.dataTransfer.files 可以拿到文件信息)。只是打印结果出不来而已。
- 截图 (opens new window)
- h5 原生拖拽不能触发 drop 事件问题:
event.dataTransfer.effectAllowed 的作用
在前端拖拽操作中,
event.dataTransfer.effectAllowed是 DataTransfer 对象的一个关键属性,用于控制拖拽源(被拖拽元素)允许的拖拽效果类型。它与event.dataTransfer.dropEffect(控制拖拽目标的放置效果)配合使用,共同决定用户在执行拖拽操作时的视觉反馈和最终行为。# 1. 作用与用途
effectAllowed的主要作用是:- 限制拖拽源允许的操作类型(如复制、移动、链接等)。
- 影响浏览器显示的鼠标样式(如箭头、复制图标、禁止符号等)。
- 与
dropEffect共同决定最终生效的操作(需两者匹配才能成功放置)。
# 2. 常用值及含义
值 描述 "none"禁止任何操作(拖拽无效)。 "copy"只允许复制(光标显示为加号或复制图标)。 "move"只允许移动(光标可能显示为箭头或移动图标)。 "link"只允许链接(光标可能显示为链式链接图标)。 "copyLink"允许复制或链接。 "copyMove"允许复制或移动。 "linkMove"允许链接或移动。 "all"允许所有操作(复制、移动、链接,默认值)。 "uninitialized"未初始化(效果等同于 "all")。# 3. 使用示例
# 示例 1:限制只能复制
JavaScriptdocument.getElementById("drag-source").addEventListener("dragstart", (event) => { event.dataTransfer.effectAllowed = "copy"; // 只允许复制 event.dataTransfer.setData("text/plain", "要拖拽的数据"); });1
2
3
4# 示例 2:动态匹配目标放置效果
JavaScript// 拖拽源:允许复制或移动 sourceElement.addEventListener("dragstart", (event) => { event.dataTransfer.effectAllowed = "copyMove"; }); // 拖拽目标:根据条件设置 dropEffect targetElement.addEventListener("dragover", (event) => { if (someCondition) { event.dataTransfer.dropEffect = "copy"; // 必须与 effectAllowed 匹配 } else { event.dataTransfer.dropEffect = "move"; } event.preventDefault(); // 必须阻止默认行为 });1
2
3
4
5
6
7
8
9
10
11
12
13
14# 4. 与
dropEffect的协作规则dropEffect必须为effectAllowed的子集才能生效。例如:
- 若
effectAllowed="copyMove",则dropEffect只能是"copy"或"move"。 - 若
effectAllowed="copy",但dropEffect="move",则实际操作会被强制设为"none"(禁止)。
- 若
最终效果由
drop事件时的dropEffect决定。
# 5. 实际应用场景
# 场景 1:文件管理器
- 拖拽文件时,
effectAllowed可区分是复制(按住 Ctrl 键)还是移动(默认)。
JavaScript document.addEventListener("dragstart", (event) => { event.dataTransfer.effectAllowed = event.ctrlKey ? "copyMove" : "move"; });1
2
3# 场景 2:禁止拖拽到某些区域
JavaScriptdragSource.addEventListener("dragstart", (event) => { event.dataTransfer.effectAllowed = "none"; // 完全禁止拖拽 });1
2
3# 6. 注意事项
- 必须在
dragstart事件中设置effectAllowed只在dragstart事件中有效,在其他事件(如dragover)中修改会被忽略。 - 视觉反馈依赖浏览器实现 不同浏览器对光标样式的渲染可能不一致(如 Firefox 和 Chrome 的图标略有差异)。
- 移动端兼容性 部分移动设备对拖拽 API 的支持有限,需额外测试。
# 7. 完整流程示例
HTML<div id="drag-source" draggable="true">拖拽我(允许复制或移动)</div> <div id="drop-target">放置区域</div> <script> const source = document.getElementById("drag-source"); const target = document.getElementById("drop-target"); // 拖拽源设置 source.addEventListener("dragstart", (event) => { event.dataTransfer.effectAllowed = "copyMove"; event.dataTransfer.setData("text/plain", "Hello, Drag!"); }); // 拖拽目标设置 target.addEventListener("dragover", (event) => { event.preventDefault(); // 必须阻止默认行为 event.dataTransfer.dropEffect = "copy"; // 显示复制效果 }); target.addEventListener("drop", (event) => { event.preventDefault(); console.log("放置效果:", event.dataTransfer.dropEffect); // 输出 "copy" console.log("获取数据:", event.dataTransfer.getData("text/plain")); }); </script>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25# 总结
effectAllowed:定义拖拽源允许的操作类型(源头控制)。dropEffect:定义拖拽目标的显示效果(目标控制)。- 两者需匹配才能完成有效拖拽,否则操作会被禁止。
DataTransferItemList 有什么作用
DataTransferItemList是 HTML5 拖拽 API 中的一个接口,用于管理拖拽操作中传递的数据项(DataTransferItem对象)。它提供了对拖拽数据的精细化控制,比直接使用DataTransfer的setData()/getData()更强大,尤其在处理文件拖拽或多类型数据时更为灵活。# 1. 核心作用
- 存储拖拽数据:支持多种类型(如文本、HTML、文件等)的数据项。
- 操作数据项:添加、删除、遍历拖拽内容。
- 文件拖拽支持:直接访问拖拽的文件列表(无需手动解析)。
# 2. 如何获取
DataTransferItemList?在拖拽事件的
event.dataTransfer.items属性中获取:JavaScriptelement.addEventListener('drop', (event) => { const items = event.dataTransfer.items; // 这就是 DataTransferItemList });1
2
3# 3. 主要方法和属性
# 方法
方法 作用 add(data, type)添加一个数据项(如 add('Hello', 'text/plain'))。remove(index)删除指定索引的数据项。 clear()清空所有数据项。 DataTransferItem(index)获取指定索引的 DataTransferItem对象(只读)。# 属性
属性 类型 描述 lengthnumber 当前数据项的数量。 # 4. 使用场景与示例
# 场景 1:检查拖拽内容类型
JavaScriptelement.addEventListener('dragover', (event) => { const hasFiles = [...event.dataTransfer.items].some( item => item.kind === 'file' ); if (hasFiles) event.preventDefault(); // 允许放置文件 });1
2
3
4
5
6# 场景 2:添加自定义拖拽数据
JavaScriptelement.addEventListener('dragstart', (event) => { event.dataTransfer.items.add('{"id": 123}', 'application/json'); });1
2
3# 场景 3:读取拖拽的文件
JavaScriptelement.addEventListener('drop', (event) => { const fileItems = [...event.dataTransfer.items] .filter(item => item.kind === 'file') .map(item => item.getAsFile()); fileItems.forEach(file => { console.log('文件名:', file.name); }); });1
2
3
4
5
6
7
8
9# 5. 与
DataTransfer传统方法的对比特性 DataTransferItemList传统 DataTransfer方法数据操作粒度 可管理多个独立数据项 单类型覆盖( setData()会覆盖之前值)文件访问 直接通过 item.getAsFile()获取需通过 files属性访问类型检查 可通过 item.kind和item.type精确判断需手动尝试 getData(type)性能 更适合大量或复杂数据 简单场景更直接 # 6. 关键对象:
DataTransferItemDataTransferItemList中的每一项是DataTransferItem对象,包含:kind:数据种类('string'或'file')。type:MIME 类型(如'text/plain')。方法
:
getAsFile():如果是文件,返回File对象。getAsString(callback):异步获取字符串内容。
# 7. 完整示例:文件拖拽上传
HTML<div id="drop-zone">拖拽文件到此处</div> <script> const dropZone = document.getElementById('drop-zone'); dropZone.addEventListener('dragover', (event) => { event.preventDefault(); }); dropZone.addEventListener('drop', (event) => { event.preventDefault(); const items = event.dataTransfer.items; for (let i = 0; i < items.length; i++) { const item = items[i]; if (item.kind === 'file') { const file = item.getAsFile(); console.log('拖拽文件:', file.name); // 上传逻辑... } } }); </script>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22# 8. 注意事项
- 浏览器兼容性
- 现代浏览器全面支持,但旧版 IE 不兼容。
- 移动端部分场景可能受限。
- 安全限制
- 跨域拖拽时,某些数据可能不可读(同源策略)。
- 性能优化
- 大量文件拖拽时,建议使用
FileAPI 而非字符串操作。
- 大量文件拖拽时,建议使用
# 总结
DataTransferItemList是拖拽 API 中管理数据的核心工具,尤其适合:- 需要同时传递多种类型数据的场景。
- 精确控制拖拽内容的增删改查。
- 高效处理文件拖拽(如上传功能)。
通过它,开发者可以更灵活地实现复杂的拖拽交互。
web worker
- https://juejin.cn/post/7139718200177983524
- (截图)[https://gitee.com/wangluoshihuang/static_article/blob/master/JS/webWorker/%E4%B8%80%E6%96%87%E5%BD%BB%E5%BA%95%E5%AD%A6%E4%BC%9A%E4%BD%BF%E7%94%A8web%20worker%20-%20%E6%8E%98%E9%87%91.html]
- https://mp.weixin.qq.com/s/Sz8SaBWj4CazH6yI9Ivu0w
- (截图)[https://gitee.com/wangluoshihuang/static_article/blob/master/JS/webWorker/Web%20%E5%A4%9A%E7%BA%BF%E7%A8%8B%E5%BC%80%E5%8F%91%E5%88%A9%E5%99%A8%20Comlink%20%E7%9A%84%E5%89%96%E6%9E%90%E4%B8%8E%E6%80%9D%E8%80%83.html]
- https://juejin.cn/post/7139718200177983524
JS 四种 Observers:监听元素
- 直接在 mdn 上直接搜索 Observer 也可以看见这 4 个 api:http://www.luyanghui.com/?p=102
关闭页面请求也可以发送成功:
- https://juejin.cn/post/7082238461121396749
JS 烧脑面试题大赏
- https://mp.weixin.qq.com/s/nTO4e4cfqlbB0p2xzYa6UA
- 文章截图 (opens new window)
- 第 4 题执行过程如下
- 网上说的都不对,实际上打印 a、b 的值,a 等于:{n:2};b 等于:{n: 1,x: {n: 2}}
- 可以让 gpt 解释第 4 题:执行赋值表达式 a.x = a = {n:2}。这个表达式先将 a 的属性 x 赋值为 a,即 a.x = a。然后将 a 的值修改为一个新的对象{n:2},即 a = {n:2}。此时 a 和 b 指向不同的对象。

- 理解的重点在于: a.x = a 先执行。然后就是 a.x 指向的是变量 a,a 到底是什么值,不会在 a.x = a 此语句执行时就被决定,后面的语句也可能更改 a 的值。
- 第 4 题执行过程如下
客户端监听浏览器事件:
- EventSource:https://developer.mozilla.org/zh-CN/docs/Web/API/EventSource
try... catch 抛出自定义对象
方式1:
try{
if(a==5){
// 抛出错误
throw {yu:7}; // 直接使用 throw 抛出对象即可
}
}catch(e){
console.log(e); //打印: loopTerminates
console.log(e.message); //打印:undefined
}
方式2:
var a = 5;
try{
if(a==5){
// 抛出错误
await Promise.reject({yui:7}) // 这样也可以
}
}catch(e){
console.log(e); //打印: loopTerminates
console.log(e.message); //打印:undefined
}
// 下面这种方法没法抛出自定义对象,因为x必须为字符串
var a = 5;
try{
if(a==5){
// 抛出错误
throw new Error(x) // x必须为字符串
}
}catch(e){
console.log(e);
console.log(e.message); //打印:这里才是x的值
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
对于 cookie 的认识
- cookie 属性以及不同值的区别:https://www.cnblogs.com/sunLemon/p/10563818.html
- Cookie 顶级域名、二级域名、三级域名共享:https://blog.csdn.net/supermao1013/article/details/83827310
当 flex 布局使用 flex-direction: column-reverse; 属性用在元素上时,元素里的元素位置会倒序,此时我们使用 js 滚动页面时:
- 假如元素要滚动到顶部时:
element.scrollTo({ top: -800000, // 对应元素滚动到顶部。这里的值不再是0, 而是一个足够小的负值 bottom: 0, left: 0, behavior: "smooth", });1
2
3
4
5
6js 实现滚动有两个好用方法:
- element.scrollIntoView({ behavior: 'smooth', block: 'start' }) 。元素滚到可视区。元素滚到流布局的可视区,换而言之如果有绝对定位以及固定定位存在那么元素即使使用了这个 api 滚动到可视区了(也是在流布局的可视区,并不是视觉上的可视区)也有可能被遮挡。
- 还有就是上面的 scrollTo 方法。
- 相对来说使用 scrollIntoView 更灵活,不需要计算位置。
ajax fetch axios 三种方式实现 progress(进度条)
- https://mp.weixin.qq.com/s/zOhYbrQZWHDs6PGlsymdtQ
前端请求大比拼:Fetch、Axios、Ajax、XHR
- https://mp.weixin.qq.com/s/8b58SicOjeEXjGt766xHAg
js 是怎么运行起来的
- https://mp.weixin.qq.com/s/QFfjss-gcHFY1ID1xiqn6Q
- 截图 (opens new window)
- 解释型和编译型语言的区别
- https://mp.weixin.qq.com/s/QFfjss-gcHFY1ID1xiqn6Q
scroll 事件:
- 现代浏览器在单独的进程上执行滚动,因此只能异步传递滚动事件。由于是异步传递,因此主线程动画容易出现卡顿。
js 监听元素发生变化
- MutationObserver:https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserver
- 还可以使用 dom 事件:https://blog.csdn.net/dejing6575/article/details/101474317
stopPropagation 和 stopImmediatePropagation 的区别
- event.stopPropagation 只会阻止相同类型(event.type 相同)事件传播,上面有提到过 移动端 触摸事件触发的顺序问题,假如 我在 touchstart 中调用了 event.stopPropagation 只会 阻止后续 event flow 上其他 touchstart 事件,并不会阻止 touchmove,touchend 等 mouseEvent 事件的发生。
- event.stopPropagation 阻止捕获和冒泡阶段中当前事件的进一步传播。如果有多个相同类型事件的事件监听函数绑定到同一个元素,当该类型的事件触发时,它们会按照被添加的顺序执行。如果其中某个监听函数执行 event.stopImmediatePropagation 方法,则当前元素剩下的监听函数将不会被执行。
workers 使用离屏 canvas
- https://my.oschina.net/ahaoboy/blog/4697059
JSON.stringify
- https://juejin.cn/post/7251786870186147901?searchId=202406040906256FB7A7CC4F424E0EE772
5 个比较实用的 api(观察 api)
- 5 高级前端常用的 API:https://mp.weixin.qq.com/s/75OiaDSXH3igkefI8IL34A
- 监听元素大小变化:ResizeObserver
- https://developer.mozilla.org/zh-CN/docs/Web/API/ResizeObserver
异常处理:
- 全局监听 js 报错
window.onerror = function (message, source, lineno, colno, error) { console.log("捕获到异常:", { message, source, lineno, colno, error }); }; // 函数参数: // message:错误信息(字符串)。可用于HTML onerror=""处理程序中的 event。 // source:发生错误的脚本URL(字符串) // lineno:发生错误的行号(数字) // colno:发生错误的列号(数字) // error:Error对象[3](对象) // 若该函数返回true,则阻止执行默认事件处理函数。1
2
3
4
5
6
7
8
9
108 种现代 JavaScript 响应式模式
- 参考:https://mp.weixin.qq.com/s/zGNE3aTVcTim5C9r3enwnw
- 截图 (opens new window)
代码注释规范:
- https://segmentfault.com/a/1190000040967907
- https://knightyun.github.io/2020/03/13/js-comment-format
- https://itmyhome.com/js/lei_xing_ding_yi.html
- https://www.shouce.ren/api/view/a/13248
不同 tab 之间就算相同 url,sessionStorage 也是不会共享的。sessionStorage 只存在于当前会话(tab 页)中
- 使用 window.open 或者点击链接跳转的页面,新页面的 sessionStorage 会拷贝老页面的。但两者之间并无关联,还是两个会话。
- 自注:主要表现在假如页面 1 使用链接或者 window.open 打开页面 2,页面 2 的 sessionStorage 会拷贝页面 1 的 sessionStorage。但是无论在哪个页面操作 sessionStorage,另外一个页面的 sessionStorage 都会不会发生变化。
- 使用 window.open 或者点击链接跳转的页面,新页面的 sessionStorage 会拷贝老页面的。但两者之间并无关联,还是两个会话。
有些事件会随着浏览器的不同而有不同的实现:
视频的自动播放:在谷歌浏览器中如果用不不对浏览器进行操作,那么视频将不会自动播放,例如:需要用户手动点击页面(页面的任何地方)后才可自动播放
页面卸载时的事件——beforeunload:在谷歌浏览器上,如果用户没有操作页面,那么直接关闭时次事件是不会触发的;但是在火狐浏览器上,不管用户有没有操作页面,直接关闭时次事件都会触发。
javascript 坐标:event.x、event.clientX、event.offsetX、event.screenX 用法
- https://www.cnblogs.com/asqq/archive/2012/04/19/2456927.html (opens new window)
- 关于位置的计算这里用得很好,避免了性能问题:https://www.npmjs.com/package/react-draggable
- https://www.cnblogs.com/asqq/archive/2012/04/19/2456927.html (opens new window)
判断数据类型
function getType(value) { return Object.prototype.toString.call(value).slice(8, -1); }// 使用示例 console.log(getType(123)); // "Number" console.log(getType('hello')); // "String" console.log(getType(true)); // "Boolean" console.log(getType(null)); // "Null" console.log(getType(undefined)); // "Undefined" console.log(getType([])); // "Array" console.log(getType({})); // "Object" console.log(getType(function(){})); // "Function" console.log(getType(new Date())); // "Date" console.log(getType(/regex/)); // "RegExp" console.log(getType(Symbol())); // "Symbol" console.log(getType(new Map())); // "Map" console.log(getType(new Set())); // "Set" console.log(getType(new Promise(() => {}))); // "Promise" // 实际执行流程 const value = [1, 2, 3]; // 执行 Object.prototype.toString.call(value) 的步骤: // 1. 获取 Object.prototype 的 toString 属性(一个函数) const originalToString = Object.prototype.toString; // 2. 通过 call() 调用: // - call() 将 toString 函数的 this 绑定为 value // - 这时 toString 内部的 this 就是数组 [1, 2, 3] // 3. toString 方法执行时: // - 检查 this(现在是数组)的 [[Class]] 内部属性 // - 返回 "[object Array]"1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
- 02
- Git 和 Husky 添加提交钩子并实现代码任务自动化01-30
- 03
- 其他工程化杂项08-29
