计算机语言
机器语言、汇编语言和高级语言
- 计算机语言指用于人与计算机之间通讯的语言,它是人与计算机之间传递信息的媒介;
- 计算机语言的种类非常多,总的来说可以分成【机器语言】、【汇编语言】和【高级语言】三大类;
- 实际上计算机最终所执行的都是【机器语言】,它是由“0”和“1”组成的二进制数,二进制是计算机语言的基础;
- 编程语言是用来控制计算机的一系列指令,它有固定的格式和词汇(不同编程语言的格式和词汇不一样),必须遵守;
- 如今通用的编程语言有两种形式:【汇编语言】和【高级语言】;
- 【高级语言】主要是相对于低级语言而言的,它并不是特指某一种具体的语言,而是包括了很多编程语言,常用的有:C语言、C++、Java、C#、Python、PHP、Go语言、Objective、Swift等;
- 【翻译器】:高级语言所编制的程序不能直接被计算机识别,必须经过转换才能被执行,为此,我们需要一个翻译器;翻译器可以将我们所编写的源代码转换为机器语言,这也被称为二进制化。记住1和0;
【编程语言】和【标记语言】的区别?
- 【编程语言】有很强的逻辑和行为能力。在编程语言里,会看到很多if else 、for、while等具有逻辑性和行为能力的指令,这是主动的;
- 【标记语言】(html)不用于向计算机发出指令,常用于格式化和链接。标记语言的存在是用来被读取的,它是被动的;
计算机基础
计算机组成
数据存储
- 计算机内部使用二进制0和1来表示数据;
- 所有数据,包括文件、图片等最终都是以二进制数据(0和1)的形式存放在硬盘中的;
- 所有程序,包括操作系统,本质都是各种数据,也以二进制数据的形式放在硬盘中。平时我们所说的安装软件,其实就是把程序文件复制到硬盘中;
- 硬盘、内存都是保存的二进制数据;
数据存储单位
程序运行
初识JavaScript
JavaScript简介
- 发明者:布兰登 艾奇
- JavaScript是一种运行在客户端的脚本语言(script是脚本的意思);
- 脚本语言:不需要编译,运行过程中由js解释器(js引擎)逐行来进行解释并执行;
- 现在也可以基于技术进行服务器端编程;
浏览器执行JS简介
- 浏览器分成两部分:【渲染引擎】和【JS引擎】;
- 【渲染引擎】:用来解析HTML与CSS,俗称【内核】,比如:chrome浏览器的blink,老版本的webkit;
- 【JS引擎】:也称为【JS解释器】。用来读取网页中的JavaScript代码,对其处理后运行,比如chrome浏览器的V8;
- 浏览器本身并不会执行JS代码,而是通过内置JavaScript引擎(解释器)来执行JS代码。JS引擎执行代码时逐行解释每一句源码(转换为机器语言),然后由计算机去执行,所以JavaScript语言归为脚本语言,会逐行解释执行;
JS组成
ECMAScript
DOM
BOM
JS的输入和输出语句
变量
什么是变量?
- 通俗:变量是用于存放数据的容器。我们通过【变量名】获取数据,甚至数据可以修改;
变量在内存中的存储
- 本质:变量是程序在内存中申请的一块用来存放数据的空间;
变量的使用
- 变量在使用时分为两步:1、声明变量;2、赋值
变量案例-弹出输入的用户名
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>变量案例-弹出用户名</title>
</head>
<body>
<script>
// 1、输入用户姓名,存储到一个 myName 的变量中
var myName = prompt('请输入用户名')
// 2、输出这个用户名
alert(myName)
</script>
</body>
</html>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
变量的语法扩展
- 更新变量:一个变量被重新赋值后,它原有的值就会被覆盖,变量值将以最后一次赋的值为准;
- 同时申明多个变量时,只需要写一个 var ,多个变量名之间使用英文逗号隔开;
- 声明变量的特殊情况:
(1)、只声明不赋值,程序也不知道里面存的是啥,所以结果是undefined
(未定义的);
(2)、不声明 不赋值 直接使用某个变量,会报错(xxx is not defined
);
(3)、不声明 直接赋值使用:可以正常使用,是一个全局变量;
变量的命名规范
- 我们尽量不要使用“name”作为变量名;
案例:显示年龄案例
<body>
<script>
var age = prompt("请输入你的年龄");
var str = '你今年已经' + age + '岁了';
alert(str)
</script>
</body>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
数据类型
为什么需要数据类型?
变量的数据类型
<script>
// int num=10; java
// var num; //这里的num 我们是不确定属于哪种数据类型的
var num = 10; //num属于数字型
// js 的变量数据类型是只有程序在运行过程中,根据等号右边的值来确定的
// js是动态语言 变量的数据类型是可以变化的
var x = 10; // x 是数字型
x = 'pink'; //x 是字符串
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
数据类型的分类
数据类型转换
- 注意:代表【空】、【否定的值】会被转换为【false】,如:‘’ 0 NaN null undefined;其余值都会被转换为 true;
隐式转换
- 【隐式转换】是我们在进行算数运算的时候,JS自动转换了数据类型;
//利用算数运算 - * / 来隐式转换;
<script>
console.log('12'-0);//隐式转换为 数字型12
console.log('123'-'120');
</script>
- 1
- 2
- 3
- 4
- 5
案例:计算年龄案例
<body>
<!-- 此案例要求在页面中弹出一个输入框,我们输入出生年份后,能计算出我们的年龄 -->
<!--
案例分析:
1、弹出一个输入框(prompt),让用户输入出生年份(用户输入);
2、把用户输入的值用变量保存起来,然后用今年的年份减去变量值,结果就是现在的年龄(程序内部处理);
3、弹出警示框(alert),把计算的结果输出(输出结果);
-->
<script>
var year=prompt("请输入你的出生年份");
var age=2022-year;//按道理year取过来的是字符串型,做减法操作这里做了隐式转换;
alert('你的年龄是'+age+'岁');
</script>
</body>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
案例:简单加法器案例
<body>
<!-- 计算两个数的值,用户输入第一个值后,继续弹出第二个输入框并输入第二个值,最后通过弹出框口显示出两次输入值相加的结果 -->
<script>
var num1 = prompt("请输入第一个值");
var num2 = prompt("请输入第二个值");
var result = parseFloat(num1) + parseFloat(num2);
alert("你的结果是:" + result);
</script>
</body>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
补充:解释型语言和编译型语言
运算符(算数运算符、递增和递减运算符、比较运算符、逻辑运算符、赋值运算符)
- 运算符(
operator
)也被称为操作符,是用于实现赋值、比较和执行算数运算等功能的符号;JavaScript
中常用的运算符有:算数运算符、递增和递减运算符、比较运算符、逻辑运算符、赋值运算符;
补充:表达式和返回值
- 表达式:是由数字、运算符、变量等以能求得数值的有意义排列方法所得的组合;简单理解:是由数字、运算符、变量等组成的式子;【表达式最终都会有一个结果,返回给我们,我们称之为返回值。】
短路运算(逻辑中断)
- 短路运算的原理:当有多个表达式(值)时,左边的表达式值可以确定结果时,就不再继续运算右边的表达式的值;
逻辑与
- 语法:表达式1
&&
表达式2; - 如果第一个表达式的值为真,则返回表达式2;
- 如果第一个表达式的值为假,则返回表达式1;
<body>
<!--
1、用我们的布尔值参与的逻辑运算 true && false == false;
-->
<script>
// 3、逻辑与短路运算
// 3.1、逻辑与短路运算 如果表达式1结果为真,则返回表达式2;
console.log(123 && 456);//456
// 3.2、逻辑与短路运算 如果第一个表达式的值为假,则返回表达式1;
console.log(0 && 456);//0
// 如果有空的或者否定的为假(如:0、''、null、undefined、NaN),其余是真的;
// 4、逻辑或短路运算
// 4.1、如果表达式1结果为真,则返回的是表达式1;
console.log(123 || 456);//123
// 4.2、如果表达式1结果为假,则返回的是表达式2;
console.log(0 || 456);//456
// 案例分析(123为真,直接返回123,后面的 num++ 就不再执行了,所以是结果是0)
var num=0;
console.log(123 || num++);
console.log(num);//0
</script>
</body>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
赋值运算符
- 概念:用来把数据赋值给变量的运算符;
<script>
var num = 10;
//num=num+1; num++
//num = num + 2; ==> num += 2;
num += 2;
console.log(num);//12
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
运算符优先级
- 一元运算符里面的逻辑非(
!
)优先级很高; - 逻辑与比逻辑或优先级高;
流程控制(顺序结构、分支结构、循环结构)
- 在一个程序执行的过程中,各条代码的执行顺序对程序的结果是有直接影响的。很多时候,我们要通过控制代码的执行顺序来实现我们要完成的功能;
- 简单理解:流程控制就是来控制我们的代码按照什么结构顺序来执行;
- 流程控制主要有三种结构,分别是:顺序结构、分支结构和循环结构,这三种结构代表三种代码执行的顺序;
- 顺序结构:是程序中最简单、最基本的流程控制,它没有特定的语法结构,程序会按照代码的先后顺序,依次执行,程序中大多数的代码都是这样执行的;
- 分支结构:由上到下执行代码的过程中,根据不同的条件,执行不同的路径代码(执行代码多选一的过程),从而得到不同的结果;
JS
语言提供了两种分支结构语句:if
语句、switch
语句;
流程控制-分支(if
分支语句、switch
分支语句、三元表达式)
案例:判断平年、闰年案例
<body>
<!--
算法:能被4整除且不能整除100的为闰年(如2004年就是闰年,1901年不是闰年)或者能被400整除的就是闰年;
-->
<script>
var year=prompt("请输入年份:");
if(year % 4 ==0 && year % 100 !== 0 || year % 400 ==0){
alert("你输入的年份是闰年");
}else{
alert("你输入的年份是平年");
}
</script>
</body>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
案例:数字补零
<body>
<!--
案例描述:用户输入数字,如果数字小于0,则在前面补零;如果数字大于0,则不需要补。
-->
<script>
var time = prompt("请输入一个0~59之间的一个数字");
var result = time < 10 ? "0" + time : time
alert(result);
</script>
</body>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
switch
语句
- 当要针对变量设置一系列的特定值的选项时,就可以用
switch
语句; -
switch
是转换、开关的意思;case
小例子或者选项的意思; - 语法结构:
switch(表达式){
case value1:
执行语句1;
break;
case value2:
执行语句2;
break;
...
default:
执行最后的语句;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 执行思路:利用我们的【表达式的值】和【
case
后面的选项值】相匹配,如果匹配上,就执行该case
里面的语句;如果都没有匹配上,那么执行default
里面的语句。 - 代码验证:
switch(2){
case 1:
console.log("这是1");
break;
case 2:
console.log("这是2");;
break;
case 3:
console.log("这是3");;
break;
default:
console.log("没有匹配结果");;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
-
switch
注意事项:
(1)、我们开发时,表达式经常写成变量;
(2)、我们num
的值和case
里面的值相匹配的时候是【全等】(必须是值和数据类型一致才可以);
(3)、break
如果当前的case
里面没有break
,则不会退出switch
,而是继续执行下一个case
;
案例:查询水果案例
<body>
<script>
var fruit = prompt("请输入水果:");
switch (fruit) {
case '苹果':
alert('苹果');
break;
case '榴莲':
alert('榴莲');
break;
default:
alert('没有此水果');
}
</script>
</body>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
-
switch
语句和if else if
语句的区别:
(1)、一般情况下,它们两个语句可以相互替换;
(2)、switch...case
语句通常处理case
为比较确定值的情况,而if...else...
语句更加灵活,常用于范围判断(大于、等于某个范围);
(3)、switch
语句进行条件判断后直接执行到程序的条件语句,效率更高。而if...else...
语句有几种条件,就得判断多少次;
(4)、当分支比较少时,if...else...
语句的执行效率比switch
语句高;
(5)、当分支比较多时,switch
语句的执行效率比较高,而且结构更清晰;
流程控制-循环(for
循环、while
循环、do while
循环)
- 循环的目的:在实际问题中,有许多具有规律性的重复操作,因此在程序中要完成这类操作就需要重复执行某些语句;
- 在JS中,主要有三种类型的循环语句:
for
循环、while
循环、do while
循环; - 在程序中,一组被重复执行的语句被称为【循环体】,能否继续重复执行,取决于循环的【终止条件】。由循环体及循环的终止条件组成的语句,被称为【循环语句】;
//for语法结构
for(初始化变量;条件表达式;操作表达式){
//循环体
}
//初始化变量:就是用var声明的一个普通变量,通常用于作为计数器使用;
//条件表达式:就是用来决定每一次循环是否继续执行,就是终止的条件;
//操作表达式:就是每次循环最后执行的代码,经常用于我们计数器变量进行更新(递增或者递减);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
-
for
循环可以重复执行不同的代码,因为我们有计数器变量i的存在,i每次循环值都会变化;
//我们想要输出1个人1~100岁
for(var i=1;i<=100;i++){
console.log('这个人今年'+i+'岁了');
}
- 1
- 2
- 3
- 4
-
for
循环重复某些相同操作。for
循环因为有了计数器的存在,我们还可以重复的执行某些操作,比如做一些算术运算;
案例:求1~100之间所有整数的累加和
<body>
<!--
案例分析:
1、需要循环100次,我们需要一个计数器i;
2、我们需要一个存储结果的变量sum,但是初始值一定是0;
3、核心算法:1+2+3+4+...sum=sum+i;
-->
<script>
var sum=0;//求和的变量
for(var i=0;i<=100;i++){
sum=sum+i;
}
console.log(sum);
</script>
</body>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
案例:for循环案例
<script>
// 1、求1-100之间所有数的平均值;
var sum = 0;
var average = 0;
for (var i = 1; i <= 100; i++) {
sum = sum + i;
}
average = sum / 100;
console.log(average);//50.5
// 2、求1-100之间所有偶数和奇数的和;
var event = 0;
var odd = 0;
for (var i = 1; i <= 100; i++) {
if (i % 2 == 0) {
event = event + i;
} else {
odd = odd + i;
}
}
console.log(event);//2550
console.log(odd);//2500
// 3、求1-100之间所有能被3整除的数字的和;
var result = 0;
for (var i = 1; i <= 100; i++) {
if (i % 3 == 0) {
result = result + i;
}
}
console.log(result);//1683
</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
- 26
- 27
- 28
- 29
- 30
- 31
- 32
案例:求学生成绩案例
<body>
<!-- 要求用户输入班级人数,之后依次输入每个学生的成绩,最后打印出该班级总的成绩以及平均成绩 -->
<script>
var num = prompt('请输入班级总人数:');
var sum = 0;
var average = 0;
for (var i = 1; i <= num; i++) {
var score = prompt('请输入第' + i + '个学生成绩');
// 因为从prompt取过来的数据是 字符串型的 需要装换为 数字型;
sum = sum + parseFloat(score);
}
average = sum / num;
alert('班级总的成绩是' + sum);
alert('班级平均分是' + average);
</script>
</body>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
案例:一行打印5颗星星
<script>
var str = '';
for (var i = 1; i <= 5; i++) {
// ('⭐');
// 我们采用追加字符串的方式,这样可以打印到控制台上;
str = str + '⭐';
}
console.log(str);
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
var num = prompt('请输入星星个数');
var str = '';
for (var i = 0; i < num; i++) {
str = str + '⭐';
}
console.log(str);
- 1
- 2
- 3
- 4
- 5
- 6
双重for
循环
- 循环嵌套是指在一个循环语句中再定义一个循环语句的语法结构,例如在
for
循环语句中,可以再嵌套一个for
循环,这样的for
循环语句我们称之为双重for
循环; - 我们可以把里面的循环看作是外层循环的语句;
- 外层的循环循环一次,里面的循环执行全部;
案例:打印5行5列星星
<script>
var str = '';
for (var i = 1; i <= 5; i++) {
for (var j = 1; j <= 5; j++) {
str = str + '⭐';
}
// 如果一行打印完毕5个星星,就要另起一行;(加 \n)
str = str + '\n';
}
console.log(str);
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
案例:打印n行n列星星
<script>
var row = prompt('请输入行数');
var column = prompt('请输入列数');
var str = '';
for (var i = 1; i <=row; i++) {
for (var j = 1; j <= column; j++) {
str = str + '⭐';
}
str = str + '\n';
}
console.log(str);
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
案例:打印倒三角案例
<script>
var str = '';
for (var i = 1; i <= 10; i++) {
for (var j = i; j <= 10; j++) {
str = str + '⭐';
}
str = str + '\n';
}
console.log(str);
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
while
循环
- 语法结构:
while(条件表达式){循环体}
; - 执行思路:当条件表达式结果为
true
,则执行循环体;否则,退出循环; - 代码验证:
var num=1;
while(num<=100){
console.log('你好');
num++;
}
- 1
- 2
- 3
- 4
- 5
- 里面应该也有计数器,初始化变量;
- 里面应该也有操作表达式,完成计数器的更新,防止死循环;
while
循环案例
<script>
// 1、打印人的一生,从1岁到100岁;
// var i=1;
// while(i<=100){
// ('这个人今年'+i+'岁了');
// i++;
// }
// 2、计算1~100之间所有整数的和;
// var i = 1;
// var sum = 0;
// while (i <= 100) {
// sum = sum + i;
// i++;
// }
// (sum);
// 3、弹出一个提示框,你爱我吗?如果输入我爱你,就提示结束,否则,一直询问;
var message = prompt('你爱我吗?');
while (message !== '我爱你') {
message = prompt('你爱我吗?');
}
alert('我也爱你呀');
</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
dowhile
循环
-
dowhile
语句其实是while
语句的一个变体。该循环会先执行一次代码块,然后对条件表达式进行判断,如果条件为真,就会重复执行循环体,否则退出循环; - 语法结构:
do{
//循环体
}while(条件表达式)
- 1
- 2
- 3
- 执行思路:跟
while
不同的地方在于dowhile
先执行一次循环体,再判断条件;如果条件表达式结果为真,则继续执行循环体,否则退出循环;
<script>
// 代码验证
var i = 1;
do {
console.log('你好');
i++;
} while (i <= 100)
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
-
dowhile
语句至少会执行一次循环体代码;
dowhile
案例
<script>
// 1、代码验证
// var i = 1;
// do {
// ('你好');
// i++;
// } while (i <= 100)
// 2、打印人的一生,从1岁到100岁;
// var i = 1;
// do {
// ('这个人今年'+i+'岁了');
// i++;
// } while (i <= 100)
// 3、计算1~100之间所有整数的和;
// var i = 1;
// var sum = 0;
// do {
// sum = sum + i;
// i++;
// } while (i <= 100)
// (sum);
// 3、弹出一个提示框,你爱我吗?如果输入我爱你,就提示结束,否则,一直询问;
do {
var message = prompt('你爱我吗?');
} while (message !== '我爱你')
alert('我也爱你呀');
</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
- 26
- 27
- 28
- 29
- 30
循环小结
- JS中循环有
for
、while
、dowhile
; - 三个循环很多情况下都可以互相替代使用;
- 如果是用来计次数,跟数字相关的,三者使用基本相同,但是我们更喜欢用
for
; -
while
、dowhile
可以做更复杂的判断条件,比for
灵活一些; -
while
和dowhile
执行顺序不一样,while
先判断,后执行;dowhile
先执行一次,再判断执行; -
while
和dowhile
执行次数不一样,dowhile
至少会执行一次循环体,而while
可能一次也不执行; - 实际工作中,我们更常用
for
循环,它的写法更简洁直观;
continue
和break
关键字
continue
关键字
- 用于【立即跳出本次循环,继续下一次循环】(本次循环体中
continue
之后的代码就会少执行一次);
continue
关键字案例
<script>
// continue关键字(退出本次,即当前次的循环;继续执行剩余次的循环)
// for (var i = 1; i <= 5; i++) {
// if (i === 3) {
// continue; // 只要遇到continue就退出本次循环,直接跳到
// }
// (i);//1 2 4 5
// }
// 案例:求1~100之间,除了能被7整除之外的整数和;
var sum = 0;
for (var i = 1; i <= 100; i++) {
if (i % 7 == 0) {
continue;
}
// sum = sum + i;
sum += i;
}
console.log(sum);
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
break
关键字
-
break
关键字用于立即跳出整个循环(循环结束);
// break关键字(退出整个循环)
for (var i = 1; i <= 5; i++) {
if (i == 3) {
break;//退出整个循环
}
console.log(i);// 1 2
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
数组
案例:求数组最大值
<script>
// 求数组[2,6,1,77,52,25,7]中的最大值;
/*
案例分析:
(1)、声明一个保存最大元素的变量max;
(2)、默认最大值可以取数组中的第一个元素;
(3)、遍历这个数组,把里面每个数组元素和max相比较;
(4)、如果这个数组元素大于max就把这个数组元素存到max里面,否则继续下一轮比较;
(5)、最后输出这个max;
*/
var arr = [2, 6, 1, 77, 52, 25, 7];
var max = arr[0];
for (var i = 1; i <= arr.length; i++) {
if (max < arr[i]) {
max = arr[i];
}
}
console.log(max);
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
数组中新增元素
- 可以通过修改
length
长度以及索引号增加数组长度;
(1)、可以通过修改length
长度来实现数组扩容的目的; -
length
属性是可读写的;
(2)、通过修改数组索引新增数组元素; - 可以通过修改数组索引的方式追加数组元素;
<script>
// 1、新增数组元素-修改length长度;
var arr = ['red', 'green', 'blue'];
console.log(arr.length);
arr.length = 5;//我们把数组长度修改为了5,里面应该有5个元素;
console.log(arr);// ['red', 'green', 'blue', empty × 2]
console.log(arr[3]);//undefined
console.log(arr[4]);//undefined
// 2、新增数组元素-通过修改数组索引新增数组元素;追加数组元素;
// 之前索引号里面没有元素时是追加元素;有元素时是替换元素;
var arr1 = ['red', 'blue', 'green'];
arr1[3] = 'pink';
console.log(arr1);//['red', 'blue', 'green', 'pink']
arr1='有点意思';
console.log(arr1);//不能直接给数组名赋值,否则会覆盖掉以前的数据;
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
案例:新建一个数组,里面存放10个整数(1-10)
<script>
var arr = [];
for (var i = 0; i < 10; i++) {
//arr=i; //不要直接给数组名赋值,否则以前的元素都没了;
arr[i] = i+1;
}
console.log(arr);// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
案例:筛选数组
方法一:
<script>
// 将数组[2,0,6,1,77,0,52,0,25,7]中大于等于10的元素选出来,放入新数组;
var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7];
var arr1 = [];
var j = 0;
for (var i = 0; i <= arr.length; i++) {
// 新数组应该从0开始,一次递增;
if (arr[i] >= 10) {
// arr1[i] = arr[i]; //[empty × 4, 77, empty, 52, empty, 25] 原因:从第四个开始有值,当i=1,2,3时是没有值存进去的;
arr1[j] = arr[i];
j++; //[77, 52, 25]
}
}
console.log(arr1);
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
方法二:
// 筛选数组方法二:
var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7];
var arr1 = [];
for (var i = 0; i <= arr.length; i++) {
// 新数组应该从0开始,一次递增;
if (arr[i] >= 10) {
// arr1[i] = arr[i]; //[empty × 4, 77, empty, 52, empty, 25] 原因:从第四个开始有值,当i=1,2,3时是没有值存进去的;
arr1[arr1.length] = arr[i];//刚开始 就是0;数组的length会根据数组长度的变化而变化;
}
}
console.log(arr1);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
案例:数组去重
<script>
// 方法一:
var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7];
var newArr = [];
// for (var i = 0; i < ; i++) {
// if ((arr[i]) === -1) {
// (arr[i]);
// }
// }
// (newArr);
// 方法二:
var mySet=new Set(arr);//利用了Set结构不能接收重复数据的特点;
for(var val of mySet){
newArr.push(val);
}
console.log(newArr);
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
案例:翻转数组
<script>
// 要求:将数组['red','green','pink','blue',purper]的内容反过来存放;
var arr = ['red', 'green', 'pink', 'blue', 'purper'];
var newArr = [];
for (var i = arr.length - 1; i >= 0; i--) {
newArr[newArr.length] = arr[i];
}
console.log(newArr);
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
复习:交换两个变量
var num1=10;
var num2=20;
var temp;
temp=num1;
num1=num2;
num2=temp;
console.log(num1,num2);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
案例:数组排序(冒泡排序)
- 冒泡排序是一种算法,把一系列的数据按照一定的顺序进行排列显示(从小到大或从大到小);
<script>
var arr = [5, 4, 3, 2, 1];
for (var i = 0; i <= arr.length - 1; i++) {//外层循环管趟数
for (var j = 0; j <= arr.length - i - 1; j++) {//里面的循环管每一趟的交换次数;
// 内部交换两个变量的值,前一个和后面一个数组元素相比较;
if (arr[j] > arr[j + 1]) {
var temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
console.log(arr);
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
函数
函数导读
- 函数:函数就是封装了一段可以被重复执行调用的代码块;目的就是让大量代码重复使用;
- 函数使用分为两步:【声明函数】和【调用函数】;
function 函数名(){
//函数体
}
函数名()
- 1
- 2
- 3
- 4
- 函数是做某件事情,函数名一般是动词;(sayHi)
- 函数不调用自己不执行;
- 注意:声明函数本身并不会执行代码,只有调用函数时才会执行函数体代码;
- 函数的封装:就是把一个或多个功能通过函数的方式封装起来,对外只提供一个简单的函数接口;
案例:利用函数求1~100的累加和
<script>
function getSum() {
var sum = 0;
for (var i = 1; i <= 100; i++) {
sum += i;
}
console.log(sum);
}
getSum();
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
函数的参数
- 我们可以利用函数的参数实现函数重复不同的代码;
- 【形参】和【实参】;
function 函数名(形参1,形参2,...){
}
函数名(实参1,实参2,...);
- 1
- 2
- 3
- 4
- 在声明函数的小括号里面是【形参】;(形式上的参数)
- 在函数调用的小括号里面是【实参】;(实际的参数)
- 形参和实参的执行过程:(形参是接收实参的;形参类似于一个变量;)
- 函数的参数可以有,也可以没有,个数不限;
案例:利用函数求任意两个数的和以及累加和
<script>
// 1、利用函数求任意两个数的和
function getSum(num1, num2) {
console.log(num1 + num2);
}
getSum(1, 3);
// 2、利用函数求任意两个数之间的和
function getSums(start, end) {
var sum = 0;
for (var i = start; i <= end; i++) {
sum += i;
}
console.log(sum);
}
getSums(1, 100);
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 注意点:
(1)、多个参数之间用逗号隔开;
(2)、形参可以看作是不用声明的变量;
函数的形参和实参匹配问题
- 如果实参的个数和形参的个数一致,则正常输出结果;
- 如果实参的个数多于形参的个数,会取到形参的个数;
- 如果实参的个数小于形参的个数,多于的形参定义为
undefined
,最终的结果就是NaN
; - 形参可以看作是不用声明的变量,num2是一个变量但是没有接受值,结果就是
undefined
; - 建议:我们尽量让实参的个数和形参相匹配;
function getSum(num1,num2){
console.log(num1+num2);
}
getSum(1,2);
getSum(1,2,3);
getSum(1);//NaN (任何数字 + undefined = NaN )
- 1
- 2
- 3
- 4
- 5
- 6
函数的返回值return
- 有时候,我们会希望函数将值返回给调用者,此时通过使用
return
语句就可以实现;
function 函数名(){
return 需要返回的结果;
}
函数名();
- 1
- 2
- 3
- 4
- 我们函数只是实现某种功能,最终的结果需要返回给函数的调用者;通过
return
来实现的; - 只要函数遇到
return
,就把后面的结果返回给函数的调用者; - 函数名() =
return
后面的结果;
function getResult(){
return 666;
}
getResult()
console.log(getResult());//666
- 1
- 2
- 3
- 4
- 5
案例:求任意两个数的和
function getSum(num1,num2){
return num1 + num2;
}
console.log(getSum(1,2));
- 1
- 2
- 3
- 4
案例:利用函数求两个数的最大值
<script>
function getMax(num1, num2) {
// if (num1 > num2) {
// return num1;
// } else {
// return num2;
// }
return num1 > num2 ? num1 : num2;
}
console.log(getMax(6, 2));
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
案例:利用函数求数组中的最大值
<script>
// var arr=[5,2,99,101,67,77];
function getArrMax(arr) {// arr 接收一个数组
var max = arr[0];
for (var i = 1; i <= arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
// (getArrMax([5, 2, 99, 101, 67, 77]));//实参是一个数组送过去
var re = getArrMax([5, 2, 99, 101, 67, 77]);
console.log(re);
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
return
终止函数并且只能返回一个值
-
return
终止函数,return
语句之后的代码不被执行;
function getSum(num1,num2){
return num1+num2;
alert("我是不会被执行的");//return 后面的的代码不会被执行
}
console.log(getSum(1,2));
- 1
- 2
- 3
- 4
- 5
-
return
只能返回一个值。如果用逗号隔开多个值,以最后一个为准;
function fn(num1,num2){
return num1,num2;//返回的结果是最后一个值
}
console.log(fn(1,2));
- 1
- 2
- 3
- 4
- 我们求任意两个数的 加减乘除 结果:
function getResult(num1,num2){
return [num1+num2,num1-num2,num1*num2,num1/num2];
}
console.log(fn(1,2));//返回的是一个数组
- 1
- 2
- 3
- 4
函数没有return
,返回undefined
;
- 我们的函数如果有
return
,则返回的是return
后面的值;如果函数没有return
,则返回undefined
;
break
、continue
、return
的区别
arguments 的使用
当我们不确定有多少个参数传递的时候,可以用arguments
来获取,在JS中,arguments
实际上它是当前函数的一个【内置对象】。所有函数都内置了一个arguments
对象,arguments
对象中【存储了传递的所有实参】;
<script>
function fn() {
console.log(arguments); // Arguments(3),arguments是以伪数组的形式来展示的;
//我们可以按照数组的方式遍历 Arguments;
}
fn(1, 2, 3)
/*
伪数组并不是真正意义上的数组:
1、具有数组的 length 属性;
2、按照索引的方式进行存储的;
3、没有真正数组的一些方法,如:pop()、push() 等;
*/
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
函数的两种声明方式
<script>
// 1、利用函数关键字自定义函数(命名函数)
function fn() { }
fn()
// 2、函数表达式(匿名函数)
//注意:函数表达式声明方式跟变量差不多,只不过变量里面存的是值,而函数表达式里面存的是函数;
// var 变量名 = function(){}
var fun = function () { } // 注意:此处的 fun 是变量名,不是函数名;
fun() // 变量名 + ()实现调用;函数表达式也可以进行传递参数;
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
arguments
案例:利用函数求任意几个数的最大值
<script>
function getMax() {
var max = arguments[0];
for (var i = 1; i < arguments.length; i++) {
if (arguments[i] > max) {
max = arguments[i];
}
}
return max;
}
console.log(getMax(7, 2, 5, 99, 0, 2346));
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
案例:利用函数封装方式,翻转任意一个数组
<script>
function getArrReverse(arr) {
var newArr = [];
for (var i = arr.length - 1; i >= 0; i--) {
newArr[newArr.length] = arr[i];
}
return newArr;
}
console.log(getArrReverse([1, 2, 3, 4, 5]));
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
案例:利用函数封装冒泡排序
<script>
function sort(arr) {
for (var i = 0; i <= arr.length - 1; i++) {
for (var j = 0; j <= arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
var temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return arr;
}
console.log(sort([5, 7, 3, 2, 0, 8, 1]));
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
案例:运用函数封装判断闰年
<script>
// 闰年:能被4整除并且不能被100整除;或者能被400整除;
// function isRunYear(year){
// if(year % 4 === 0 && year % 100 !=0 || year % 400 === 0){
// return year+'年是闰年';
// }else{
// return year+'年是平年';
// }
// }
// (isRunYear(2020));
function isRunYear(year){
// 如果是闰年我们返回true;否则返回false;
var flag = false;
if(year % 4 === 0 && year % 100 !=0 || year % 400 === 0){
flag = true;
}
return flag;
}
console.log(isRunYear(2000));
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
函数可以调用另外一个函数
- 因为每个函数都是独立的代码块,用于完成特殊任务,因此经常会用到函数相互调用的情况;
function fn1(){
console.log(11);
fn2();//在fn1函数里面调用了fn2函数;
}
fn1();
function fn2(){
console.log(22);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
一个函数调用另外一个函数案例:用户输入年份,输出当前年份2月份的天数
<script>
function backDay(){
var year = prompt('请输入年份');
if(isRunYear(year)){//调用函数需要加小括号
alert('当前年份是闰年,2月份有29天');
}else{
alert('当前年份是平年,2月份有28天');
}
}
backDay();
// 判断是否为闰年的函数
function isRunYear(year){
// 如果是闰年我们返回true;否则返回false;
var flag = false;
if(year % 4 === 0 && year % 100 !=0 || year % 400 === 0){
flag = true;
}
return flag;
}
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
Javascript作用域
作用域概述:
通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的【可用性的代码范围】就是这个名字的作用域。作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字的冲突。
Javascript作用域: 就是代码名字(变量)在某个范围内起作用和效果;目的是为了提高程序的可靠性,更重要的是减少命名冲突;js作用域(es6)之前:全局作用域 局部作用域;
全局作用域: 【整个 script 标签】或者是一个【单独的js文件】
局部作用域(函数作用域): 在函数内部就是局部作用域;这个代码的名字只在函数内部起效果和作用;
变量的作用域:
- 根据作用域的不同,我们把变量分为【全局变量】和【局部变量】
全局变量:
- 全局变量:在全局作用域下声明的变量(在函数外部定义的变量),在全局下都可以使用;
- 全局变量在代码的任何位置都可以使用;
- 在全局作用域下var声明的变量是【全局变量】;
- 特殊情况下,在函数内不使用var声明的变量也是全局变量(不建议使用);
- 注意:如果在函数内部,没有声明直接赋值的变量也属于【全局变量】;
局部变量:
- 在局部作用域下声明的变量,或者在函数内部定义的变量就是局部变量;
- 局部变量只能在该函数内部使用;
- 在函数内部var声明的变量是局部变量;
- 注意: 函数的形参也可以看做是【局部变量】;
从执行效率来看【全局变量】和【局部变量】:
- 全局变量只有浏览器关闭的时候才会销毁,比较占内存资源;
- 局部变量当我们程序执行完毕就会销毁,比较节约内存资源;
块级作用域:
- 用 {} 包裹
作用域链:
内部函数访问外部函数的变量,采取的是链式查找的方式来决定取哪个值,这种结构我们称为作用域链。(就近原则)
- 只要是代码,就至少有一个作用域;
- 写在函数内部的局部作用域;
- 如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域;
- 根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称为【作用域链】;
预解析
- JavaScript代码是由浏览器中的JavaScript解析器(引擎)来执行的。JavaScript解析器在运行JavaScript代码的时候分为两步:【预解析】和【代码执行】。
- 预解析: js引擎会把js里面所有的 var,还有 function 提升到当前作用域的最前面;
- 代码执行:按照代码书写的顺序从上往下执行;
- 预解析分为【变量预解析(变量提升)】和【函数预解析(函数提升)】。
变量提升:
- 就是把所有的变量声明提升到当前的作用域最前面,不提升赋值操作;
函数提升:
- 就是把所有的函数声明提升到当前作用域的最前面,不调用函数;
// 1问
console.log(num) // 报错
// 2问
console.log(num) // undefined 坑1
var num=10
// 相当于执行了以下代码
var num ;
console.log(num)
num=10
// 3问
fn() // 11
function fn(){
console.log(11)
}
fn() // 11
// 4问
fun() // 报错 fun is not a function
var fun=function(){ // 函数表达式 调用必须写在函数表达式的下面
console.log(22)
}
fun() // 22
//相当于执行了以下代码
var fun ;
fun();
fun=function(){
console.log(22)
}
- 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
- 30
- 注意:
var a=b=c=9;
// 相当于:var a=9;b=9;c=9 区别于【集体声明】
//所以此处的 b 和 c 直接赋值,没有 var 声明,此处的 b 和 c 当全局变量看;
// 集体声明(用逗号隔开)
var a=9,b=9,c=9
- 1
- 2
- 3
- 4
- 5
- 6
对象
什么是对象?
- 在Javascript中,对象是一组无序的相关属性和方法的集合,所有的事务都是对象,例如:字符串、数值、数组、函数等;
- 对象是由【属性】和【方法】组成的:
【属性】:事物的特征,在对象中用属性来表示(常用名词);
【方法】:事物的行为,在对象中用方法来表示(常用动词);
为什么需要对象?
- 保存一个值时,可以使用变量;保存多个值(一组值)时,可以使用数组。JS中的对象表达结构更清晰,更强大。
创建对象的三种方式
1、利用【字面量】创建对象;
- 【对象字面量】就是花括号 {} ,里面包含了表达这个具体事物(对象)的属性和方法;
- 调用属性还有一种方法:对象名[‘属性名’]
2、利用 【new Object】 创建对象;
3、利用【构造函数】创建对象;
- 我们为什么需要使用构造函数?就是因为我们前面两种创建对象的方式一次只能创建一个对象;我们一次创建一个对象,里面很多的属性和方法是大量相同的,我们只能复制;因此,我们可以利用函数的方法,重复这些相同的代码,我们就把这个函数称为构造函数。又因为这个函数不一样,里面封装的不是普通代码,而是【对象】。
- 构造函数:就是把我们对象里面一些相同的属性和方法抽象出来,封装到函数里面;
- 构造函数: 是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与new运算符一起使用。我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面。
//构造函数的语法格式
function 构造函数名(){
this.属性=值
this.方法=functon(){}
}
new 构造函数名() //调用构造函数
- 1
- 2
- 3
- 4
- 5
- 6
function Star(uname,age,sex){
this.name=uname;
this.age=age;
this.sex=sex;
this.sing=function(sang){
console.log(sang)
}
}
// 调用函数返回的是一个对象
var ldh = new Star('刘德华',18,'男')
ldh.sing('冰雨');
console.log(typeof ldh)
console.log(ldh.name)
console.log(ldh['sex'])
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
注意:
1、构造函数名字首字母要大写;
2、我们构造函数不需要return 就可以返回结果;
3、我们调用构造函数,必须使用new;
4、我们只要 new Sar()
调用函数,就创建一个对象;
5、我们的属性和方法前面必须添加this
;
构造函数和对象的区别?
- 对象:是特指一个具体的事务,例如:刘德华;
- 构造函数:抽象了对象的公共部分,封装到了函数里面,它泛指某一大类,例如:明星;它类似于Java语言里的类(class);
- 我们利用构造函数(new关键字)创建对象的过程,也称为对象的【实例化】;
new关键字执行过程(new在执行时会做四件事)
1、new
构造函数可以在内存中创建了一个空的对象;
2、this
就指向刚才创建的空对象;
3、执行构造函数里面的代码,给这个空对象添加属性和方法;
4、返回这个新对象(所以构造函数里面不需要return
);
遍历对象属性:for...in
语句用于对【数组】或者【对象的属性】进行【循环】操作;
//for in 遍历对象
// 语法规则:for (变量 in 对象){}
for(var k in obj){
console.log(k); // k:变量,输出得到的是:属性名
console.log(obj[k]); // obj[k] 得到的是:属性值
//注意:此处的 k 是一个变量,无需用引号包裹;
// 我们使用 for in 时,里面的变量,我们喜欢写 k 或者 key
// for in 也可以遍历出对象里面的方法
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
小结:
- 对象可以让代码结构更清晰;
- 对象是复杂数据类型
Object
; - 对象的本质:就是一组无序的相关属性和方法的集合;
- 构造函数泛指某一大类,比如苹果,不管是红色苹果还是绿色苹果,都统称为苹果;
- 对象实例特指一个事物,比如这个苹果等;
-
for in
语句用于对对象的属性进行循环操作;
【变量】【属性】【函数】【方法】的区别
- 变量:变量和属性的相同点:他们都是用来存储数据的;
- 变量:单独声明并赋值,使用的时候直接写变量名,单独存在;
- 属性:在对象里面的不需要声明的,使用的时候必须是 对象.属性;
- 函数和方法的相同点:都是实现某种功能,做某件事;
- 函数是单独声明,并且调用的;函数名 + ()调用;单独存在的;
- 方法在对象里面,调用的时候:对象.方法()调用;
JavaScript内置对象
- JavaScript中的对象分为3种:自定义对象、内置对象、浏览器对象;
- 前面两种对象是JS基础内容,属于
ECMAScript
;第三个浏览器对象属于我们JS独有的; - 【内置对象】就是指JS语言自带的一些对象,这些对象供开发者使用,并提供了一些常用的或是最基本而必要的功能(属性和方法);
- JavaScript提供了多个内置对象:
Math
、Date
、Array
、String
等; - /zh-CN/
//利用对象封装自己的数学对象,里面有 PI 最大值和最小值
var myMath={
PI:3.141592653,
max:function(){
var max=arguments[0];
for(var i=1;i<arguments.length;i++){
if(arguments[i]>max){
max=arguments[i]
}
}
return max;
},
min:function(){
var min=arguments[0];
for(var i=1;i<arguments.length;i++){
if(arguments[i]<min){
min=arguments[i]
}
}
return min;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
// 猜数字游戏案例
function getRandom(min,max){
return Math.floor(Math.random() * (max-min + 1)) + min;
}
var random =getRandom(1,10);
while(true){ //死循环
var num = prompt('你来猜?输入1~10之间的一个数字');
}
if(num>random){
alert('你猜大了')
}else if(num<random){
alert('你猜小了')
}else{
alert('猜对了!')
break; // 退出整个循环,结束程序
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
日期对象(Date()
)
- 日期对象是一个构造函数,必须使用
new
来调用创建我们的日期对象; - 使用
Date()
,如果没有参数,返回当前系统的当前时间; - 参数常用的写法:数字型:
2019,10,01
或者是字符串型:2019-10-1 8:8:8
//格式化日期年月日星期(星期天返回的是0)
var arr=['星期天','星期一','星期二','星期三','星期四','星期五','星期六']
var date=new Date();
var day=date.getDay();
console.log(arr[day])
- 1
- 2
- 3
- 4
- 5
//封装一个函数返回当前的时分秒,格式:08:08:08
function getTimer(){
var time=new Date();
var h=time.getHours();
h = h<10?'0'+h:h
var m=time.getMinutes()
m = m<10?'0'+m:m
var s=time.getSeconds()
s = s<10?'0'+s:s
return h+':'+m+':'+s
}
console.log(getTimer())
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
倒计时案例:
数组
字符串
基本包装类型
- 对象才有属性和方法;复杂数据类型才有属性和方法;简单数据类型为什么会有
length
属性呢? - 基本包装类型:为了方便操作基本数据类型,JavaScript还提供了三个特殊的引用类型:String、Number 和 Boolean(三种基本包装类型);基本包装类型就是把【简单数据类型】包装成为【复杂数据类型】,这样基本数据类型就有了【属性】和【方法】;
(1)、把简单数据类型,包装成复杂数据类型;
(2)、把临时变量的值给str;
(3)、销毁这个临时变量;
var str = 'andy';
console.log(str.length);
var temp = new Sring('andy');
str = temp;
temp = null;
- 1
- 2
- 3
- 4
- 5
字符串的不可变
- 字符串的不可变:指的是里面的值不可变,虽然看上去可以改变内容,但其实是地址改变了,内存中新开辟了一个内存空间;所以不要大量的拼接字符串;
- 字符串所有的方法,都不会修改字符串本身(字符串是不可变的),操作完成会返回一个新的字符串;
// 案例:查找字符串“abcoefoxyozzopp”中所有o出现的位置以及次数;
/*
核心算法:先查找第一个o出现的位置,然后,只要 indexOf 返回的结果不是 -1,就继续往后查找;因为 indexOf 只能查找到第一个,所以后面的查找一定是当前索引加1,从而继续查找;
*/
var str = 'abcoefoxyozzopp'
var index = str.indexOf('o')
var num = 0;
while(index !== -1){
console.log(index)
num++
index = str.indexOf('0',index+1);
}
console.log('o出现的次数是' + num)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
//案例:遍历字符串
// charAt(index) 根据位置返回字符
var str= 'andy'
console.log(str.charAt(3))
//遍历所有字符串
for(var i=0;i<str.length;i++){
console.log(str.charAt(i))
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
// 有一个对象,判断该对象里有没有该属性 对象['属性名']
var o={
age:18
}
if(o['age']){
console.log('里面有该属性')
}else{
console.log('里面没有该属性')
}
// 案例:统计字符串 'abcoefoxyozzopp' 中出现次数最多的字符
/*
核心算法:利用 charAt() 遍历这个字符串;把每个字符都存储给对象,如果对象没有该属性,就为1,如果存在了就 +1;遍历对象,得到最大值和该字符;
*/
var str = 'abcoefoxyozzopp';
var o ={}
for(var i=0;i<str.length;i++){
var charts=str.charAt(i) // charts 是字符串的每一个字符
if(o[charts]){ //o[charts]得到的是属性值
o[charts]++
}else{
o[charts]=1
}
}
console.log(o)
// 遍历对象,求出出现最多的次数
var max = 0;
var ch = '';//统计出现次数最多的字符
for(var k in o){ //遍历对象用 for in
// k 得到的是属性名
// o[k] 得到的是属性值
if(o[k]>max){
max=o[k];
ch=k
}
}
console.log(max)
console.log(ch)
- 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
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 替换字符:
('被替换的字符','替换为的字符')
,只会替换第一个字符;
//案例:有一个字符 'abcoefoxyozzopp' ,要求把里面所有的 o 替换为 *;(该方法可用于实现过滤敏感词等功能)
var str = 'abcoefoxyozzopp';
while(str.indexOf('o') !== -1){
str = str.replace('o','*')
}
console.log(str)
- 1
- 2
- 3
- 4
- 5
- 6
JavaScript简单数据类型和复杂数据类型
数据类型内存分配
- 【简单数据类型】又叫做【基本数据类型】或【值类型】;【复杂类型】又叫做【引用类型】;
(1)、值类型:简单数据类型/基本数据类型,在存储时变量中存储的是值本身,因此叫做值类型;(string 、number 、boolean 、 undefined 、null(null 返回的是一个空的对象 Object))
注意:如果有个变量我们以后打算存储为对象,暂时没想好放啥,这个时候就给 null;
(2)、引用类型:复杂数据类型,在存储时变量中存储的仅仅是【地址】(引用),因此叫做引用数据类型;通过 new 关键字创建对象(系统对象、自定义对象),比如 Object 、Array 、 Date 等;
堆和栈
- 堆栈空间分配区别?
(1)、栈(操作系统):由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈;简单数据类型存放到栈里面,里面直接开辟一个空间,存放的是值;
(2)、堆(操作系统):存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收;复杂数据类型存放在堆里面;(复杂数据类型:首先在栈里面存放用【用十六进制表示】的地址,然后这个地址指向堆里面的数据)
注意:JavaScript中没有堆栈的概念,通过堆栈的方式,可以让大家更容易理解代码的一些执行方式,便于将来学习其他语言;
简单类型传参(简单数据类型传参传值,复杂数据类型传参传地址)
- 函数的形参也可以看做是一个变量,当我们把一个值类型变量作为参数传给函数的形参时,其实是把变量在栈空间里的值复制了一份给形参,那么在方法内部对形参做任何修改,都不会影响到外部的变量;
function fn(a) {
a++
console.log(a); // 11
}
var x = 10
fn(x)
console.log(x);// 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
复杂类型传参
- 函数的形参也可以看作是一个变量,当我们把引用类型变量传给形参时,其实是把变量在栈空间里保存的堆地址复制给了形参,形参和实参其实保存的是同一个堆地址,所以操作的是同一个对象。
function Person(name){
this.name=name
}
function f1(x){//x=p
console.log(x.name)//2、这里输出什么?刘德华
x.name='张学友'
console.log(x.name)//3、这里输出什么?张学友
}
var p=new Person('刘德华')
console.log(p.name)//1、这里输出什么?刘德华
f1(p)
console.log(p.name)//4、这里输出什么?张学友
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
Web APIs和JS基础
- API:是为我们程序员提供的一个接口,帮助我们实现某种功能,我们会使用就可以了,不必纠结内部如何实现;
- Web API:是浏览器提供的一套操作【浏览器功能】和【页面元素】的API(BOM和DOM)。主要是针对于浏览器提供的接口,主要针对于浏览器做交互效果;
- Web API一般都有输入和输出(函数的传参和返回值),Web API很多都是方法(函数)。
Dom
- 什么是Dom?文档对象模型(Document Object Model,简称Dom),是W3C组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口。
- W3C已经定义了一系列DOM接口,通过这些DOM接口可以改变网页的内容、结构和样式。
- Dom树:
- 文档:一个页面就是一个文档,DOM中使用document表示。
- 元素:页面中的所有标签都是元素,DOM中使用element表示。
- 节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM中使用node表示。
- DOM把以上内容都看做是对象。
- DOM在我们实际开发中主要用来操作元素的。
- 获取页面中的元素可以使用以下几种方法:(返回的是一个元素对象)
(1)、根据ID获取;
(2)、根据标签名获取;(返回的是获取过来元素对象的集合,以伪数组的形式存储的)(还可以获取某个元素(父元素)内部所有指定标签名的子元素,注意:父元素必须是【单个对象】(必须指明是哪一个元素对象),获取的时候不包括元素自己)var ol=('ol') (ol[0].('li') )
简单做法:给父元素添加ID,通过ID获取父元素,然后获取父元素里面的子元素;
(3)、通过HTML5新增的方法获取;()
、('选择器')
(根据指定选择器返回第一个元素对象)、('选择器')
(根据指定选择器返回所有元素对象集合)
(4)、特殊元素获取; - ()打印我们返回的元素对象,更好的查看里面的属性和方法;
- 获取body元素:
- 获取html元素:
事件
- JavaScript使我们有能力创建动态页面,而事件是可以被JavaScript侦测到的行为;简单理解:触发 — 响应机制;
- 事件三要素:事件是由三部分组成:事件源、事件类型、事件处理程序,被称为事件三要素;
(1)、事件源:事件被触发的对象;
(2)、事件类型:如何触发,什么事件。比如:鼠标点击、鼠标经过、键盘按下;
(3)、事件处理程序:通过一个函数赋值的方式完成;
<button id='btn'>按钮</button>
var btn=document.getElementById('btn');
btn.onclick=function(){
alert('弹窗')
}
- 1
- 2
- 3
- 4
- 5
- 6
操作元素
- JavaScript的DOM操作可以改变网页内容、结构和样式,我们可以利用DOM操作元素来改变元素里面的内容、属性等。注意以下都是属性;
改变元素内容
-
从起始位置到终止位置的内容,但它取出
html
标签,同时空格和换行也会去掉;(不识别html标签)非标准 去除空格和换行
<button>点击改变时间</button>
<div>写死的时间</div>
<p>123</p>
<script>
// 1、获取元素
var btn = document.querySelector('button');
var div = document.querySelector('div')
// 注册事件
btn.onclick = function () {
// = '2022-1-2'
div.innerText = getDate()
}
function getDate() {
var date = new Date()
var year = date.getFullYear();
var month = date.getMonth();
var dates = date.getDate();
var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
var day = date.getDay();
return '今天是:' + year + '年' + month + '月' + dates + '日' + arr[day]
}
// 我们元素可以不用添加事件
var p = document.querySelector('p')
p.innerText = getDate()
</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
- 26
- 27
-
起始位置到终止位置的全部内容,包括
html
标签,同时保留空格和换行;(识别html标签)W3C标准 保留空格和换行
var p = document.querySelector('p')
p.innerHTML = '<strong>今天是:</strong>2022-1-2' //实现给‘今天是’加粗
- 1
- 2
- 这两个属性是可读写的,可以获取元素里面的内容。
<p>
我是文字
<span>123</span>
</p>
var p=document.querySelector('p')
console.log(p.innerText)//我是文字 123
console.log(p.innerHTML)//我是文字 <span>123</span>(空格和换行依然保留)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
修改元素属性
常用元素的属性操作
-
innerText
、innerHTML
改变元素内容; -
src
、href
; -
id
、alt
、title
;
//案例:分时问候案例
<img src="./images/" alt="">
<div>上午好</div>
<script>
// 获取元素
var img = document.querySelector('img')
var div = document.querySelector('div')
// 得到当前的小时数
var date = new Date();
var h = date.getHours();
// 判断小时数改变图片和文字信息
if (h < 12) {
img.src = './images/'
div.innerHTML = '上午好'
} else if (h < 18) {
img.src = './images/'
div.innerHTML = '下午好'
} else {
img.src = './images/'
div.innerHTML = '晚上好'
}
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
表单元素的属性操作
- 利用 DOM 可以操作如下表单元素的属性:
type
value
checked
selected
disabled
//1、获取元素
var btn= document.querySelector('button')
var input= document.querySelector('input')
//2、注册事件 处理程序
btn.onclick=function(){
//=true //禁用按钮
this.disabled=true //this 指向的是事件函数的调用者
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
//案例:仿京东显示隐藏密码明文案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>显示隐藏密码案例</title>
<style>
.box {
position: relative;
width: 400px;
border-bottom: 1px solid #ccc;
margin: 100px auto;
}
.box input {
width: 370px;
height: 30px;
border: 0;
outline: none;
}
.box img {
position: absolute;
top: 2px;
right: 2px;
width: 24px;
}
</style>
</head>
<body>
<div class="box">
<label for="">
<img src="./images/green_close_eye.png" alt="" id="eye">
</label>
<input type="password" name="" id="pwd">
</div>
<script>
var eye = document.getElementById('eye')
var pwd = document.getElementById('pwd')
//方法1: 利用flag变量记录点击
var flag = 0
eye.onclick = function () {
// 点击一次过后,flag一定要变化
if (flag == 0) {
pwd.type = 'text'
eye.src='./images/green_open_eye.png'
flag = 1;//赋值操作
} else {
pwd.type = 'password'
eye.src='./images/green_close_eye.png'
flag = 0;
}
}
//方法2: 计数器思想记录点击
var count = 0;
eye.onclick = function () {
count++
if (count % 2 == 0) {
eye.src = "./images/green_close_eye.png"
pwd.type = "password"
} else {
eye.src = "./images/green_open_eye.png"
pwd.type = "text"
}
}
</script>
</body>
</html>
- 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
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
样式属性操作
- 我们可以通过JS修改元素的大小、颜色、位置等样式;
-
行内样式操作;
-
类名样式操作;
- 注意:JS里面的样式采取驼峰命名法,比如:
fontSize
backgroundColor
;JS修改style样式操作,产生的是行内样式,CSS权重比较高;
循环精灵图背景
//案例:循环精灵图背景;可以利用for循环设置一组元素的精灵图背景。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>循环遍历精灵图</title>
<style>
* {
margin: 0;
padding: 0;
}
li {
list-style-type: none;
}
.box {
width: 250px;
margin: 100px auto;
}
.box li {
float: left;
width: 24px;
height: 24px;
background-color: pink;
margin: 15px;
background: url(./images/icons.png) no-repeat;
}
</style>
</head>
<body>
<div class="box">
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
<script>
// 1、获取所有元素,所有的li
var lis = document.querySelectorAll('li')
// 2、让索引号 乘以 44 就是每个 li 的背景y坐标,index就是我们的y坐标;
for (var i = 0; i < lis.length; i++) {
var index = i * 24 //我这张精灵图是24
lis[i].style.backgroundPosition = '0-' + index + 'px'//精灵图的y坐标是负的;x坐标永远是0
//lis[i]. = '0 0' //全部展示第一张图片
//lis[i]. = '0 -24px' //全部展示第二张图片
}
</script>
</body>
</html>
- 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
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
案例:当鼠标点击文本框时,里面的默认文字隐藏;当鼠标离开文本框时,里面的文字显示;
//案例:当鼠标点击文本框时,里面的默认文字隐藏;当鼠标离开文本框时,里面的文字显示;
//`onfocus` `onblur`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>显示隐藏文本框内容案例</title>
<style>
input {
color: #999;
}
</style>
</head>
<body>
<input type="text" value="手机">
<script>
var text = document.querySelector('input')
text.onfocus = function () {
console.log('得到了焦点');
if (this.value === '手机') {
this.value = ''
}
this.style.color = '#333'//获得焦点时把文本框里的文字的颜色变深
}
text.onblur = function () {
console.log('失去了焦点');
if (this.value === '') {
this.value = '手机'
}
this.style.color = '#999'//失去焦点时把文本框里的文字的颜色变浅
}
</script>
</body>
</html>
- 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
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
样式属性操作:我们可以通过JS修改元素的颜色、大小、位置等样式
-
行内样式操作;
-
类名样式操作;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>使用className修改样式属性</title>
<style>
div{
width: 50px;
height: 50px;
background-color: green;
}
.change{
width: 100px;
height: 100px;
background-color: aqua;
margin-top: 100px;
}
</style>
</head>
<body>
<div class='fist'>文本</div>
<script>
var test=document.querySelector('div')
test.onclick=function(){
//我们可以通过 修改元素的 className 更改元素的样式,适合于样式较多或者功能复杂的情况
this.className='change'//点击时给div加上change的类名
//如果想要保留原先的类名,我们可以这么做 ---> 多类名选择器
this.className='fist change'
}
</script>
</body>
</html>
- 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
- 30
- 31
- 32
- 33
- 34
- 注意:className 会直接更改元素的类名,会覆盖原先的类名;
- 如果想要保留原先的类名,我们可以这么做 —> 多类名选择器
案例:密码框验证信息
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>密码框验证信息案例</title>
<style>
div {
width: 600px;
margin: 100px auto;
}
.message {
display: inline-block;
font-size: 12px;
color: #999;
background: url(./images/reg.jpg) no-repeat left center;
padding-left: 20px;
}
.wrong {
color: red;
background-image: url(./images/wrong.jpg);//注意:此处不用写no-repeat left center
}
.right {
color: green;
background-image: url(./images/right.jpg);//注意:此处不用写no-repeat left center
}
</style>
</head>
<body>
<div class="register">
<input type="password" class="ipt">
<p class="message">请输入6~16位密码</p>
</div>
<script>
var ipt = document.querySelector('.ipt')
var messege = document.querySelector('.message')
ipt.onblur = function () {
if (this.value.length < 6 || this.value.length > 16) {
messege.className = 'message wrong';
messege.innerHTML = '你输入的位数不对,要求6~16位'
} else {
messege.className = 'message right';
messege.innerHTML = '你输入的正确'
}
}
</script>
</body>
</html>
- 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
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
操作元素小结:
排他思想
- 如果有同一组元素,我们想要某一个元素实现某种样式,需要用到循环的排他思想算法;
(1)、第一步:所有元素全部清除样式;
(2)、第二步:给当前元素设置样式;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>排他思想</title>
</head>
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<script>
// 首先先排除其他人,然后才设置自己的样式,这种排除其他人的思想我们称为排他思想
var btns = document.querySelectorAll('button')
for (var i = 0; i < btns.length; i++) {
btns[i].onclick = function () {
// 1、我们先把所有按钮的背景颜色去掉
for (var i = 0; i < btns.length; i++) {
btns[i].style.backgroundColor = ''
}
// 2、然后才让当前的元素背景颜色为pink
this.style.backgroundColor = 'pink'
}
}
</script>
</body>
</html>
- 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
- 30
- 31
- 32
百度换肤效果案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>百度换肤效果案例</title>
<style>
* {
margin: 0;
padding: 0;
}
body {
background: url(./images/01.jpeg) no-repeat center top;
}
.baidu {
overflow: hidden;
margin: 100px auto;
background-color: #fff;
width: 410px;
padding-top: 3px;
}
.baidu li {
/* list-style: none; */
float: left;
margin: 0 1px;
cursor: pointer;
}
.baidu img {
width: 100px;
}
</style>
</head>
<body>
<ul class="baidu">
<li><img src="./images/" alt=""></li>
<li><img src="./images/" alt=""></li>
<li><img src="./images/" alt=""></li>
<li><img src="./images/" alt=""></li>
</ul>
<script>
// 1、获取元素(类名是 baidu 下的 img)
var imgs = document.querySelector('.baidu').querySelectorAll('img')
// 2、循环注册事件
for (var i = 0; i < imgs.length; i++) {
imgs[i].onclick = function () {
// 就是我们点击的图片的路径
// 把这个路径 给 body 就可以了
//获取body的背景图片
document.body.style.backgroundImage = 'url(' + this.src + ')'
}
}
</script>
</body>
</html>
- 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
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
表格隔行变色效果案例
//onmouseover鼠标经过 onmouseout鼠标离开
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>表格隔行变色效果案例</title>
<style>
table{
width: 800px;
margin: 100px auto;
text-align: center;
border-collapse: collapse;//设置表格的边框是否被合并为一个单一的边框
font-size: 14px;
}
thead tr{
height: 30px;
background-color: skyblue;
}
tbody tr{
height: 30px;
}
tbody td{
border-bottom: 1px solid #d7d7d7;
color: blue;
}
.bg{
background-color: pink;
}
</style>
</head>
<body>
<table>
<thead>
<tr>
<th>代码</th>
<th>名称</th>
<th>最新公布净值</th>
<th>累计净值</th>
<th>前单位净值</th>
<th>净值增长率</th>
</tr>
</thead>
<tbody>
<tr>
<td>003526</td>
<td>农行金穗3个月定期开放债券</td>
<td>1.075</td>
<td>1.079</td>
<td>1.074</td>
<td>+0.047%</td>
</tr>
<tr>
<td>003527</td>
<td>农行金穗4个月定期开放债券</td>
<td>1.075</td>
<td>1.079</td>
<td>1.074</td>
<td>+0.047%</td>
</tr>
</tbody>
</table>
<script>
// 1、获取元素 获取 tbody 里面所有的 tr
var trs=document.querySelector('tbody').querySelectorAll('tr')
// 2、利用循环绑定注册事件
for(var i=0;i<trs.length;i++){
// 3、鼠标经过事件 onmouseover
trs[i].onmouseover=function(){
this.className='bg';
}
// 4、鼠标离开事件 onmouseout
trs[i].onmouseout=function(){
this.className='';
}
}
</script>
</body>
</html>
- 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
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
表单全选取消全选案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>表单全选取消全选案例</title>
<style>
.wrap {
width: 300px;
margin: 100px auto;
}
table {
width: 100%;
margin: 100px auto;
text-align: center;
border-collapse: collapse;
font-size: 14px;
}
thead tr {
height: 30px;
background-color: skyblue;
}
tbody tr {
height: 30px;
}
tbody td {
border-bottom: 1px solid #d7d7d7;
}
</style>
</head>
<body>
<div class="wrap">
<table>
<thead>
<tr>
<th>
<input type="checkbox" id="j_cbAll">
</th>
<th>商品</th>
<th>价钱</th>
</tr>
</thead>
<tbody id="j_tb">
<tr>
<td>
<input type="checkbox">
</td>
<td>iphone8</td>
<td>8000</td>
</tr>
<tr>
<td>
<input type="checkbox">
</td>
<td>iphone9</td>
<td>9000</td>
</tr>
<tr>
<td>
<input type="checkbox">
</td>
<td>iphone10</td>
<td>10</td>
</tr>
</tbody>
</table>
</div>
<script>
// 第一步:全选和取消全选的做法:让下面所有复选框的checked属性(选中状态)跟随 全选按钮即可
// 1、获取元素
var j_cbAll = document.getElementById('j_cbAll'); // 全选按钮
var j_tbs = document.getElementById('j_tb').getElementsByTagName('input');//下面所有的复选框
// 2、注册事件
j_cbAll.onclick = function () {
// 它可以得到当前复选框的选中状态,如果是 true 就选中,如果是 false ,就是未选中;
console.log(this.checked);
for (var i = 0; i < j_tbs.length; i++) {
j_tbs[i].checked = this.checked;//将全选按钮的选中或未选中状态赋值给所有的 checkbox
}
}
//第二步:下面复选框需要全部选中,上面全选才能选中做法:给下面所有复选框绑定点击事件,每次点击,都要循环遍历
for (var i = 0; i < j_tbs.length; i++) {
j_tbs[i].onclick = function () {
// flag 控制全选按钮是否选中
var flag = true
// 每次点击下面的复选框都要循环检查这四个小按钮是否全被选中
for (var i = 0; i < j_tbs.length; i++) {
if (!j_tbs[i].checked) {
flag = false;
break;//退出for循环,这样可以提高执行效率;因为只要有一个没有选中,剩下的就循环判断了;
}
}
j_cbAll.checked = flag
}
}
</script>
</body>
</html>
- 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
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
自定义属性的操作
获取自定义属性值
-
element.属性
获取属性值;
<div id='demo'></div>
var div=document.querySelector('div')
// 获取元素的属性
// 方法1:element.属性
console.log(div.id); // demo
- 1
- 2
- 3
- 4
- 5
- 6
-
('属性')
attribute 本意“属性”;
<div id='demo'></div>
var div=document.querySelector('div')
// 获取元素的属性
// 方法2:('属性')
console.log(div.getAttribute('id')); // demo
- 1
- 2
- 3
- 4
- 5
- 6
-
element.属性
获取属性值 和('属性')
获取属性值 的区别?
(1)、element.属性
获取内置属性值(元素本身自带的属性)如:id class等;
(2)、('属性')
主要获得自定义的属性(标准)我们程序员自定义的属性;
设置属性值
-
element.属性 = '值'
设置内置属性值;
<div id='demo' class='nav'></div>
var div = document.querySelector('div')
div.className= 'sss'
- 1
- 2
- 3
- 4
-
('属性','值')
;主要针对于自定义属性;
<div id='demo' index='1' class='nav'></div>
var div = document.querySelector('div')
div.setAttribute('index','2')
// class比较特殊,这里面写的就是class,不是className
div.setAttribute('class','sss')
- 1
- 2
- 3
- 4
- 5
- 6
移除属性
('属性')
<div id='demo' index='1' class='nav'></div>
var div = document.querySelector('div')
div.removeAttribute('index')
- 1
- 2
- 3
- 4
tab栏切换案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>tab栏切换案例</title>
<style>
.tab {
width: 1200px;
height: 100px;
}
.tab_list {
width: 100%;
float: left;
}
.tab_con {
width: 100%;
float: left;
padding: 20px 60px;
}
.tab_list ul{
width: 95%;
height: 39px;
background: rgb(223, 221, 221);
}
.tab_list li {
float: left;
height: 39px;
line-height: 39px;
padding: 0 20px;
text-align: center;
cursor: pointer;
list-style: none;
}
.tab_list .current {
background-color: #c81623;
color: #fff;
}
.item_info {
padding: 20px 0 0 20px;
}
.item {
display: none;
}
</style>
</head>
<body>
<div class="tab">
<div class="tab_list">
<ul>
<li class="current">商品介绍</li>
<li>规格与包装</li>
<li>售后保障</li>
<li>商品评价</li>
<li>手机社区</li>
</ul>
</div>
<div class="tab_con">
<div class="item" style="display: block;">
商品介绍模块内容
</div>
<div class="item">
规格与包装模块内容
</div>
<div class="item">
售后保障模块内容
</div>
<div class="item">
商品评价模块内容
</div>
<div class="item">
手机社区模块内容
</div>
</div>
</div>
<script>
// 先获取父组件,再获取父组件下的所有的li
var tab_list = document.querySelector('.tab_list');
var lis = tab_list.querySelectorAll('li');
var items = document.querySelectorAll('.item')
// for循环绑定点击事件
for (var i = 0; i < lis.length; i++) {
// 开始给5个小li 设置索引号
lis[i].setAttribute('index', i) // ('属性','值')
// 1、上面的模块选项卡:点击某一个,当前这个底色会是红色,其余不变(排他思想) 修改类名的方式
// 干掉所有人,其余的li清除class这个类
lis[i].onclick = function () {
for (var i = 0; i < lis.length; i++) {
lis[i].className = '';
}
// 留下我自己
this.className = 'current'
/*
2、下面的显示内容模块:下面的模块显示内容和上面的选项卡一一对应,相匹配;
给上面的tab_list里面的所有小li添加自定义属性,属性值从0开始编号;
*/
var index = this.getAttribute('index')//('属性')
console.log(index);
// 干掉所有人,让其余的item 这些div隐藏
for (var i = 0; i < lis.length; i++) {
items[i].style.display = 'none'
}
// 留下我自己,让对应的item显示出来
items[index].style.display = 'block'
}
}
</script>
</body>
</html>
- 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
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
H5自定义属性
- 自定义属性目的:是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中;
- 自定义属性获取是通过
('属性')
获取;但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性;
<div getTime='20'></div>
// getTime 是自定义属性,只能通过 getAttribute 获取
var div = document.querySelect('div')
console.log(div.getTime) // undefined
console.log(div.getAttribute('getTime'))
- 1
- 2
- 3
- 4
- 5
- 6
H5给我们新增了自定义属性
设置H5自定义属性
- H5规定自定义属性以
data-
开头作为属性名并且赋值;
<div data-index='1'></div>
// 或者使用JS设置 ('data-index',2)
div.setAttribute('data-time',20)
- 1
- 2
- 3
- 4
获取H5自定义属性
- 兼容性获取
('data-index')
; - H5新增
或者
['index']
ie11才开始支持;(只能获取以data-
开头的)
<div getTime="20" data-index="2" data-list-name="andy"></div>
<script>
var div=document.querySelector('div')
// H5新增的获取自定义属性的方法
// dataset 是一个【集合】,里面存放了所有以data开头的自定义属性
console.log(div.dataset);// DOMStringMap {index: '2'}
console.log(div.dataset.index);// 2
console.log(div.dataset['index']);// 2
// 如果自定义属性里面有多个 - 连接的单词,我们获取的时候采用【驼峰命名法】
console.log(div.dataset.listName); //andy
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
DOM中的节点操作
- 获取元素通常使用两种方式:
(1)、利用DOM提供的方法获取元素:如:()
等;这种方法逻辑性不强、繁琐;
(2)、利用节点层级关系获取元素:利用父子兄节点关系获取元素;这种方法逻辑性强,但是兼容性稍差;
** 这两种方法都可以获取元素节点,我们后面都会用到,但是节点操作更简单。
节点概述
- 网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM中,节点使用
node
来表示; -
HTML DOM
树中的所有节点均可以通过JavaScript
进行访问,所有HTML
元素(节点)均可被修改,也可以创建和删除; - 一般的,节点至少拥有
nodeType
(节点类型)、nodeName
(节点名称)、nodeValue
(节点值)这三个基本属性; - 元素节点
nodeType
为1; - 属性节点
nodeType
为2; - 文本节点
nodeType
为3;(文本节点包含文字、空格、换行等) - 我们在实际开发中,节点操作主要操作的是元素节点;
<div class="box"></div>
var box=document.querySelector('.box')
console.dir(box)
- 1
- 2
- 3
- 4
节点操作之父节点
节点层级
- 利用
DOM
树可以把节点划分为不同的层级关系,常见的是【父子兄层级关系】;
父级节点:
- 得到的是离元素最近的父级节点;如果指定的节点没有父节点就返回
null
;
<div class="box">
<span class="erweima"></span>
</div>
//获取父节点
var erweima=document.querySelector('.erweima')
//获取 erweima 节点的父节点;得到的是离元素最近的父级节点
erweima.parentNode
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
节点操作之子节点
子节点:
(标准)(获取到的是所有的子节点,包含 元素节点、文本节点等)
-
返回包含指定节点的子节点的集合,该集合为即时更新的集合;
- 注意:返回值里面包含了所有的子节点,包括元素节点、文本节点等;如果只想要获得里面的元素节点,则需要专门处理。所以我们一般不提倡使用
childNodes
;
<ul>
<li></li>
<li></li>
<li></li>
</ul>
//DOM提供的方法(API)获取
var ul=document.querySelector('ul')
var lis=ul.querySelectorAll('li')
//子节点(获取到的是所有的子节点,包含 元素节点、文本节点等)
console.log(ul.childNodes)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 专门处理:只想要获得里面的元素节点
var ul=document.querySelector('ul')
for(var i=0;i<ul.childNodes.length;i++){
if(ul.childNodes[i].nodeType == 1){
//[i]是元素节点
console.log(ul.childNodes[i])
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
-
(非标准):是一个只读属性,返回所有的子元素节点。它只返回子元素节点,其余节点不返回(这个是我们重点掌握的);虽然
是一个非标准,但是得到了各个浏览器的支持,因此我们可以放心使用。
//children 获取所有的子元素节点(也是我们实际开发常用的)
var ul=document.querySelector('ul')
console.log(ul.children )
- 1
- 2
- 3
节点操作之第一个子元素和最后一个子元素
<ol>
<li></li>
<li></li>
<li></li>
</ol>
var ol=document.querySelector('ol')
//1、firstChild 第一个子节点,不管是文本节点还是元素节点;找不到就返回 null
console.log(ol.firstChild)
console.log(ol.lastChild)
//2、firstElementChild 返回第一个子元素节点
console.log(ol.firstElementChild)
console.log(ol.lastElementChild)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
-
、
注意:这两个方法有兼容性问题,IE9 以上才支持;
- 实际开发中,
firstChild
和lastChild
包含其他节点,操作不方便;而firstElementChild
lastElementChild
又有兼容性问题,那么我们如何获取第一个子元素节点或最后一个子元素节点呢?
(1)、如果想要第一个子元素节点,可以使用[0]
;
//实际开发的写法,既没有兼容性问题又返回第一个子元素
console.log(ol.children[0])
console.log(ol.children[3])//第四个子元素
//得到最后一个子元素
console.log(ol.children[ol.children.length-1])
- 1
- 2
- 3
- 4
- 5
- 6
新浪下拉菜单案例
<ul class="nav">
<li>
<a href="#">微博</a>
<ul>
<li>
<a href="">私信</a>
</li>
<li>
<a href="">评论</a>
</li>
<li>
<a href="">@我</a>
</li>
</ul>
</li>
<li>
<a href="#">微博</a>
<ul>
<li>
<a href="">私信</a>
</li>
<li>
<a href="">评论</a>
</li>
<li>
<a href="">@我</a>
</li>
</ul>
</li>
<li>
<a href="#">微博</a>
<ul>
<li>
<a href="">私信</a>
</li>
<li>
<a href="">评论</a>
</li>
<li>
<a href="">@我</a>
</li>
</ul>
</li>
</ul>
<script>
// 1、获取元素
var nav = document.querySelector('.nav');
var lis = nav.children; //得到四个小li
// 2、循环遍历事件
for (var i = 0; i < lis.length; i++) {
lis[i].onmouseover = function () {
this.children[1].style.display = 'block'
}
lis[i].onmouseout = function () {
this.children[1].style.display = 'none'
}
}
</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
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
兄弟节点
、
、
、
-
返回当前元素的下一个兄弟节点(包括【元素节点】 和 【文本节点】等等),找不到就返回null;同样,也是包含所有的节点;
<div>我是div</div>
<span>我是span<span>
var div=document.querySelector('div')
console.log(div.nextSibling) //得到div的兄弟节点,包括元素节点 和 文本节点 #text
- 1
- 2
- 3
- 4
- 5
-
返回当前元素的上一个兄弟节点(包括【元素节点】 和 【文本节点】等等),找不到就返回null;同样,也是包含所有的节点;
-
返回当前元素下一个兄弟元素节点,找不到就返回null;
-
返回当前元素上一个兄弟元素节点,找不到就返回null;
-
、
这两个方法有兼容性问题,IE9以上才支持;
如何解决兼容性问题?自己封装一个兼容性的函数。
function getNextElementSibling(element){
var el=element;
while(el=el.nextSibling){
if(el.nodeType === 1){
return el;
}
}
return null
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
节点操作之创建和添加节点
创建节点:('tagName')
-
()
方法创建由tagName
指定的HTML
元素。因为这些元素原先不存在,是根据我们的需求动态生成的,所以我们也称之为【动态创建元素节点】;
<ul></ul>
//创建元素节点(只是创建了节点,未添加到页面上)
var li=document.createElement('li');
- 1
- 2
- 3
- 4
添加节点:(child)
、 (child,指定元素)
-
(child)
方法将一个节点添加到指定父节点的子节点列表【末尾】。类似于css
里面的after
伪元素;(node
是父级;child
是子级)
<ul></ul>
//创建元素节点(只是创建了节点,未添加到页面上)
var li=document.createElement('li');
var ul=document.querySelector('ul')
//将节点添加到页面上
ul.appendChild(li)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
-
(child,指定元素)
方法将一个节点添加到父节点的指定子节点的【前面】。类似于css
里面的before
伪元素;
<ul></ul>
//创建元素节点(只是创建了节点,未添加到页面上)
var lili=document.createElement('li');
var ul=document.querySelector('ul')
//将节点添加到ul的第一个子节点的前面上
ul.insertBefore(lili,ul.children[0])
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 总结:我们想要页面添加一个新的元素:1、创建元素;2、添加元素;
案例:简单版本发布留言
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>简单版发布留言案例</title>
</head>
<body>
<textarea name="" id="" cols="30" rows="10"></textarea>
<button>发布</button>
<ul></ul>
<script>
// 1、获取元素
var btn = document.querySelector('button');
var text = document.querySelector('textarea');
var ul = document.querySelector('ul');
// 2、注册事件
btn.onclick = function () {
if (text.value == '') {
alert('你没有输入内容')
return false
} else {
// (1)、创建元素
var li = document.createElement('li');
// 先有li才能赋值
li.innerHTML = text.value
// (2)、添加元素
// (li) //添加到最后
// 添加到最前面
ul.insertBefore(li,ul.children[0])
}
}
</script>
</body>
</html>
- 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
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
节点操作 - 删除节点 (child)
-
(child)
方法从DOM
中删除一个子节点,返回删除的节点;
<button>删除</button>
<ul>
<li>熊大</li>
<li>熊二</li>
<li>光头强</li>
<ul>
//1、获取元素
var ul=document.querySelector('ul');
//2、删除元素
//([0]) //删除“熊大”
//3、点击按钮,依次删除里面的孩子
var btn=document.querySelector('button');
btn.onclick=function(){
if(ul.children.length == 0){
this.disabled= 'true' // 元素删完让按钮置灰
}else{
ul.removeChild(ul.children[0])
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
案例:删除留言案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>简单版发布留言案例</title>
<style>
li {
width: 300px;
padding: 5px;
background-color: pink;
color: red;
font-size: 14px;
margin: 15px 0;
}
li a {
float: right;
}
</style>
</head>
<body>
<textarea name="" id="" cols="30" rows="10"></textarea>
<button>发布</button>
<ul></ul>
<script>
// 1、获取元素
var btn = document.querySelector('button');
var text = document.querySelector('textarea');
var ul = document.querySelector('ul');
// 2、注册事件
btn.onclick = function () {
if (text.value == '') {
alert('你没有输入内容')
return false
} else {
// (1)、创建元素
var li = document.createElement('li');
// 先有li才能赋值
// 小技巧:阻止连接跳转需要添加 javascript:void(0); 或 javascript:;
li.innerHTML = text.value + "<a href='javascript:void(0)'>删除</a>"
// (2)、添加元素
// (li) //添加到最后
// 添加到最前面
ul.insertBefore(li, ul.children[0])
// (3)、删除元素 删除的是当前链接的li,它的父亲
var as = document.querySelectorAll('a')
for (var i = 0; i < as.length; i++) {
as[i].onclick = function () {
ul.removeChild(this.parentNode);
}
}
}
}
</script>
</body>
</html>
- 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
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
-
小技巧:阻止
<a></a>
连接跳转需要添加javascript:void(0);
或javascript:;
如:<a href='javascript:void(0);'>删除</a>
节点操作 - 复制节点(克隆节点) ()
-
()
方法返回调用该方法的节点的一个副本。也称为【克隆节点】或【拷贝节点】;
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
var ul=document.querySelector('ul')
//1、克隆节点,第一个li
var lili= ul.children[0].cloneNode()
//2、将克隆的第一个节点放到页面中
ul.appendChild(lili)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
-
注意:
(1)、如果括号参数【空】或者为【false】,则是【浅拷贝】,即只克隆复制节点本身,不克隆里面的子节点。(只复制标签,不复制里面的内容。)()
(2)、 想要深拷贝,括号里面填true
即可(既复制标签,也复制里面的内容);(true)
案例:动态生成表格
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>动态生成表格案例</title>
<style>
table {
width: 500px;
margin: 100px auto;
border-collapse: collapse;
text-align: center;
}
td,
th {
border: 1px solid #333;
}
thead tr {
height: 40px;
background-color: #ccc;
}
</style>
</head>
<body>
<table cellspacing="'0">
<thead>
<tr>
<th>姓名</th>
<th>科目</th>
<th>成绩</th>
<th>操作</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script>
// 1、先准备好学生的数据
var datas = [
{ name: '张三', subject: 'javaSript', score: 100 },
{ name: '李四', subject: 'javaSript', score: 100 },
{ name: '王五', subject: 'javaSript', score: 100 },
]
// 2、往 tbody 里面创建行,有几个人(通过数组的长度)我们就创建几行;
var tbody = document.querySelector('tbody')
for (var i = 0; i < datas.length; i++) { //外面的for循环管行 tr
// 创建 tr 行
var tr = document.createElement('tr')
tbody.append(tr) //将创建的 tr 放到 tbody 里
// 行里面创建单元格 td (跟数据有关系的三个单元格),单元格的数量取决于每个对象里面的属性个数 for循环遍历对象
for (var k in datas[i]) { //里面的for循环管列 td
//创建单元格
var td = document.createElement('td')
// 把对象里面的属性值 datas[i][k] 给 td
console.log(datas[i][k]); //对象里面的属性值
td.innerHTML = datas[i][k];
tr.append(td) //将创建好的 td 放到 tr 里
}
// 3、创建有删除2个字的单元格
var td = document.createElement('td');
td.innerHTML = '<a href="javascript:;">删除</a>';
tr.appendChild(td)
}
// 4、删除操作
var as = document.querySelectorAll('a')
for (var i = 0; i < as.length; i++) {
as[i].onclick = function () {
// 点击a,删除当前a所在的行(链接的爸爸的爸爸)
tbody.removeChild(this.parentNode.parentNode)
}
}
// 复习:for in 遍历对象
// for(var k in obj){
// k 得到的是属性名
// obj[k] 得到的是属性值
// }
</script>
</body>
</html>
- 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
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
节点操作 -
创建元素
三种动态创建元素的区别:
-
是直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘;(页面上之前的元素被清除,重新创建了一个新的页面,新页面上只展示创建的元素)
<button>点击</button>
<p>abdjk</p>
<script>
// 会导致页面重绘(页面上之前的元素被清除,重新创建了一个新的页面,新页面上只展示创建的元素);(如果页面文档流加载完毕,再调用这句话会导致页面重绘)
var btn=document.querySelector('button')
btn.onclick=function(){
document.write('<div>123</div>')
}
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
//当整个页面都加载完了,再调用里面的函数
window.onload=function(){}
- 1
- 2
-
和
效率对比:
(1)、是将内容写入某个
DOM
节点,不会导致页面全部重绘;创建多个元素效率更高(不是拼接字符串,而是采取数组的形式拼接),结构稍微复杂;
(2)、创建多个元素效率稍微低一点点,但是结构更清晰;
(3)、总结:不同浏览器下,效率要比
高;
Dom
重点核心总结
- 文档对象模型(Document Object Model,简称 DOM),是W3C组织推荐的处理可扩展标记语言(HTML 或 XML)的标准【编程接口】;
- W3C已经定义了一系列的DOM接口,通过这些DOM接口可以改变网页的内容、结构和样式;
- 对于 javaSript ,为了能够使 javaSript 操作 HTML ,javaSript 就有了一套自己的 DOM 编程接口;
- 对于 HTML ,dom 使得 html 形成一棵 dom树,包含文档、元素、节点;
- 我们获取过来的DOM元素是一个对象(Object),所以称为【文档对象模型】;
- 关于DOM操作,我们主要针对于【元素的操作】。主要有:创建、增、删、改、查、属性操作、事件操作;
- 创建:
、
innerHtml
、createElement
- 增:
appendChild
、insertBefore
- 删:
removeChild
- 改:主要修改dom的元素属性,dom元素的内容、属性、表单的值等
(1)、修改元素属性:src
href
title
等;
(2)、修改普通元素内容:innerHTML
innerText
;
(3)、修改表单元素:value
type
disabled
等;
(4)、修改元素样式:style
className
; - 查:主要获取查询dom的元素:
(1)、DOM提供的API方法:getElementById
等;
(2)、H5提供的新方法:querySelector
querySelectorAll
;
(3)、利用节点操作获取元素:父(parentNode
)、子(children
)、兄(previousElementSibling
nextElementSibling
)提倡使用; - 属性操作:主要针对于自定义属性
(1)、setAttribute
:设置dom的属性值;
(2)、getAttribute
:得到dom的属性值;
(3)、removeAttribute
:移除属性; - 事件操作:给元素注册事件,采取 事件源.事件类型=事件处理程序
事件高级
注册事件两种方式
- 给元素添加事件,称为【注册事件】或者【绑定事件】;
- 注册事件有两种方式:【传统方式】和【方法监听注册方式】;
(1)、传统方式:利用 on 开头的事件onclick
;特点:注册事件的【唯一性】,即同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数;
<button onclick='alert("hi~")'></button>
btn.onclick=function(){}
- 1
- 2
(2)、方法监听注册方式:W3C标准推荐方式;addEventListener()
它是一个方法;IE9之前的IE不支持此方法,可使用attachEvent()
代替;特点:同一个元素同一个事件可以注册多个监听器(事件处理函数);按注册顺序依次执行;
addEventListener()
- 事件监听方式
-
(type,lister[,useCapture])
方法将指定的监听器注册到eventTarget
(目标对象)上,当该对象触发指定的事件时,就会执行事件处理函数;
(1)、type
:事件类型字符串,如:click
mouseover
注意这里不要带on
;
(2)、listener
事件处理函数,事件发生时,会调用该监听函数;
(3)、useCapture
可选参数,是一个布尔值,默认是false
;
//注意:事件监听注册事件 addEventListener 里面的事件类型是字符串,要加引号,而且不带 on
//同一个元素,同一个事件可以添加多个侦听器(事件处理程序)
btn.addEventListener('click',function(){})
- 1
- 2
- 3
attachEvent
注册事件(IE9以前的版本支持)
(eventNameWithon,callback)
-
(eventNameWithon,callback)
方法将指定的监听器注册到eventTarget
(目标对象)上,当该对象触发指定的事件时,指定的回调函数就会被执行; - 该方法接收两个参数:
(1)、eventNameWithon
:事件类型字符串,比如:onclick
onmouseover
这里要带 on ;
(2)、callback
:事件处理函数,当目标触发事件时回调函数被调用;
btn.attachEvent('onclick',function(){})
- 1
注册事件兼容性解决方案(封装兼容性函数)
- 兼容性处理的原则:首先照顾大多数浏览器,再处理特殊浏览器;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>注册事件兼容性解决方案</title>
</head>
<body>
<script>
function addEventListener(element, eventName, fn) {
// 判断当前浏览器是否支持 addEventListener 方法
if (element.addEventListener) {
element.addEventListener(eventName, fn);//第三个参数 默认是false
} else if (element.attachEvent) {
element.attachEvent('on' + eventName, fn)
} else {
// 相当于 = fn
element['on' + eventName] = fn
}
}
</script>
</body>
</html>
- 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
删除事件(解绑事件)
删除事件的方式:
(1)、传统注册方式
eventTarget.onclick = null
- 1
<body>
<div>1</div>
<div>2</div>
<div>3</div>
<script>
var divs = document.querySelectorAll('div')
divs[0].onclick = function () {
alert(11)
//传统方法删除事件
divs[0].onclick = null
}
</script>
</body>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
(2)、方法监听注册方式
- 方法1:
eventTarget.removeEventListener(type,listener[,useCapture]);
- 1
<body>
<div>1</div>
<div>2</div>
<div>3</div>
<script>
var divs = document.querySelectorAll('div')
// removeEventListener 删除元素
divs[1].addEventListener('click', fn) //里面的 fn 不需要加小括号调用
function fn() {
alert(22);
divs[1].removeEventListener('click', fn)
}
</script>
</body>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 方法2:(谷歌浏览器不兼容)
eventTarget.detachEvent(eventNameWithOn,callback);
- 1
<div>1</div>
<div>2</div>
<div>3</div>
var divs = document.querySelectorAll('div')
divs[2].attachEvent('onclick', fn1);
function fn1() {
alert(33)
divs[2].detachEvent('onclick', fn1)
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
删除事件兼容性解决方案
function removeEventListener(element,eventName,fn){
//判断当前浏览器是否支持 removeEventListener 方法
if(element.removeEventListener){
element.removeEventListener(eventName,fn);//第三个参数,默认是false
}else if(element.detachEvent){
element.detachEvent('on'+eventName,fn);
}else{
element['on'+eventName]=null;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
DOM事件流
- 事件流描述的是从页面中接收事件的顺序;
- 事件发生时会在元素节点之间按照待定的顺序传播,这个传播过程即DOM事件流;
-
注意:
(1)、JS代码中只能执行捕获或者冒泡其中的一个阶段;
(2)、onclick
和attachEvent
只能得到冒泡阶段;
(3)、addEventListener(type,listener[,useCapture])
第三个参数如果是true
,表示在事件捕获阶段调用事件处理程序;如果是false
(不写默认是false),表示在事件冒泡阶段调用事件处理程序;
(4)、实际开发中我们很少使用事件捕获,更关注事件冒泡;
(5)、有些事件是没有冒泡的,比如:onblur
onfocus
onmouseenter
onmouseleave
;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DOM事件流</title>
<style>
.father {
width: 200px;
height: 200px;
background-color: aqua;
}
.son {
width: 100px;
height: 100px;
background-color: blueviolet;
margin: 0 auto;
}
</style>
</head>
<body>
<div class="father">
<div class="son">son盒子</div>
</div>
<script>
/*
DOM事件流 三个阶段:
1、JS代码中只能执行捕获或者冒泡其中的一个阶段;
2、onclick 和 attachEvent(ie)只能得到冒泡阶段;
3、捕获阶段 如果 addEventListener 第三个参数是 true 那么则处于捕获阶段;document->html->body->father->son
*/
// var son = ('.son')
// ('click', function () {
// alert('son')
// }, true)
// var father = ('.father')
// ('click', function () {
// alert('father')
// }, true)
// 4、冒泡阶段 如果 addEventListener 第三个参数是 false 或者省略, 那么则处于冒泡阶段;son->father->body->html->document
var son = document.querySelector('.son')
son.addEventListener('click', function () {
alert('son')
}, false)
var father = document.querySelector('.father')
father.addEventListener('click', function () {
alert('father')
}, false)
document.addEventListener('click', function () {
alert('document')
})
</script>
</body>
</html>
- 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
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
事件对象
eventTarget.onclick=function(event){}
eventTarget.addEventListener('click',function(event){})
- 1
- 2
- 这个
event
就是事件对象,我们还喜欢写成e
或者evt
; - 这个
event
是个形参,系统帮我们设定为事件对象,不需要传递实参过去; - 当我们注册事件时,event对象就会被系统自动创建,并依次传递给事件监听器(事件处理函数);
- 官方解释:
event
对象代表事件的状态,比如键盘按钮的状态、鼠标的位置、鼠标按钮的状态; - 简单解释:事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象event,它有很多属性和方法;比如:谁绑定了这个事件;鼠标触发事件的话,会得到鼠标的相关信息,如鼠标位置;键盘触发事件的话,会得到键盘的相关信息,如按了哪个键;
- 在IE6~8中,浏览器不会给方法传递参数,如果需要的话,需要到
中获取查找;解决:
e=e ||
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>事件对象</title>
</head>
<body>
<div>123</div>
<script>
var div = document.querySelector('div')
div.onclick = function (event) {
console.log(event);
}
div.addEventListener('click', function (event) {
console.log(event);
})
/*
1、event 就是一个事件对象,写到我们侦听函数的 小括号里面,当形参来看;
2、事件对象只有有了事件才会存在,它是系统给我们自动创建的,不需要我们传递参数;
3、事件对象是我们事件的一系列相关数据的集合,跟事件相关的;
比如鼠标点击里面就包含了鼠标的相关信息,鼠标坐标;如果是键盘事件,里面就包含了键盘事件的信息,比如:判断用户按下了哪个键;
4、这个事件对象我们可以自己命名,比如:event、evt、e;
5、事件对象也有兼容性问题,ie678通过 获取;兼容性写法:e=e || ;
*/
</script>
</body>
</html>
- 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
- 30
- 31
- 32
事件对象的常见属性和方法
1、target
和 this
区别
- (1)、
返回的是触发事件的对象(元素);
<body>
<div>123</div>
<ul>
<li>abc</li>
<li>abc</li>
<li>abc</li>
</ul>
<script>
var div=document.querySelector('div')
div.addEventListener('click',function(e){
console.log(e.target); //<div>123</div>
console.log(this); //<div>123</div>
})
</script>
</body>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
注意:this
返回的是绑定事件的对象(元素);
<body>
<div>123</div>
<ul>
<li>abc</li>
<li>abc</li>
<li>abc</li>
</ul>
<script>
var div = document.querySelector('div')
div.addEventListener('click', function (e) {
console.log(e.target); //<div>123</div>
console.log(this); //<div>123</div>
})
var ul = document.querySelector('ul')
ul.addEventListener('click', function (e) {
//我们给ul绑定了事件,那么 this 就指向 ul
console.log(this);//<ul><ul>
// 注意:此处没有写第三个参数,所以默认是false(冒泡),li 没有绑定点击事件,点击的是 li ,li没找到事件就往上找,这是冒泡;
console.log(e.currentTarget);// 了解:跟 this 有个非常相似的属性 currentTarget (IE678不兼容)
console.log(e.target);//<li><li>
})
/*
区别: 点击了哪个元素,就返回哪个元素;this 哪个元素绑定了这个点击事件,那么就返回谁;
*/
// 考虑兼容性问题的写法
div.onclick = function (e) {
e = e || window.event;
var target = e.target || e.srcElement;
console.log(target);
}
</script>
</body>
- 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
- 30
- 31
- 32
- 33
2、
<body>
<div>123</div>
<a href="">百度</a>
<form action="">
<input type="submit" value="提交" name="sub">
</form>
<script>
// 常见事件对象的属性和方法
// 返回事件类型
var div = document.querySelector('div')
div.addEventListener('click', fn);
div.addEventListener('mouseover', fn)
div.addEventListener('mouseout', fn)
function fn(e) {
console.log(e.type);
}
</script>
</body>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
3、事件对象阻止默认行为
<a href="">百度</a>
<form action="">
<input type="submit" value="提交" name="sub">
</form>
// 阻止默认行为(事件):让链接不跳转,或者让提交按钮不提交;
var a=document.querySelector('a');
a.addEventListener('click',function(e){
e.preventDefault();//DOM推荐的标准写法(低版本IE浏览器不支持)
})
// 传统的注册方式
a.click = function (e) {
// 普通浏览器 ();---> 方法
e.preventDefault()
// 低版本浏览器 ie678 用 returnValue ---> 属性
e.returnValue;
/*
我们可以利用 return false ,也能阻止默认行为,而且没有兼容性问题;
特点:return后面的代码不执行了,而且只限于传统的注册方式;
*/
return false
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
4、阻止事件冒泡
- 事件冒泡:开始时由最具体的元素接收,然后逐级向上传播到DOM最顶层节点;事件冒泡本身的特性,会带来的坏处,也会带来好处,需要我们灵活掌握;
- 阻止事件冒泡:标准写法:利用事件对象里面的
stopPropagation()
方法;
<body>
<div class="father">
<div class="son">son盒子</div>
</div>
<script>
var son = document.querySelector('.son')
son.addEventListener('click', function (e) {
alert('son')
e.stopPropagation(); //stop停止 propagation 传播 ;有兼容性问题
e.cancelBubble=true;// 低版本IE浏览器
}, false)
var father = document.querySelector('.father')
father.addEventListener('click', function () {
alert('father')
}, false)
document.addEventListener('click', function () {
alert('document')
})
if(e && e.stopPropagation){
e.stopPropagation();
}else{
window.event.cancelBubble=true;
}
</script>
</body>
- 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
5、事件委托(代理、委派)
- ul里面有多个li,点击每个li都会弹出对话框,以前需要给每个li注册事件,是非常辛苦的,而且访问DOM的次数越多,这就会延长整个页面的交互就绪时间;
- 事件委托:也称为事件代理,在
jQuery
里面称为事件委派; - 事件委托的原理:不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点。以上案例:给ul注册点击事件,然后利用事件对象的
target
来找到当前点击的li,因为点击li,事件会冒泡到ul上,ul有注册事件,就会触发事件监听器; - 事件委托的作用:我们只操作了一次
DOM
,提高了程序的性能;
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
var ul = document.querySelector('ul')
ul.addEventListener('click', function fn(e) {
// alert('被点击了')
// 可以得到我们点击的对象
e.target.style.backgroundColor = 'pink'
})
</script>
</body>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
6、常用的鼠标事件
-
event
对象代表事件的状态,跟事件相关的一系列信息的集合。现阶段我们主要是用鼠标事件对象MouseEvent
和键盘事件对象KeyboardEvent
;
- 禁止鼠标右键菜单:
contextmenu
主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单;
document.addEventListener('contextmenu',function(e){
e.preventDefault();
})
- 1
- 2
- 3
- 禁止鼠标选中:
selectstart
开始选中;
document.addEventListener('selectstart',function(e){
e.preventDefault();
})
- 1
- 2
- 3
<body>
我是一段不愿意分享的文字
<script>
// contextmenu 可以禁用右键菜单
document.addEventListener('contextmenu', function (e) {
e.preventDefault();
})
// 禁止选中文字 selectstart
document.addEventListener('selectstart', function (e) {
e.preventDefault();
})
</script>
</body>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 获得鼠标在页面中的坐标:鼠标事件对象
MouseEvent
<script>
// 鼠标事件对象 MouseEvent
document.addEventListener('click', function (e) {
// 1、client 鼠标在可视区的x和y坐标
console.log(e.clientX);
console.log(e.clientY);
// 2、page 鼠标在页面文档的x和y坐标
console.log(e.pageX);
console.log(e.pageY);
// 3、screen 鼠标在电脑屏幕的x和y坐标
console.log(e.screenX);
console.log(e.screenY);
})
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 案例:跟随鼠标的天使
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>跟随鼠标的天使</title>
<style>
img {
position: absolute;
}
</style>
</head>
<body>
<img src="./images/" alt="">
<script>
/*
1、鼠标不断的移动,使用鼠标移动事件:mousemove;
2、在页面中移动,给 document 注册事件;
3、图片要移动距离,而且不占位置,我们使用绝对定位即可;
4、核心原理:每次鼠标移动,我们都会获得最新的鼠标坐标,把这个 x 和 y 坐标作为图片的 top 和 left 值就可以移动图片;
*/
var pic = document.querySelector('img')
document.addEventListener('mousemove', function (e) {
// mousemove 只要我们鼠标移动1px,就会触发这个事件;
var x = e.pageX;
var y = e.pageY;
console.log('x坐标是' + x, 'y坐标是' + y);
// 注意:千万不要忘记给 left 和 top 添加 px 单位;
// 减50和40是减去图片的长和宽的一半,从而使鼠标箭头的位置处于图片的中心;
pic.style.left = x - 50 + 'px';
pic.style.top = y - 40 + 'px';
})
</script>
</body>
</html>
- 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
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
7、常用的键盘事件
- 三个事件的执行顺序:keydown --> keypress --> keyup
- 利用
keyCode
判断用户按下哪个键; - 键盘事件对象中的
keyCode
属性可以得到相应键的ASCII
值码;
<body>
<script>
// 键盘事件对象中的 keyCode 属性可以得到相应键的 ASCII 码值;
// 1、我们的 keyup 和 keydown 事件不区分字母大小写;例如:a 和 A 得到的都是65;
// 2、我们的 keypress 事件,区分字母大小写;例如:a 得到的都是 97 和 A 得到的都是 65;
document.addEventListener('keyup', function (e) {
console.log(e);
console.log('up:' + e.keyCode);
if (e.keyCode === 65) {
alert('按下了a键')
} else {
alert('没有按下a键')
}
})
document.addEventListener('keypress', function (e) {
console.log(e);
console.log('press:' + e.keyCode);
})
</script>
</body>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 案例:模拟京东按键输入内容
<body>
<input type="text">
<script>
/*
1、核心思路:检测用户是否按下了s键,如果按下s键,就把光标定位到搜索框里面;
2、使用键盘事件对象里面的keyCode判断用户按下的是否是s键;
3、搜索框获得焦点:使用js里面的 focus() 方法;
*/
var search = document.querySelector('input')
document.addEventListener('keyup', function (e) {//此处用keydowm会把s填入输入框
console.log(e.keyCode);
if (e.keyCode === 83) {
search.focus();
}
})
</script>
</body>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 案例:模拟京东快递单号查询
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>模拟京东快递单号查询</title>
<style>
body,
html {
margin: 0;
padding: 0;
}
.search {
position: relative;
width: 178px;
margin: 100px;
}
.con {
display: none;
position: absolute;
top: -40px;
width: 171px;
border: 1px solid rgba(0, 0, 0, .2);
box-shadow: 0 2px 4px rgba(0, 0, 0, .2);
padding: 5px 0;
font-size: 18px;
line-height: 20px;
color: #333;
}
.con::before { /* 倒三角形 */
content: '';
width: 0;
height: 0;
position: absolute;
top: 28px;
left: 18px;
border: 8px solid #000;
border-style: solid dashed dashed;
border-color: #fff transparent transparent;
}
</style>
</head>
<body>
<!--
案例分析:
(1)、快递单号输入内容时,上面的大号字体盒子(con)显示(这里面的字号更大);
(2)、表单检测用户输入:给表单添加键盘事件;
(3)、同时把快递快递单号里面的值(value)获取过来赋值给con盒子(innerText)作为内容;
注意:keydown 和 keypress 在文本框里的特点:他们两个事件触发的时候,文字还没有落入文本框中;keyup 事件触发的时候,文字已经落入文本框里面了;
-->
<div class="search">
<div class="con">123</div>
<input type="text" placeholder="请输入您的快递单号" class="jd">
</div>
<script>
var con = document.querySelector('.con');
var jd_input = document.querySelector('.jd');
jd_input.addEventListener('keyup', function () {
if (this.value === '') {
con.style.display = 'none';
} else {
con.style.display = 'block';
con.innerText = this.value;
}
})
//当我们失去焦点,就隐藏这个con盒子
jd_input.addEventListener('blur', function () {
con.style.display = 'none'
})
//当我们获得焦点,就显示这个con盒子
jd_input.addEventListener('focus', function () {
if (this.value !== '') {
con.style.display = 'block'
}
})
</script>
</body>
</html>
- 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
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85