JavaScript
重点集结
【了解】了解什么是JavaScript
【了解】为什么要学JavaScript
【掌握】掌握JavaScript的组成
【掌握】掌握在HTML中使用JavaScript
【掌握】掌握ECMAScript语法结构
【掌握】掌握ECMAScript常见内置对象
【了解】什么是浏览器对象模型
【了解】什么是文档对象模型
【掌握】掌握常用window对象函数
【了解】基本浏览器对象
【掌握】掌握文档对象模型结构以及相关操作
【掌握】掌握正则表达式实现表单验证
【掌握】掌握Promise的使用
一、初识JavaScript
官网: https://www.w3.org/standards/webdesign/script
说明:
JavaScript语法规范是ECMAScript,ECMAScript由ECMA国际(前身European Computer Manufacturers Association 欧洲计算机制造商协会)设计,但是其中的浏览器API由W3C进行维护。
ECMA标准列表: https://www.ecma-international.org/publications/standards/Stnindex.htm
ECMAScript标准: https://www.ecma-international.org/publications/standards/Ecma-262.htm
ECMAScript标准内容: https://www.ecma-international.org/ecma-262/11.0/index.html
JavaScript推荐教程:
英文: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/First_steps中文: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference
W3School JavaScript资料 : https://www.w3school.com.cn/js/index.asp
菜鸟教程 JS资料:https://www.runoob.com/js/js-tutorial.html
ES6参考书:https://es6.ruanyifeng.com/
1.1 什么是JavaScript
JavaScript和Java没有任何关系。
JavaScript(缩写:JS)是一门完备的动态编程语言。当应用于 HTML 文档时,可为网站提供动态交互特性。
JavaScript 是一种脚本,一门编程语言,它可以在网页上实现复杂的功能,网页展现给你的不再是简单的静态信息,而是实时的内容更新,交互式的地图,2D/3D 动画,滚动播放的视频等等。
JavaScript 是一种脚本语言,可以用来创建动态更新的内容,控制多媒体,制作图像动画,还有很多。
特点:
是一种轻量级解释性语言,边解释便执行(对比:Java语言执行→编写Java代码,编译成class字节码,通过虚拟机加载运行)
是一种弱类型语言:声明变量不能使用具体的数据类型,变量的数据类型由值决定。(Java声明变量必须有具体的数据类型)
通常用来HTML网页中,用来处理与用户的交互。
脚本语言:
在运行之前不需要预处理的程序语言。通常由语言的解析引擎来解释执行。
说明:
JavaScript很多场景下简称为js
1.2 为什么要学习JavaScript
- 用于表单验证
- 用于检验数据的合法性,避免错误数据的产生
- 用于减轻服务器的压力
- 用于页面的交互特效
- 常见的页面动画效果
- 软件业务要求的处理
- jQuery、Vue.js、React.js、微信小程序等等的学习基础
- 因为其是脚本语言,所以它还可以用于游戏的编写
二、JavaScript的组成
- ECMAScript:语法规范标准,现在常用的语法规范标准是ES6版本。
- 变量
- 数据类型
- 运算符
- 程序逻辑:顺序结构,分支结构(条件结构),循环结构
- 数组、函数
- 对象
- 关键字,保留字
- BOM对象:(Brower Object Model)浏览器对象模型,提供了与浏览器交互通信。(面试常问)
- DOM对象:(Document Object Model)文档对象模型,用来访问和操作HTML文档。(面试常问)
三、ECMAScript的语法
3.1 使用JavaScript的方式
在HTML中使用JS脚本的三种方式
3.1.1 嵌入式:
内部JavaScript(Internal JavaScript):通过在页面中使用
<script type="text/javascript">
// 书写JS代码(在控制台显示内容)
console.log('Hello World!!!')
// 书写JS代码(在页面显示内容)
document.write('Hello World!!!');
</script>
3.1.2 外部文件引入(External JavaScript):
通过页面中使用
<!-- 引入外部自定义js文件 -->
<script type="text/javascript" src="./js/index.js"></script>
3.1.3 事件定义方式(Inline JavaScript handlers):
通过在页面标签中添加事件属性,书写JS脚本(不推荐)
<button onclick="console.log('你点了我')">点我</button>
3.2 变量(熟记)
官方地址:https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/First_steps/Variables
- 变量的命名规则
- 首字符:只能使用 字母、下划线(_)、美元符号($)
- 其余部分:只能使用 字母、下划线(_)、美元符号($)和数字
- 不能使用关键字和保留字(ES6关键字和保留字:http://wiki.xuetang9.com/?p=7476)
- 变量的命名规范
- 使用驼峰命名:第一个单词的首字母小写,其余单词的首字母大写
- 不建议使用单个字母作为变量名,取名要语义化。见名知意。
- 变量的使用步骤
- 声明变量
- 变量赋值
- 使用变量
3.2.1 var声明变量
JavaScript是一种弱类型语言,没有明确的数据类型
在声明变量时,不需要指定变量类型,变量的类型由赋给变量的值决定
我们每一行代码结尾都是使用了;号表示一行代码的结束,在非严格要求下是可以不写;号的,推荐加上
//先声明后赋值
var number;
number = 20;
//声明并赋值
var name = "Jack";
var weight = 120,height = 175;
//不声明直接赋值(不允许使用)
count = 1000;
// 在ES5中没有赋值的变量默认值为 undefined
var age;
console.log(age);
// ES5变量提升(不允许使用)
console.log(sex);
var sex = 12;
3.2.2 let声明变量
ES6.0 新增了let命令,用来声明变量,它的用法类似于var,let与var的作用域不同且不会变量提升
//ES6作用域不同
{
var num1 = 1;
let num2 = 2;
}
console.log(num1);//输出1
console.log(num2);//异常
//ES6没有变量提升
console.log(sex);
let sex = 12;
3.3 常量(熟记)
使用const关键字定义常量。常量不能再次赋值。通常常量名使用全大写,多个单词使用下划线连接。
// 定义常量
const DAYS = 7;
const ADD_USER_INFO;
// 常量不能再次赋值
DAYS ++; //Uncaught TypeError: Assignment to constant variable.
// 常量在定义时必须赋值
const FOO; //SyntaxError: Missing initializer in const declaration
3.4 数据类型(熟记)
尽管在声明变量时不需要声明变量的数据类型,这并不代表JavaScript中没有数据类型,它由赋给变量的值决定。在JavaScript中,提供了常用的基本数据类型
3.4.1 5种简单数据类型
类型 | 说明 |
---|---|
number | 数值,包括整数浮点数 |
string | 字符串,使用单引号或者双引号包裹 |
boolean | boolean类型,0为false,非零为true |
null | 空,表示没有任何值的指向。认为null是一种特殊的object |
undefined | 未赋值,表示未赋值的变量 |
3.4.2 复杂的数据类型
类型 | 说明 |
---|---|
Object | 对象 |
Function | 函数 |
Array | 数组,存储多个值(特殊的对象) |
判断数据类型:使用 typeof 获取类型
示例:
console.log(1,typeof 1); // number
console.log('123',typeof '123'); // string
console.log(true,typeof true); // boolean
console.log(null,typeof null); // object
console.log(undefined,typeof age);// age未定义,或者没有初始化 ,undefined
console.log({},typeof {}); // object
console.log(function(){},typeof function(){}); // function
console.log([],typeof []); // object
3.4 运算符(熟记)
3.4.1算数运算符
+、-、 *、 /、 %、**、++、--
说明
两个数字不能计算时:结果为 NAN。
除0的时候:结果Infinity。表示无限大
在JavaScript中
**
表示指数运算
console.log('加法运算:%d',1 + 2);
console.log('减法运算:%d',20 - 58);
console.log('乘法运算:%d',5 * 6);
console.log('除法运算:%f',60 / 7);
console.log('取模运算:%d',3000 % 67);
let num1 = 100,num2 = 80;
console.log('数字++:%d',num1++);
console.log('数字++之后:%d',num1);
console.log('++数字:%d',++num2);
let num3 = 50,num4 = 30;
console.log('数字--:%d',num3--);
console.log('数字--之后:%d',num3);
console.log('--数字:%d',--num4);
3.4.2 关系运算符(比较运算符)
>、< 、>= 、<=、==、!=、===、!==
说明
=、! 表示恒等或恒不等,比较过程中会比较数据的类型
3.4.3 逻辑运算符
! 、&&、||
- 逻辑或:通常用于赋默认值。
3.4.4 赋值运算符:
= 、+= 、-=、*= 、/= 、%= 、**=
3.5 程序逻辑(熟记)
3.5.1 顺序
一般情况下都是同步逻辑,即从上至下依次执行代码。后续我们会接触到异步逻辑,其逻辑会延迟等待服务器响应后才会继续执行。
3.5.2 分支
- if-[else if]-else
说明:
- 基础的条件结构
- ES中依旧支持三元运算符
- 配合逻辑运算符使用:
- &&:多个条件同时为true,则返回true,任意一个条件为false,则返回false
- ||:任一一个条件为true,则返回true,否则,返回false
- !:非运算符,表示取反条件,若原条件为true,则返回false,反之返回true
示例:
四川话中形容男的胖叫闷得儿,女的胖叫丰满,男的瘦叫干心儿,女的瘦叫苗条
国际标准体重的计算zd方法是男性标准体重=(身高cm-80)×70﹪,女性标准体重=(身高cm-70)×60﹪。标准体重正负10﹪为正常体重,标准体重正负10﹪~ 20﹪为体重过重或过轻,标准体重正负20﹪以上为肥胖或体重不足
prompt()方法,其作用是弹出一个输入提示框,用于接收用户输入的内容
let sex = prompt('请输入您的性别(男/女)');
if(sex === '男'){
let height = prompt('先生,请输入您的身高(cm)');
let weight = prompt('先生,请输入您的体重(kg)');
let standard = (height - 80) * 0.7; //计算男士的标准体重
if(weight > standard * 1.2) {
alert('闷得儿- 。-!');
}else if(weight < standard * 0.8) {
alert('干心儿- 。-!');
}else {
alert('标准身材!!');
}
}else if(sex === '女') {
let height = prompt('女士,请输入您的身高(cm)');
let weight = prompt('女士,请输入您的体重(kg)');
let standard = (height - 70) * 0.6; //计算女士的标准体重
if(weight > standard * 1.2) {
alert('丰满!!');
}else if(weight < standard * 0.8) {
alert('苗条!!');
}else {
alert('标准身材!!');
}
}else {
alert('输入的不是性别,自动结束');
}
- switch-case
语法:
switch(表达式或变量) {
case a:
代码块
break;
case b:
代码块
break;
default:
默认代码块
}
说明:
横值判断的条件结构
如果一个case末尾没有写break,那么在当前case的逻辑执行完毕后,会继续执行紧靠的下一个case中的逻辑
示例:
let constellation = prompt('请输入您的星座');
switch (constellation) {
case '白羊座':
alert('白羊座是十二宫第一个星座,白羊们乐观开朗,活泼可爱,性格上也大大咧咧,给人一中看上去就非常愉悦的感觉,这是上天赋予他们的天赋,总是那么的热情、阳光、率真。白羊对朋友也非常的仗义,爱恨分明,慷慨大方,虽然有些时候会有一点脾气,但是谁还没有二两脾气呢?和白羊座交朋友,他们会给你带来无限的欢声笑语,让你永远在祥和的气氛中生活。');
break;
case '金牛座':
alert('踏实、稳健的金牛座是一个保守的星座,他们喜欢安定的生活,性格上属于慢热型,无论是工作、生活,他们都需要一段时间的适应。财富是金牛座与生俱来的特质,他们在投资方面有着独到的眼光,金牛座对恋人的格言是:我负责挣钱养家,你只需负责貌美如花。而且金牛座对美食也有着很高的鉴赏水平,喜欢宁静的环境,喜欢一切美好的事物。');
break;
case '双子座':
alert('双子座不会拒绝任何新鲜的事物,好奇的双子座有着极高的情商,和双子座聊天永远不会让你感觉寂寞,聪明的小脑袋里装满都是新鲜和古灵精怪的东西,这也让双子座有着更多的朋友。双子座如果想带你去一个地方玩的话,他会把这个地方说成人间仙境一般,甚至都不落下一个细节。双子总是给人一种花心的感觉,实际上双子只是喜欢新鲜事物,而且一直追求着。');
break;
default:
alert('其他星座');
}
3.5.3 循环
- while
只要条件为 true,循环结构中的代码块能够一直重复执行
语法:
while (条件) {
要执行的代码块
}
- do-while
是 while 循环的变体。在检查条件是否为真之前,这种循环会执行一次代码块,然后只要条件为真就会重复循环
语法:
do {
要执行的代码块
} while (条件);
- for
假如您需要运行代码多次,且每次使用不同的值,那么循环for相当方便使用
语法:
for (语句 1; 语句 2; 语句 3) {
要执行的代码块
}
示例
斐波那契数列:由意大利数学家列昂纳多·斐波那契发明,这个数列从第三项开始,每一项都等于前两项之和,如:1、1、2、3、5、8……
现在我们用for循环来输出前50位斐波那契数列的值
let str = "";
let one = 1,two = 1; //记录前两个数
let num = 50; //要输出的总数
for(let i = 1;i <= num; i++) {
if(i >= 3) {
let end = one + two; //先计算当前数的值
one = two; //将第二个数的值赋值给第一个数
two = end; //将新的值赋值给第二个数
if(i === 50) {
str += end;
}else {
str += end + '、';
}
}else {
str += 1 + '、';
}
}
console.log(str);
- 结束循环的方式
break:终止整个循环,让逻辑往后继续
continue:跳过本次循环,继续后续的循环
return:它只能放在函数中,其作用是跳出整个函数逻辑,相当于循环也结束了
3.6 函数编程
3.6.1 概念(熟记)
函数 允许你在定义的区块内存储一段代码用来执行一个单独的任务,然后调用该段代码时,你需要使用一个简短的命令,而不用重复编写多次该段代码。
函数与方法
方法是在对象内定义的函数 , 参考链接 https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/Building_blocks/Functions
3.6.2 函数语法(熟记)
function 函数名(参数1,参数2...) {
// 代码
[return [返回值];]
}
说明
- 普通函数名规则与规范遵守变量命名规则规范,作为构造函数时使用帕斯卡命名规范(后续讲解)
- 因为JavaScript本身是弱类型,所以它的参数也没有类型检查和类型限定。函数中的参数是可选的,根据函数是否需要带参,可分为不带参的无参函数和有参函数
- 参数列表的多个参数使用逗号隔开,例如
(name,age)
,且参数名不能相同- return语句用来规定函数的返回值,当然函数不一定需要返回值
匿名函数:
使用function定义,function关键字后没有名称时,称为匿名函数
let 函数名 = function(参数1,参数2...){
...
}
3.6.3 调用语法(熟记)
要执行一个函数,必须先调用这个函数,当调用函数时,必须指定函数名以及后面的参数(如果是有参函数)
函数名(实参列表);
3.6.4 自执行函数(了解)
直接执行匿名函数,无需通过额外的方式调用
//1 可以使用开头
!function(形参列表){
//alert(形参列表);
}(实参列表);
//2 使用()将函数及函数后的括号包裹
(function(){}());
//3 使用()值包裹函数值(无法表明函数与之后的()的整体性,不推荐使用)
(function(){})();
3.6.5 参数的默认值(熟记)
function log(x, y = 'World') {
console.log(x, y);
}
3.6.6 扩展参数rest(了解)
用于获取函数的多余参数。rest参数搭配的变量是一个数组,该变量将多余的参数放入数组中
rest 参数之后不能再有其他参数(即只能是最后一个参数)
function push(...items) {
console.log(items);
}
push(1, 2, 3);
3.6.7 解构(了解)
ES6可以从数组中提取值,按照对应位置,对变量赋值
let [a, b, c] = [1, 2, 3];
console.log(a);
let [ , , z] = ["a", "b", "c"];
console.log(z);
let [head, ...tail] = [1, 2, 3, 4];
console.log(head);
console.log(tail);
let [foo = true] = [];
3.6.8 闭包(了解)
词法作用域:词法作用域根据源代码中声明变量的位置来确定该变量在何处可用。嵌套函数可访问声明于它们外部作用域的变量
function init() {
let name = "老九学堂"; // name 是一个被 init 创建的局部变量
function displayName() { // displayName() 是内部函数,一个闭包
alert(name); // 使用了父函数中声明的变量
}
displayName();
}
基础用法:
function welcomeFunc() {
let text = "老九学堂欢迎大家";
return function () {
alert(text);
}
}
let myFunc = welcomeFunc();
myFunc();
进阶用法:
function addFunc(x) {
return function(y) {
return x + y;
};
}
let add5 = addFunc(5);
let add10 = addFunc(10);
console.log(add5(2)); // 7
console.log(add10(2)); // 12
3.7 箭头函数定义(熟记)
箭头函数语法比函数表达式更简洁,但是它没有自己的this
基本语法:
3.7.1 多个参数时
//普通函数
function f(参数1, 参数2,..., 参数N){
//内部逻辑
}
//箭头函数
(参数1, 参数2, ..., 参数N) => {
//内部逻辑
}
3.7.2 单个参数时
//普通函数
function f(参数1) {
//内部逻辑
}
//箭头函数
参数1 => {
//内部逻辑
}
3.7.3 无参数时
//普通函数
function f() {
//内部逻辑
}
//箭头函数
() => {
//内部逻辑
}
3.7.4 返回一个单行表达式
//普通函数
function f() {
return 表达式;
}
//箭头函数
() => 表达式;
3.7.5 返回对象
//普通函数
function f(参数1, 参数2,..., 参数N) {
return {
属性名: 值,
...
}
}
//箭头函数
(参数1, 参数2,..., 参数N) => ({
属性名: 值,
...
});
3.8 对象
3.8.1 自定义对象(熟记)
- 自定义对象方式:
let 对象名 = {
属性名:值,
...
}
属性的值可以是任何数据类型,包括其它对象、函数
- 为对象赋值或者添加新的属性并赋值
对象名.属性名 = 值;
对象名.新属性名 = 值; // 新属性名在对象的大括号中没有定义
对象名[属性名字符串] = 值; //该方式常用于动态设置属性,因为[]中可以是变量
- 对象取值
let 变量名 = 对象名.属性名;
let 变量名 = 对象名[属性名字符串];
- in运算符:查看对象的某个属性是否存在
let 变量名 = "属性名" in 对象名;
- delete操作符:删除对象的某个属性
delete 对象名.属性名;
3.8.2 遍历对象方式
- for-in:遍历对象属性
迭代获取对象属性名称
// 创建对象
let section = {
id:375,
name:'官方公告区',
iconPath:'../imgs/notic.png',
description:'官方发布公告的内容'
};
// 迭代对象
for(let propertyName in section){
console.log(propertyName+":"+section[propertyName]);
}
- for-of:遍历对象数组
遍历对象数组中的每个对象(类似于java中的foreach结构)
for(let sectionName of sections){
console.log(sectionName);
}
3.8.3 this关键字
在function定义的函数中,this关键字指代函数的调用对象
var name = 'window';
function show(){
console.log(this);
console.log(this.name);
}
show(); //一次调用
function show2(){
show(); //二次调用
}
show2();
//对象隐式绑定
var obj = {
name: 'obj',
show: show //对show方法进行引用
}
obj.show();
//显示绑定
show.apply(obj);
show.call(obj);
show.bind(obj)();
箭头函数的this是函数被创建时绑定的,它指向当前词法作用域中的this
- 自身没有this
- 不会因被怎么样的方式调用改变绑定
var str = 'window';
const obj = {
str:'obj',
nativeFn: function(){
console.log(this.str, '当前词法作用域中的this');
return function(){
console.log('原生函数',this.str);
}
},
arrowFn: function(){
console.log(this.str, '当前词法作用域中的this');
return ()=>{
console.log('箭头函数',this.str);
}
}
};
const obj2 = { str: 'obj2'};
var nativeFn = obj.nativeFn();
var arrowFn = obj.arrowFn();
console.log('函数调用一 **********');
nativeFn();
arrowFn();
console.log('函数调用二 **********');
nativeFn.call(obj2);
arrowFn.call(obj2);
console.log('函数调用三 **********');
setTimeout(function(){
nativeFn();
arrowFn();
},50);
3.9 内置对象(熟记)
3.9.1 String
- 构造函数
构造函数 | 说明 |
---|---|
String() | 无参构造创建字符串对象 |
String(字符串) | 通过带参构造创建字符串对象 |
ES中主要使用单引号或者双引号创建字符串对象,注意使用引号创建的字符串属于’string’类型,但是使用new String()创建的对象属于’object’类型
- 属性与方法
几乎java字符串有的方法在ES的内置对象String中都有
类别 | 名称 | 说明 |
---|---|---|
属性 | length | 获取字符串长度 |
方法 | charAt(索引) | 获取指定索引字符 |
方法 | indexOf(查找字符串) | 获取指定值在字符串中首次发现所在索引,未找到返回-1 |
方法 | split(字符) | 按照指定的字符进行分割形成字符串数组 |
方法 | slice(起点,终点) | 获取指定索引的字符串,不包含终点(终点索引不能比起点小) |
方法 | substr(起点,长度) | 获取指定索引,指定个数字符组成的字符串 |
方法 | substring(起点,终点) | 获取两个指定索引之间的字符串(终点索引可以比起点小) |
方法 | toLowerCase()/toUperCase() | 将字符串转换为小写/大写 |
方法 | replace(目标字符串,新字符串) | 将字符串中指定内容替换为新字符串内容(支持正则表达式) |
let message = "JavaScript 的标准是 ECMAScript 。截至 2012 年,所有的现代浏览器都完整的支持 ECMAScript 5.1,旧版本的浏览器至少支持 ECMAScript 3 标准。2015年6月17日,ECMA国际组织发布了 ECMAScript 的第六版,该版本正式名称为 ECMAScript 2015,但通常被称为 ECMAScript 6 或者 ES6。自此,ECMAScript 每年发布一次新标准。";
//获取字符串长度
console.log(message.length);
//获取指定索引字符
console.log(message.charAt(5));
//获取首个指定字符串所在的索引位置
console.log(message.indexOf('ECMAScript'));
//拆分
console.log(message.split('。'));
//获取指定索引的字符串,不包含终点(终点索引不能比起点小)
console.log(message.slice(3,5));
//获取指定索引,指定个数字符组成的字符串
console.log(message.substr(3,5));
//获取两个指定索引之间的字符串(终点索引可以比起点小)
console.log(message.substring(3,0));
//将字符串转换为小写
console.log(message.toLocaleLowerCase());
//将字符串转换为大写
console.log(message.toLocaleUpperCase());
//普通文本替换
console.log(message.replace('微博','***'));
//正则表达式替换
console.log(message.replace(/微博/g,'***'));
- 模板字符串
模板字符串(template string)是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量(需要将变量名写在${}之中)
它是增强版的字符串,因此它同样可以使用上面的属性和方法
let name = '使命召唤手游'; //游戏名称
let company = '腾讯'; //厂商
let description = '周杰伦助阵代言,TGA最佳移动游戏,《使命召唤手游》终于在战士们的期待声中于2020年12月25日强势登场。作为使命召唤系列在移动端的延续,我们在努力还原经典玩法地图角色的同时,还结合手机端的操作特点进行了适配优化。同时,我们也针对大家反馈的匹配机制、枪械平衡、配音特效等问题进行了调整,希望给战士们带来最优质的游戏体验。';
//字符串拼接方式,繁杂且容易出错
document.write(
'<h4>游戏名称:' + name + '</h4>' +
'<h6>厂商:' + company + '</h6>' +
'<p>' + description + '</p>'
);
//模板字符串方式,简单,不易出错
document.write(`
<h4>游戏名称:${name}</h4>
<h6>厂商:${company}</h6>
<p>${description}</p>
`)
3.9.2 Array
- 构造函数
构造函数 | 说明 |
---|---|
Array() | 创建空数组 |
Array(长度) | 创建指定空间数组 |
Array(元素列表) | 根据传入的元素个数创建数组 |
说明:
在ES中使用主要中括号方式创建数组
- 属性与方法
类别 | 名称 | 说明 |
---|---|---|
属性 | length | 设置或返回数组中元素的数目 |
方法 | 数组[索引] | 访问数组指定索引元素 |
方法 | join(分割符) | 把数组所有元素放入一个字符串, 通过一个分割符进行分割(不适用于对象数组) |
方法 | push(元素) | 向数组末尾添加一个或多个元素,并返回新的数组长度 |
方法 | pop() | 移除并返回数组最后一个元素 |
方法 | splice(索引,删除个数,添加元素列表) | 从数组中的指定索引位置,添加或删除指定数量的元素 |
方法 | indexOf(元素) | 获取对应元素的索引位置(不适用于对象数组) |
方法 | concat(待拼接数组列表) | 把几个数组合并成一个数组并返回 |
方法 | forEach(callback(value[,index])) | 数组每个元素都执行一次回调函数 value为值(必须有)、index为索引(可以有) |
方法 | filter(callback(value[,index])) | 检测数组元素,并返回符合条件所有元素的数组 value为值(必须有)、index为索引(可以有) |
方法 | map(callback(value[,index])) | 创建一个新数组,其结果是该数组中的每个元素都 调用一个提供的函数后返回的结果 value为值(必须有)、index为索引(可以有) |
//基本数据类型数组
let array1 = [1,2,3,4,5,6];
//对象数组
let array2 = [
{
name: '张三',
age: 12,
score: 89
},
{
name: '李四',
age: 14,
score: 78
},
{
name: '王五',
age: 13,
score: 93
}
];
//获取数组长度
console.log(`数组1的长度为:${array1.length}`);
//获取指定索引元素
console.log(`数组2索引1的数据为:`,array2[1]);
//分割
console.log(`数组1使用短横线分割后:${array1.join('-')}`);
//向数组末尾添加一个或多个元素,并返回新的数组长度
console.log(`数组1添加一个100:${array1.push(100)}`);
array2.push({
name: '赵六',
age: 13,
score: 100
})
console.log(`数组2添加一个对象:`,array2);
//移除最后一个元素
console.log(`移除前:`,array1);
array1.pop();
console.log(`移除后:`,array1);
3.9.3 JSON
JSON 是一种语法,用来序列化对象、数组、数值、字符串、布尔值和 null
JSON的 属性名称必须是双引号括起来的字符串;最后一个属性后不能有逗号
- JSON对象基本结构示例
let responseData = {
"data": {
"list": [
{
"name": '张三',
"age": 12,
"score": 89
},
{
"name": '李四',
"age": 14,
"score": 78
},
{
"name": '王五',
"age": 13,
"score": 93
}
],
"totalNumber": 48
},
"message": '获取学生列表数据成功',
"code": 200
}
- 方法列表
类别 | 名称 | 说明 |
---|---|---|
方法 | parse | 解析JSON字符串并返回对应的值 |
方法 | stringify | 返回与指定值对应的JSON字符串 |
在vue中,我们经常使用JSON.parse(JSON.stringify(数据))的方式,对数据进行深度拷贝
3.9.4 Date
- 构造函数
构造函数 | 说明 |
---|---|
new Date() | 当前时间日期对象 |
new Date(毫秒数) | 指定毫秒数日期对象,1970-01-01 00:00:00开始 |
new Date(dateString) | 指定格式字符串日期,MM DD,YYYY hh:mm:ss |
new Date(年,月,日,小时,分,秒,毫秒) | 创建指定数值的日期对象 |
- 成员方法
名称 | 说 明 |
---|---|
getFullYear() | 从 Date 对象以四位数字返回年份 |
getMonth() | 从 Date 对象返回月份 (0 ~ 11) |
getDate() | 从 Date 对象返回一个月中的某一天 (1 ~ 31) |
getDay () | 从 Date 对象返回一周中的某一天 (0 ~ 6),0为星期天 |
getHours () | 返回 Date 对象的小时 (0 ~ 23),24时自动变为0 |
getMinutes() | 返回 Date 对象的分钟 (0 ~ 59) |
getSeconds() | 返回 Date 对象的秒数 (0 ~ 59) |
getMilliseconds() | 返回 Date 对象的毫秒(0 ~ 999) |
getTime() | 返回 1970 年 1 月 1 日至今的毫秒数。 |
//获取当前的日期对象
let dateData = new Date();
//获取当前的年份
let year = dateData.getFullYear();
console.log(`今年是:${year}年`);
//获取当前的月份(0~11)
let month = dateData.getMonth() + 1;
console.log(`本月是:${month}月`);
//获取当天的日期
let date = dateData.getDate();
console.log(`今天是:${date}日`);
//获取当天的星期数
let day = dateData.getDay();
console.log(`今天的星期数是:${day}`);
//获取当前的小时数(0~23),24时自动变为0
let hour = dateData.getHours();
console.log(`当前是:${hour}点`);
//获取当前的分钟数(0~59)
let minute = dateData.getMinutes();
console.log(`当前是:${minute}分`);
//获取当前的秒数(0~59)
let second = dateData.getSeconds();
console.log(`当前是:${second}秒`);
//获取当前的豪秒数(0~59)
let millisecond = dateData.getMilliseconds();
console.log(`当前是:${millisecond}豪秒`);
//获取 1970 年 1 月 1 日至今的毫秒数
let time = dateData.getTime();
console.log(`1970 年 1 月 1 日至今的毫秒数是:${time}豪秒`);
//获取本月有多少天
let mineDate = new Date(year,month,0);
console.log(`${year}年${month}月一共有:${mineDate.getDate()}天`)
3.9.5 Math
- 属性和方法
类别 | 方法 | 描述 |
---|---|---|
属性 | E | 返回算术常量 e,即自然对数的底数(约等于2.718) |
属性 | PI | 返回圆周率(约等于3.14159) |
方法 | abs(x) | 返回 x 的绝对值 |
方法 | ceil(x) | 对 x 进行上舍入 |
方法 | floor(x) | 对 x 进行下舍入 |
方法 | max(x,y,z,…,n) | 返回最高值 |
方法 | min(x,y,z,…,n) | 返回最低值 |
方法 | pow(x,y) | 返回 x 的 y 次幂 |
方法 | random() | 返回 0 ~ 1 之间的随机数(不包括1) |
方法 | round(x) | 把 x 四舍五入为最接近的整数 |
方法 | sqrt(x) | 返回 x 的平方根 |
//算术常量e的值
console.log(Math.E);
//圆周率
console.log(Math.PI);
//绝对值
console.log(Math.abs(-183));
//获取最大值
let number = [2,56,23,567,13,54];
console.log(Math.max(...number));
/**
* 获取指定范围的随机一个整数值
* @param minNum 最小值
* @param maxNum 最大值
* @returns number 整数
*/
function getRandomNum(minNum, maxNum) {
//假设我们希望获取一个10~100的随机整数
//1. Math.random() 获取一个0~1的随机小数(不包括1) 也就是[0,1)
//2. maxNum - minNum 计算出两个数的差值 也就是100-10=90
//3. Math.random() * (maxNum - minNum) 的值就变成了[0,90)
//4. Math.random() * (maxNum - minNum) + minNum 的值就变成了[10,100)
//5. Math.floor(Math.random() * (maxNum - minNum) + minNum) 的值就变成了[10,99],可以发现这里100没有包含进来,因此在maxNum - minNum需要+1
return Math.floor(Math.random() * (maxNum - minNum + 1) + minNum);
}
8. 浏览器中的JS代码调试
- 设置断点
- 刷新页面运行程序
- 通过单行或者进入的方式查看程序执行过程以及,执行过程中的数据
8.1 设置断点
- 通过F12键 ,进入浏览器调试模式
- 找到浏览开发者窗体Source选项
- 在page界面中找到需要调试的代码
- 在代码的指定行设置断点
8.2 开始调试
- 在开发者窗体按Ctrl+R
- 在页面展示窗体按F5或者Shift + F5, Shift + F5会帮助我们清空本地缓存从服务器重新获取数据
4. 客户端 Web API
全称Client side Web API
w3c官方介绍页:https://www.w3.org/standards/webdesign/script
mozilla Web 介绍首页:https://developer.mozilla.org/zh-CN/docs/learn
mozilla WebAPI参考页:https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/Client-side_web_APIs
JavaScript组成部分回顾
- ECMAScript, 语法结构组成
- BOM (Browser Object Model) , 浏览器对象模型
- DOM (Document Object Model) , 文档对象模型
4.1 什么是浏览器对象模型
Internet Explore 3 和 Netspace Navigator3 有一个共同的特色,那就是支持可以访问和操作浏览器窗口的浏览器对象模型(BOM)。开发人员使用BOM可以控制浏览器显示的页面以外的部分。而BOM真正与众不同的地方,还是他作为JavaScript实现的一部分却没有相关的标准。这个问题在HTML5中得到了解决,HTML5致力于把很多BOM功能写入正式规范。
本质上讲,BOM只处理浏览器窗口和框架;但大家习惯上也把所有针对浏览器的JavaScript扩展算作BOM的一部分。算入扩展的内容.
- 弹出新浏览器窗口的功能
- 移动、缩放和关闭浏览器的功能
- 提供浏览器详细的navigator对象
- 提供浏览器所加载页面的详细信息的location对象
- 提供用户显示器分辨率详细信息的screen对象
- 对cookies的支持
- 像XMLHttpRequest和ActiveObject这样的自定义对象。
上述内容来源于:《Professional JavaScript for Web Developers》 4th Edition , [JavaScript 高级程序设计] 第10~11页。
4.2 什么是文档对象模型
参考链接: https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/Client-side_web_APIs/Manipulating_documents
在浏览器标签中当前载入的文档用文档对象模型来表示。这是一个由浏览器生成的“树结构”,使编程语言可以很容易的访问HTML结构 — 例如浏览器自己在呈现页面时,使用它将样式和其他信息应用于正确的元素,而页面呈现完成以后,开发人员可以用JavaScript操作DOM
HTML文档中每个元素或子元素都是一个节点:
- 整个文档是一个文档节点
- 每个HTML元素是一个元素节点
- 包含在HTML元素中的文本是文本节点
- 每个HTML属性是一个属性节点
- 注释属于注释节点
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>DOM节点的示例</title>
</head>
<body>
<img src="./img/xuetang9.jpg" alt="老九学堂" id="ljxt" />
<h1>老九学堂校友会</h1>
<p>DOM应用</p>
</body>
</html>
5. 浏览器对象模型
5.1 常见BOM
- window : 表示浏览器窗口对象,提供了一系列的函数、属性、可绑定事件。https://developer.mozilla.org/zh-CN/docs/Web/API/Window
- location: 表示其链接到的对象的位置(URL)。所做的修改反映在与之相关的对象上。window与document对象都将location对象作为属性。https://developer.mozilla.org/zh-CN/docs/Web/API/Location
- history:是一个只读属性,用来获取History 对象的引用,History 对象提供了操作浏览器会话历史(浏览器地址栏中访问的页面,以及当前页面中通过框架加载的页面)的接口。https://developer.mozilla.org/zh-CN/docs/Web/API/History
5.2 window 对象
5.2.1 常用函数
**参考地址:**https://developer.mozilla.org/zh-CN/docs/Web/API/Window
说明:
js内置函数在属于ECMAScript语言与WebAPI无关,不过对于浏览器而言函数直接绑定在window对象上。内置函数地址: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects
函数 | 说明 |
---|---|
alert(消息) | 弹出消息警告窗,包含一个“确认”按钮,传入的任何消息都会转化为文本 |
confirm(消息) | 弹出消息确认窗,包含“确定”、“取消"两个按钮,选择确定返回true,否则返回false |
prompt(消息,默认值) | 弹出输入消息窗,当用户确认时返回用户输入内容,否则返回null |
parseInt(字符串,进制) | js内置函数,将输入字符串转化为整数,进制表示字符串表示字符串的进制单位,默认为10进制 |
parseFloat(字符串) | js内置函数,将输入数据转化为浮点数 |
isNaN(内容) | js内置函数,判断传入内容是否不是一个数字 |
open(地址,窗口名称,窗口特征) | 打开一个新的窗口,窗口特征包括 大小,位置,滚动条等 |
addEventListener(事件名,事件函数) | 给窗体添加一个指定的事件 |
removeEventListener(事件名) | 移除添到窗体的一个指定的事件 |
setTimeout(函数,延时,参数) | 在指定延时毫秒单位之后,执行传入函数。函数参数在第三个从参数传递,返回值为定时器编号,可以根据该编号取消执行定时器函数 |
clearTimeout(编号) | 取消执行定时器函数,参数为setTimeout()函数返回的编号 |
setInterval(函数,延时,参数) | 根据给定的时间周期执行传入的函数,第三个参数为函数执行需要的参数,返回值为定时器编号,可以根据该编号取消执行该函数 |
clearInterval(编号) | 取消执行setInterval()启动的定时器,参数会setInterval函数的返回值 |
getComputedStyle(element) | 用于计算指定元素的样式信息,只读 |
5.2.2 常用事件属性
说明:
- 事件属性赋值通常直接赋值一个事件回调函数,即事件发生时需要执行的操作
- 对于事件而言,参数为事件在执行时,事件执行对象传递给事件指定函数的参数列表,即可以**在方法中接收到的数据**
- 未列出事件查看:https://developer.mozilla.org/zh-CN/docs/Web/API/Window
属性名 | 说明 |
---|---|
onload | 在文档装载完成后会触发 load 事件。此时,在文档中的所有对象都在DOM中,所有图片,脚本,链接以及子框都完成了装载 |
onclose | 关闭窗体时触发的事件 |
onresize | 窗体尺寸发生变化时触发的事件 |
onscroll | 窗体页面内容滚动时触发的事件 |
onkeydown | 全局监听键盘按下的事件 |
onkeyup | 全局监听键盘松开的事件 |
onkeypress | 全局监听键盘按下并产生字符时的事件(ctrl、shift之类的键不会触发) |
5.2.3 示例
window.onload = function () {
//将字符转为数字
let money = "1838";
console.log(typeof parseInt(money));
//判断内容是否为数字
console.log(isNaN("¥1835.00"));
//添加一个键盘按下事件
window.addEventListener('keydown',function (e) {
console.log(e);
});
//监听页面滚动事件
window.onscroll = function (e) {
console.log(e);
}
}
5.3 location 对象
5.3.1 常用属性与函数
**参考地址:**https://developer.mozilla.org/zh-CN/docs/Web/API/Location
类别 | 名称 | 说明 |
---|---|---|
属性 | href | 表示url的字符串,可以修改用于加载新的页面 |
属性 | protocol | 当前页面的协议 |
属性 | host | 当前页面的域名,域名、端口号 |
属性 | hostname | 当前页面域名,无端口号 |
属性 | port | 当前页面端口号 |
方法 | reload() | 刷新当前页面 |
方法 | replace(页面地址) | 加载一个指定地址的页面 |
5.3.2 示例
window.onload = function () {
console.log(`当前页面的连接为:${location.href}`);
console.log(`当前页面所使用的协议为:${location.protocol}`);
//按下回车键,页面跳转至百度
window.addEventListener('keydown',e => {
if(e.key === 'Enter') {
//location.href = "http://www.baidu.com";
location.replace("http://www.baidu.com");
}
});
}
5.4 history 对象(了解)
5.4.1 常用属性与函数
**参考地址:**https://developer.mozilla.org/zh-CN/docs/Web/API/History
类别 | 名称 | 说明 |
---|---|---|
属性 | length | 当前历史记录中页面的个数,包括当前页面 |
方法 | back() | 回退一个页面,当没有页面的时候不报错 |
方法 | forward() | 前进一个页面,当没有页面的时候不报错 |
方法 | go(前进或后退的数值) | 根据数值前进或者后退,正数前进、负数后退、0刷新 |
5.4.2 示例
起始页面
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>history对象起始页面</title>
</head>
<body>
<h2>起始页面</h2>
<a href="./2.4-history-html2.html">前往目标页面</a>
<script type="text/javascript">
window.addEventListener('keydown',e => {
//前往下一个
if(e.key === 'Enter') {
history.forward();
}
});
</script>
</body>
</html>
目标页面
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>history对象目标页面</title>
</head>
<body>
<h2>目标页面</h2>
<script type="text/javascript">
window.addEventListener('keydown',e => {
//返回上一个页面
if(e.key === 'Enter') {
history.back();
}
});
</script>
</body>
</html>
6. 文档对象模型
6.1 常见DOM
**参考网址:**https://developer.mozilla.org/zh-CN/docs/Web/API/Document_Object_Model
- Document(文档对象), 表示加载到浏览器的页面文件。提供一系列对页面中标签、标签属性、文本、注释等操作的对象与方法。将页面标签、标签属性、文本、注释放在一颗树结构中进行操作
- Node、NodeList、ChildNode、ParentNode(节点对象),页面解析成的树中的所有成员都可以用节点来表示
- Element、HTMLElement(元素对象),表示HTML页面上的标签
- Attr(属性对象),表示添加在标签上的属性
- Text(文本对象), 表示HTML页面上的文本
- Comment(注释对象),表示HTML页面上的注释
- Event(事件对象),表示为标签、窗体等添加的事件。
6.2 document对象(重要)
6.2.1 常见属性与方法
参考地址: https://developer.mozilla.org/zh-CN/docs/Web/API/Document
类别 | 名称 | 说明 |
---|---|---|
属性 | body | 获得页面的body标签对象 |
属性 | forms | 获得页面的表单列表 |
属性 | cookie | 用分号分隔的 cookie 列表,或设置 cookie。HTML5新加 |
属性 | referrer | 获取页面的来源url |
属性 | title | 获取页面标题字符串 |
属性 | defaultView | 获取界面绑定的window对象 |
方法 | getElementById(名称) | 根据id名称查找一个元素 |
方法 | getElementsByClassName(名称) | 根据样式名称查找元素 |
方法 | getElementsByName(名称) | 根据名称属性名查找元素 |
方法 | getElementsByTagName(名称) | 根据标签名查找元素 |
方法 | querySelector(CSS选择器) | 根据选择器字符串查找单个元素,存在多个取第一个 |
方法 | querySelectorAll(CSS选择器) | 根据选择器字符串查找元素 |
方法 | createElement(元素名) | 根据元素名在内存中创建元素对象 |
方法 | write(文本) | 输出文本到页面上,可以输出标签文本会被解析 |
方法 | writeln(文本) | 输出文本到页面上,可以输出标签文本会被解析,产生换行符 |
document.write() 系列方法会覆盖原有的代码内容,因此建议少用或者不用
6.2.2 示例
window.onload = function () {
document.cookie = "name=张三";
document.cookie = "age=18";
console.log(document.cookie);
console.log(document.querySelector("p"));
console.log(document.querySelectorAll("p"));
console.log(document.createElement("a"));
}
6.3 Node节点对象
说明:
对于Node而言,最重要的是nodeType。主要根据nodeType判断当前是什么节点,用的比较少。
参考链接:https://developer.mozilla.org/zh-CN/docs/Web/API/Node
6.3.1 常见属性
属性 | 说明 |
---|---|
nodeType | 节点类型 |
nodeName | 节点名称 |
nodeValue | 节点值 |
childNodes | 所有的子节点对象数组 |
parentNode | 父节点 |
parentElement | 父元素节点 |
firstChild | 第一个子节点 |
lastChild | 最后一个子节点 |
nextSibling | 下一个兄弟节点 |
previousSibling | 前一个兄弟节点 |
innerHTML | 输出或设置HTML代码文本 |
outerHTML | 将节点以字符串形式输出 |
innerText | 输出或设置源码文本 |
6.3.2 nodeType对应表
中文名 | 节点类型名 | Value |
---|---|---|
元素节点 | ELEMENT_NODE | 1 |
属性节点 | ATTRIBUTE_NODE | 2 |
文本节点 | TEXT_NODE | 3 |
CDATA节点 | CDATA_SECTION_NODE | 4 |
实体引用节点 | ENTITY_REFERENCE_NODE | 5 |
实体节点 | ENTITY_NODE | 6 |
处理指令节点 | PROCESSING_INSTRUCTION_NODE | 7 |
注释节点 | COMMENT_NODE | 8 |
文档节点 | DOCUMENT_NODE | 9 |
文档类型节点 | DOCUMENT_TYPE_NODE | 10 |
文档判断节点 | DOCUMENT_FRAGMENT_NODE | 11 |
符号节点 | NOTATION_NODE | 12 |
6.3.3 示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>演示Node节点对象</title>
</head>
<body>
<div class="container">
<h2>内容标题</h2>
</div>
<script type="text/javascript">
window.onload = function () {
let container = document.querySelector(".container");
console.log(container.nodeType); //节点类型
console.log(container.nodeName); //节点名称
console.log(container.nodeValue); //节点值
console.log(container.childNodes); //所有子节点
console.log(container.innerHTML);
console.log(container.outerHTML);
}
</script>
</body>
</html>
6.4 Element节点对象(重要)
**Element节点对象参考链接:**https://developer.mozilla.org/zh-CN/docs/Web/API/Element
6.4.1 常见属性
名称 | 说明 |
---|---|
attributes | 所有属性列表 |
children | 子元素列表 |
style | 行内样式属性对象 |
className | 内部或者外部样式名称 |
classList | 样式列表: add(class1[,class2,…])给元素添加一个或多个类样式名,如果指定的类样式名已存在,则不会添加 remove(class1[,class2,…])移除元素中一个或多个类样式名 contains(className)返回布尔值,判断指定的类名是否存在 |
id | 获取元素的id |
firstElementChild | 第一个子元素节点(不兼容IE) |
lastElementChild | 最后一个子元素节点(不兼容IE) |
nextElementSibling | 下一个兄弟节点(不兼容IE) |
previousElementSibling | 上一个兄弟节点(不兼容IE) |
clientWidth | 边框内的宽度:包括了内容的宽度和panding,但不包含滚动条宽度 |
clientHeight | 边框内的高度 |
clientLeft | 内容左侧距离 |
clientTop | 内容顶部距离 |
scrollTop | 读取或设置元素滚动条到元素顶部的距离(元素的内容没有产生垂直方向的滚动条,那么它的scrollTop值为0) |
scrollLeft | 读取或设置元素滚动条到元素左边的距离(元素的内容没有产生水平方向的滚动条,那么它的scrollLeft值为0) |
6.4.2 常见方法
名称 | 说明 |
---|---|
appendChild(node) | 将节点拼接在当前节点内部的最后面 |
insertBefore(newNode, referenceNode) | 将节点拼接在当前节点内部的最前面 referenceNode表示父节点的指定子节点,如果传入null表示将newNode添加到父节点的内部最后面 |
removeChild(node) | 删除节点中的指定子节点 |
replaceChild(newNode, oldChild) | 将节点的指定子节点(oldChild)替换为新的节点(newNode) |
getAttribute(name) | 获取节点指定的name属性 |
hasAttribute(name) | 判断节点是否存在指定的name属性 |
setAttribute(name,value) | 为节点添加指定的name属性并且值为value |
6.4.4 示例
节点拼接
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>演示Element节点对象</title>
</head>
<body>
<table>
<thead>
<tr>
<th><input type="checkbox" /></th>
<th>商品编号</th>
<th>商品简称</th>
<th>单位</th>
<th>规格</th>
<th>商品分类</th>
<th>采购单价</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" /></td>
<td>00001</td>
<td>青岛啤酒纯度8度</td>
<td>青岛纯生</td>
<td>箱</td>
<td>600mlx24</td>
<td>32.00</td>
<td>
<button>上架</button>
<button>编辑</button>
<button>删除</button>
<button>一店一价</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>00002</td>
<td>青岛啤酒纯度8度</td>
<td>青岛纯生</td>
<td>箱</td>
<td>600mlx24</td>
<td>32.00</td>
<td>
<button>上架</button>
<button>编辑</button>
<button>删除</button>
<button>一店一价</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>00003</td>
<td>青岛啤酒纯度8度</td>
<td>青岛纯生</td>
<td>箱</td>
<td>600mlx24</td>
<td>32.00</td>
<td>
<button>上架</button>
<button>编辑</button>
<button>删除</button>
<button>一店一价</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>00004</td>
<td>青岛啤酒纯度8度</td>
<td>青岛纯生</td>
<td>箱</td>
<td>600mlx24</td>
<td>32.00</td>
<td>
<button>上架</button>
<button>编辑</button>
<button>删除</button>
<button>一店一价</button>
</td>
</tr>
</tbody>
</table>
<script type="text/javascript">
window.onload = function () {
//移除第二个tr
let tr = document.querySelector('table tr:nth-child(2)');
tr.parentNode.removeChild(tr);
//给最后一个tr的最后一个td添加一个属性data-id,值为4
document.querySelector('table tr:last-child td:last-child').setAttribute('data-id','4');
//给tbody再添加一个tr
let trNode = document.createElement('tr');
trNode.innerHTML = `
<td><input type="checkbox" /></td>
<td>00005</td>
<td>青岛啤酒纯度8度</td>
<td>青岛纯生</td>
<td>箱</td>
<td>600mlx24</td>
<td>32.00</td>
<td>
<button>上架</button>
<button>编辑</button>
<button>删除</button>
<button>一店一价</button>
</td>
`;
document.querySelector('table tbody').appendChild(trNode);
}
</script>
</body>
</html>
6.5 HTMLElement节点
HTMLElement节点参考链接: https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLElement
6.5.1 常见属性
名称 | 说明 |
---|---|
offsetWidth | 布局宽度:包含元素的边框、水平线上的内边距、竖直方向滚动条以及CSS设置的宽度的值 |
offsetHeight | 布局高度 |
offsetTop | 获取当前DOM节点元素距离浏览器顶部的距离,单位是像素 |
offsetLeft | 获取当前DOM节点元素距离浏览器左侧的距离,单位是像素 |
6.5.2 常见鼠标事件
名称 | 说明 |
---|---|
click | 单击 |
dbclick | 双击 |
mousedown | 按下 |
mouseup | 松开 |
mouseenter | 光标移入元素时触发 |
mouseleave | 光标移出元素时触发 |
mouseover | 光标移入元素时触发,进入子元素也会触发 |
mouseout | 光标移出元素时触发,离开子元素也会触发 |
mousemove | 光标在元素上移动时触发 |
6.5.3 常见键盘事件
名称 | 说明 |
---|---|
keydown | 键盘按下 |
keyup | 键盘松开 |
keypress | 键盘按下并产生字符时的事件(ctrl、shift之类的键不会触发) |
6.5.4 特殊事件
名称 | 说明 |
---|---|
focus | 输入框获取焦点 |
blur | 输入框失去焦点 |
select | 内容选中 |
input | 输入框输入内容 |
change | 元素内容发生改变 |
6.5.5 示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>演示HTMLElement节点对象</title>
<style type="text/css">
table {
border-collapse: collapse;
}
table.border th,table.border td {
border: 1px solid black;
}
</style>
</head>
<body>
<table>
<thead>
<tr>
<th><input type="checkbox" /></th>
<th>商品编号</th>
<th>商品简称</th>
<th>单位</th>
<th>规格</th>
<th>商品分类</th>
<th>采购单价</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" /></td>
<td>00001</td>
<td>青岛啤酒纯度8度</td>
<td>青岛纯生</td>
<td>箱</td>
<td>600mlx24</td>
<td>32.00</td>
<td>
<button>上架</button>
<button>编辑</button>
<button>删除</button>
<button>一店一价</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>00002</td>
<td>青岛啤酒纯度8度</td>
<td>青岛纯生</td>
<td>箱</td>
<td>600mlx24</td>
<td>32.00</td>
<td>
<button>上架</button>
<button>编辑</button>
<button>删除</button>
<button>一店一价</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>00003</td>
<td>青岛啤酒纯度8度</td>
<td>青岛纯生</td>
<td>箱</td>
<td>600mlx24</td>
<td>32.00</td>
<td>
<button>上架</button>
<button>编辑</button>
<button>删除</button>
<button>一店一价</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>00004</td>
<td>青岛啤酒纯度8度</td>
<td>青岛纯生</td>
<td>箱</td>
<td>600mlx24</td>
<td>32.00</td>
<td>
<button>上架</button>
<button>编辑</button>
<button>删除</button>
<button>一店一价</button>
</td>
</tr>
</tbody>
</table>
<button class="border-btn">表格边框</button>
<script type="text/javascript">
window.onload = function () {
let table = document.querySelector('table');
//点击“表格边框”按钮,实现添加或移除表格边框的样式
document.querySelector('button.border-btn').addEventListener('click',e => {
if(table.classList.contains('border')) {
table.classList.remove('border');
}else {
table.classList.add('border');
}
});
}
</script>
</body>
</html>
7. 表单验证(掌握)
输入元素参考链接: https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLInputElement
**表单元素参考链接:**https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLFormElement
7.1 获取输入元素值
- 使用元素value属性
7.2 表单对象验证事件与方法
类型 | 名称 | 说明 |
---|---|---|
方法 | submit() | 提交表单 |
方法 | reset() | 重置表单 |
事件 | submit | 表单提交时执行,当事件执行函数返回false时, 会阻止表单向服务器提交数据,表示数据验证不通过 |
事件 | reset | 表单重置时执行 |
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>演示表单验证基础</title>
</head>
<body>
<form method="post">
<label>
<input type="text" name="account" placeholder="请填写账号" />
</label>
<button>普通按钮</button>
<input type="submit" value="表单提交按钮" />
</form>
<script type="text/javascript">
//普通按钮执行表单提交方法
document.querySelector('button').addEventListener('click',e => {
console.log('手动执行表单提交');
document.querySelector('form').submit();
});
//表单提交事件
document.querySelector('form').addEventListener('submit',e => {
console.log('触发表单提交事件');
//阻止表单提交(e.preventDefault()的作用是阻止默认的行为)
e.preventDefault();
});
</script>
</body>
</html>
7.3 正则表达式(重要)
**参考链接:**https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions
7.3.1 什么是正则表达式
正则表达式是用于匹配字符串中字符组合的模式。在 JavaScript中,正则表达式也是对象。
7.3.2 js中创建正则表达式
let reg = /^[a-zA-Z\d_]{6,10}$/; //快速创建正则表达式方式
let reg2 = new RegExp('^[a-zA-Z\d_]{6,10}$'); //通过对象创建正则表达式
7.3.3 字符元字符
字符 | 含义 |
---|---|
\ | 转义字符,可以将特殊符号转移为普通字符, 例如+,代表一个’+‘号,\代表’'本身。特殊情况:\n代表一个换行符 |
^ | 匹配字符串开始的位置,与后面紧邻的字符进行配合 |
$ | 匹配字符串结束的位置,与前面紧邻的字符进行配合 |
* | 匹配前面的字符或者表达式出现0次或多次,等价于{0,} |
+ | 匹配前面的字符或者表达式出现一次或多次,等价于{1,} |
? | 匹配前面的字符或者表达式出现零次或一次,等价于{0,1} |
. | 匹配除换行符\n之外的任何单个字符 |
| | 或者的意思。例如,/green|red/匹配“green apple”中的‘green’和“red apple”中的‘red’ |
() | 将表达式组合起来,括号中的内容可以被上面的特殊符号修饰 |
7.3.4 表达式元字符
字符 | 含义 |
---|---|
{n} | 匹配前面的字符或者表达式,指定匹配次数为n次 |
{n,} | 匹配前面的字符或者表达式,指定匹配次数至少为n次 |
{n,m} | 匹配前面的字符或者表达式,指定匹配次数至少n次,最多m次 |
[xyz] | 字符合集,匹配里面包含的任意一个字符。例如[abcd]代表abcd中的任意一个字符,也可以用-来进行范围约束,例如[a-z]、[0-9]、[A-z]、[A-z0-9]、[A-z0-9_]、[\u4e00-\u9fa5] 等 |
[^xyz] | 匹配不包含里面字符的其他任意一个字符。例如[^abcd] 代表除了abcd以外的任意一个字符 |
\d | 匹配0-9中任意一个阿拉伯数字,相当于[0-9]。 |
\D | 匹配一个非阿拉伯数字,等价于[^0-9] 。 |
\f | 匹配一个换页符(U+000C)。 |
\n | 匹配一个换行符(U+000A)。 |
\r | 匹配一个回车符(U+000D)。 |
\s | 匹配一个空白字符,包括空格、制表符、换页符和换行符。等价于[ \f\n\r\t\v\u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff] 。 |
\S | 匹配一个非空白字符。等价于 [^ \f\n\r\t\v\u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff] 。 |
\t | 匹配一个水平制表符 (U+0009)。 |
\v | 匹配一个垂直制表符 (U+000B)。 |
\w | 匹配一个单字字符(字母、数字或者下划线)。等价于 [A-Za-z0-9_] 。 |
\W | 匹配一个非单字字符。等价于 [^A-Za-z0-9_] 。 |
7.3.6 正则表达式方法
字符 | 含义 |
---|---|
exec | 查找字符串中满足规则的字符串,它返回一个数组(未匹配到则返回 null)。每次只匹配一个,其会返回lastIndex来表示下一个匹配的起始索引值,当我们再次执行exec时,自动从这里开始继续搜索,知道为null为止 |
test | 测试字符串是否匹配规则,它返回 true 或 false |
7.3.7 高级搜索标志
字符 | 含义 |
---|---|
g | 全局搜索 |
i | 不区分大小写搜索 |
let str = 'a1c240eabc0abc1';
let result;
let reg = /[A-z0-9]{3}/;
//通过循环来查找所有能够匹配的字符串
while ((result = reg.exec(str)) !== null) {
console.log(result);
}
let reg2 = /[A-z0-9]{3}/g;
while ((result = reg2.exec(str)) !== null) {
console.log(result);
}
7.3.8 贪婪模式与非贪婪模式
贪婪模式的元字符包括:
{n,}
、{n,m}
、?
、*
、+
贪婪模式的特性:匹配尽可能多的字符
非贪婪模式的特性:匹配尽量少的字符
在贪婪模式元字符后面加上?即可将其变为非贪婪模式:
{n,}?
、{n,m}?
、??
、*?
、+?
//贪婪模式
let str = 'd131adafdae';
let reg = /d\w+/; //\w+将会匹配d之后所有的字符,有多少匹配多少
console.log(reg.exec(str));
let reg2 = /d\w+d/; //虽然\w中包含有d,但是为了使整个表达式匹配成功,\w会让出最后一个匹配的d
console.log(reg2.exec(str));
//非贪婪模式
let reg3 = /d\w+?/; //\w+?只会匹配d之后的1个字符
console.log(reg3.exec(str));
let reg4 = /d\w+?d/; //尽可能少的匹配字符,为了让整个表达式匹配成功,不得不多匹配几个字符才能让后面的d匹配
console.log(reg4.exec(str));
7.4 表单验证示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>演示表单验证</title>
</head>
<body>
<form method="post">
<label>
<input type="text" name="account" autocomplete="off" placeholder="请填写账号" />
<p class="tip"></p>
</label>
<label>
<input type="password" name="pwd" autocomplete="off" placeholder="请填写密码" />
<p class="tip"></p>
</label>
<input type="submit" value="表单提交按钮" />
</form>
<script type="text/javascript">
//表单提交事件
document.querySelector('form').addEventListener('submit',e => {
//校验账号是否符合规则
let accountValidate = false;
let accountIpt = document.querySelector('input[name="account"]');
let accountTip = accountIpt.nextSibling.nextSibling;
let accountVal = accountIpt.value;
//账号要求: 1.不能为空 2.6~10位字母或者数字
let iptReg = /^[a-zA-Z0-9]{6,10}$/;
if(accountVal.length === 0) {
accountTip.innerHTML = '账号不能为空';
}else if(!iptReg.test(accountVal)) {
accountTip.innerHTML = '账号格式不正确,请输入6~10位字母或者数字';
}else {
accountTip.innerHTML = '';
accountValidate = true;
}
//校验密码是否符合规则
let pwdValidate = false;
let pwdIpt = document.querySelector('input[name="pwd"]');
let pwdTip = pwdIpt.nextSibling.nextSibling;
let pwdVal = pwdIpt.value;
//账号要求: 1.不能为空 2.6~10位字母或者数字或者下划线
let pwdReg = /^\w{6,10}$/;
if(pwdVal.length === 0) {
pwdTip.innerHTML = '密码不能为空';
}else if(!pwdReg.test(pwdVal)) {
pwdTip.innerHTML = '密码格式不正确,请输入6~10位字母或者数字或者下划线';
}else {
pwdTip.innerHTML = '';
pwdValidate = true;
}
//如果校验不通过,那么禁止提交表单
if(!accountValidate || !pwdValidate) e.preventDefault();
});
</script>
</body>
</html>
8.承诺 Promise
Promise 是异步编程的一种解决方案。简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息
参考链接:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise
8.1 Promise的三种状态
待定(pending): 初始状态,既没有被兑现,也没有被拒绝
已兑现(fulfilled): 意味着操作成功完成
已拒绝(rejected): 意味着操作失败
8.2 Promise的特点
待定状态的 Promise 对象要么会通过一个值被兑现(fulfilled),要么会通过一个原因(错误)被拒绝(rejected),它不会受到外界因素的影响
如果一个 promise 已经被兑现(fulfilled)或被拒绝(rejected),那么我们可以说它处于已敲定(settled)状态,一旦已敲定,就不会再被更改。
我们还会听到一个经常跟 promise 一起使用的术语:已决议(resolved),它表示 promise 已经处于已敲定(settled)状态,或者为了匹配另一个 promise 的状态被"锁定"了
8.3 Promise方法
方法名 | 描述 |
---|---|
then(onFulfilled, onRejected) | 添加兑现(fulfillment)和拒绝(rejection)回调到当前 promise, 返回一个新的 promise。当这个回调函数被调用,新 promise 将以它的返回值来resolve,否则如果当前promise 进入fulfilled状态,则以当前promise的完成结果作为新promise的完成结果 onFulfilled表示:当 Promise 变成已兑现(fulfilled)时调用的函数 onRejected表示:当 Promise 变成拒绝状态(rejected)时调用的函数 |
catch(onRejected) | 添加一个拒绝(rejection) 回调到当前 promise, 返回一个新的promise,将以回调的返回值来resolve |
finally | 加一个事件处理回调于当前promise对象,并且在原promise对象解析完毕后,返回一个新的promise对象。回调会在当前promise运行完毕后被调用,无论当前promise的状态是完成(fulfilled)还是失败(rejected) |
因为then、catch、finally都会返回一个新的Promise对象,因此它们是可以串联使用的。
8.3 示例
8.3.1 普通示例
/**
* 创建一个Promise对象
* resolve:Promise逻辑执行成功时调用
* reject:Promise逻辑执行失败时调用
*/
let divisionPromise = new Promise(function (resolve, reject) {
let num = parseInt(prompt('请输入一个值,用于与100相除'));
if(isNaN(num)) {
reject('输入的不是数字');
}else if(num === 0) {
reject('除数不能为0');
}else {
let end = 100 / num;
resolve(end);
}
});
//添加兑现和拒绝的回调到当前Promise
divisionPromise.then(function (endNum) {
alert(`除法成功,最终值为:${endNum}`);
},function (message) {
alert(`除法失败:${message}`);
});
8.3.2 模拟数据统计
window.onload = function () {
new Promise(resolve => {
alert('下面进行一个数据统计,每个人说一个数:');
resolve();
})
.then(() => {
return new Promise((resolve, reject) => {
let num = parseInt(prompt('我是张三,我说的数字是:'));
isNaN(num) ? reject('输入的不是数字') : resolve(num);
});
})
.then((num) => {
return new Promise((resolve, reject) => {
let num2 = parseInt(prompt('我是李四,我说的数字是:'));
isNaN(num2) ? reject('输入的不是数字') : alert(`两个数的总和是:${num + num2}`);
});
})
.catch(message => {
alert(message);
})
.finally(() => {
alert('数据统计结束!');
})
}
8.3.3 使用串联方式连续实现动画
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Promise连续动画</title>
<style type="text/css">
div {
width: 200px;
height: 200px;
background-color: #17a2b8;
position: absolute;
top: 0;
left: 0;
transition: all 1s linear;
}
div.start {
border-radius: 50%;
}
div.move-right {
left: calc(100vw - 200px);
}
div.color {
background-color: #c69500;
}
div.move-bottom-right {
top: calc(100vh - 200px);
left: 0;
}
</style>
</head>
<body>
<div></div>
<script type="text/javascript">
window.onload = function () {
let div = document.querySelector('div');
new Promise(resolve => {
setTimeout(() => {
div.classList.add('start');
resolve();
},1500)
})
.then(() => {
return new Promise(resolve => {
setTimeout(() => {
div.classList.add('move-right');
resolve();
},1500);
});
})
.then(() => {
return new Promise(resolve => {
setTimeout(() => {
div.classList.add('color');
resolve();
},1000);
});
})
.then(() => {
return new Promise(resolve => {
setTimeout(() => {
div.classList.add('move-bottom-right');
resolve();
},1000);
});
})
}
</script>
</body>
</html>
seInt(prompt(‘我是李四,我说的数字是:’));
isNaN(num2) ? reject(‘输入的不是数字’) : alert(两个数的总和是:${num + num2}
);
});
})
.catch(message => {
alert(message);
})
.finally(() => {
alert(‘数据统计结束!’);
})
}
#### 8.3.3 使用串联方式连续实现动画
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Promise连续动画</title>
<style type="text/css">
div {
width: 200px;
height: 200px;
background-color: #17a2b8;
position: absolute;
top: 0;
left: 0;
transition: all 1s linear;
}
div.start {
border-radius: 50%;
}
div.move-right {
left: calc(100vw - 200px);
}
div.color {
background-color: #c69500;
}
div.move-bottom-right {
top: calc(100vh - 200px);
left: 0;
}
</style>
</head>
<body>
<div></div>
<script type="text/javascript">
window.onload = function () {
let div = document.querySelector('div');
new Promise(resolve => {
setTimeout(() => {
div.classList.add('start');
resolve();
},1500)
})
.then(() => {
return new Promise(resolve => {
setTimeout(() => {
div.classList.add('move-right');
resolve();
},1500);
});
})
.then(() => {
return new Promise(resolve => {
setTimeout(() => {
div.classList.add('color');
resolve();
},1000);
});
})
.then(() => {
return new Promise(resolve => {
setTimeout(() => {
div.classList.add('move-bottom-right');
resolve();
},1000);
});
})
}
</script>
</body>
</html>