跳到主要内容
JavaScript 基础入门与核心语法详解 | 极客日志
JavaScript 大前端 java
JavaScript 基础入门与核心语法详解 JavaScript 基础入门教程涵盖语言特点、脚本分类、DOM 操作、事件处理、数组与对象方法以及客户端数据存储。内容包含 HelloWorld、弹窗交互、表单校验、时钟显示等实战案例,详细讲解 ES5/ES6 函数定义、闭包、变量声明及类型转换,并提供 Cookie、SessionStorage 和 LocalStorage 的封装与应用示例,适合初学者系统掌握前端开发核心技能。
信号故障 发布于 2026/2/6 更新于 2026/6/2 21 浏览JavaScript 基础入门与核心语法详解
心法 :本章使用 Maven 父子结构项目进行练习。
练习项目结构如下 :
|_ v2-9-web-javascript |_ 8080test
武技 :搭建练习项目结构。
创建父项目 v2-9-web-javascript,删除 src 目录。
创建子项目 test,注意是 Maven Archetype 类型,不需要添加任何依赖。
将子项目中自带的 index.jsp 替换为 index.html:
<!DOCTYPE html >
<html lang ="en" >
<head >
<meta charset ="UTF-8" >
<title > 基础入门</title >
</head >
<body >
<p > Hello JavaScript!</p >
</body >
</html >
在 IDEA 中调整对 ES6 语法的支持:
部署项目:将子项目部署到 Tomcat 服务器,项目发布名设为'js'即可。
访问首页:启动 Tomcat 服务并访问 http://localhost:8080/js/index.html 首页。
S01. JS 基础入门
心法 :JavaScript6,简称 JS6,是一门用于与浏览器及其内容等几乎所有方面的交互的编程语言,在 1995 年由 NetScape 公司在网景导航者浏览器上首次设计实现而成,原名 LiveScript,后因与 Sun 合作更名为 JavaScript 并被纳入 ECMA-262 标准(ECMA 是欧洲计算机制造联合会,旨在建立统一的电脑操作格式标准),故 JS 也可被称为 ES。
语言特点 描述 解释型 程序的运行过程中逐行进行解释,不需要编译 面向对象 JS 不仅能使用现有的对象,还可以创建新的对象 弱类型 JS 拥有数据类型但不需要声明强调 事件驱动 JS 采用事件驱动进行编程,可以对用户的操作做出实时的响应 跨平台性 JS 不依赖于操作系统,仅依赖于浏览器,浏览器兼容性良好
JS 组成结构 :JS 除了 ECMA 核心引擎之外,还分为 DOM 和 BOM 两种结构:
对比项 DOM 文档对象模型 BOM 浏览器对象模型 赋予 JS 什么能力 操作 DOM 树的能力 操作浏览器的能力 示例 得到元素,删除元素等 弹窗,关窗,剪切板等 浏览器兼容性 部分兼容 完全不兼容 关键字 document,不能省略 window,可省略
JS 分类 优先级 使用方式 特点 内嵌 最高 直接在某标签上使用 onclick 等属性挂载 JS 事件 代码耦合度极高,仅临时调试使用,正式开发不推荐 内部 中等 在页体末尾的 <script></script> 中开发 多个 <script></script> 区域会按编写顺序依次执行 脚本与页面绑定,适合学习或单页面小场景 外部 最低 在页体末尾使用 <script src="JS 文件路径"> 引入 开发场景下推荐使用
开发 view/基础 - 脚本分类.html 页面文件:
<button type ="button" onclick ="alert('内嵌 JS 脚本')" > 测试内嵌 JS 脚本</button > <script src ="../script/基础 - 脚本分类.js" > </script > <script > alert ('内部:页面加载完毕!' );</script >
开发 script/基础 - 脚本分类.js 脚本文件:
访问 view/基础 - 脚本分类.html 页面,效果如下:
E01. 案例 - HelloWorld
心法 :【案例 01】- 编写 JS 版的 HelloWorld。
案例需求 :点击【打印】按钮,在浏览器的控制台输出'hello world'以及当前浏览器的相关信息。
案例相关知识点 简述 说明 onload = () => {}加载函数 在页面全部元素(包括 DOM,图片,视频等)加载完毕后自动执行 多个加载函数会发生覆盖,尽量不要这么干 console.log('', '')输出语句 多值输出使用逗号分隔即可,浏览器控制台表现为空格分隔 document.querySelector('C3 选择器')单抓元素 从 DOM 树中根据 CSS 选择器抓取单个元素 返回值一律使用 let 接收 抓取失败(如元素不存在)时返回 null 元素.onclick = () => {}点击事件 为元素挂载点击事件
武技 :开发 view/入门案例/HelloWorld.html 页面,并编写【案例 01】代码。
<button id ="btn" type ="button" > 打印</button >
onload = () => {
let btn = document .querySelector ('#btn' );
btn.onclick = () => {
console .log ('hello' , 'world' );
console .log (window .navigator .userAgent );
};
};
E02. 案例 - NewPage
点击【打开新页面】按钮,打开一个新的空白窗口并在新页面上编写'HelloWorld 'HTML 代码。
点击【跳转新页面】按钮,跳入百度页面。
案例相关知识点 简述 说明 open('页面 URL')当前窗口 在当前窗口展示指定的 URL 页面 open('页面 URL', '_blank')新窗口指定页面 开启一个新窗口,展示指定的 URL 页面,返回新窗口对象 open('about:blank', '_blank')新窗口空白页面 开启一个新窗口,展示空白的页面,返回新窗口对象 document.write('HTML 内容')文档写入 HTML 在整个文档上写入指定的 HTML 内容 location.href = ''跳转新页面 支持网络 URI 地址或本地资源地址 close()关闭新窗口 仅支持关闭被 open() 打开的页面 关闭最后一个页面时浏览器也会退出 top.close()关闭父窗口 在子页面中关闭父页面
武技 :开发 view/入门案例/页面相关操作.html 页面,并编写【案例 02】代码。
<button id ="openBtn" type ="button" > 打开新页面</button >
<button id ="jumpBtn" type ="button" > 跳转新页面</button >
onload = () => {
let openBtn = document .querySelector ('#openBtn' );
let jumpBtn = document .querySelector ('#jumpBtn' );
openBtn.onclick = () => {
let newWindow = open ('about:blank' , '_blank' );
newWindow.document .write ('<h1>HelloWorld</h1>' );
};
jumpBtn.onclick = () => {
location.href = 'https://www.baidu.com' ;
};
};
E03. 案例 - Alert
点击【普通小弹窗】按钮,弹出'你好'提示。
点击【确认小弹窗】按钮,弹出'即将删除,确定吗?'提示,并在控制台输出用户的对应动作。
点击【输入小弹窗】按钮,弹出'请输入密码阅读'提示,并在控制台输出用户的对应动作。
案例相关知识点 简述 说明 alert('弹窗内容')普通弹窗 仅包含一个确定按钮 confrim('弹窗内容')确认弹窗 包含确定按钮和取消按钮 点击确定:返回 true 点击取消:返回 false prompt('弹窗内容', '默认值')输入弹窗 包含确定按钮,取消按钮和一个输入框 点击确定:返回用户输入的内容(无任何输入时返回空串) 点击取消:返回 null
武技 :开发 view/入门案例/三种小型弹窗.html 页面,并编写【案例 03】代码。
<button id ="alertBtn" type ="button" > 普通小弹窗</button >
<button id ="confirmBtn" type ="button" > 确认小弹窗</button >
<button id ="promptBtn" type ="button" > 输入小弹窗</button >
onload = () => {
let alertBtn = document .querySelector ('#alertBtn' );
let confirmBtn = document .querySelector ('#confirmBtn' );
let promptBtn = document .querySelector ('#promptBtn' );
alertBtn.onclick = () => {
alert ('你好' );
};
confirmBtn.onclick = () => {
let result = confirm ('即将删除,确定吗?' );
console .log ('响应:' , result);
};
promptBtn.onclick = () => {
let result = prompt ('请输入密码阅读' );
console .log ('响应:' , result);
};
};
E04. 案例 - RememberMe
当鼠标移入【记住密码】多选框时,展示敏感操作提示'请不要再公共场合勾选此项!',
当鼠标移出【记住密码】多选框时,隐藏敏感操作提示。
案例相关知识点 简述 说明 元素.innerText = ''文本内容 设置元素的纯文本内容 元素.innerHTML = ''HTML 内容 设置元素的 HTML 文本内容 元素.style['样式'] = ''元素样式 设置元素的 CSS 样式 元素.onmouseover = () => {}移入事件 当鼠标移入该元素时触发 元素.onmouseout = () => {}移出事件 当鼠标移出该元素时触发
武技 :开发 view/入门案例/鼠标经过提示.html 页面,并编写【案例 04】代码。
<input id ="cbx" type ="checkbox" /> <label for ="cbx" > 记住密码</label >
<mark id ="tips" > </mark >
onload = () => {
let cbx = document .querySelector ('#cbx' );
let tips = document .querySelector ('#tips' );
tips.innerHTML = '<strong>请不要在公共场合勾选此项!</strong>' ;
tips.style ['display' ] = 'none' ;
cbx.onmouseover = () => tips.style ['display' ] = 'inline' ;
cbx.onmouseout = () => tips.style ['display' ] = 'none' ;
};
E05. 案例 - HighLight
当鼠标移入某行歌词时,该行歌词背景高亮(变红色)。
当鼠标移出某行歌词时,该行歌词背景恢复原状。
案例相关知识点 说明 document.querySelectorAll('C3 选择器')从 DOM 树 中,根据 CSS 选择器抓取元素集合 元素不存在时返回 null 元素.querySelectorAll('C3 选择器')从 指定元素内部 根据 CSS 选择器抓取元素集合 元素不存在时返回 null
武技 :开发 view/入门案例/鼠标经过高亮.html 页面,并编写【案例 05】代码。
<ul id ="list01" >
<li class ="item" > 在我心上用力的开一枪</li >
<li class ="item" > 让一切归零在这声巨响</li >
<li class ="item" > 如果爱是说什么都不能忘</li >
<li class ="item" > 我不挣扎</li >
<li class ="item" > 也许我也没差</li >
</ul >
<ul id ="list02" >
<li class ="item" > 在我心上用力的开一枪</li >
<li class ="item" > 让一切归零在这声巨响</li >
<li class ="item" > 如果爱是说什么都不能忘</li >
<li class ="item" > 我不挣扎</li >
<li class ="item" > 也许我也没差</li >
</ul >
onload = () => {
let list01 = document .querySelector ('#list01' );
let items = list01.querySelectorAll ('.item' );
for (let i = 0 , j = items.length ; i < j; i++) {
items[i].onmouseover = () => items[i].style ['background-color' ] = 'red' ;
items[i].onmouseout = () => items[i].style ['background-color' ] = '' ;
}
};
E06. 案例 - AllCheck
当点击【全选】按钮时,选中全部用户(无论之前是否打勾,都打勾),再次点击则取消全部用户。
当点击【反选】按钮时,反选全部用户(打勾 → 取消,取消 → 打勾)。
案例相关知识点 简述 说明 元素.checked确认选中 元素被选中时返回 true,否则返回 false
武技 :开发 view/入门案例/全选反选按钮.html 页面,并编写【案例 06】代码。
<input id ="allCbx" type ="checkbox" > <label for ="allCbx" > 全选</label >
<input id ="revCbx" type ="checkbox" > <label for ="revCbx" > 反选</label >
<hr >
<input id ="cbx01" name ="user" type ="checkbox" > <label for ="cbx01" > 赵四</label >
<input id ="cbx02" name ="user" type ="checkbox" > <label for ="cbx02" > 刘能</label >
<input id ="cbx03" name ="user" type ="checkbox" > <label for ="cbx03" > 广坤</label >
<input id ="cbx04" name ="user" type ="checkbox" > <label for ="cbx04" > 王云</label >
<input id ="cbx05" name ="user" type ="checkbox" > <label for ="cbx05" > 飞机</label >
onload = () => {
let users = document .querySelectorAll ('input[name="user"]' );
let allCbx = document .querySelector ('#all-cbx' );
let revCbx = document .querySelector ('#rev-cbx' );
allCbx.onclick = () => {
for (let i = 0 , j = users.length ; i < j; i++) {
users[i].checked = allCbx.checked ;
}
};
revCbx.onclick = () => {
for (let i = 0 , j = users.length ; i < j; i++) {
users[i].checked = !users[i].checked ;
}
};
};
E07. 案例 - BatchRemove 案例需求 :当点击【批量删除】按钮时,模拟删除全部被选中的用户:
删除之前,必须进行空删保护:
若 0 个用户被选中,则弹出提示'删除失败:您至少要选择一项!'。
删除之前,必须进行误删保护:弹出提示框'您将要删除 N 个用户,确认吗?',(其中 N 是真实选中的用户数量)。
若点击【确定】按钮,则弹出提示'删除成功'。
若点击【取消】按钮,则无事发生。
案例相关知识点 简述 说明 return结束函数 该关键字用于结束并退出其所在的函数 ${xx}变量插值 ES6 支持使用反引号作为字符串符号,且在反引号中可以使用 ${xx} 进行变量插值
武技 :开发 view/入门案例/批量删除提示.html 页面,并编写【案例 07】代码。
<button id ="deleteBtn" type ="button" > 批量删除</button >
<hr >
<input id ="cbx01" name ="user" type ="checkbox" > <label for ="cbx01" > 赵四</label >
<input id ="cbx02" name ="user" type ="checkbox" > <label for ="cbx02" > 刘能</label >
<input id ="cbx03" name ="user" type ="checkbox" > <label for ="cbx03" > 广坤</label >
<input id ="cbx04" name ="user" type ="checkbox" > <label for ="cbx04" > 王云</label >
<input id ="cbx05" name ="user" type ="checkbox" > <label for ="cbx05" > 飞机</label >
onload = () => {
let deleteBtn = document .querySelector ('#deleteBtn' );
deleteBtn.onclick = () => {
let checkedUsers = document .querySelectorAll ('input[name="user"]:checked' );
if (checkedUsers.length <= 0 ) {
alert ('删除失败:您至少要选择一项!' );
return ;
}
if (confirm (`您将要删除${checkedUsers.length} 个用户,确认吗?` )) {
alert ('删除成功!' );
}
};
};
E08. 案例 - CheckUsername 案例需求 :当账号框丧失焦点时,判断账号是否已存在:
若账号框内容为空,则无事发生。
若账号已存在(固定为 admin),则给出红色提示'该账号不可使用'。
若账号不存在(不为 admin),则给出绿色提示'该账号可以使用'。
案例相关知识点 简述 说明 元素.onblur = () => {}失焦事件 当元素丧失焦点时触发 值 1 === 值 2全等比较 全等比较不会自动转换数据类型进行比较
武技 :开发 view/入门案例/账号失焦判断.html 页面,并编写【案例 08】代码。
<label for ="ipt" > 账号:</label >
<input id ="ipt" >
<span id ="tips" > </span >
onload = () => {
let tips = document .querySelector ('#tips' );
let usernameIpt = document .querySelector ('#username-ipt' );
usernameIpt.onblur = () => {
if (usernameIpt.value === '' ) {
tips.style ['display' ] = 'none' ;
return ;
}
let isAdmin = 'admin' === usernameIpt.value ;
tips.style ['display' ] = 'inline-block' ;
tips.innerText = isAdmin ? '该账号不可使用' : '该账号可以使用' ;
tips.style ['color' ] = isAdmin ? 'red' : 'green' ;
};
};
E09. 案例 - CheckForm01
心法 :【案例 09】- 表单空值校验(普通按钮版)。
案例需求 :输入账号和密码后,使用普通按钮进行表单提交:
若账号为空,则提示'账号不能为空!'并重设账号框焦点。
若密码为空,则提示'密码不能为空!'并重设密码框焦点。
若账号密码均合法,则提交表单到百度。
案例相关知识点 简述 说明 元素.focus()获得焦点事件 使元素立刻获取焦点,一般元素类型为 <input>, <select>, <textarea> 等 表单元素.submit()表单提交函数 提交数据,一般元素类型为 <form> 表单
武技 :开发 view/入门案例/普通按钮判空.html 页面,并编写【案例 09】代码。
<form id ="loginForm" action ="https://www.baidu.com" autocomplete ="off" >
<label for ="usernameIpt" > 账号:</label >
<input id ="usernameIpt" type ="text" name ="username" />
<label for ="passwordIpt" > 密码:</label >
<input id ="passwordIpt" type ="password" name ="password" />
<button type ="button" id ="loginBtn" > 登录</button >
</form >
onload = () => {
let usernameIpt = document .querySelector ('#usernameIpt' );
let passwordIpt = document .querySelector ('#passwordIpt' );
let loginForm = document .querySelector ('#loginForm' );
let loginBtn = document .querySelector ('#loginBtn' );
usernameIpt.focus ();
loginBtn.onclick = () => {
if ('' === usernameIpt.value || null === usernameIpt.value ) {
alert ('账号不能为空!' );
usernameIpt.focus ();
return ;
}
if ('' === passwordIpt.value || null === passwordIpt.value ) {
alert ('密码不能为空!' );
passwordIpt.focus ();
return ;
}
loginForm.submit ();
};
};
E10. 案例 - CheckForm02
心法 :【案例 10】- 表单空值校验(提交按钮版)。
案例需求 :输入账号和密码后,使用提交按钮进行表单提交:
若账号为空,则提示'账号不能为空!'并重设账号框焦点。
若密码为空,则提示'密码不能为空!'并重设密码框焦点。
若账号密码均合法,则提交表单到百度。
案例相关知识点 简述 说明 表单元素.onsubmit = () => {}表单提交事件 当表单被提交时触发 return false阻止默认行为 阻止浏览器的默认行为,如提交表单,事件冒泡等
武技 :开发 view/入门案例/提交按钮判空.html 页面,并编写【案例 10】代码。
<form id ="loginForm" action ="https://www.baidu.com" autocomplete ="off" >
<label for ="usernameIpt" > 账号:</label >
<input id ="usernameIpt" type ="text" name ="username" />
<label for ="passwordIpt" > 密码:</label >
<input id ="passwordIpt" type ="password" name ="password" />
<button type ="submit" id ="loginBtn" > 登录</button >
</form >
onload = () => {
let usernameIpt = document .querySelector ('#usernameIpt' );
let passwordIpt = document .querySelector ('#passwordIpt' );
let loginForm = document .querySelector ('#loginForm' );
usernameIpt.focus ();
loginForm.onsubmit = () => {
if ('' === usernameIpt.value || null === usernameIpt.value ) {
alert ("账号不能为空!" );
usernameIpt.focus ();
return false ;
}
if ('' === passwordIpt.value || null === passwordIpt.value ) {
alert ("密码不能为空!" );
passwordIpt.focus ();
return false ;
}
};
};
E11. 案例 - Clock 案例需求 :页面加载完毕的 3 秒后,显示一个实时的动态数码时钟,要求包括年,月,日,时,分,秒六大时间元素。
案例相关知识点 简述 说明 setInterval(任务函数名称,毫秒数)开启周期定时器 每隔 t 毫秒重复执行一次任务函数 返回数字类型的定时器编号 clearInterval(定时器编号)关闭周期定时器 通过定时器编号来关闭周期定时器 setTimeout(任务函数名称,毫秒数)开启延迟定时器 在 t 毫秒后仅执行一次任务函数 返回数字类型的定时器编号 clearTimeout(定时器编号)关闭延迟定时器 通过定时器编号来关闭延迟定时器 let now = new Date()获取本地时间 let yy = now.getFullYear():获取年份let mm = now.getMonth() + 1:获取月份let dd = now.getDate():获取日let wk = now.getDay():获取星期let hh = now.getHours():获取时let mi = now.getMinutes():获取分let ss = now.getSeconds():获取秒
武技 :开发 view/入门案例/显示数码时钟.html 页面,并编写【案例 11】代码。
<section id ="clock" class ="clock" > 将在 3 秒后显示数码时钟</section >
.clock {
width : 550px ;
margin : 20px auto;
text-align : center;
border : 5px inset black;
padding : 20px ;
color : red;
font-size : 50px ;
}
let timer01;
onload = () => {
let clock = document .querySelector ('#clock' );
setTimeout (() => {
clearInterval (timer01);
function task ( ) {
let now = new Date ();
let yy = now.getFullYear ();
let mm = now.getMonth () + 1 < 10 ? '0' + (now.getMonth () + 1 ) : now.getMonth () + 1 ;
let dd = now.getDate () < 10 ? '0' + now.getDate () : now.getDate ();
let wk = '零一二三四五六日' .charAt (now.getDay ());
let hh = now.getHours () < 10 ? '0' + now.getHours () : now.getHours ();
let mi = now.getMinutes () < 10 ? '0' + now.getMinutes () : now.getMinutes ();
let ss = now.getSeconds () < 10 ? '0' + now.getSeconds () : now.getSeconds ();
clock.innerHTML = `${yy} 年${mm} 月${dd} 日 星期${wk} ${hh} :${mi} :${ss} ` ;
}
task ();
timer01 = setInterval (task, 1000 );
}, 3000 );
};
E12. 案例 - MouseFollow 案例需求 :当鼠标移动时,会有一个圆形的容器跟随移动。
案例相关知识点 简述 说明 ev键鼠对象 每个函数的首位参数都可以用来表示鼠标或键盘对象,命名建议 ev:ev.clientX:获取鼠标相对于视口原点的 X 坐标,不带单位ev.clientY:获取鼠标相对于视口原点的 Y 坐标,不带单位ev.pageX:获取鼠标相对于文档原点的 X 坐标,不带单位ev.pageY:获取鼠标相对于文档原点的 Y 坐标,不带单位ev.screenX:获取鼠标相对于屏幕原点的 X 坐标,不带单位ev.screenY:获取鼠标相对于屏幕原点的 Y 坐标,不带单位 document.onmousemove = (ev) => {}鼠标移动事件 当鼠标在文档上移动时触发 元素.offsetWidth元素宽度数值 获取元素当前的宽度,不带单位,适用于计算 元素.offsetHeight元素高度数值 获取元素当前的高度,不带单位,适用于计算
武技 :开发 view/入门案例/鼠标跟踪效果.html 页面,并编写【案例 12】代码。
<div id ="pen" class ="pen" > </div >
.pen {
width : 50px ;
height : 50px ;
background : yellow;
border-radius : 50% ;
position : absolute;
}
onload = () => {
let pen = document .querySelector ('#pen' );
document .onmousemove = ev => {
pen.style ['left' ] = ev.clientX - pen.offsetWidth / 2 + 'px' ;
pen.style ['top' ] = ev.clientY - pen.offsetHeight / 2 + 'px' ;
};
};
E13. 案例 - Snake 案例需求 :初始布局是一只拥有 1 个头关节 + 5 个身关节的贪食蛇,当按下某个【方向键】时,贪食蛇可以按照对应的方向进行移动,每次移动一个关节的位置且不允许超出指定的边界范围。
案例相关知识点 简述 说明 ev.key获取键盘描述 获取键盘对应的文字描述字符串
武技 :开发 view/入门案例/贪食蛇移动版.html 页面,并编写【案例 13】代码。
<section id ="board" class ="board" >
<div class ="snake" > </div >
<div class ="snake" > </div >
<div class ="snake" > </div >
<div class ="snake" > </div >
<div class ="snake" > </div >
<div class ="snake" > </div >
</section >
.board {
width : 500px ;
height : 500px ;
outline : 10px solid red;
position : relative;
margin : 20px auto;
}
.snake {
width : 50px ;
height : 50px ;
border-radius : 10px ;
background-color : green;
position : absolute;
}
.snake :nth-child (1 ) {
background-color : black;
z-index : 1 ;
}
let boardWidth, boardHeight, snakeWidth, snakeHeight;
onload = () => {
let snakes = document .querySelectorAll (".snake" );
let board = document .querySelector ('#board' );
boardWidth = board.offsetWidth ;
boardHeight = board.offsetHeight ;
snakeWidth = snakes[0 ].offsetWidth ;
snakeHeight = snakes[0 ].offsetHeight ;
document .onkeydown = ev => {
snakeBodyMove (snakes);
snakeHeadMove (ev, snakes[0 ]);
};
};
function snakeBodyMove (snakes ) {
for (let i = snakes.length - 1 ; i > 0 ; i--) {
snakes[i].style ['left' ] = snakes[i - 1 ].style ['left' ];
snakes[i].style ['top' ] = snakes[i - 1 ].style ['top' ];
}
}
function snakeHeadMove (ev, snakeHead ) {
let left = snakeHead.offsetLeft ;
let top = snakeHead.offsetTop ;
switch (ev.key ) {
case 'ArrowLeft' :
if (left <= 0 ) return ;
snakeHead.style ['left' ] = left - snakeWidth + 'px' ;
break ;
case 'ArrowUp' :
if (top <= 0 ) return ;
snakeHead.style ['top' ] = top - snakeHeight + 'px' ;
break ;
case 'ArrowRight' :
if (left >= boardWidth - snakeWidth) return ;
snakeHead.style ['left' ] = left + snakeWidth + 'px' ;
break ;
case 'ArrowDown' :
if (top >= boardHeight - snakeHeight) return ;
snakeHead.style ['top' ] = top + snakeHeight + 'px' ;
break ;
}
}
E14. 案例 - EventBubble 案例需求 :当点击【事件冒泡】按钮时,自身的点击事件和父元素的点击事件被触发,但要求爷元素的点击事件不被触发。
案例相关知识点 简述 说明 ev.cancelBubble = true阻止事件冒泡 在子元素的事件中阻止向上触发父级元素的相同事件的冒泡效果
武技 :开发 view/入门案例/阻止事件冒泡.html 页面,并编写【案例 14】代码。
<body id ="body" class ="body" >
<section id ="sec" class ="sec" >
<button id ="btn" class ="btn" type ="button" > 事件冒泡</button >
</section >
</body >
.body {
border : 5px solid red;
}
.sec {
margin : 100px auto;
width : 60% ;
height : 100px ;
border : 5px solid green;
text-align : center;
}
.btn {
margin-top : 35px ;
}
onload = () => {
let bubbleBody = document .querySelector ("#body" );
let bubbleSec = document .querySelector ("#sec" );
let bubbleBtn = document .querySelector ("#btn" );
bubbleBody.onclick = () => { console .log ("body..." ); }
bubbleSec.onclick = ev => {
console .log ("section..." );
ev.cancelBubble = true ;
};
bubbleBtn.onclick = () => { console .log ("button..." ); }
};
S02. JS 基础语法
E01. 常量变量
1. 声明赋值
心法 :在整个运行过程中,可以 发生变化的量叫变量,不能 发生变化的量叫常量。
声明赋值代码 中文 基本规则 const a = 10常量 1. 声明时必须立即赋值(即声明和赋值必须在同一行) 2. 基本类型赋值后值不可修改,引用类型赋值后仅不可修改引用地址 3. 无预解析
声明赋值代码 版本 默认值 是否会被预解析 重复声明 规范性 var a = 10ES5 undefined 完全预解析(变量提升) 允许 不规范,易出错,不推荐 let a = 10ES6+ undefined 无预解析 禁止 更严谨,推荐
预解析 :预解析的本质是'变量提升',是 JS 引擎执行代码前的预处理逻辑,仅针对 var 变量和函数声明,JS 代码中的 var 变量,函数的内置参数,函数内的另一个函数声明以及函数内的 var 变量都会被预解析,优先级从高到低,其具体流程分为两步,如下:
将变量的声明部分提升至所在函数的首行(非所在代码块)。
变量的赋值操作仍保留在原代码位置。
武技 :开发 view/基础 - 变量常量.html 页面,并测试 JS 变量的预解析效果。
<button id ="varBtn" type ="button" > 测试 var 变量是否会预解析</button >
<button id ="letBtn" type ="button" > 测试 let 变量是否会预解析</button >
onload = () => {
let varBtn = document .querySelector ('#varBtn' );
let letBtn = document .querySelector ('#letBtn' );
varBtn.onclick = () => {
console .log ('money' , money);
{
var money = 100 ;
var money = 200 ;
}
};
letBtn.onclick = () => {
console .log ('money' , money);
{
let money = 100 ;
}
};
};
2. 数据类型
心法 :JS 是弱类型语言(变量的类型由赋值的'值'决定,而非声明时指定,且类型可动态改变),不需要强调类型,但不代表没有类型,可以使用 typeof 关键字测得值的本质类型。
数据类型 中文 核心特征 & 示例 特殊说明 number 数字 包含整数和浮点数 包含特殊值 NaN 包含特殊值 Infinity 和 -Infinity 1. NaN 是特殊数字(非数字) 2. NaN !== NaN 3. Infinity 表示无穷大 string 字符串 支持单,双,反三种引号 反引号可配${}快速插值 boolean 布尔 仅含 true 和 false,可直接作为判断条件 0 ,空串 ,null 和 undefined 视为假,其余为真function 函数 包括 ES5 中的普通函数 包括 ES6 中的箭头函数 包括 JS 中的内置函数 函数可作为其它函数的参数或返回值 object 对象 包括普通 JSON 对象 包括数组对象 包括从页面端抓取到的 DOM 元素均可视为对象类型 null 会被检测为 object 类型,属于历史 BUG undefined 未定义 包括仅声明但未赋值的变量 包括不存在的对象属性 包括无返回值的函数 布尔判断为假
非数字函数 isNaN():用于判断非数字(NaN,即 Not a Number),但 NaN 不一定等于 NaN。
武技 :开发 view/基础 - 数据类型.html 页面,并测试 JS 变量的数据类型。
<button id ="btn" type ="button" > 按钮</button >
onload = () => {
let result;
console .log (result, typeof result);
result = 1 ;
console .log (result, typeof result, isNaN (result) ? '非数字' : '数字' );
result = 'abc' ;
result = "abc" ;
result = `abc` ;
console .log (result, typeof result, isNaN (result) ? '非数字' : '数字' );
result = true ;
console .log (result, typeof result);
result = function ( ) {};
console .log (result, typeof result);
result = () => {};
console .log (result, typeof result);
result = document .querySelector ('#btn' );
console .log (result, typeof result);
result = null ;
console .log (result, typeof result);
let a = 0 ;
console .log ('a = 0' , a ? '真' : '假' );
let b = 1 ;
console .log ('b = 1' , b ? '真' : '假' );
let c = '' ;
console .log ('c = \'\'' , c ? '真' : '假' );
let d = 'hello' ;
console .log ('d = \'hello\'' , d ? '真' : '假' );
let e = null ;
console .log ('e = null' , e ? '真' : '假' );
let f = undefined ;
console .log ('f = undefined' , f ? '真' : '假' );
};
3. 类型转换
心法 :JS 类型转换分为 显示转换 (开发者主动用函数来控制类型转换) 和 隐式转换 (JS 引擎在运算或判断时自动触发的类型转换)两种。
转换方法 核心规则 特殊说明 parseInt(str)1. 逐字符转整数,遇非数字停止 2. 忽略前导空格 parseInt('12abc34') → 12parseInt('abc1234') → NaNparseInt('12.99') → 12parseInt(' 12') → 12parseFloat(str)1. 逐字符转浮点数,遇非数字停止 2. 忽略前导空格 3. 仅识别一个小数点 parseFloat('3.14a15') → 3.14parseFloat('a3.1415') → NaNparseFloat('12.34.56') → 12.34Number(val)整体转换为数字(而非逐字符) Number('123') → 123Number('123abc')→ NaNNumber(true) → 1Number(null) → 0Number(undefined) → NaN数字.toFixed(n)四舍五入保留 n 位小数 返回 字符串类型 (1.234).toFixed(2) → '1.23'(1).toFixed(2) → '1.00'String(val)整体转换为字符串 String(123)→ '123'String(null) → 'null'String(undefined) → "undefined"Boolean(val)转换为布尔值 假值列表:0 / '' / null / undefined / NaN / false Boolean(0) → falseBoolean([]) → trueBoolean({}) → trueBoolean('0') → true
场景 转换规则 值 1 == 值 21. 类型相同直接比较 2. null/undefined 互相相等(仅等于自身) 3. 其他类型先转数字再比较 10 == '10' → true0 == false → true'' == 0 → truenull == undefined → trueNaN == NaN → false字符串 1 - 字符串 2双方先转数字,再执行减法 '100' - '20' → 80'100' - 'abc' → NaN'100' - true → 99(true 转 1)字符串 1 + 字符串 2直接拼接为字符串 加号只要一侧是字符串,就触发拼接 '100' + '20' → '10020'100 + '20' → '10020'100 + true → 101(true 转 1)* / % 算术运算所有操作数先转数字,再执行运算 '10' / '2' → 510 % '3' → 1'abc' * 10 → NaN! 值 逻辑非先转布尔值,再取反 !0 → true!'' → true![] → false!!0 → false(双重非转布尔)if/while 判断条件自动转布尔值 假值列表:0 / '' / null / undefined / NaN / false if (空数组) → trueif (空对象) → true
武技 :开发 view/基础 - 类型转换.html 页面,并测试 JS 类型转换。
console .log (parseInt (' 123' ));
console .log (parseInt ('abc123' ));
console .log (parseInt ('123e0' ));
console .log (parseInt ('' ));
console .log (parseFloat ('3.1a4' ));
console .log (parseFloat ('3.a14' ));
console .log (parseFloat ('abc34' ));
console .log ('3.1499999 →' , 3.1499999 .toFixed (2 ));
console .log (10 + 20 );
console .log (10 + '20' );
console .log (10 + true );
console .log (10 + []);
console .log (10 + {});
console .log (0 == false );
console .log ('' == 0 );
console .log (null == undefined );
console .log ([] == 0 );
console .log ({} == '[object Object]' );
console .log (0 === false );
console .log (null === undefined );
console .log (!0 );
console .log (![]);
console .log (!!'abc' );
console .log ('100' - '1' );
E02. 函数方法
心法 :JS 函数的四要素包括返回值,形参列表,函数名和函数体,可作为另一个函数的参数、返回值,或直接赋值给一个变量。
1. ES5 函数定义
心法 :ES5 使用 function 函数名 ( 形参 ){ 函数体 } 格式定义函数,使用带名函数时,建议使用。
要素 规则 函数名 使用字母,下划线或 $ 开头,区分大小写 形参列表 1. 不允许写具体类型,也不允许使用 var 或 let 关键字 2. 数量可与实参不一致 3. 若实参数 < 形参数:未传参的形参为 undefined 4. 若实参数 > 形参数:可用 arguments 内置对象获取 5. 形参支持设置常量,变量,表达式,函数调用等类型的默认值 6. 支持使用 (...params) 来代表余下参数(本质是一个数组),变量名随意 函数体 1. 可包含任意 JS 代码,支持 return 返回值 2. 在不使用 return 的情况下,均默认返回 undefined 返回值 1. return 可返回任意类型,如基本类型,对象,函数等 2. 执行 return 后函数立即终止 arguments 函数体内的内置对象,可直接使用,代表所有实参 类数组,有 length 属性和下标,但无数组方法
武技 :开发 view/基础-ES5 函数定义.html 页面,并测试 ES5 函数定义。
onload = () => {
es5 (1 , 2 , 3 , 4 , 5 , 6 );
}
function fn ( ) {
return 3 ;
}
function es5 (a, b, c = a + b + 1 + fn(), ...params ) {
console .log (a, b, c);
console .log ('params' , params);
console .log ('arguments' , arguments );
}
2. ES6 函数定义
心法 :ES6 使用 let 函数名 = ( 形参 ) => { 函数体 } 格式定义函数(不支持 arguments 内置关键字),使用匿名函数时,建议使用。
场景 语法格式示例 注意事项 多参数 多行函数体 let r = (a, b) => { return a + b; }多行函数体 {} 和 return 均不能省略 多参数 单行函数体 let r = (a, b) => a + b省略 {} 时,自动返回单行代码结果,无需写 return 单参数 任意函数体 let r = (n) => n * 2let r = n => n * 2仅单参数可省略 (),多参数或无参数必须加 () 无参数 任意函数体 let r = () => 10无参数时 () 不可省略
武技 :开发 view/基础-ES6 函数定义.html 页面,并测试 ES6 函数定义。
onload = () => {
es6 (1 , 2 , 3 , 4 , 5 , 6 );
}
function fn ( ) {
return 3 ;
}
let es6 = (a, b, c = a + b + 1 + fn(), ...params ) => {
console .log (a, b, c);
console .log ('params' , params);
console .log ('arguments' , arguments );
};
3. this 关键字
心法 :函数体内支持使用 this 内置关键字指向绑定该事件的元素(ES5)或者 window 对象(ES6)。
在 ES5 函数中,this 关键字指向的是绑定该事件的 DOM 元素(事件源),是变化的。
在 ES6 函数中,this 关键字永远指向 window 对象,是不变的。
ev.target 是事件对象(ev)的核心属性,其始终指向触发事件的原始 DOM 元素(事件源),不受函数类型(ES5/ES6)影响,是跨场景获取事件源的通用方案,推荐优先使用。
需注意:ev 作为事件触发时自动传入的参数,仅在 事件绑定的匿名函数 / 箭头函数参数列表中 可直接声明并使用,若在函数内部手动调用该事件函数,需手动传入事件对象才能正常访问 ev.target 属性。
武技 :开发 view/基础-this 关键字.html 页面,并测试事件函数中的 this 指向。
<button id ="es5Btn" type ="button" > 测试 ES5 函数中的 this 指向</button >
<button id ="es6Btn" type ="button" > 测试 ES6 函数中的 this 指向</button >
onload = () => {
let es5Btn = document .querySelector ('#es5Btn' );
let es6Btn = document .querySelector ('#es6Btn' );
es5Btn.onclick = function (ev ) {
console .log ('this' , this );
console .log ('ev.target' , ev.target );
};
es6Btn.onclick = (ev ) => {
console .log ('this' , this );
console .log ('ev.target' , ev.target );
};
};
4. 函数闭包
心法 :JS 的函数可以发生嵌套,此效果被称为闭包。
子函数中可以直接使用自己的变量,也可以直接使用父函数的变量。
父函数中可以直接使用自己的变量,但无法使用子函数变量。
外界无法直接调用子函数。
武技 :开发 view/基础 - 函数闭包.html 页面,并测试 JS 函数闭包。
onload = () => {
let fu = '父函数变量' ;
function fn ( ) {
let zi = '子函数变量' ;
console .log ('子函数访问自己的变量' , zi);
console .log ('子函数访问父函数的变量' , fu);
}
fn ();
console .log ('父函数访问自己的变量' , fu);
console .log ('父函数访问子函数的变量' , zi);
};
E03. DOM 操作
1. 属性操作
心法 :JS 中的属性分为 原生属性 (自动映射到 DOM 元素的 JS 对象上,如 id, class 等)和 标签属性 (自定义的属性,如 data-id,apple 等)两种,而操作属性主要有三种方式,分为 分量符(点语法) ,中括号 和 DOM_API 三种操作方式,三种方式均遵循同名覆盖规则。
方式 代码 描述 其它 分量符 obj.idobj.id = 'joezhou'delete obj.id获取 属性,不存在返回 undefined 添加/修改 属性,重复设置会发生覆盖删除 属性无法直接读取标签属性 不反映在 HTML 标签上 会反映在 HTML 标签上 中括号 obj['id']obj['id'] = 'joezhou'delete obj['id']获取 属性,不存在返回 undefined 添加/修改 属性,重复设置会发生覆盖删除 属性无法直接读取标签属性 不反映在 HTML 标签上 会反映在 HTML 标签上 DOM_API obj.getAttribute('id')obj.setAttribute('id', 'joezhou')obj.removeAttribute('id')获取 属性,不存在返回 null 添加/修改 属性,重复设置会发生覆盖删除 属性允许直接读取标签属性 会反映在 HTML 标签上 会反映在 HTML 标签上
武技 :开发 view/文档 - 属性操作.html 文件,并测试 JS 属性的相关操作。
<div id ="box" class ="container" apple ="good" data-id ="100" > </div >
onload = () => {
const box = document .querySelector ('#box' );
console .log ('box.id' , box.id );
console .log ('box.class' , box.class );
console .log ('box.className' , box.className );
console .log ('box.apple' , box.apple );
box.age = 20 ;
console .log ('新增后' , box.age )
box.age = 21 ;
console .log ('修改后' , box.age );
delete box.age ;
console .log ('删除后' , box.age );
console .log (`box['id']` , box['id' ]);
console .log (`box['class']` , box['class' ]);
console .log (`box['className']` , box['className' ]);
console .log (`box['apple']` , box['apple' ]);
console .log (`box['data-id']` , box['data-id' ]);
box['age' ] = 101 ;
console .log ('新增后' , box['age' ]);
box['age' ] = 102 ;
console .log ('修改后' , box['age' ]);
delete box['age' ];
console .log ('删除后' , box['age' ]);
console .log (`box.getAttribute('id')` , box.getAttribute ('id' ));
console .log (`box.getAttribute('class')` , box.getAttribute ('class' ));
console .log (`box.getAttribute('className')` , box.getAttribute ('className' ));
console .log (`box.getAttribute('apple')` , box.getAttribute ('apple' ));
console .log (`box.getAttribute('data-id')` , box.getAttribute ('data-id' ));
box.setAttribute ('age' , '200' );
console .log (`新增后` , box.getAttribute ('age' ));
box.setAttribute ('age' , '201' );
console .log (`修改后` , box.getAttribute ('age' ));
box.removeAttribute ('age' );
console .log (`删除后` , box.getAttribute ('age' ));
};
2. 样式操作
心法 :JS 操作 DOM 元素样式主要分「行内样式操作」和「计算样式读取」两类,核心区别在于样式获取范围。
操作类型 语法 样式范围 核心场景 读取样式 obj.style['样式名']getComputedStyle(obj)['样式名']读取行内样式 读取所有最终渲染样式 读取自己设置的行内样式 读取元素实际显示的样式 操作样式 obj.style['样式名'] = '样式值'仅行内样式 临时修改单个样式 操作类名 obj.classList.add(类名)obj.classList.remove(类名)obj.classList.toggle(类名)类对应的所有样式 批量添加样式 批量移除样式 批量切换样式
武技 :开发 view/文档 - 样式操作.html 文件,并测试 JS 样式的相关操作。
<div id ="div" class ="a" style ="color: red" > </div >
#div {
font-size : 177px ;
}
.a {
border : 10px solid green;
}
.b {
border : 10px solid yellow;
}
onload = () => {
let div = document .querySelector ("#div" );
console .log ('内嵌 color:' , div.style ['color' ]);
console .log ('内部 fontSize:' , div.style ['fontSize' ]);
console .log ('内嵌 color:' , getComputedStyle (div)['color' ]);
console .log ('内部 fontSize:' , getComputedStyle (div)['fontSize' ]);
div.style ['width' ] = '100px' ;
div.style ['height' ] = '100px' ;
div.style ['backgroundColor' ] = 'red' ;
div.classList .remove ('a' );
div.classList .add ('b' );
};
3. 元素操作
心法 :JS 获取 DOM 元素分为「静态集合」和「动态集合」两类,核心区别在于集合是否随 DOM 变化自动更新。
获取方式 代码 返回类型 静态获取 document.querySelector(selector)document.querySelectorAll(selector)单个 DOM 元素 NodeList 集合(DOM 变化后集合不更新) 动态获取 document.getElementById(id)document.getElementsByName(name)document.getElementsByTagName(tag)单个 DOM 元素(不加井号,只能通过 document 关键字获取) NodeList 集合(DOM 变化后集合自动更新) HTMLCollection 集合(DOM 变化后集合自动更新) 获取父元素 子.parentNode单个 DOM 元素 获取子元素 父.childNodes父.childrenNodeList 集合,包括文本元素 HTMLCollection 集合,不包括文本元素 创建元素 document.createElement('')通过标签名凭空创造一个 DOM 元素 追加或移动元素 父.appendChild(子)追加 :若子元素本不存在,则表示追加,即追加到父元素内部的末尾移动 :若子元素本就存在,则表示移动,即从原来的位置移动到末尾插入元素 父.insertBefore(子 A, 子 B)将子元素 A 插入到子元素 B 之前 删除元素 父.removeChild(子)从父元素中删除子元素
武技 :开发 view/文档 - 元素操作.html 文件,并测试 JS 元素操作。
<button id ="btn01" type ="button" > 静态获取元素</button >
<button id ="btn02" type ="button" > 动态获取元素</button >
<button id ="btn03" type ="button" > 获取父元素</button >
<button id ="btn04" type ="button" > 获取子元素</button >
<button id ="btn05" type ="button" > 追加 2222 到末尾</button >
<button id ="btn06" type ="button" > 移动 2222 到末尾</button >
<button id ="btn07" type ="button" > 插入 0000 到头部</button >
<button id ="btn08" type ="button" > 删除末尾的元素</button >
<ul id ="items" >
<li id ="li1111" > 1111</li >
</ul >
onload = () => {
let btn01 = document .querySelector ('#btn01' );
let btn02 = document .querySelector ('#btn02' );
let btn03 = document .querySelector ('#btn03' );
let btn04 = document .querySelector ('#btn04' );
let btn05 = document .querySelector ('#btn05' );
let btn06 = document .querySelector ('#btn06' );
let btn07 = document .querySelector ('#btn07' );
let btn08 = document .querySelector ('#btn08' );
btn01.onclick = () => {
let items = document .querySelector ('#items' );
let lis = items.querySelectorAll ('li' );
items.innerHTML += `<li>2222</li>` ;
console .log ('length: ' + lis.length );
items.innerHTML += `<li>3333</li>` ;
console .log ('length: ' + lis.length );
items.innerHTML += `<li>4444</li>` ;
console .log ('length: ' + lis.length );
};
btn02.onclick = () => {
let items = document .getElementById ('items' );
let lis = items.getElementsByTagName ('li' );
items.innerHTML += `<li>2222</li>` ;
console .log ('length: ' + lis.length );
items.innerHTML += `<li>3333</li>` ;
console .log ('length: ' + lis.length );
items.innerHTML += `<li>4444</li>` ;
console .log ('length: ' + lis.length );
};
btn03.onclick = () => {
let items = document .querySelector ('#items' );
console .log (items.parentNode );
};
btn04.onclick = () => {
let items = document .querySelector ('#items' );
console .log ('childNodes' , items.childNodes );
console .log ('children' , items.children );
};
btn05.onclick = () => {
let items = document .querySelector ('#items' );
let li = document .createElement ('li' );
li.innerText = '2222' ;
items.appendChild (li);
};
btn06.onclick = () => {
let items = document .querySelector ('#items' );
let li2222 = document .createElement ('li' );
li2222.id = 'li2222' ;
li2222.innerText = '2222' ;
items.appendChild (li2222);
let li3333 = document .createElement ('li' );
li3333.id = 'li3333' ;
li3333.innerText = '3333' ;
items.appendChild (li3333);
items.appendChild (li2222);
};
btn07.onclick = () => {
let items = document .querySelector ('#items' );
let li1111 = document .querySelector ('#li1111' );
let li = document .createElement ('li' );
li.innerText = '0000' ;
items.insertBefore (li, li1111);
};
btn08.onclick = () => {
let items = document .querySelector ('#items' );
let li2222 = document .createElement ('li' );
li2222.id = 'li2222' ;
li2222.innerText = '2222' ;
items.appendChild (li2222);
let li3333 = document .createElement ('li' );
li3333.id = 'li3333' ;
li3333.innerText = '3333' ;
items.appendChild (li3333);
let lis = items.querySelectorAll ('li' );
items.removeChild (lis[lis.length - 1 ]);
};
};
E04. Array 数组
心法 :JavaScript 数组是 动态可变的有序集合 ,支持存储任意类型元素(数字、字符串、对象、函数等),但实际开发中建议存储同类型元素以提升代码可读性和性能。
数组创建的 4 种常用方式 :empty 是空占位符,不是 null 也不是 undefined,但访问时输出 undefined 结果,和 undefined 不同的是,遍历时 empty 会被跳过,而 undefined 不会:
数组创建方式 语法示例 示例结果 字面量创建(推荐) let arr = [1, 2, 3]let arr = []let arr = [1, 'a', true][1, 2, 3] [] [1, 'a', true] new Array(元素列表) let arr = new Array(1, 2, 3)[1, 2, 3] new Array(列表长度) let arr = new Array(3)[empty, empty, empty] Array.of(元素列表) let arr = Array.of(1, 2, 3)let arr = Array.of(3)[1, 2, 3] [3] Array.from(类数组) let arr = Array.from(arguments)对应参数组成的数组 Array.from(可迭代对象) let arr = Array.from('abc')let arr = Array.from(new Set([1,2,3]))let arr = Array.from(new Map([['a',1]]))let arr = Array.from({length:3})['a', 'b', 'c'] [1, 2, 3] ['a', 1] [undefined, undefined, undefined]
数组验证 Array.isArray(arr):判断 arr 是否是一个数组对象,返回布尔结果。
武技 :开发 view/基础 - 数组声明.html 页面,并测试 JS 数组声明。
const arr01 = ['a' , 'b' , 'c' ];
const arr02 = new Array (1 , 2 , 3 );
const arr03 = Array .of (3 );
const arr04 = Array .from ('hello' );
console .log ('通过字面量创建:' , arr01);
console .log ('通过 new Array() 创建:' , arr02);
console .log ('通过 Array.of() 创建:' , arr03);
console .log ('通过 Array.from() 创建:' , arr04);
console .log ('arr01 是否为数组:' , Array .isArray (arr01) ? '是' : '否' );
let result01 = '' ;
for (let i = 0 , j = arr01.length ; i < j; i++) {
result01 += i + ':' + arr01[i] + ' ' ;
}
console .log ('for-i 遍历:' , result01);
let result02 = '' ;
for (let i in arr01) {
result02 += i + ':' + arr01[i] + ' ' ;
}
console .log ('for-in 遍历:' , result02);
let result03 = '' ;
arr01.forEach (v => result03 += v + ' ' );
console .log ('forEach 遍历:' , result03);
let result04 = '' ;
arr01.forEach ((v, i ) => result04 += i + ':' + v + ' ' );
console .log ('forEach 遍历(带下标):' , result04);
1. Array 解构技巧
心法 :解构的意义在于快速从一个数组中获取一个或多个元素的值,解构过程中,多余的变量均赋值 undefined。
相关代码 描述 let [a, b] = arr将数组中的元素对位赋值给 a 和 b let [a = 3] = arr将数组 0 号位赋值给 a,若 0 号位不存在则将 3 赋值为 a let [ , , c] = arr将数组 2 号位赋值给 c let [a, [b, c], d] = arr支持多维数组对位解构 let [a, ...p] = arr将数组 0 号位赋值给 a,其余位依次赋给 p 数组
武技 :开发 view/基础 - 数组解构.html 页面,并测试 JS 数组解构。
let [a1, a2] = [1 , 2 , 3 , 4 ];
console .log (a1, a2);
let [b1 = 3 ] = [];
console .log (b1);
let [, , c3] = [1 , 2 , 3 , 4 ];
console .log (c3);
let [d1, [d21, d22], d3] = [1 , [11 , 12 ], 2 ];
console .log (d1, d21, d22, d3);
let [e1, ...e] = [1 , 2 , 3 , 4 ];
console .log (e1, e);
2. Array 常用方法 数组常用 API 方法 描述 返回值 arr.toString()将 arr 转为字符串,使用 , 分隔 拼接后的新数组 arr.join('-')将 arr 转为字符串,使用 自定义符号 分隔 拼接后的新数组 arr.concat(arr01)在 arr 末尾 拼接 arr01 数组 拼接后的新数组 arr.indexOf(e)arr.lastIndexOf(e)在 arr 中正方向查找元素 e( 正向寻找 ) 在 arr 中反方向查找元素 e( 反向寻找 ) 首现位置,不存在返回 -1 arr.map(e => {})让 arr 的每个元素依次进入函数进行 处理 处理后的新数组 arr.filter(e => {})让 arr 的每个元素依次进入函数进行 筛选 满足条件的新数组 arr.every(e => {})让 arr 的每个元素依次进入函数进行 判断 全部元素满足条件才返回 true 有一个元素不满足就返回 false arr.some(e => {})让 arr 的每个元素依次进入函数进行 判断 某个元素满足条件就返回 true 全部元素都不满足才返回 false arr.reduce((p1, p2) => {})arr.reduceRight((p1, p2) => {})让 arr 的每个元素依次进入函数进行 正向归约 让 arr 的每个元素依次进入函数进行 反向归约 归约流程: 1. 初始将数组的第一个元素赋值给 p1 2. 初始将数组的第二个元素赋值给 p2 3. 进入函数体进行数据处理 4. 每次都将处理的结果重新赋值给 p1 5. 读取数组的下一个元素并赋值给 p2 6. 继续重复处理,直到数组最后一个元素 整体归约完毕后的新数组
数组常用 API 方法 描述 返回值 arr.unshift(元素列表)在 arr 头部 添加 元素列表(整体添加,而非依次添加) 添加后的数组长度 arr.shift()从 arr 头部 删除 一个元素 被删除的那个元素 arr.push(元素列表)在 arr 尾部 添加 元素列表(整体添加,而非依次添加) 添加后的数组长度 arr.pop()从 arr 尾部 删除 一个元素 arr.splice(n, m, [元素列表])从 arr 的 n 号位(包括)开始,删 m 个元素,并插入元素列表 被删除的元素数组 arr.sort()arr.sort((a, b) => a - b)arr.sort((a, b) => b - a)将 arr 按字符串规则升序排序 将 arr 按数字大小升序排序(正数往前移,负数往后移,零不动) 将 arr 按数字大小降序排序(正数往前移,负数往后移,零不动) 排序后的数组
武技 :开发 view/基础 - 数组常用方法.html 页面,并测试 JS 数组常用方法。
console .log ('toString(): ' , ['a' , 'b' , 'c' , 'd' , 'e' ].toString ());
console .log ('join(): ' , ['a' , 'b' , 'c' , 'd' , 'e' ].join ('-' ));
console .log ('concat(): ' , ['a' , 'b' ].concat (['c' , 'd' ]));
console .log ('indexOf(): ' , ['a' , 'p' , 'p' , 'l' , 'e' ].indexOf ('p' ));
console .log ('lastIndexOf(): ' , ['a' , 'p' , 'p' , 'l' , 'e' ].lastIndexOf ('p' ));
console .log ('map(): ' , [1 , 3 , 5 , 7 , 9 ].map (e => e * 2 ));
console .log ('filter(): ' , [1 , 3 , 5 , 7 , 9 ].filter (e => e > 3 ));
console .log ('every(): ' , [1 , 3 , 5 , 7 , 9 ].every (e => e > 3 ));
console .log ('some(): ' , [1 , 3 , 5 , 7 , 9 ].some (e => e > 6 ));
console .log ('reduce(): ' , [1 , 3 , 5 , 7 , 9 ].reduce ((a, b ) => {
console .log ('a =' , a, ', b =' , b);
return a - b;
}));
console .log ('reduceRight(): ' , [1 , 3 , 5 , 7 , 9 ].reduceRight ((a, b ) => {
console .log ('a =' , a, ', b =' , b);
return a - b;
}));
let arr;
arr = ['c' , 'd' ];
console .log ('unshift(): ' , arr.unshift ('a' , 'b' ), arr.toString ());
arr = ['a' , 'b' ];
console .log ('shift(): ' , arr.shift (), arr.toString ());
arr = ['a' , 'b' ];
console .log ('push(): ' , arr.push ('c' , 'd' ), arr.toString ());
arr = ['a' , 'b' ];
console .log ('pop(): ' , arr.pop (), arr.toString ());
arr = ['a' , 'd' ];
console .log ('splice-insert(): ' , arr.splice (1 , 0 , 'b' , 'c' ), arr.toString ());
arr = ['a' , 'x' , 'y' , 'd' ];
console .log ('splice-update(): ' , arr.splice (1 , 2 , 'b' , 'c' ), arr.toString ());
arr = ['a' , 'x' , 'y' , 'b' ];
console .log ('splice-delete(): ' , arr.splice (1 , 2 ), arr.toString ());
arr = [1 , 3 , 5 , 2 , 11 ];
console .log ('sort-string(): ' , arr.sort (), arr.toString ());
console .log ('sort-number-asc(): ' , arr.sort ((a, b ) => a - b), arr.toString ());
console .log ('sort-number-desc(): ' , arr.sort ((a, b ) => b - a), arr.toString ());
E05. JSON 对象
心法 :JSON 全称 JavaScript Object Notation,是一种轻量级的,相对无序的数据交换语言,通过 键值对 的格式存储数据,可以单独封装成 JSON 文件(该文件必须是 UTF-8 编码且不支持编写任何注释)。
相关代码 描述 let user = {'k1': v1, 'k2': v2 .. }每个键值对的 KEY 值必须用单引号或双引号包裹 user['k']按 KEY 取值,不存在返回 undefined user['k'] = v按 KEY 修改,不存在视为添加操作 delete user['k']按 KEY 删除 user.hasOwnProperty('k')true 表示 k 是自己定义的,false 表示 k 是是继承下来的
武技 :开发 view/基础-JSON 声明.html 页面,并测试 JSON 声明。
let user = {'id' : 1 , 'name' : '赵四' , 'gender' : '男' , 'hobby' : ['抽烟' , '喝酒' ]};
console .log (user['id' ], user['name' ], user['gender' ], user['hobby' ].toString ());
user['age' ] = 28 ;
console .log ('新添加的 JSON 项' , user['age' ]);
user['age' ] = 29 ;
console .log ('修改后的 JSON 项' , user['age' ]);
delete user['gender' ];
console .log ('删除后的 JSON 项' , user['gender' ]);
for (let key in user) {
if (user.hasOwnProperty (key)) {
console .log (key, user[key]);
}
}
1. JSON 解构技巧
心法 :解构的意义在于快速从一个 JSON 中获取一个或多个元素的 value 值,解构过程中,多余的变量均赋值 undefined。
相关 API 描述 let {id, age} = user将 JSON 中的元素按 KEY 名对位赋值给 id 和 age 变量 let {password:pwd} = user将 JSON 中 password 项赋值给 pwd 变量 let {age = 9} = user将 JSON 中 age 项赋值给 age 变量,若 age 项不存在则赋默认值 9
武技 :开发 view/基础-JSON 解构.html 页面,并测试 JSON 解构。
let user = {'id' : 1 , 'name' : '赵四' , 'gender' : '男' , 'hobby' : ['抽烟' , '喝酒' ]};
let {id, name} = user;
console .log ('id' , id);
console .log ('name' , name);
let {hobby : aiHao} = user;
console .log ('aiHao' , aiHao.toString ());
let {sal = 5000 } = user;
console .log ('sal' , sal);
2. JSON 常用方法
心法 :JSON 和数组均可以执行 序列化 和 反序列化 操作。
方法 描述 let str = JSON.stringify(json)将 JSON 对象的 全部属性序列化 为字符串 let str = JSON.stringify(json, [id, age])将 JSON 对象的 指定属性序列化 为字符串 let json = JSON.parse(str)将字符串 反序列 化成 JSON 对象,要求改字符串严格满足 JSON 格式
武技 :开发 view/基础-JSON 方法.html 页面,并测试 JSON 常用方法。
let user = {'id' : 1 , 'name' : '赵四' , 'gender' : '男' , 'hobby' : ['抽烟' , '喝酒' ]};
console .log ("全部属性序列化" , JSON .stringify (user));
console .log ("部分属性序列化" , JSON .stringify (user, ['name' , 'gender' ]));
console .log ("反序列化" , JSON .parse ('{"name": "赵四", "gender": "男"}' ));
E06. 数据存储
心法 :JS 在客户端存储数据主要有 Cookie、sessionStorage、localStorage 三种方案,三者均遵循同名覆盖规则,且存储的值 仅支持字符串类型 ,若需要存储对象或数组,需先通过 JSON.stringify() 序列化,读取时用 JSON.parse() 反序列化即可。
1. Cookie 存储
心法 :cookie 默认是 会话级别 的客户端存值方案(浏览器关闭后失效),若手动设置过期时间(Expires/Max-Age),则在过期时间内,即使关闭浏览器 / 电脑,该 Cookie 值也会持续有效。
传输机制 :客户端每次向服务端发送 HTTP 请求时,会自动将当前域名下的 Cookie 数据携带到请求头中提交给服务端,服务端也可通过响应头 Set-Cookie 向客户端写入或修改 Cookie 的值。
大小限制 :不同浏览器略有差异,通常单个域名下最多存储 20+ 个 Cookie(非全局 200 个),单个 Cookie 最大约 4KB。
相关代码 描述 document.cookie='k=v'存值,同名覆盖,默认过期时间为当前会话 document.cookie='k=v;expires=过期时间'存值,同名覆盖,指定过期时间 document.cookie='k=v;expires=-1'存储,同名覆盖,指定过期时间为当前会话 document.cookie返回包含全部 cookie 的字符串,获取单个值需要自行按 ; 切割
武技 :开发 view/存储-cookie.html 页面,并测试 cookie 操作。
document .cookie = `id=1` ;
document .cookie = `name=zhaosi` ;
let now = new Date ();
now.setDate (now.getDate () + 2 );
document .cookie = `info=亚洲舞王;expires=${now} ` ;
document .cookie = `hobby=唱歌;expires=Thu, 1 Jan 2027 00:00:00 GMT` ;
document .cookie = `id=2` ;
console .log ('cookie' , document .cookie );
document .cookie .split ('; ' ).forEach (e => {
let arr = e.split ('=' );
console .log (arr[0 ], arr[1 ]);
});
在浏览器开发者工具中查看 cookie 过期时间 :
2. 封装 CookieUtil 工具 方法 描述 setCookie(key, val, eDay = 1)向 Cookie 中添加一条指定条目,默认 1 天后过期 getCookie(key)从 Cookie 中按 KEY 取值 delCookie(key)在 Cookie 中按 KEY 删值
开发 util/cookie-util.js 工具文件:
function setCookie (key, val, eDay ) {
let result = false ;
if (null === key || null === val) return false ;
if (null === eDay || undefined === eDay) {
document .cookie = `${key} =${val} ` ;
}
else {
let now = new Date ();
now.setDate (now.getDate () + eDay);
document .cookie = `${key} =${val} ;expires=${now} ` ;
}
result = true ;
return result;
}
function getCookie (key ) {
let result = null ;
if (null === key) return null ;
document .cookie .split ('; ' ).forEach (e => {
let kvs = e.split ('=' );
if (kvs[0 ] === key) {
result = kvs[1 ];
}
});
return result;
}
function delCookie (key ) {
if (null === getCookie (key)) return false ;
return setCookie (key, '' , -1 );
}
测试 util/cookie-util.js 工具文件:
<!DOCTYPE html >
<html lang ="en" >
<head >
<meta charset ="UTF-8" >
<title > cookie-util</title >
</head >
<body >
<button id ="set-btn" type ="button" > 设置 cookie</button >
<button id ="get-btn" type ="button" > 获取 cookie</button >
<button id ="del-btn" type ="button" > 删除 cookie</button >
<script src ="../script/cookie-util.js" > </script >
<script >
onload = () => {
let setBtn = document .querySelector ('#set-btn' );
let getBtn = document .querySelector ('#get-btn' );
let delBtn = document .querySelector ('#del-btn' );
setBtn.onclick = () => {
setCookie ('name' , 'zhaosi' );
setCookie ('age' , '18' );
setCookie ('gender' , '男' );
setCookie ('hobby' , '唱歌' , 2 );
};
getBtn.onclick = () => console .log (getCookie ('name' ));
delBtn.onclick = () => delCookie ('name' );
};
</script >
</body >
</html >
3. SessionStorage 存储
心法 :sessionStorage 是 会话级别 的客户端存储方案,仅在当前浏览器标签页的会话中有效,当标签页关闭或浏览器退出后,数据会自动删除,它不支持手动设置过期时间,且 不同标签页间不共享 (即使同域名)。
传输机制 :仅存储在客户端,不会随 HTTP 请求自动提交到服务端。
大小限制 :单个域名下约 5MB(不同浏览器略有差异)。
作用域 :仅当前标签页有效,同域名的其他标签页无法访问。
相关方法 简述 详述 sessionStorage.setItem('k', 'v')存值 向 sessionStorage 中存储一个键值对 sessionStorage.getItem('k')取值 从 sessionStorage 中按 KEY 取值 sessionStorage.removeItem('k')删除 在 sessionStorage 中按 KEY 删值 sessionStorage.clear()清空 清空 sessionStorage 中的全部内容
武技 :开发 view/存储-sessionStorage.html 页面,并测试 sessionStorage 操作。
sessionStorage .clear ();
sessionStorage .setItem ('id' , '1' );
sessionStorage .setItem ('username' , 'joezhou' );
console .log ('id' , sessionStorage .getItem ('id' ));
console .log ('username' , sessionStorage .getItem ('username' ));
sessionStorage .removeItem ('id' );
console .log ('id' , sessionStorage .getItem ('id' ));
console .log ('username' , sessionStorage .getItem ('username' ));
在浏览器开发者工具中查看 sessionStorage 存储情况 :
4. LocalStorage 存储
心法 :localStorage 是 本地持久化 的客户端存储方案,数据存储在浏览器本地文件中,除非手动删除,否则永久存在(即使关闭浏览器或电脑),它不支持手动设置过期时间,需通过代码模拟过期逻辑。
传输机制 :仅存储在客户端,不会随 HTTP 请求自动提交到服务端。
大小限制 :单个域名下约 5MB(不同浏览器略有差异)。
作用域 :同域名下的所有标签页或窗口共享,跨会话持久化。
相关方法 简述 详述 localStorage.setItem('k', 'v')存值 向 localStorage 中存储一个键值对 localStorage.getItem('k')取值 从 localStorage 中按 KEY 取值 localStorage.removeItem('k')删除 在 localStorage 中按 KEY 删值 localStorage.clear()清空 清空 localStorage 中的全部内容
武技 :开发 view/存储-localStorage.html 页面,并测试 localStorage 操作。
localStorage .clear ();
localStorage .setItem ('id' , '1' );
localStorage .setItem ('username' , 'joezhou' );
console .log ('id' , localStorage .getItem ('id' ));
console .log ('username' , localStorage .getItem ('username' ));
localStorage .removeItem ('id' );
console .log ('id' , localStorage .getItem ('id' ));
console .log ('username' , localStorage .getItem ('username' ));
在浏览器开发者工具中查看 localStorage 存储情况 :
相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online