- 初始JavaScript
- 变量
- 数据类型
- 标识符、关键字、保留字
- JavaScript运算符
- JavaScript流程控制
- 数组
- 函数
- JavaScript对象
- JavaScript内置对象
- JavaScript简单类型和复杂类型
- 正则表达式
- DOM简介
- BOM简介
- JSON
一、JS基础:基础
-
let/const变量、数据类型、ES6模板字符串
-
运算符、分支、循环
-
数组
-
函数
-
对象、内置对象
二、WebAPIS: 应用
-
DOM获取&属性操作
-
事件核心
-
事件进阶
-
DOM操作&移动端滑动
-
正则&阶段案例
-
京东实战、放大镜、电梯导航
三、JS进阶
-
解构&箭头函数&剩余与展开
-
构造函数&ES6+函数
-
深入面向对象
-
异常、性能优化、深度拷贝
1. 初始JavaScript
1.1. JavaScript历史
- 布兰登艾奇发明
- 10天完成JavaScript设计
- 网景公司最初命名位liveScript,后来于Sun合作之后将其改为JavaScript
1.2. JavaScript是什么
- JavaScript是世界上最流行的语言之一,是一种运行在客户端的脚本语言(Script是脚本的意思)
- 脚本语言:不需要编译,运行过程中由js解释器(js引擎)逐行来进行解释并执行
- 现在也可以基于Node.js技术进行服务器端编程
- 学习javaScript的权威网站MDN
1.3. JavaScript的作用
- 表单动态校验(密码强度检测)(JS产生最初的目的)
- 网页特效
- 服务端开发(Node.js)
- 桌面程序(Electron)
- APP(Cordova)
- 控制硬件-物联网(Ruff)
- 游戏开发(cocos2d-js)
1.4. 浏览器执行JS简介
- 浏览器分成两部分:渲染引擎和js引擎
- 渲染引擎:用来解析HTML与CSS,俗称内核,比如chrome浏览器的bink,老版本的webkit
- JS引擎:也称为JS解释器。用来读取网页中的JavaScript代码,对其处理后运行,比如chrome浏览器的V8
- 浏览器本身并不会执行JS代码,而是通过内置JavaScript引擎(解释器)来执行JS代码。JS引擎执行代码时逐行解释每一句源码(转换为机器语言),然后由计算机去执行,所以JavaScript语言归为脚本语言,会逐行执行
1.5. JS的组成

或者

- ECMAScript
- ECMAScript是由ECMA国际(原欧洲计算机制造商协会)进行标准化一门编程语言,这种语言在万维网上应用广泛,它往往被称为JavaScript,但实际上后两者是ECMAScript语言的实现和扩展。

- ECMAScript:ECMAScript规定了JS的编程语法和基础核心知识(比如: 变量、分支语句、循环语句、对象等),是所有浏览器厂商共同遵守的一套JS语法工业标准。
- Web APIs:
- ① DOM------文档对象模型
- 文档对象模型,是W3C组织推荐的处理可扩展标记语言的标准编程接口,通过DOM提供的接口可以对页面上的各种元素进行操作(大小、位置、颜色等)。
- ② BOM------浏览器对象模型
- BOM,是指浏览器对象模型,它提供了独立于内容的、可以与浏览器窗口进行互动的对象结构。通过BOM可以操作浏览器窗口,比如弹出框、控制浏览器跳转,获取分辨率等
- ① DOM------文档对象模型
1.6. JS初体验
1.6.1. 行内式(内部JS)
- 直接写在html文件里,用script标签包住
- 规范: script标签写在< /body>上面
javascript
<body>
<script>
alert('弹出框')
</script>
</body>
- 可以将单行或少量JS代码写在HTML标签的事件属性中(以on开头的属性)
- 注意单双引号的使用:在HTML中我们推荐使用双引号,js中我们推荐使用单引号>
- 可读性差,在HTML中编写JS大量代码时,不方便阅读
- 引号易错,引号多层嵌套匹配时,非常容易混淆
- 特殊情况下使用
- 注意事项:
我们将< script>放在HTML文件的底部附近的原因是浏览器会按照代码在文件中的顺序加载 HTML 如果先加载的JavaScript。期望修改其下方的 HTML,那么它可能由于 HTML 尚未被加载而失效。 因此,将JavaScript 代码放在HTML页面的底部附近通常是最好的策略。
1.6.2. 内嵌式
- 最常用的方法,代码写在标签内部。
javascript
<body>
<button onclick="alert('逗你玩~~~')"> 点击我月薪过万 </button>
</body>
1.6.3. 外部JS
- 代码写在以.js结尾的文件里
- 语法: 通过script标签,引入到html页面中:
javascript
<script src="my.js"></script>
- 利于HTML页面代码结构化,把大段JS代码独立到HTML页面之外,既美观,也方便文件级别的复用
- 引用外部JS文件的script标签中间不可以写代码
- 适用于js代码量比较大的情况
- 注意事项:
- 1.script标签中间无需写代码,否则会被忽略!
- 2.外部lavaScript会使代码更加有序,更易于复用,且没有了脚本的混合,HTML也会更加易读,因此这是个好的习惯。
1.7. js注释
-
单行注释用 //
-
多行注释用 /**/
-
结束符
- 作用:使用英文的 ; 代表语句结束
- 实际情况: 实际开发中,可写可不写,浏览器(lavaScript 引擎)可以自动推断语句的结束位置
- 现状:在实际开发中,越来越多的人主张,书写JavaScript 代码时省略结束符
- 约定:为了风格统一,结束符要么每句都写,要么每句都不写(按照团队要求.)

1.8. JS输入输出语法
-
输入输出语句
- 为了方便信息的输入输出,JS中提供了一些输入输出语句,其常用的语句如下:

- 为了方便信息的输入输出,JS中提供了一些输入输出语句,其常用的语句如下:
-
输入语法
prompt('请输入你的姓名:')- 作用: 作用:显示一个对话框,对话框中包含一条文字信息,用来提示用户输入文字
- 展示:

-
输出
- document.write 网页输出 (里面可以写字,也可以写标签)
- console.log 控制台输出
- alert('') 弹出窗口
1.9. JS的代码执行顺序
- 按HTML文档流顺序执行JavaScript代码
- alert()和 prompt()它们会跳过页面渲染先被执行(目前作为了解,后期讲解详细执行过程)
1.10. 字面量
- 在计算机科学中,字面量(literal)是在计算机中描述事/物
- 比如:
- 我们工资是: 1000 此时 1000 就是 数字字面量
- 黑马程序员'字符串字面量
- 还有接下来我们学的[]数组字面量、{}对象字面量等等
2. 变量
2.1. 什么是变量
- 白话:变量就是一个装东西的盒子
- 通俗:变量用于存放数据的容器。我们通过变量名获取数据,甚至数据可以修改
2.2. 变量在内存中存储
- 本质:变量是程序在内存中申请的一块用来存放数据的空间
2.3. 变量的使用
-
声明变量
- var是一个js关键字,用来声明变量。使用该关键字声明变量后,计算机会自动为变量分配内存空间,不需要程序员管
- age是程序员定义的变量名,我们要通过变量名来访问内存中分配的空间
-
赋值
javascript
<script>
var age;
age=1;
</script>
javascript
<script>
//1. 用户输入姓名 存储到一个 myname的变量里面
var myname = prompt(" 请输入您的名字");
//2. 输出这个用户名
alert(myname);
</script>
2.4. 变量语法拓展声明变量特殊情况
- ① 更新变量
- 一个变量被重新赋值后,它原有的值就会被覆盖,变量值将以最后一次赋的值为准。
javascript
var age = 18;
age = 81; // 最后的结果就是81因为18 被覆盖掉了
-
② 同时声明多个变量
- 同时声明多个变量时,只需要写一个 var, 多个变量名之间使用英文逗号隔开。
var age = 10, name = 'zs', sex = 2;
-
③ 声明变量特殊情况
-

2.5. 变量命名规范
- 由字母(A-Za-z)、数字(0-9)、下划线、美元符号组成,如usrAge,numo1,name
- 严格区分大小写,varapp和varApp是两个变量
- 不能以数字开头,18age是错误的
- 不能是关键字、保留字,例如:var、for、while
- 变量名必须有意义,nlbbd不行
- 遵守驼峰命名法,首字母小写,后面单词的首字母要大写
2.6. 案例:变量的两个值交换
javascript
<script>
var temp;
var appl1 = '青苹果', appl2 = '红苹果';
temp = appl1;
appl1 = appl2;
appl2 = temp;
console.log(appl1);
console.log(appl2);
</script>
3. 数据类型
变量是用来存储值的所在处,它们有名字和数据类型。变量的数据类型决定了如何将代表这些值的位存储到计算机的内存中。JavaScript是一种弱类型或者说动态语言。这意味着不用提前声明变量的类型,在程序运行过程中,类型会被自动确定。
javascript
var age=10; // 这是一个数字型
var areYouOk = "是的"; //这是一个字符串
3.1. 数据类型
- 在js中,运行代码时,变量的数据类型是由JS引擎根据=号右边变量值的数据类型来判断的,运行完毕之后变量就确定了数据类型
- js是动态语言变量的数据类型是可以变化的
javascript
<script>
var x = 10;
x = 'pink';
</script>
3.2. 数据类型分类
- js把数据类型分为两类:
- 简单数据类型
- 复杂数据类型(object)
3.3. 简单数据类型

3.3.1. 数字型Number
- 数字型进制
- 八进制:0-7以0打头
- 十六进制:0-9,a-f以0x打头
javascript
var number1 = 010;
var number2 = 0xa;
- 范围
- 数字型的最大值:Number.MAX_VALUE
- 数字型的最小值:Number.MIN_VALUE
javascript
var number3 = Number.MAX_VALUE;
var number4 = Number.MIN_VALUE;
- 数字型特殊值
- Infinity ,代表无穷大,大于任何数值
- -Infinity ,代表无穷小,小于任何数值
- NaN ,Not a number,代表一个非数值
javascript
alert(Infinity); // Infinity
alert(-Infinity); // -Infinity
alert(NaN); // NaN
javascript
var number3 = Number.MAX_VALUE * 2;
var number4 = -Number.MAX_VALUE * 2;
- 判断一个变量是否为数字型
- isNaN()用来判断一个变量是否为非数字的类型,返回 true 或者 false

- isNaN()用来判断一个变量是否为非数字的类型,返回 true 或者 false
3.3.2. 字符串型String
- 字符串型可以是引号中的任意文本,其语法为 双引号 "" 和 单引号''
- 因为 HTML 标签里面的属性使用的是双引号,JS 这里我们更推荐使用单引号。
javascript
var strMsg = "我爱北京天安门~"; // 使用双引号表示字符串
var strMsg2 = '我爱吃猪蹄~'; // 使用单引号表示字符串
// 常见错误
var strMsg3 = 我爱大肘子; // 报错,没使用引号,会被认为是js代码,但js没有这些语法
- 字符串引号嵌套
- JS 可以用单引号嵌套双引号 ,或者用双引号嵌套单引号 (外双内单,外单内双)
javascript
var strMsg = '我是"高帅富"程序猿'; // 可以用''包含""
var strMsg2 = "我是'高帅富'程序猿"; // 也可以用"" 包含''
// 常见错误
var badQuotes = 'What on earth?"; // 报错,不能 单双引号搭配
- 字符串转义符
- 类似HTML里面的特殊字符,字符串中也有特殊字符,我们称之为转义符。转义符都是 \ 开头的,常用的转义符及其说明如下:

- 类似HTML里面的特殊字符,字符串中也有特殊字符,我们称之为转义符。转义符都是 \ 开头的,常用的转义符及其说明如下:
- 转义符使用的时候一定要用引号包裹起来转义符
javascript
var str1 = "我是一个'高富帅'的\n程序员";
- 字符串长度
- 字符串是由若干字符组成的,这些字符的数量就是字符串的长度。通过字符串的 length 属性可以获取整个字符串的长度。
javascript
Var strMsg = "我是帅气多金的程序猿!";
alert (strMsg.length); //显示 11
- 字符串拼接+
- 多个字符串之间可以使用 + 进行拼接,其拼接方式为 **字符串 + 任何类型 = 拼接之后的新字符串 **
- 拼接前会把与字符串相加的任何类型转成字符串,再拼接成一个新的字符串
javascript
<script>
console.log('沙漠' + '骆驼');
console.log('pink老师' + 18);
console.log('pink老师' + true);
console.log('12' + 12);
console.log('pink老师' + 18 + '岁');
</script>
- +号总结口诀:数值相加 ,字符相连
- 我们经常会将字符串和变量来拼接,因为变量可以很方便地修改里面的值
- 变量是不能添加引号的,因为加引号的变量会变成字符串
- 如果变量两侧都有字符串拼接,口诀"引引加加 ",删掉数字,变量写加中间
javascript
//加强
var age = 28;
console.log('pink老师' + age + '岁');
//console.log('pink老师' + age);
3.3.3. 布尔型boole
- 布尔型只有两个值:true、false
- 布尔型参与运算,true是1,false是0
javascript
console.log(true + 1); // 2
console.log(false + 1); // 1
3.3.4. undefined、null
- 一个声明后没有被赋值的变量会有一个默认值 undefined ( 如果进行相连或者相加时,注意结果)
- 一个声明变量给 null 值,里面存的值为空(学习对象时,我们继续研究null)
javascript
<script>
var str1 = undefined;
console.log(str1 + 'pink');// undefinedpink
console.log(str1+1); //NaN
var space = null;
console.log(str1 + 'pink'); //nullpink
console.log(str1+1); //1
</script>
3.4. 获取变量数据类型typeof
javascript
<script>
var num = 10;
console.log(typeof num);
var str = 'pink';
console.log(typeof str);
</script>

3.5. 数据类型转换
- 使用表单、prompt 获取过来的数据默认是字符串类型的,此时就不能直接简单的进行加法运算,而需要转换变量的数据类型。通俗来说,就是把一种数据类型的变量转换成另外一种数据类型。
- 常见的数据类型转换:
- 转换为字符串类型
- 转换为数字型
- 转换为布尔型
3.5.1. 转换为字符串

- 最重要的是:加号拼接字符串第三种也成为隐式转换
显式转换
编写程序时过度依靠系统内部的隐式转换是不严禁的,因为隐式转换规律并不清晰,大多是靠经验总结的规律。
为了避免因隐式转换带来的问题,通常根逻辑需要对数据进行显示转换
概念:
- 自己写代码告诉系统该转成什么类型
转换为数字型
- Number(数据)
- 转成数字类型
- 如果字符串内容里有非数字,转换失败时结果为NaN(NotaNumber)即不是一个数字
- NaN也是number类型的数据,代表非数字
parseInt(数据)
- 只保留整数
parseFloat(数据
- 可以保留小数
隐式转换某些运算符被执行时,系统内部自动将数据类型进行转换,这种转换称为隐式转换
规则:
- +号两边只要有一个是字符串,都会把另外一个转成字符串
- 除了+以外的算术运算符 比如-*/等都会把数据转成数字类型
缺点:
- 转换类型不明确,靠经验才能总结
小技巧:
- +号作为正号解析可以转换成数字型
- 任何数据和字符串相加结果都是字符串
javascript
<script>
var num = 10;
var str = num.toString();
console.log(str);
console.log(String(num));
console.log('' + num);
</script>
3.5.2. 转换为数字型

- 前两种最为常用、重点
javascript
<script>
var age = '18';
console.log(parseInt(age)); //18
console.log(parseInt('3.9')); //3 取整
console.log(parseInt('120px')); //120 自动去掉px
console.log(parseInt('rem120px')); //NaN
console.log(parseFloat('3.14')); //3.14
console.log(parseFloat('120px')); //120
console.log(parseFloat('rem120px')); //NaN
console.log(Number('123'));//123
console.log('12'-0); //数字12
</script>
- 案例1:计算年龄
javascript
<!-- 在页面中弹出一个输入框,我们输入出生年月份后,能计算出我们的年龄 -->
<script>
var year = prompt('请输入出生年份');
var age = 2018 - year;
//year过来是字符串型 ,但是我们用的是减号,有隐式转换
alert('您今年' + age + '岁啦');
</script>
- 案例2:简单加法计算器
javascript
<script>
var num1 = prompt('请输入第一个数值');
var num2 = prompt('请输入第二个数值');
alert('最终结果为:' + (parseFloat(num1) + parseFloat(num2)));
</script>
3.5.3. 转化为布尔型

- 代表空、否定的值会被转换为 false ,如 ''、0、NaN、null、undefined
- 其余值都会被转换为 true
javascript
console.log(Boolean('')); // false
console.log(Boolean(0)); // false
console.log(Boolean(NaN)); // false
console.log(Boolean(null)); // false
console.log(Boolean(undefined)); // false
console.log(Boolean('小白')); // true
console.log(Boolean(12)); // true
4. 标识符、关键字、保留字
4.1. 标识符
- 定义:就是指开发人员为变量、属性、函数、参数取的名字
- 标识符不能是关键字或保留字。
4.2. 关键字
- 关键字:是指 JS本身已经使用了的字,不能再用它们充当变量名、方法名。
- 包括:break、case、catch、continue、default、delete、do、else、finally、for、function、if、in、instanceof、new、return、switch、this、throw、try、typeof、var、void、while、with 等。
4.3. 保留字
- 保留字:实际上就是预留的"关键字",意思是现在虽然还不是关键字,但是未来可能会成为关键字,同样不能使用它们当变量名或方法名。
- 包括:boolean、byte、char、class、const、debugger、double、enum、export、extends、fimal、float、goto、implements、import、int、interface、long、mative、package、private、protected、public、short、static、super、synchronized、throws、transient、volatile 等。
- 注意:如果将保留字用作变量名或函数名,那么除非将来的浏览器实现了该保留字,否则很可能收不到任何错误消息。当浏览器将其实现后,该单词将被看做关键字,如此将出现关键字错误。
5. JavaScript运算符
5.1. 运算符
- 运算符也被称为操作符,是用于实现赋值、比较和执行算数运算等功能的符号。
- JavaScript常见的运算符有:
- 算数运算符
- 递增和递减运算符
- 比较运算符
- 逻辑运算符
- 赋值运算符
5.1.1. 算术运算符
- 定义:算术运算使用的符号,用于执行两个变量或值的算术运算。

- 浮点数进行算数运算会有问题的
javascript
var result = 0.1 + 0.2; // 结果不是 0.3,而是:0.30000000000000004
console.log(0.07 * 100); // 结果不是 7, 而是:7.000000000000001
Q: 如何处理浮点数运算精度缺少问题?
在JavaScript中,浮点数运算确实可能会遇到精度问题,这主要是由于浮点数的表示方式是基于IEEE 754标准的。这种表示方式在某些情况下会导致精度丢失,尤其是在进行多次运算或涉及到小数点运算时。
常见问题
精度丢失:例如,0.1 + 0.2 并不总是等于 0.3,而是等于 0.30000000000000004。
非精确比较:直接比较两个浮点数是否相等可能会因为精度问题而失败。
解决方法
- 使用Number.EPSILON进行近似比较
当需要比较两个浮点数是否"足够接近"时,可以使用Number.EPSILON:
Number.EPSILON 是 JavaScript 中的一个静态属性,用于表示 1 与大于 1 的最小浮点数之间的差值。它的值约为 2.220446049250313e-16 即
javascript
function numbersCloseEnough(num1, num2) {
return Math.abs(num1 - num2) < Number.EPSILON;
}
console.log(numbersCloseEnough(0.1 + 0.2, 0.3)); // true
- 使用toFixed()方法
将数字转换为指定小数位数的字符串,然后再转换回数字,可以减少精度问题:
javascript
function preciseAddition(a, b) {
return Number((a + b).toFixed(15)); // 或者其他合适的小数位数
}
console.log(preciseAddition(0.1, 0.2)); // 0.3
- 使用第三方库
有一些第三方库如decimal.js或big.js提供了更精确的数学运算功能,它们可以处理任意大小的数字和任意精度的运算:
javascript
// 使用 decimal.js
const Decimal = require('decimal.js');
const result = new Decimal(0.1).plus(new Decimal(0.2));
console.log(result.toString()); // "0.3"
- 使用BigInt(对于大整数)
如果你在处理非常大的整数,可以使用BigInt类型:
javascript
const bigNumber = BigInt(12345678901234567890);
console.log(bigNumber); // BigInt 类型输出
- 四舍五入或截断
对于某些场合,你可能需要四舍五入或截断到特定的小数位数:
javascript
function roundTo(value, decimals) {
return +value.toFixed(decimals); // 注意前面的+号是为了转换为数字类型
}
console.log(roundTo(0.1 + 0.2, 1)); // 0.3 (四舍五入到一位小数)
总结
选择哪种方法取决于你的具体需求:如果你需要处理精确的财务计算,使用decimal.js或big.js可能是最佳选择。如果只是简单的四舍五入或比较,使用toFixed()或Number.EPSILON可能就足够了。理解你的数据和需求是选择正确方法的关键。
5.1.2. 递增递减运算符++ii++
-
在js中,递增和递减既可以放在变量前面,也可以放在变量后面。
-
放在变量前面时,我们可以称为前置递增(递减)运算符;
-
放在变量后面时,我们可以称为后置递增(递减)运算符
-
注意:递增和递减运算符必须和变量配合使用
-
小结:
- 1、前置自增和后置自增如果单独使用效果是一样的
- 2、后置递增:先表达式返回原值后面变量再+1
- 3、前置递增:先变量+1,后表达式返回原值
- 4、与其他代码连用时,执行结果会不同
javascript
<script>
var age = 10;
++age;
var p = 10;
console.log(++p + 10);
var age = 10;
console.log(age++ + 10);
var a = 10;
++a;
var b = ++a + 2;
console.log(b);
var c = 10;
c++;
var d = c++ + 2;
console.log(d);
var e = 10;
var f = e++ + ++e;
console.log(f);
</script>
5.1.3. 比较运算符
- 定义:比较运算符(关系运算符)是两个数据进行比较时所使用的运算符,比较运算后,会返回一个布尔值(true/false)作为比较运算的结果

- 等号有隐式转换。全等要求两侧的值、数据类型必须一样。双等只要求数值相等
5.1.4. 逻辑运算符
- 定义:逻辑运算符是用来进行布尔值运算的运算符,其返回值也是布尔值。
- 与&&

- 或||

- 非!
- 逻辑非(!)也叫作取反符,用来取一个布尔值相反的值,如true的相反值是false
- 短路运算原理:当有多个表达式(值)时,左边的表达式值可以确定结果时,就不再继续运算右边的表达式的值
javascript
<script>
/*
短路运算
逻辑与短路运算特点
语法:表达式1&&表达式2
如果第一个表达式为真,则返回表达式2
如果第一个表达式为假,则返回表达式1
逻辑或运算特点
语法:表达式1||表达式2
如果第一个表达式为真,则返回表达式1
如果第一个表达式为假,则返回表达式2
*/
console.log(123 && 456);// 456
console.log(0 && 456);// 0
console.log(0 && 1 + 2 && 456);// 0
console.log(123 || 456);// 123
console.log(0 || 456);// 456
</script>
5.1.5. 赋值运算符
- 定义:用来把数据赋值给变量的运算符

5.1.6. 运算符优先级

- 一元运算符里面的逻辑非优先级很高
- 逻辑与比逻辑或优先级高
5.2. 表达式和返回值
- 表达式:是由数字、运算符、变量等以能求得数值的有意义排列方法所得的组合
- 简单理解:是由数字、运算符、变量等组成的式子
6. JavaScript流程控制
6.1. 流程控制
- 在一个程序执行的过程中,各条代码的执行顺序对程序的结果是有直接影响的。很多时候我们要通过控制代码的执行顺序来实现我们要完成的功能。
- 简单理解: 流程控制就是来控制我们的代码按照什么结构顺序来执行
- 流程控制主要有三种结构,分别是顺序结构、分支结构和循环结构,这三种结构代表三种代码执行的顺序。

6.2. 顺序结构
- 顺序结构:是程序中最简单、最基本的流程控制,他没有特定的语法结构,程序会按照代码的先后顺序、依次执行,程序中大多数的代码都是这样执行的

6.3. 分支结构
6.3.1. 分支结构---if语句
由上到下执行代码的过程中,根据不同的条件,执行不同的路径代码(执行代码多选一的过程),从而得到不同的结果
javascript
// 结构
if(条件表达式){
// 执行语句
}
- 条件表达式为真,则继续执行大括号里面代码,为假则不执行
javascript
if(3<5) {
alert('123');
}
6.3.2. 分支结构---ifelse语句(双分支语句)

javascript
结构
if(条件表达式){
}
else{
}
6.3.3. 分支结构---ifelseif语句
就是利用多个条件来选择不同的语句执行得到不同的结果多选1的过程
javascript
//结构
if(条件表达式1){
//语句1
}
else if(条件表达式2){
//语句2
}
else if(条件表达式3){
//语句3
}
else{
//最后的语句
}
- 执行思路
- 如果条件表达式1满足就执行 语句1执行完毕后,退出整个if 分支语句
- 如果条件表达式1不满足,则判断条件表达式2 满足的话,执行语句2 以此类推
- 如果上面的所有条件表达式都不成立,则执行else 里面的语句
- 注意点
- 多分支语句还是多选1 最后只能有一个语句执行
- else if 里面的条件理论上是可以任意多个的
- else if 中间有个空格了

6.3.4. 三元表达式
- 三元表达式结构
javascript
条件表达式 ? 表达式 1 : 表达式 2
- 如果条件表达式结果为真,则返回表达式1的值;如果结果为假,则返回表达式2的值。
6.3.5. switch语句
- 定义:switch语句也是多分支语句,它用于基于不同的条件来执行不同的代码。当要针对变量设置一系列的特点之的选项时,就可以使用switch
javascript
switch(表达式){
case value1:执行语句1;break;
case value2:执行语句1;break;
case value3:执行语句1;break;
case value4:执行语句1;break;
default:执行最后的语句;
}
- 注意
- 如果case都没有匹配上,switch中如果有default语句,则执行这个,如果没有则不执行
- switch后面的括号和case后面的value的值是全等的形式
- switch后面的括号必须是整数型常量,包括char,short,int,long等,不能是浮点数
6.3.6. 小结
- switch 语句和 if else if 语句的区别
- 一般情况下,它们两个语句可以相互替换'
- switch...case 语句通常处理 case为比较确定值的情况, 而 if...else...语句更加灵活,常用于范围判断(大于、等于某个范围)
- switch 语句进行条件判断后直接执行到程序的条件语句,效率更高。而if...else 语句有几种条件,就得判断多少次。
- 当分支比较少时,if... else语句的执行效率比 switch语句高。
- 当分支比较多时,switch语句的执行效率比较高,而且结构更清晰。
6.4. 循环结构
- 在实际问题中,有许多具有规律性的重复操作,因此在程序中要完成这类操作就需要重复执行某些语句
- 循环的主要语句
- for循环
- while循环
- do...while循环
6.4.1. for循环
- 在程序中,一组被重复执行的语句被称之为循环体,能否继续重复执行,取决于循环的终止条件。由循环体及循环的终止条件组成的语句,被称之为循环语句
javascript
// for循环结构
for(初始化变量;条件表达式;操作表达式){
循环体
}
-
断点调试
- 断点调试是指自己在程序的某一行设置一个断点,调试时,程序运行到这一行就会停住,然后你可以一步一步往下调试,调试过程中可以看各个变量当前的值,出错的话,调试到出错的代码行即显示错误,停下。
断点调试可以帮我们观察程序的运行过程 - 浏览器中按 F12--> sources -->找到需要调试的文件-->在程序的某一行设置断点
- Watch: 监视,通过watch可以监视变量的值的变化,非常的常用。
- F11: 程序单步执行,让程序一行一行的执行,这个时候,观察watch中变量的值的变化。
- 代码调试的能力非常重要,只有学会了代码调试,才能学会自己解决bug的能力。初学者不要觉得调试代码麻烦就不去调试,知识点花点功夫肯定学的会,但是代码调试这个东西,自己不去练,永远都学不会。
- 今天学的代码调试非常的简单,只要求同学们记住代码调试的这几个按钮的作用即可,后面还会学到很多的代码调试技巧。
- 断点调试是指自己在程序的某一行设置一个断点,调试时,程序运行到这一行就会停住,然后你可以一步一步往下调试,调试过程中可以看各个变量当前的值,出错的话,调试到出错的代码行即显示错误,停下。
-
for循环重复执行相同代码
javascript
// 基本写法
for(var i = 1; i <= 10; i++){
console.log('媳妇我错了~');
}
// 用户输入次数
var num = prompt('请输入次数:');
for ( var i = 1 ; i <= num; i++) {
console.log('媳妇我错了~');
}
- for循环重复执行不相同代码
javascript
// 基本写法
for (var i = 1; i <= 100; i++) {
console.log('这个人今年' + i + '岁了');
}
- for循环重复某些相同操作
javascript
// for 里面是可以添加其他语句的
for (var i = 1; i <= 100; i++) {
if (i == 1) {
console.log('这个人今年1岁了, 它出生了');
} else if (i == 100) {
console.log('这个人今年100岁了,它死了');
} else {
console.log('这个人今年' + i + '岁了');
}
}
6.4.2. for循环的案例
javascript
//课堂案例 1: 求1-100之间所有整数的累加和
<script>
var sum = 0;
for(var i = 1;i <= 100; i++){
sumNum += i;
}
console.log('1-100之间整数的和 = ' + sum);
</script>
javascript
<script>
// 1. 求1-100之间所有数的平均值 需要一个 sum 和的变量 还需要一个平均值 average 变量
var sum = 0;
var average = 0;
for (var i = 1; i <= 100; i++) {
sum = sum + i;
}
average = sum / 100;
console.log(average);
// 2. 求1-100之间所有偶数和奇数的和 我们需要一个偶数的和变量 even 还需要一个奇数 odd
var even = 0;
var odd = 0;
for (var i = 1; i <= 100; i++) {
if (i % 2 == 0) {
even = even + i;
} else {
odd = odd + i;
}
}
console.log('1~100 之间所有的偶数和是' + even);
console.log('1~100 之间所有的奇数和是' + odd);
// 3. 求1-100之间所有能被3整除的数字的和
var result = 0;
for (var i = 1; i <= 100; i++) {
if (i % 3 == 0) {
// result = result + i;
result += i;
}
}
console.log('1~100之间能够被3整数的数字的和是:' + result);
</script>
- 弹出输入框,求平均值
javascript
<script>
//弹出输入框 输入总的班级人数(num)
//依次输入学生成绩 保存起来 score
//求平均值
var num = prompt('请输入总的班级人数');
var sum = 0;
var average = 0;
for (var i = 1; i <= num; i++) {
var score = prompt('请输入第' + i + '个学生的成绩');
sum = sum + parseFloat(score);
//prompt取过来的数据是字符串型的需要转换
}
average = sum / num;
alert('班级总的成绩是' + sum);
alert('班级总的平均分成绩是' + average);
</script>
- 打印星星
javascript
<script>
//打印星星 一行五个
var str = '';
for (var i = 1; i <= 5; i++) {
str = str + '★';
}
console.log(str);
//如果直接输出星星,他会不在一行显示,所以用字符串加号链接的形式
</script>
<script>
//打印 5×5 阵列星星
var str = '';
//用于链接星星
for (var j = 1; j <= 5; j++) {
//控制行数
for (var k = 1; k <= 5; k++) {
str = str + '★';
}
str = str + '\n';
}
console.log(str);
</script>
<script>
//打印 从上往下 逐行递减的星星阵列
var str = '';
//用于链接星星
for (var j = 1; j <= 10; j++) {
//控制行数
for (var k = j; k <= 10; k++) {
str = str + '★';
}
str = str + '\n';
}
console.log(str);
</script>
<script>
//用户输入几行几列
var row = prompt('请您输入行数');
var col = prompt('请您输入列数');
var str = '';
for (var i = 1; i <= row; i++) {
//控制行数
for (var k = 1; k <= col; k++) {
str = str + '★';
}
str = str + '\n';
}
console.log(str);
</script>
<script>
//用户输入几行,第一行的个数,每一行的个数逐行递减
var row = prompt('请您输入行数');
var s = prompt('请您输入第一行的星星个数');
var str = '';
console.log('行数是' + row);
console.log('每一行的个数是' + s);
for (var i = row; i > 0; i--) {
//控制行数
for (var k = 1; k <= i; k++) {
str = str + '★';
}
str = str + '\n';
}
console.log(str);
</script>
- 九九乘法口诀表
javascript
<script>
//打印 九九乘法口诀表
var str = '';
for (var i = 1; i <= 9; i++) {
for (var j = 1; j <= i; j++) {
//1×2=2
//str=str;
str = str + j + '×' + i + '=' + i * j + '\t';
//'\t' 表示此公式运行完以后,在一个tab空格
}
str = str + '\n';
}
console.log(str);
</script>
6.4.3. for循环小结
- for 循环可以重复执行某些相同代码
- for 循环可以重复执行些许不同的代码,因为我们有计数器
- for 循环可以重复执行某些操作,比如算术运算符加法操作随着需求增加,双重
- for循环可以做更多、更好看的效果双重
- for 循环,外层循环一次,内层 for 循环全部执行
- for 循环是循环条件和数字直接相关的循环分析要比写代码更重要一些核心算法想不到,但是要学会,分析它执行过程举一反三,自己经常总结,做一些相似的案例
6.4.4. while循环
javascript
//while结构
//初始化变量
while(条件表达式){
//循环体
//操作表达式
}
javascript
<script>
// while循环案例
// 1. 打印人的一生,从1岁到100岁
var i = 1;
while (i <= 100) {
console.log('这个人今年' + i + '岁了');
i++;
}
// 2. 计算 1 ~ 100 之间所有整数的和
var sum = 0;
var j = 1;
while (j <= 100) {
sum += j;
j++
}
console.log(sum);
// 3. 弹出一个提示框, 你爱我吗? 如果输入我爱你,就提示结束,否则,一直询问。
var message = prompt('你爱我吗?');
while (message !== '我爱你') {
message = prompt('你爱我吗?');
}
alert('我也爱你啊!');
</script>
6.4.5. do...while循环
javascript
do{
}while(条件表达式);
javascript
<script>
// while循环案例
// 1. 打印人的一生,从1岁到100岁
var i = 1;
do {
console.log('这个人今年' + i + '岁了');
i++;
} while (i <= 100)
// 2. 计算 1 ~ 100 之间所有整数的和
var sum = 0;
var j = 1;
do {
sum += j;
j++;
} while (j <= 100)
console.log(sum);
// 3. 弹出一个提示框, 你爱我吗? 如果输入我爱你,就提示结束,否则,一直询问。
do {
var message = prompt('你爱我吗?');
} while (message !== '我爱你')
alert('我也爱你啊');
</script>
6.5. 循环小结
- JS 中循环有 for 、while 、 do while
- 三个循环很多情况下都可以相互替代使用
- 如果是用来计次数,跟数字相关的,三者使用基本相同,但是我们更喜欢用 for
- while 和 do...while 可以做更复杂的判断条件,比 for 循环灵活一些
- while 和 do...while 执行顺序不一样,while 先判断后执行,do...while 先执行一次,再判断执行
- while 和 do...while 执行次数不一样,do...while 至少会执行一次循环体, 而 while 可能一次也不执行
- 实际工作中,我们更常用for 循环语句,它写法更简洁直观, 所以这个要重点学习
6.6. continue关键字
- 定义:用于立即跳出本次循环,继续下一次循环(本次循环体中continue之后的代码就会减少执行一次)
javascript
<script>
// continue 关键字 退出本次(当前次的循环) 继续执行剩余次数循环
for (var i = 1; i <= 5; i++) {
if (i == 3) {
continue; // 只要遇见 continue就退出本次循环 直接跳到 i++
}
console.log('我正在吃第' + i + '个包子');
}
// 1. 求1~100 之间, 除了能被7整除之外的整数和
var sum = 0;
for (var i = 1; i <= 100; i++) {
if (i % 7 == 0) {
continue;
}
sum += i;
}
console.log(sum);
</script>
6.7. break关键字
- 定义:用于立即跳出整个循环(循环结束)
javascript
for (var i = 1; i <= 5; i++) {
if (i == 3) {
break;
}
console.log('我正在吃第' + i + '个包子');
}
6.8. JavaScript 命名规范以及语法格式
- 标识符命名规范
- 变量、函数的命名必须要有意义
- 变量的名称一般用名词
- 函数的名称一般用动词
- 操作符规范
javascript
// 操作符的左右两侧各保留一个空格
for (var i = 1; i <= 5; i++) {
if (i == 3) {
break; // 直接退出整个 for 循环,跳到整个for循环下面的语句
}
console.log('我正在吃第' + i + '个包子呢');
}
- 单行注释规范
javascript
for (var i = 1; i <= 5; i++) {
if (i == 3) {
break; // 单行注释前面注意有个空格
}
console.log('我正在吃第' + i + '个包子呢');
}
- 其他规范

7. 数组
7.1. 数组的概念
- 定义:数组是指一组数据的集合,其中每个数据被称作元素,在数组中可以存放任意类型的元素。数组是一种将一组数据存储在单个变量名下的优雅方式。
7.2. 数组的创建方式
- 利用数组字面量创建数组
- 利用new创建数组
javascript
//创建数组 两种方式
//1、利用数组字面量
var arr = [1, 2, 3];
console.log(arr[0]);
//2 利用new Array()
var arr1 = new Array();
var arr2 = new Array(2);//表示数组长度为2 里面有两个空的数组元素
var arr3 = new Array(3, 3);//等价于 [3,3] 表示里面有两个数组元素,一个是3一个是3
console.log(arr3);
7.3. 遍历数组

- 数组可以通过索引来访问、设置、修改对应的数组元素,我们可以通过"数组名[索引]"的形式来获取数组中的元素。
javascript
// 定义数组
var arrStus = [1,2,3];
// 获取数组中的第2个元素
alert(arrStus[1]);
javascript
<script>
var s = [2, 6, 1, 77, 52, 25, 7]
var max = s[0];
//因为我们的数组索引号从0开始 ,通常 i 从 0开始 i < 3
for (var i = i; i <= s.length; i++) { //s.length 就是数组的长度
if (max < s[i]) {
max = s[i];
}
}
console.log(max);
</script>
7.4. 新增数组元素
javascript
<script>
// 1. 新增数组元素 修改length长度
var arr = ['red', 'green', 'blue'];
console.log(arr.length);
arr.length = 5; // 把我们数组的长度修改为了 5 里面应该有5个元素
console.log(arr);
console.log(arr[3]); // undefined
console.log(arr[4]); // undefined
// 2. 新增数组元素 修改索引号 追加数组元素
var arr1 = ['red', 'green', 'blue'];
arr1[3] = 'pink';
console.log(arr1);
arr1[4] = 'hotpink';
console.log(arr1);
arr1[0] = 'yellow'; // 这里是替换原来的数组元素
console.log(arr1);
arr1 = '有点意思';
console.log(arr1); // 不要直接给 数组名赋值 否则里面的数组元素都没有了
</script>
7.5. 数组案例
7.5.1. 案例:筛选数组
javascript
<script>
//方法1
var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7];
var newarr = [];
var j = 0; //新数组索引
for (var i = 0; i <= arr.length; i++) {
if (arr[i] >= 10) {
newarr[j] = arr[i];
j++;
}
}
console.log(newarr);
</script>
//方法2
<script>
var arr = [1, 2, 3, 4, 5];
var newArr = [];
for (var i = 0; i <= arr.length; i++) {
newarr[newarr.length] = arr[i]; //妙啊
}
console.log(newarr);
</script>
7.5.2. 案例:冒泡排序(重点)

javascript
<script>
// 冒泡排序
var arr = [4, 1, 2, 3, 5];
for (var i = 0; i <= arr.length-1; i++) { // 外层循环管趟数
for (var j = 0; j <= arr.length-i-1; j++) { // 里面的循环管 每一趟的交换次数
// 内部交换2个变量的值 前一个和后面一个数组元素相比较
if (arr[j] > arr[j + 1]) {
var temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
console.log(arr);
</script>
7.5.3. 案例:翻转数组
javascript
<script>
// 将数组 ['red', 'green', 'blue', 'pink', 'purple'] 的内容反过来存放
// 1、声明一个新数组 newArr
// 2、把旧数组索引号第4个取过来(arr.length - 1),给新数组索引号第0个元素 (newArr.length)
// 3、我们采取 递减的方式 i--
var arr = ['red', 'green', 'blue', 'pink', 'purple', 'hotpink'];
var newArr = [];
for (var i = arr.length - 1; i >= 0; i--) {
newArr[newArr.length] = arr[i]
}
console.log(newArr);
</script>
8. 函数
8.1. 函数的概念
-
定义:在JS里面,可能会定义非常多的相同代码或者功能相似的代码,这些代码可能需要大量重复使用。虽然for循环语句也能实现一些简单的重复操作,但是比较具有局限性,此时我们就可以使用JS中的函数
-
函数:就是封装了一段可被重复调用执行的代码块。通过此代码块可以实现大量代码的重复使用。
8.2. 函数的使用
- 声明函数和调用函数
javascript
<script>
function 函数名(形参1,形参2) {
return 需要返回的结果;
}
函数名(实参1,实参2);
</script>
function cook(aru) {
console.log(aru);
}
cook('酸辣土豆丝');
- 调用函数:函数名();一定要加小括号
- 函数名常常采用名词
- 函数不调用,函数不执行
- 函数调用一定要写小括号
- 声明函数用function关键字
javascript
<script>
// 利用函数计算1-100之间的累加和
// 1. 声明函数
function getSum() {
var sum = 0;
for (var i = 1; i <= 100; i++) {
sum += i;
}
console.log(sum);
}
// 2. 调用函数
getSum();
getSum();
</script>
8.3. 形参和实参
- 在声明函数时,可以在函数名称后面的小括号中添加一些参数,这些参数被称为形参,而在调用该函数时,同样也需要传递相应的参数,这些参数被称为实参

- 参数的作用:在函数内部某些值不能固定,我们可以通过参数在调用函数时传递不同的值进去
- 如果实参的个数和形参的个数一致,则正常输出结果
- 如果实参的个数多余形参的个数会取到形参的个数
- 如果实实参的个数小于形参的个数,假设形参(num1,num2)给了num1值没有给num2,但是函数的形参是一个局部变量,并且是一个没有接收值的underfined所以结果是:定义了,未赋值,结果为NaN
- 在函数内部,未声明直接赋值的变量也是全局变量
javascript
// 1. 利用函数求任意两个数的和
function getSum(num1, num2) {
console.log(num1 + num2);
}
getSum(1, 3);
getSum(3, 8);
// 2. 利用函数求任意两个数之间的和
function getSums(start, end) {
var sum = 0;
for (var i = start; i <= end; i++) {
sum += i;
}
console.log(sum);
}
getSums(1, 100);
getSums(1, 10);
// 3. 注意点
// (1) 多个参数之间用逗号隔开
// (2) 形参可以看做是不用声明的变量
8.4. return
- 我们函数只是实现某种功能,最终的结果需要返回给函数的调用者函数名()通过return实现的
- 只要函数遇到return就把后面的结果返回给函数的调用者 后面的代码不会执行。 返回函数名()=return后面的结果
- 只能返回一个值,如果需要返回多个值,则用数组return[num1.num2......],或者用对象
- 如果函数里面有return则返回的是return后面的值,如果函数没有return,则返回的是underfined
- return不仅能退出循环,还能返回return语句后面的值
- 在使用 return 语句时,函数会停止执行,并返回指定的值
- 如果函数没有 return ,返回的值是 undefined
- 注意事项:
javascript
// 1. return 终止函数
function getSum(num1, num2) {
return num1 + num2; // return 后面的代码不会被执行
alert('我是不会被执行的哦!')
}
console.log(getSum(1, 2));
// 2. return 只能返回一个值
function fn(num1, num2) {
return num1, num2; // 返回的结果是最后一个值
}
console.log(fn(1, 2));
// 3. 我们求任意两个数的 加减乘数结果
function getResult(num1, num2) {
return [num1 + num2, num1 - num2, num1 * num2, num1 / num2];
}
var re = getResult(1, 2); // 返回的是一个数组
console.log(re);
// 4. 我们的函数如果有return 则返回的是 return 后面的值,如果函数没有 return 则返回undefined
function fun1() {
return 666;
}
console.log(fun1()); // 返回 666
function fun2() {
}
console.log(fun2()); // 函数返回的结果是 undefined
- break ,continue ,return 的区别
- break :结束当前的循环体(如 for、while)
- continue :跳出本次循环,继续执行下次循环(如 for、while)
- return :不仅可以退出循环,还能够返回 return 语句中的值,同时还可以结束当前的函数体内的代码
8.5. 函数案例
8.5.1案例:求最大值
javascript
<script>
//利用函数求数组 【5,2,99,101,67,77】中的最大值
function getMax(s) {
var max = s[0];
for (var i = 1; i <= s.length; i++) {
if (s[i] > max) {
max = s[i];
}
}
return max;
}
var re = getMax([5, 2, 99, 101, 67, 77]);
console.log(re);
</script>
8.5.2. 案例:反转数组
javascript
<script>
//;利用函数翻转 任意数组 reverse翻转
function reverse(arr) {
var newArr = [];
for (var i = arr.length - 1; i >= 0; i--) {
newArr[newArr.length] = arr[i];
}
return newArr;
}
var arr1 = reverse([1, 3, 4, 6, 9]);
console.log(arr1);
var arr2 = reverse(['red', 'pink', 'blue']);
console.log(arr2);
/* 结果为:
9 6 4 3 1
blue pink red */
</script>
8.5.3. 案例:冒泡排序
javascript
<script>
// 函数封装 冒泡排序 sort 排序
function sort(arr) {
for (var i = 0; i <= arr.length - 1; i++) {
//外层循环 负责躺数 5个值 是4躺
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;
}
var arr1=sort([9,4,7]);
console.log(arr1);
</script>
8.6. 用榨汁机模拟函数

8.7. arguments
- 当我们不确定有多少个参数传递的时候,我们可以用arguments来获取,在JS中,arguments实际上它是当前函数的一个内置对象。所有的函数都内置了一个arguments对象,arguments对象中存储了传递的所有实参
- 只有函数才有,并且每个函数都有一个arguments对象
- arguments是一个伪数组,特点:
- 具有数组的length属性
- 按照索引的方式进行存储的
- 他没有真正数组的一些方法pop()push()等等
javascript
<script>
// arguments 的使用 只有函数才有 arguments对象 而且是每个函数都内置好了这个arguments
function fn() {
console.log(arguments); // 里面存储了所有传递过来的实参 arguments = [1,2,3]
console.log(arguments.length);
console.log(arguments[2]);
// 我们可以按照数组的方式遍历arguments
for (var i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}
fn(1, 2, 3);
fn(1, 2, 3, 4, 5);
</script>
javascript
<script>
// 利用函数求任意个数的最大值
function getMax() { // arguments = [1,2,3]
var max = arguments[0];
for (var i = 1; i < arguments.length; i++) {
if (arguments[i] > max) {
max = arguments[i];
}
}
return max;
}
console.log(getMax(1, 2, 3));
console.log(getMax(1, 2, 3, 4, 5));
console.log(getMax(11, 2, 34, 444, 5, 100));
</script>
<script>
// 利用函数翻转任意数组 reverse 翻转
function reverse(arr) {
var newArr = [];
for (var i = arr.length - 1; i >= 0; i--) {
newArr[newArr.length] = arr[i];
}
return newArr;
}
var arr1 = reverse([1, 3, 4, 6, 9]);
console.log(arr1);
var arr2 = reverse(['red', 'pink', 'blue']);
console.log(arr2);
</script>
- 其他例子
javascript
<script>
// 利用函数冒泡排序 sort 排序
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;
}
var arr1 = sort([1, 4, 2, 9]);
console.log(arr1);
var arr2 = sort([11, 7, 22, 999]);
console.log(arr2);
</script>
<script>
// 利用函数判断闰年
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));
console.log(isRunYear(1999));
</script>
javascript
<script>
// 用户输入年份,输出当前年份2月份的天数
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>
8.8. 函数的声明方式
- 利用function创建函数也成为命名函数
- 匿名函数只不过是这个变量里面存储的是一个函数,调用的时候是变量名+()也可以传递参数
javascript
// 函数的2中声明方式
// 1. 利用函数关键字自定义函数(命名函数)
function fn() {
}
fn();
// 2. 函数表达式(匿名函数)
var 变量名 = function() {};
javascript
var fun = function(aru) {
console.log('我是函数表达式');
console.log(aru);
}
// fun('pink老师');
// (1) fun是变量名 不是函数名
// (2) 函数表达式声明方式跟声明变量差不多,只不过变量里面存的是值 而 函数表达式里面存的是函数
// (3) 函数表达式也可以进行传递参数
8.9. Javascript作用域
-
作用域
- 通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。作用 域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突
-
JavaScript(es6前)中的作用域有两种::局部作用域和全局作用域
- 全局作用域:作用于所有代码执行的环境(整个 script 标签内部)或者一个独立的 js 文件。
- 局部作用域(函数作用域):在函数内部就是局部作用域 这个代码的名字只在函数内部起效果和作用
-
变量的作用域
- 变量的作用域:根据作用域的不同我们变量分为全局变量和局部变量
- ① 全局变量:在全局作用域下声明的变量(在函数外部定义的变量)。
- 全局变量在代码的任何位置都可以使用
- 在全局作用域下 var 声明的变量 是全局变量
- 特殊情况下,在函数内不使用 var 声明的变量也是全局变量(不建议使用)
- 注意: 如果在函数内部 没有声明直接赋值的变量也属于全局变量
- ① 全局变量:在全局作用域下声明的变量(在函数外部定义的变量)。
- 变量的作用域:根据作用域的不同我们变量分为全局变量和局部变量
javascript
var num = 10; // num就是一个全局变量
console.log(num);
function fn() {
console.log(num);
}
fn();
// console.log(aru);
-
-
- ② 局部变量:在局部作用域下声明的变量(在函数内部定义的变量)
- 局部变量只能在该函数内部使用
- 在函数内部 var 声明的变量是局部变量
- 函数的形参实际上就是局部变量
- 注意: 函数的形参也可以看做是局部变量
- ② 局部变量:在局部作用域下声明的变量(在函数内部定义的变量)
-
javascript
function fun(aru) {
var num1 = 10; // num1就是局部变量 只能在函数内部使用
num2 = 20;
}
fun();
-
-
- ③ 全局变量和局部变量的区别
- (1) 全局变量只有浏览器关闭的时候才会销毁,比较占内存资源;在任何一个地方都可以使用。
- (2) 局部变量 当我们程序执行完毕就会销毁, 比较节约内存资源;只在函数内部使用,当其所在的代码块被执行时,会被初始化。
- ③ 全局变量和局部变量的区别
-
javascript
<script>
// 作用域链 : 内部函数访问外部函数的变量,采取的是链式查找的方式来决定取那个值 这种结构我们称为作用域链 就近原则
var num = 10; // 全局变量
function fn() { // 外部函数
var num = 20; // 局部变量
function fun() { // 内部函数
console.log(num);
}
fun();
}
fn();
</script>jj
- JS 没有块级作用域
- 块作用域由 { } 包括。
- js中没有块级作用域 js的作用域: 全局作用域 局部作用域 现阶段我们js 没有块级作用域
- 我们js 也是在 es6 的时候新增的块级作用域
- 块级作用域 {} if {} for {}
8.10. 作用域链
- 只要是代码,就至少有一个作用域
- 写在函数内部的局部作用域
- 如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
- 根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作作用域链
javascript
function f1(){
var num=123;
function f2(){
console.log(num);
}
f2();
}
var num=456;
f1();
// 最后输出的是123;采取就近原则,一层一层的往上找

- 作用域链:采取就近原则的方式来查找变量最终的值。
- 练习:
javascript
var a = 1;
function fn1() {
var a = 2;
var b = '22';
fn2();
function fn2() {
var a = 3;
fn3();
function fn3() {
var a = 4;
console.log(a); //a的值 4
console.log(b); //b的值 22
}
}
}
fn1();
8.11. JavaScript 预解析
8.11.1. 预解析
- JavaScript代码是由浏览器中的JavaScript解析器来执行的,JavaScript解析器在运行JavaScript代码的时候分为两步,第一步预解析,第二步代码执行
8.11.2. 变量预解析和函数预解析
- 预解析:在当前作用域下, JS 代码执行之前,浏览器会默认把带有 var 和 function 声明的变量在内存中进行提前声明或者定义。
- 预解析分为:变量预解析(变量提升)和函数预解析(函数提升)
第二步:代码执行: 从上到下执行JS语句。 - 变量预解析(变量提升)
- 变量提升:就是把所有的变量声明提升到当前的作用域最前面,注意不提升赋值操作
javascript
console.log(num); // 结果是多少?
var num = 10; // 10
- 函数预解析(函数提升)
- 函数提升:就是把所有的函数声明提升到当前作用域的最前面,但是不调用函数
javascript
fn();
function fn() {
console.log('打印');
}
8.11.3. 案例:预解析
javascript
<script>
//预解析案例
//案例1
var num = 10; //
fun();
function fun() {
console.log(num);
var num = 20; //
}
// 相当于执行了以下操作
var num;
function fun() {
var num;
console.log(num);
num = 20;
}
num = 10;
fun();
</script>
javascript
<script>
//案例2
var num = 10;
function fn() {
console.log(num);
var num = 20;
console.log(num);
}
fn();
// 相当于以下代码
var num;
function fn() {
var num;
console.log(num);
num = 20;
console.log(num);
}
num = 10;
fn();
</script>
javascript
<script>
// 案例3
var a = 18;
f1();
function f1() {
var b = 9;
console.log(a);
console.log(b);
var a = '123';
}
// 相当于以下代码
var a;
function f1() {
var b;
var a;
b = 9;
console.log(a);
console.log(b);
a = '123';
}
a = 18;
f1();
</script>
javascript
<script>
// 案例4
f1();
console.log(c);
console.log(b);
console.log(a);
function f1() {
var a = b = c = 9;
console.log(a);
console.log(b);
console.log(c);
}
// 以下代码
function f1() {
var a;
a = b = c = 9;
// 相当于 var a = 9; b = 9; c = 9; b 和 c 直接赋值 没有var 声明 当 全局变量看
// 集体声明 var a = 9, b = 9, c = 9;
console.log(a);//9
console.log(b);//9
console.log(c);//9
}
f1();
console.log(c);//9
console.log(b);//9
console.log(a);//报错
</script>
9. JavaScript对象
9.1. 对象定义
- 定义:万物皆对象,对象是一个具体的事物,看得见摸得着的实物。例如:一本书、一辆汽车、一个人。可以是"对象",一个数据库、一张网页、一个与远程服务器的连接也可以是"对象"。
9.2. 对象的组成
- 对象是由属性和方法组成的。所有的事物都是对象,例如字符串、数值、数组、函数等。
- 对象是由属性和方法组成的:
- 属性:事物的特征,在对象中用属性来表示(常用名词)
- 方法:事物的行为,在对象中用方法来表示(常用动词)
9.3. 创建对象使用对象
- 在 JavaScript 中,现阶段我们可以采用三种方式创建对象(object):
- 利用字面量创建对象
- 利用newObject创建对象
- 利用构造函数创建对象
9.3.1. 字面量创建对象
- 对象字面量:就是花括号 { } 里面包含了表达这个具体事物(对象)的属性和方法。{ } 里面采取键值对的形式表示
- 键:相当于属性名
- 值:相当于属性值,可以是任意类型的值(数字类型、字符串类型、布尔类型,函数类型等)
javascript
var star = {
name : 'pink',
age : 18,
sex : '男',
sayHi : function(){
alert('大家好啊~');
}
};
- 对象的调用
- 对象里面的属性调用 : 对象.属性名 ,这个小点 . 就理解为" 的 "
- 对象里面属性的另一种调用方式 : 对象['属性名'],注意方括号里面的属性必须加引号,我们后面会用
- 对象里面的方法调用:对象.方法名() ,注意这个方法名字后面一定加括号
javascript
console.log(star.name) // 调用名字属性
console.log(star['name']) // 调用名字属性
star.sayHi(); // 调用 sayHi 方法,注意,一定不要忘记带后面的括号
- 变量、属性、函数、方法总结
- 变量:单独声明赋值,单独存在
- 属性:对象里面的变量称为属性,不需要声明,用来描述该对象的特征
- 函数:单独存在的,通过"函数名()"的方式就可以调用
- 方法:对象里面的函数称为方法,方法不需要声明,使用"对象.方法名()"的方式就可以调用,方法用来描述该对象的行为和功能。
javascript
<script>
// 变量、属性、函数、方法的区别
// 1.变量和属性的相同点 他们都是用来存储数据的
var num = 10;
var obj = {
age: 18,
fn: function() {
}
}
function fn() {
}
console.log(obj.age);
// console.log(age);
// 变量 单独声明并赋值 使用的时候直接写变量名 单独存在
// 属性 在对象里面的不需要声明的 使用的时候必须是 对象.属性
// 2. 函数和方法的相同点 都是实现某种功能 做某件事
// 函数是单独声明 并且调用的 函数名() 单独存在的
// 方法 在对象里面 调用的时候 对象.方法()
</script>
9.3.2. 利用newObject创建对象
javascript
var andy = new Obect();
andy.name = 'pink';
andy.age = 18;
andy.sex = '男';
andy.sayHi = function(){
alert('大家好啊~');
}
- Object() :第一个字母大写
- new Object() :需要 new 关键字
- 使用的格式:对象.属性 = 值;
- 注意
- 我们是利用等号赋值的方法,添加对象的属性和方法
- 每个属性和方法之间用分号结尾
9.3.3. 利用构造函数创建对象
- 构造函数定义:是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与new运算符一起使用,我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面
- 在 js 中,使用构造函数要时要注意以下两点:
- 构造函数用于创建某一类对象,其首字母要大写
- 构造函数要和 new 一起使用才有意义
- 我们为什么需要使用构造函数? 就是因我们前面两种创建对象的方式一次只能创建一个对象。
- 实例
javascript
function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
this.sayHi = function() {
alert('我的名字叫:' + this.name + ',年龄:' + this.age + ',性别:' + this.sex);
}
}
var bigbai = new Person('大白', 100, '男');
var smallbai = new Person('小白', 21, '男');
console.log(bigbai.name);
console.log(smallbai.name);
- 注意:
- 构造函数约定首字母大写。
- 函数内的属性和方法前面需要添加 this ,表示当前对象的属性和方法。
- 构造函数中不需要 return 返回结果。
- 当我们创建对象的时候,必须用 new 来调用构造函数。
9.4. 构造函数和对象
- 构造函数,如Stars(),抽象了对象的公共部分,封装到了函数里面,它泛指某一大类(class)
- 创建对象,如newStars(),特指某一个,通过new关键字创建对象的过程我们也成为对象实例化

9.5. new关键字执行过程
- new在执行时会做四件事情:
- 在内存中创建一个新的空对象
- 让this指向这个新的对象
- 执行构造函数里面的代码,给这个新对象添加属性和方法
- 返回这个新对象(所以构造函数不需要return)
9.6. 遍历对象 for(变量in对象)
- for...in 语句用于对数组或者对象的属性进行循环操作。
javascript
for (变量 in 对象名字) {
// 在此执行代码
}
javascript
for (var k in obj) {
console.log(k); // 这里的 k 是属性名
console.log(obj[k]); // 这里的 obj[k] 是属性值
}
-
语法中的变量是自定义的,它需要符合命名规范,通常我们会将这个变量写为 k 或者 key。
-
实例:
javascript
<script>
function Perpos(name, age, sex, height, width) {
this.name = name;
this.age = age;
this.sex = sex;
this.height = height;
this.width = width;
this.worker = function (worker) {
this.worker = worker;
}
}
var daidaigou = new Perpos('呆呆狗', 20, '女', 180, '50KG');
daidaigou.worker('全栈开发工程师');
for (var k in daidaigou) {
console.log(k);
console.log(daidaigou[k]);
}
</script>
9.7. 对象小结
- 对象可以让代码结构更清晰
- 对象复杂数据类型object
- 本质:对象就是一组无序的相关属性和方法的集合
- 构造函数泛指某一大类,比如苹果,不管是红色苹果还是绿色苹果,都统称为苹果
- 对象实例特指一个事物,比如这个苹果、正在给你们讲课的pink老师等
- for......in语句用于对对象的属性进行循环操作
10. JavaScript内置对象
10.1. JavaScript中的对象分类
- JavaScript 中的对象分为3种:自定义对象 、内置对象、 浏览器对象
- 前面两种对象是JS 基础 内容,属于 ECMAScript; 第三个浏览器对象属于我们JS 独有的, 我们JS API 讲解
- 内置对象就是指 JS 语言自带的一些对象,这些对象供开发者使用,并提供一些常用的或是最基本而必要的功能(属性和方法)
- 内置对象最大的优点就是帮助我们快速开发
- JavaScript 提供了多个内置对象:Math、 Date 、Array、String等
10.2. Math对象
10.2.1. Math概述
- Math 对象不是构造函数,它具有数学常数和函数的属性和方法。跟数学相关的运算(求绝对值,取整、最大值等)可以使用 Math 中的成员。
javascript
Math.PI // 圆周率
Math.floor() // 向下取整
Math.ceil() // 向上取整
Math.round() // 四舍五入版 就近取整 注意 -3.5 结果是 -3
Math.abs() // 绝对值
Math.max()/Math.min() // 求最大和最小值
javascript
<script>
// math 数学对象 不是一个构造函数,所以我们不需要new来调用,而是直接使用里面的数学和方法即可
console.log(Math.PI);// 一个属性 圆周率
console.log(Math.max(1, 99, 3));//99
console.log(Math.max(-1, -10)); // -1
console.log(Math.max(1, 99, 'pink老师')); // NaN
console.log(Math.max()); // -Infinity
//max如果没有参数 则返回负无穷大
</script>
- 案例:封装自己的数学对象
javascript
<script>
// 利用对象封装自己的数学对象 里面有 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;
}
}
console.log(myMath.PI);
console.log(myMath.max(1, 5, 9));
console.log(myMath.min(1, 5, 9));
</script>
- 其他案例
javascript
<script>
// 1.绝对值方法
console.log(Math.abs(1)); // 1
console.log(Math.abs(-1)); // 1
console.log(Math.abs('-1')); // 隐式转换 会把字符串型 -1 转换为数字型
console.log(Math.abs('pink')); // NaN
// 2.三个取整方法
// (1) Math.floor() 地板 向下取整 往最小了取值
console.log(Math.floor(1.1)); // 1
console.log(Math.floor(1.9)); // 1
// (2) Math.ceil() ceil 天花板 向上取整 往最大了取值
console.log(Math.ceil(1.1)); // 2
console.log(Math.ceil(1.9)); // 2
// (3) Math.round() 四舍五入 其他数字都是四舍五入,但是 .5 特殊 它往大了取
console.log(Math.round(1.1)); // 1
console.log(Math.round(1.5)); // 2
console.log(Math.round(1.9)); // 2
console.log(Math.round(-1.1)); // -1
console.log(Math.round(-1.5)); // 这个结果是 -1
</script>
10.2.2. 随机数方法 random()
- 随机数方法 random() : 返回的是一个浮点数 取值是[0,1) 0 =< x < 1 ,这个方法不跟参数
javascript
<script>
//
// 得到一个两数之间的随机整数 不包括两个数在内
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min)) + min; //不含最大值,含最小值
}
console.log(getRandomInt(10, 20));
// 得到一个两数之间的随机整数 包括两个数在内
function getRandomIntInclusive(min, max) {
// min = Math.ceil(min);
// max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min; //含最大值,含最小值
}
console.log(getRandomIntInclusive(20, 30));
</script>
- 案例:猜数字游戏1231
javascript
<script>
// 猜数字游戏
// 1.随机生成一个1~10 的整数 我们需要用到 Math.random() 方法。
// 2.需要一直猜到正确为止,所以需要一直循环。
// 3.while 循环更简单
// 4.核心算法:使用 if else if 多分支语句来判断大于、小于、等于。
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~50之间的一个数字 但是只有 10次猜的机会
</script>
10.3. 日期对象
10.3.1. Date 概述
- Date 对象和 Math 对象不一样,他是一个构造函数,所以我们需要实例化后才能使用
- Date 实例用来处理日期和时间
10.3.2. Date()方法的使用
- 第一步:获取当前时间必须实例化
javascript
var now = new Date();
console.log(now);
- 第二步:Date() 构造函数的参数
- 如果括号里面有时间,就返回参数里面的时间。例如日期格式字符串为'2019-5-1',可以写成new Date('2019-5-1') 或者 new Date('2019/5/1')。
- 如果Date()不写参数,就返回当前时间
- 如果Date()里面写参数,就返回括号里面输入的时间
- 实例:
javascript
<script>
// Date() 日期对象 是一个构造函数 必须使用new 来调用创建我们的日期对象
var arr = new Array(); // 创建一个数组对象
var obj = new Object(); // 创建了一个对象实例
// 1. 使用Date 如果没有参数 返回当前系统的当前时间
var date = new Date();
console.log(date);
// 2. 参数常用的写法 数字型 2019, 10, 01 或者是 字符串型 '2019-10-1 8:8:8'
var date1 = new Date(2019, 10, 1);
console.log(date1); // 返回的是 11月 不是 10月
var date2 = new Date('2019-10-1 8:8:8');
console.log(date2);
</script>
10.3.3. 日期格式化

- 案例:格式化日期 年月日
javascript
<script>
// 格式化日期 年月日
var date = new Date();
console.log(date.getFullYear()); // 返回当前日期的年 2019
console.log(date.getMonth() + 1); // 月份 返回的月份小1个月 记得月份+1 呦
console.log(date.getDate()); // 返回的是 几号
console.log(date.getDay()); // 3 周一返回的是 1 周六返回的是 6 但是 周日返回的是 0
// 我们写一个 2019年 5月 1日 星期三
var year = date.getFullYear();
var month = date.getMonth() + 1;//补回上面的坑
var dates = date.getDate();
var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
var day = date.getDay();
console.log('今天是:' + year + '年' + month + '月' + dates + '日 ' + arr[day]);
</script>
- 案例: 格式化日期 时分秒
javascript
<script>
// 格式化日期 时分秒
var date = new Date();
console.log(date.getHours()); // 时
console.log(date.getMinutes()); // 分
console.log(date.getSeconds()); // 秒
// 要求封装一个函数返回当前的时分秒 格式 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());
</script>
10.3.4. 获取日期的总的毫秒形式(时间戳)
- Date 对象是基于1970年1月1日(世界标准时间)起的毫秒数
- 如何获取毫秒
javascript
// 实例化Date对象
var now = new Date();
// 1. 用于获取对象的原始值
console.log(date.valueOf())
console.log(date.getTime())
// 2. 简单写可以这么做
var now = + new Date();
// 3. HTML5中提供的方法,有兼容性问题
var now = Date.now();
- 案例:倒计时效果
javascript
<script>
// 倒计时效果
// 1.核心算法:输入的时间减去现在的时间就是剩余的时间,即倒计时 ,但是不能拿着时分秒相减,比如 05 分减去25分,结果会是负数的。
// 2.用时间戳来做。用户输入时间总的毫秒数减去现在时间的总的毫秒数,得到的就是剩余时间的毫秒数。
// 3.把剩余时间总的毫秒数转换为天、时、分、秒 (时间戳转换为时分秒)
// 转换公式如下:
// d = parseInt(总秒数/ 60/60 /24); // 计算天数
// h = parseInt(总秒数/ 60/60 %24) // 计算小时
// m = parseInt(总秒数 /60 %60 ); // 计算分数
// s = parseInt(总秒数%60); // 计算当前秒数
function countDown(time) {
var nowTime = +new Date(); // 返回的是当前时间总的毫秒数
var inputTime = +new Date(time); // 返回的是用户输入时间总的毫秒数
var times = (inputTime - nowTime) / 1000; // times是剩余时间总的秒数
var d = parseInt(times / 60 / 60 / 24); // 天
d = d < 10 ? '0' + d : d;
var h = parseInt(times / 60 / 60 % 24); //时
h = h < 10 ? '0' + h : h;
var m = parseInt(times / 60 % 60); // 分
m = m < 10 ? '0' + m : m;
var s = parseInt(times % 60); // 当前的秒
s = s < 10 ? '0' + s : s;
return d + '天' + h + '时' + m + '分' + s + '秒';
}
console.log(countDown('2019-5-1 18:00:00'));
var date = new Date();
console.log(date);
</script>
10.3.5. 日期格式化2
-
- 使用 Intl.DateTimeFormat API
javascript
const date = new Date();
const formatter = new Intl.DateTimeFormat('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false
});
console.log(formatter.format(date)); // 输出:2026/02/05 09:31:03
-
- 使用第三方库(如 date-fns 或 dayjs)
javascript
const dayjs = require('dayjs');
const formattedDate = dayjs().format('YYYY-MM-DD HH:mm:ss');
console.log(formattedDate); // 输出:2026-02-05 09:31:03
-
- 使用 toLocaleString() 方法
javascript
const date = new Date();
console.log(date.toLocaleString('zh-CN')); // 输出:2026/2/5 09:31:03
10.4. 数组对象
10.4.1. 数组对象的创建
- 创建数组对象的两种方式
- 字面量方式
- new Array()
javascript
<script>
// 创建数组的两种方式
// 1. 利用数组字面量
var arr = [1, 2, 3];
console.log(arr[0]);
// 2. 利用new Array()
// var arr1 = new Array(); // 创建了一个空的数组
// var arr1 = new Array(2); // 这个2 表示 数组的长度为 2 里面有2个空的数组元素
var arr1 = new Array(2, 3); // 等价于 [2,3] 这样写表示 里面有2个数组元素 是 2和3
console.log(arr1);
</script>
10.4.2. 检测是否为数组instanceof
- instanceof 运算符,可以判断一个对象是否属于某种类型
javascript
var arr = [1, 23];
var obj = {};
console.log(arr instanceof Array); // true
console.log(obj instanceof Array); // false
console.log(Array.isArray(arr)); // true
console.log(Array.isArray(obj)); // false
- Array.isArray()用于判断一个对象是否为数组,isArray() 是 HTML5 中提供的方法
- 实例
javascript
<script>
// 翻转数组
function reverse(arr) {
// if (arr instanceof Array) {
if (Array.isArray(arr)) { //
var newArr = [];
for (var i = arr.length - 1; i >= 0; i--) {
newArr[newArr.length] = arr[i];
}
return newArr;
} else {
return 'error 这个参数要求必须是数组格式 [1,2,3]'
}
}
console.log(reverse([1, 2, 3]));
console.log(reverse(1, 2, 3));
// 检测是否为数组
// (1) instanceof 运算符 它可以用来检测是否为数组
var arr = [];
var obj = {};
console.log(arr instanceof Array);
console.log(obj instanceof Array);
// (2) Array.isArray(参数); H5新增的方法 ie9以上版本支持
console.log(Array.isArray(arr));
console.log(Array.isArray(obj));
</script>
10.4.3. 添加删除数组元素的方法

javascript
<script>
// 添加删除数组元素方法
// 1. push() 在我们数组的末尾 添加一个或者多个数组元素 push 推
var arr = [1, 2, 3];
// arr.push(4, 'pink');
console.log(arr.push(4, 'pink'));
console.log(arr);
// (1) push 是可以给数组追加新的元素
// (2) push() 参数直接写 数组元素就可以了
// (3) push完毕之后,返回的结果是 新数组的长度
// (4) 原数组也会发生变化
// 2. unshift 在我们数组的开头 添加一个或者多个数组元素
console.log(arr.unshift('red', 'purple'));
console.log(arr);
// (1) unshift是可以给数组前面追加新的元素
// (2) unshift() 参数直接写 数组元素就可以了
// (3) unshift完毕之后,返回的结果是 新数组的长度
// (4) 原数组也会发生变化
</script>
javascript
<script>
// 3. pop() 它可以删除数组的最后一个元素
console.log(arr.pop());
console.log(arr);
// (1) pop是可以删除数组的最后一个元素 记住一次只能删除一个元素
// (2) pop() 没有参数
// (3) pop完毕之后,返回的结果是 删除的那个元素
// (4) 原数组也会发生变化
// 4. shift() 它可以删除数组的第一个元素
console.log(arr.shift());
console.log(arr);
// (1) shift是可以删除数组的第一个元素 记住一次只能删除一个元素
// (2) shift() 没有参数
// (3) shift完毕之后,返回的结果是 删除的那个元素
// (4) 原数组也会发生变化
</script>
- 案例: 筛选数组
javascript
<script>
// 有一个包含工资的数组[1500, 1200, 2000, 2100, 1800],要求把数组中工资超过2000的删除,剩余的放到新数组里面
var arr = [1500, 1200, 2000, 2100, 1800];
var newArr = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i] < 2000) {
// newArr[newArr.length] = arr[i];
newArr.push(arr[i]);
}
}
console.log(newArr);
</script>
10.4.4. 数组排序

javascript
<script>
// 数组排序
// 1. 翻转数组
var arr = ['pink', 'red', 'blue'];
arr.reverse();
console.log(arr);
// 2. 数组排序(冒泡排序)
var arr1 = [13, 4, 77, 1, 7];
arr1.sort(function(a, b) {
// return a - b; 升序的顺序排列
return b - a; // 降序的顺序排列
});
console.log(arr1);
</script>
10.4.5. 数组索引方法

javascript
<script>
// 返回数组元素索引号方法 indexOf(数组元素) 作用就是返回该数组元素的索引号 从前面开始查找
// 它只返回第一个满足条件的索引号
// 它如果在该数组里面找不到元素,则返回的是 -1
// var arr = ['red', 'green', 'blue', 'pink', 'blue'];
var arr = ['red', 'green', 'pink'];
console.log(arr.indexOf('blue'));
// 返回数组元素索引号方法 lastIndexOf(数组元素) 作用就是返回该数组元素的索引号 从后面开始查找
var arr = ['red', 'green', 'blue', 'pink', 'blue'];
console.log(arr.lastIndexOf('blue')); // 4
</script>
- 案例: 数组去重(重点案例)
javascript
<script>
// 数组去重 ['c', 'a', 'z', 'a', 'x', 'a', 'x', 'c', 'b'] 要求去除数组中重复的元素。
// 1.目标: 把旧数组里面不重复的元素选取出来放到新数组中, 重复的元素只保留一个, 放到新数组中去重。
// 2.核心算法: 我们遍历旧数组, 然后拿着旧数组元素去查询新数组, 如果该元素在新数组里面没有出现过, 我们就添加, 否则不添加。
// 3.我们怎么知道该元素没有存在? 利用 新数组.indexOf(数组元素) 如果返回时 - 1 就说明 新数组里面没有改元素
// 封装一个 去重的函数 unique 独一无二的
function unique(arr) {
var newArr = [];
for (var i = 0; i < arr.length; i++) {
if (newArr.indexOf(arr[i]) === -1) {
newArr.push(arr[i]);
}
}
return newArr;
}
// var demo = unique(['c', 'a', 'z', 'a', 'x', 'a', 'x', 'c', 'b'])
var demo = unique(['blue', 'green', 'blue'])
console.log(demo);
</script>
10.4.6. 数组转换为字符串

javascript
<script>
// 数组转换为字符串
// 1. toString() 将我们的数组转换为字符串
var arr = [1, 2, 3];
console.log(arr.toString()); // 1,2,3
// 2. join(分隔符)
var arr1 = ['green', 'blue', 'pink'];
console.log(arr1.join()); // green,blue,pink
console.log(arr1.join('-')); // green-blue-pink
console.log(arr1.join('&')); // green&blue&pink
</script>
10.4.7. 课下查询

- slice() 和 splice() 目的基本相同,建议同学们重点看下 splice()
10.5. 字符串对象
10.5.1. 基本包装类型
- 为了方便操作基本数据类型,JavaScript 还提供了三个特殊的引用类型:String、Number和 Boolean。基本包装类型就是把简单数据类型包装成为复杂数据类型,这样基本数据类型就有了属性和方法。
javascript
// 下面代码有什么问题?
var str = 'andy';
console.log(str.length);
- 按道理基本数据类型是没有属性和方法的,而对象才有属性和方法,但上面代码却可以执行,这是因为 js 会把基本数据类型包装为复杂数据类型,其执行过程如下 :
javascript
// 1. 生成临时变量,把简单类型包装为复杂数据类型
var temp = new String('andy');
// 2. 赋值给我们声明的字符变量
str = temp;
// 3. 销毁临时变量
temp = null;
10.5.2. 字符串的不可变
- 指的是里面的值不可变,虽然看上去可以改变内容,但其实是地址变了,内存中新开辟了一个内存空间。

javascript
var str = 'abc';
str = 'hello';
// 当重新给 str 赋值的时候,常量'abc'不会被修改,依然在内存中
// 重新给字符串赋值,会重新在内存中开辟空间,这个特点就是字符串的不可变
// 由于字符串的不可变,在大量拼接字符串的时候会有效率问题
var str = '';
for (var i = 0; i < 100000; i++) {
str += i;
}
console.log(str); // 这个结果需要花费大量时间来显示,因为需要不断的开辟新的空间
10.5.3. 根据字符返回位置
- 字符串所有的方法,都不会修改字符串本身(字符串是不可变的),操作完成会返回一个新的字符串

javascript
//字符串对象 根据字符串返回位置
// indexOf(想要查找的字符,起始位置)
var str = '改革春风吹满面,春天来了';
console.log(str.indexOf('春'));
console.log(str.indexOf('春', 3)); // 从索引号是 3的位置开始往后查找
- 案例:返回字符串所有o出现的位置以及次数
javascript
//案例 o出现的位置及次数
var str = 'abcoefoxyozzopp';
var index = str.indexOf('o');
var num = 0;
while (index !== -1) {
console.log(index);
num++;
index = str.indexOf('o', index + 1);
}
console.log(num);
10.5.4. 根据位置返回字符(重点)

javascript
<script>
// 根据位置返回字符
// 1. charAt(index) 根据位置返回字符
var str = 'andy';
console.log(str.charAt(3));
// 遍历所有的字符
for (var i = 0; i < str.length; i++) {
console.log(str.charAt(i));
}
// 2. charCodeAt(index) 返回相应索引号的字符ASCII值 目的: 判断用户按下了那个键
console.log(str.charCodeAt(0)); // 97
// 3. str[index] H5 新增的
console.log(str[0]); // a
</script>

- 案例:出现次数最多的字符,并统计其次数
javascript
// 判断一个字符串 'abcoefoxyozzopp' 中出现次数最多的字符,并统计其次数。
// o.a = 1
// o.b = 1
// o.c = 1
// o.o = 4
// 核心算法:利用 charAt() 遍历这个字符串
// 把每个字符都存储给对象, 如果对象没有该属性,就为1,如果存在了就 +1
// 遍历对象,得到最大值和该字符
var str = 'abcoefoxyozzopp';
var o = {};
for (var i = 0; i < str.length; i++) {
var chars = str.charAt(i); // chars 是 字符串的每一个字符
if (o[chars]) { // o[chars] 得到的是属性值
o[chars]++;
} else {
o[chars] = 1;
}
}
console.log(o);
// 2. 遍历对象
var max = 0;
var ch = '';
for (var k in o) {
// k 得到是 属性名
// o[k] 得到的是属性值
if (o[k] > max) {
max = o[k];
ch = k;
}
}
console.log(max);
console.log('最多的字符是' + ch);
10.5.5. 字符串的操作方法

javascript
//字符串拼接
// 1. concat('字符串1','字符串2')
var str = 'andy'
console.log(str.concat('red'));// andyred
// 2 substr('截取的起始位置','截取几个字符')
var str1 = '改革春风吹满地'
console.log(str1.substr(2, 3));//春风吹
10.5.6. replace()方法
- replace() 方法用于在字符串中用一些字符替换另一些字符。其使用格式如下:
javascript
replace(被替换的字符串, 要替换为的字符串);
javascript
var str = 'andy';
// replace('被替换的字符','替换为的字符') 只能替换被第一次匹配到的字符
console.log(str.replace('a', 'b'));//bndy
javascript
<script>
// 1. 替换字符 replace('被替换的字符', '替换为的字符') 它只会替换第一个字符
var str = 'andyandy';
console.log(str.replace('a', 'b'));
// 有一个字符串 'abcoefoxyozzopp' 要求把里面所有的 o 替换为 *
var str1 = 'abcoefoxyozzopp';
while (str1.indexOf('o') !== -1) {
str1 = str1.replace('o', '*');
}
console.log(str1);
</script>
10.5.7. split()方法
- split()方法用于切分字符串,它可以将字符串切分为数组。在切分完毕之后,返回的是一个新数组。例如下面代码:
javascript
var str = 'a,b,c,d';
console.log(str.split(',')); // 返回的是一个数组 [a, b, c, d]
10.5.8. 课下查阅
- toUpperCase() 转换大写
- toLowerCase() 转换小写
11. JavaScript简单类型和复杂类型
11.1. 简单类型与复杂类型
- 简单类型又叫做基本数据类型或者值类型,复杂类型又叫做引用类型。
- 值类型:简单数据类型/基本数据类型,在存储时变量中存储的是值本身,因此叫做值类型string ,number,boolean,undefined,null
- 引用类型:复杂数据类型,在存储时变量中存储的仅仅是地址(引用),因此叫做引用数据类型 通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等
11.2. 堆和栈
- 堆栈空间分配区别:
- 1、栈(操作系统):由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈;简单数据类型存放到栈里面
- 2、堆(操作系统):存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。复杂数据类型存放到堆里面

- 注意:JavaScript中没有堆栈的概念,通过堆栈的方式,可以让大家更容易理解代码的一些执行方式,便于将来学习其他语言。

11.3. 简单类型的内存分配
- 值类型(简单数据类型): string ,number,boolean,undefined,null
- 值类型变量的数据直接存放在变量(栈空间)中

11.4. 复杂类型的内存分配
- 引用类型(复杂数据类型):通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等
- 引用类型变量(栈空间)里存放的是地址,真正的对象实例存放在堆空间中

11.5. 简单类型传参
- 函数的形参也可以看做是一个变量,当我们把一个值类型变量作为参数传给函数的形参时,其实是把变量在栈空间里的值复制了一份给形参,那么在方法内部对形参做任何修改,都不会影响到的外部变量。
javascript
function fn(a) {
a++;
console.log(a);
}
var x = 10;
fn(x);
console.log(x);

11.6. 复杂类型传参
- 函数的形参也可以看做是一个变量,当我们把引用类型变量传给形参时,其实是把变量在栈空间里保存的堆地址复制给了形参,形参和实参其实保存的是同一个堆地址,所以操作的是同一个对象。
javascript
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. 这个输出什么 ?

12. 正则表达式
- 正则表达式用于定义一些字符串的规则
- 计算机可以根据正则表达式,来检查一个字符串是否符合规则
- 获取将字符串中符合规则的内容提取出来
- 语法:
javascript
var 变量 =new RegExp("正则表达式","匹配模式");
// 使用typeof检查正则对象,会返回object
var reg =new RegExp("a");
//这个正则表达式可以来检查一个字符串中是否含有a【严格区分大小写】
//在构造器中可以传递一个匹配模式作为第二个参数
//可以是
//i 忽略大小写
//g 全局匹配模式
- 正则表达式的方法:
- test()
- 使用这个方法可以用来检查一个字符串是否符合正则表达式的规则
- 如果符合则返回true,否则返回false
- reg.test(str)
- test()
javascript
var reg =new RegExp("a|b","i");
var boo =reg.test("B");
console.log(boo);
12.1. 正则表达式字面量方式
- 使用字面量来创建正则表达式
- 语法:var 变量 =/正则表达式/匹配模式
- 使用字面量的方式创建更加简单,但使用构造函数创建更加灵活。
javascript
/*[]里的内容也是或的关系
[ab] == a| b
[a-z] 任意小写字母
[A-Z] 任意大写字母
[0-9] 任意数字
[A-z] 任意字母,忽略大小写
*/
var reg2 =/[0-9]/;
var boo2 =reg2.test("3854");
console.log(boo2);
-
\^\]除了
var reg3 =/[^a-z]/;
var boo3 =reg3.test("3854");//true
var boo3 =reg3.test("a");//false
console.log(boo2);
console.log(boo3);
* 注意:
```javascript
var reg4 =/a[ecd]g/;//aeg | acg| adg
12.2. 字符串&正则表达式
- split()
- 可以将一个字符串拆分为一个数组
- 方法中可以传递一个正则表达式作为参数,这样方法将会根据正则表达式去拆分字符串
- 这个方法即使不指定全局匹配,也会全都拆分
javascript
var str = "1a2b3c4d5f6g7h8j9k10";
var result =str.split(/[A-z]/);
console.log(result);
- search()
- 可以搜索字符串中是否含有指定内容
- 如果搜索到指定内容,则会返回第一次出现的索引,如果没有收索到返回-1
- 它可以接受一个正则表达式作为参数,然后回根据正则表达式去检索字符串
- serach()只会查找第一个,即使设置全局匹配也没用
javascript
var str ="hello zhen chun i love you";
var result =str.search(/[zc]h/);
console.log(result);
- match()
- 可以根据正则表达式,从一个字符串中将符合条件的内容提取出来
- 默认情况下我们的match只会找到第一个符合要求的内容,找到以后就停止检索
- 我们可以设置正则表达式为全局匹配,这样就会匹配到所有的内容(使用了"g"标识符或者设置它了的global属性值为ture时,那么新创建的正则表达式对象将使用模式对要将要匹配的字符串进行全局匹配)
- 可以为正则表达式设置多个匹配模式,且顺序无所谓
- match()会将匹配到的内容封装到一个数组中返回,即使只查询到一个结果。
javascript
var str = "1a2b3c4d5f6g7h8j9k10";
var result =str.match(/[a-z]/gi);
console.log(result);
- replace()
- 可以将字符串指定内容替换新的内容
- 参数
- 被替换的内容,可以接收一个正则表达式作为参数
- 新的内容
- 默认只会替换第一个,所以当你想全替换的时候,可以使用全局匹配
javascript
var str = "1a2a3c4a5a6A7A8a9a10";
var result =str.replace(/a/ig,",");//如果你没有传第二个参数进去,那就是undefined把a替换了!
console.log(result);
12.3. 正则表达式语法1
- 量词
- 通过量词可以设置一个内容出现的次数
- 量词只对它前边的一个内容起作用
- {n}至少出现n次
- {m,n}出现m到n次
- {m,}m次以上
- +至少一个,相当于{1,}
- *0个或多个,相当于{0,}
- ?0个或1个,相当于{0,1}
javascript
var reg =/a{3}/;//至少出现3次
var str ="aaaa";
var result= reg.test(str);
console.log(result);
var reg1 =/a{1,3}/;//出现1次到3次
var str1 ="aaaa";
var result1= reg1.test(str1);
console.log(result1);
var reg3 =/a+/;//相当于{1,},一般用"x+"这种方式
var str3 ="aaaa";
var result3 =reg3.test(str3);
console.log(result3);
- 检查一个字符串的开头语结尾
- ^表示开头
- $表示结束
javascript
var reg =/^a/;//a字开头
var str ="abaaabb";
var result1 =reg.test(str);
console.log(result1);
javascript
var reg1 =/a$/;
var str1 ="bbbba";
var result2 =reg1.test(str1);
console.log(result2);
- 注意:如果在正则表达式同时使用^ $则要求字符串必须完全符合正则表达式
12.4. 正则表达式语法2
- \w
- 任意字符、数字、_ (相当于[A-z 0-9 _])
- \W
- 除了字母、数字、_ ([ ^A-z 0-9 _ ])
- \d
- 任意的数字[0-9]
- \D
- 除了数字 [ ^0-9 ]
- \s
- 空格
- \S
- 除了空格
- \b
- 单词边界
- \B
- 除了单词边界
javascript
var str =prompt("请输入")
str =str.replace(/^\s*| s*$/g,"");//去掉前尾空格
console.log(str);
12.5 常见正则校验示例
- 1.邮箱地址验证
javascript
const emailRegex = /a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
console.log(emailRegex.test("user@example.com")); // true
- 2.手机号码验证(中国大陆)
javascript
const phoneRegex = /-9]\d{9}$/;
console.log(phoneRegex.test("13812345678")); // true
- 3.密码强度验证
javascript
const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/;
console.log(passwordRegex.test("MyPass123!")); // true
- 4.身份证号码验证(18位)
javascript
const idCardRegex = /-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))((0[1-9])|([1-2]\d)|(3[0-1]))\d{3}(\d|X|x)$/;
console.log(idCardRegex.test("110101199003072315")); // true
- 5.URL地址验证
javascript
const urlRegex = /^(https?|ftp):\/\/[^\s/$.?#].[^\s]*$/;
console.log(urlRegex.test("https://www.example.com")); // true
- 6.日期格式验证(YYYY-MM-DD)
javascript
const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
console.log(dateRegex.test("2026-02-05")); // true
- 验证YYYY-MM-DD HH:mm:ss格式
javascript
function validateDateTimeYYYYMMDDHHMMSS(dateStr) {
const regex = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;
return regex.test(dateStr);
}
- 7.验证用户名(4-16位字母数字下划线)
javascript
function validateUsername(username) {
const regex = /a-zA-Z0-9_]{4,16}$/;
return regex.test(username);
}
- 8.验证邮政编码(6位数字)
javascript
function validatePostalCode(code) {
const regex = /-9]{6}$/;
return regex.test(code);
}
13. DOM简介
13.1. DOM查询
- DOM,全称Document Object Model 文档对象
- JS通过DOM来对HTML文档进行操作。只要理解了DOM就可以随心所欲的操作WEB页面
- 文档
- 表示就是整个HTML网页文档
- 对象
- 对象表示将网页中的每一部分都转换为了一个对象
- 模型
- 使用模型来表示对象之间的关系,这样方便我们获取对象

- 使用模型来表示对象之间的关系,这样方便我们获取对象
13.1.1. 基本知识
- 节点
- 节点Node 构成HTML文档最基本的单元
- 常用节点为四类
- 文档节点:整个HTML文档
- 元素节点:HTML文档中的HTML标签
- 属性标签:元素的标签
- 文本节点:HTML标签中的文本内容

- 节点的属性
- 获取元素节点
- getElementById()
- 通过id属性获取一个元素节点对象
- getElementsByTagName()
- 通过标签名获取一组元素的对象
- 这个方法会给我们返回一个类数组对象,所有查询的元素都会封装到对象中
- 即使查询到的元素只有一个,也会封装到数组中返回
- getElentsByName()
- 通过name属性获取一组元素节点对象
- innerHTML
- getElementById()
- 元素节点的子节点
- getElementsByTagName()
- 方法,返回当前节点的所有子节点
- childNodes
- 属性,表示当前节点的所有子节点
- 根据DOM,标签之间的空白也会当成文本节点
- 注意:在IE8及以下的浏览器中,不会将空白文档当成子节点,所以该属性在IE8中会返回4个子元素而其他浏览器是9个
- children
- 属性,可以获取当前元素的所有子元素【推荐】
- firstChild
- 属性,表示当前节点的第一个子节点
- firstElementChild
- 获取当前元素的第一个子元素
- 不支持IE8以下的浏览器,如果需要兼容他们尽量不要使用
- lastChild
- 属性,表示当前节点的最后一个子节点
- getElementsByTagName()
- 获取父节点和兄弟节点
- 通过具体的节点调用
- parentNode
- 属性,表示当前节点的父节点
- previousSibling
- 属性,表示当前节点的前一个人兄弟节点
- 可能获取到空白的文本
- nextSibling
- 属性,表示当前节点的后一个兄弟节点
- innerText
- 该属性可以获取元素的文本内容
- 它和innerHTML类似,不同的是它会自动将html去除
- previousElementSibling
- 获取前一个兄弟 元素,IE8及以下不支持
13.1.2. 查询剩余属性、方法
- body
- 属性,在document中有一个body属性,它保存的是body的引用
- documentElement
- 此属性为document的属性,保存的是html根标签
- all
- 此属性为document的属性,代表页面的所有元素
- getElementByClassName()
- 可以根据class属性获取一组元素节点对象
- 该方法不支持IE8
- querySelector()
- 需要一个选择器的字符串作为参数,可以根据一个CSS选择器来查询一个元素节点对象
- 虽然IE8中没有getElementsByClassName(),但是可以使用querySelector()代替
- 使用该方法总会返回唯一的元素,如果满足条件的元素有多个,那它只会返回第一个
- querySelectorAll()
- 该方法和querySelector()用法类似,不同的是它会将符合条件的元素封装到一个数组中返回
- 即使符合条件的元素只有一个,它会返回数组
代码实现
javascript
script>
window.onload=function (){
var all =document.all;
console.log(all.length);
var query =document.querySelector("#box div");
console.log(query.innerHTML);
var query1 =document.querySelectorAll("#box");
console.log(query1);
var de =document.documentElement;
console.log(de);
var body =document.body;
console.log(body);
};
13.2. DOM删除
- removeChild()
- 删除子节点
- confirm()
- 用于弹出一个带有确认和取消按钮的提示框,需要一个字符串作为参数,改字符串将会作为提示文字显示出来,如果用户点击确认会返回true,果果点击取消返回false
javascript
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>添加删除记录练习</title>
<link rel="stylesheet" type="text/css" href="css.css" />
<script type="text/javascript">
function deleteA(){
var tr = this.parentNode.parentNode;
//获取要删除的员工的名字
//var name = tr.getElementsByTagName("td")[0].innerHTML;
var name = tr.children[0].innerHTML;
//删除之前弹出一个提示框
/*
* confirm()用于弹出一个带有确认和取消按钮的提示框
* 需要一个字符串作为参数,该字符串将会作为提示文字显示出来
* 如果用户点击确认则会返回true,如果点击取消则返回false
*/
var flag = confirm("确认删除"+name+"吗?");
//如果用户点击确认
if(flag){
//删除tr
tr.parentNode.removeChild(tr);
}
/*
* 点击超链接以后,超链接会跳转页面,这个是超链接的默认行为,
* 但是此时我们不希望出现默认行为,可以通过在响应函数的最后return false来取消默认行为
*/
return false;
};
window.onload = function(){
//获取所有额超链接
var allA = document.getElementsByTagName("a");
//为每个超链接都绑定一个单击响应函数
for(var i=0 ; i < allA.length ; i++) {
allA[i].onclick = deleteA;
}
var addEmpButton =document.getElementById("addEmpButton");
addEmpButton.onclick =function (){
var empName =document.getElementById("empName").value;
var email =document.getElementById("email").value;
var salary =document.getElementById("salary").value;
// var a =document.createElement("a");
// a.innerText ="Delete";
var tr =document.createElement("tr");
// var nameTd =document.createElement("td");
// var emailTd =document.createElement("td");
// var salaryTd =document.createElement("td");
// var aTd =document.createElement("td");
tr.innerHTML ="<td>"+empName+"</td>"+
"<td>"+email+"</td>"+
"<td>"+salary+"</td>"+
"<td><a href='javascript:;'>Delete</a></td>";
var a =tr.getElementsByTagName("a")[0];//哪怕只有一个元素,该方法也会返回一个集合
a.onclick =deleteA;
// var nameText =document.createTextNode(empName);
// var emailText =document.createTextNode(email);
// var salaryText =document.createTextNode(salary);
// var delText =document.createTextNode("delete");
//
//
// // a.appendChild(delText);上面有innerText
// a.href ="javascript:;";
// aTd.appendChild(a);
// nameTd.appendChild(nameText);
// emailTd.appendChild(emailText);
// salaryTd.appendChild(salaryText);
//
// tr.appendChild(nameTd);
// tr.appendChild(emailTd);
// tr.appendChild(salaryTd);
// tr.appendChild(aTd);
var employeeTable =document.getElementById("employeeTable");
var tbody =employeeTable.getElementsByTagName("tbody")[0];
tbody.appendChild(tr);
};
};
</script>
</head>
<body>
<table id="employeeTable">
<tr>
<th>Name</th>
<th>Email</th>
<th>Salary</th>
<th> </th>
</tr>
<tr>
<td>Tom</td>
<td>tom@tom.com</td>
<td>5000</td>
<td><a href="javascript:;">Delete</a></td>
</tr>
<tr>
<td>Jerry</td>
<td>jerry@sohu.com</td>
<td>8000</td>
<td><a href="deleteEmp?id=002">Delete</a></td>
</tr>
<tr>
<td>Bob</td>
<td>bob@tom.com</td>
<td>10000</td>
<td><a href="deleteEmp?id=003">Delete</a></td>
</tr>
</table>
<div id="formDiv">
<h4>添加新员工</h4>
<table>
<tr>
<td class="word">name: </td>
<td class="inp">
<input type="text" name="empName" id="empName" />
</td>
</tr>
<tr>
<td class="word">email: </td>
<td class="inp">
<input type="text" name="email" id="email" />
</td>
</tr>
<tr>
<td class="word">salary: </td>
<td class="inp">
<input type="text" name="salary" id="salary" />
</td>
</tr>
<tr>
<td colspan="2" align="center">
<button id="addEmpButton" value="abc">
Submit
</button>
</td>
</tr>
</table>
</div>
</body>
</html>
- 注意:
- for循环会在页面加载完成之后立即执行,而响应函数会在超链接被点击时才执行,当响应函数执行时,for循环早已执行完毕。
13.3. 操作样式
13.3.1. 操作内联样式
- 通过JS修改的样式:
- 语法:元素.style.样式名 =样式值
- 注意:
- 如果CSS的样式中含有-,这种名称在JS中式不合法的,比如:background-color需要将这种样式名改为驼峰命名法,去掉-,然后将-后的字母大写
- 通过style属性设置样式都是内联样式,而内联样式有较高的优先级,所以通过JS修改的样式往往会立即显示
- 但是如果在样式中写了!important,则此时样式会有最高的优先级,即使通过JS也不能覆盖该样式,此时将会导致JS修改样式失效,所以尽量不要为样式添加!important
- 通过style属性设置和读取内联样式
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>操作内联样式</title>
<style>
#box {
width: 100px;
height: 100px;
background-color: red;
}
</style>
<script>
window.onload = function () {
var button = document.getElementById("button");
button.onclick = function () {
box.style.width = "300px";
box.style.height = "300px";
box.style.backgroundColor = "yellow";
};
var button1 = document.getElementById("button1");
button1.onclick = function () {
alert(box.style.width);
alert(box.style.height);
alert(box.style.backgroundColor);
};
};
</script>
</head>
<body>
<div id="box"></div>
<button id="button">点我一下</button>
<button id="button1">查看内联样式</button>
</body>
</html>
13.3.2. 获取元素当前显示样式
- currentStyle
- 语法:元素.currentStyle.样式名
- 它可以用来读取当前正在显示的样式,如果当前元素没有设置该样式,则获取它的默认值
- 提示:只有IE支持,其他浏览器不支持
- getComputedStyle() 推荐
- 这个方法来获取元素当前的样式,这个方法是window的方法,可以直接使用,需要两个参数
- 第一个:要获取的样式的元素
- 第二个:可以传一个伪参数,一般传null
- 该方法会返回一个对象,对象中封装了当前元素对应的样式(属性),可以通过对象.样式名来读取样式,如果获取的样式没有设置,则会获取到真实的值,而不是默认值,比如:没有设置width,它不会获取到auto,而是一个长度,但是该方法不支持IE8及以下的浏览器
- 通过currentStyle和和getComputedStyle()读取到的样式都是只读的,不能修改,如果要修改必须通过style属性
- 自定义函数实现获取元素当前显示样本
- 定义一个函数,用来获取指定元素的当前的样式
- 参数:obj 要获取样式的元素
- name 要获取的样式名
javascript
/**
* 这种思想常用来解决兼容性问题
* @param obj 对象
* @param name 字符串属性
* @returns {*}
*/
function getStyle(obj ,name){
if(window.getComputedStyle){
//这里最好加window. 因为不加的话,他就是变量,变量没找到会报错,下面就没有机会执行了,
// 要是属性的话,是undefined,就转false,去执行else,不会报错了。
return getComputedStyle(obj,null)[name];
}else {
return obj.currentStyle[name];
}
}
13.3.3. 其他样式操作的属性
- clientWidth clientHeight
- 这两个属性可以获取元素的可见宽度于高度,这些【包括后面的】属性都是不带px的,返回都是一个数字,可以直接进行计算,会获取元素的高度和宽度,包括内容区和内边距,这些属性都是只读的,不能修改。
- offsetWidth offsetHeight
- 获取元素整个宽度和高度,包括内容区、内边距和边框
javascript
alert(box.offsetWidth);
- offsetParent
- 可以用来获取当前元素是的定位父元素
- 会获取离当前元素最近的开启了定位的祖先元素
- 如果所有的祖先元素都没有开启定位,则会返回body
- 可以用来获取当前元素是的定位父元素
javascript
var op =box.offsetParent
- offsetLeft
- 当前元素相对于其定位父元素的水平
javascript
alert(box.offsetLest);
- offsetTop
- 当前元素相对于其定位父元素的垂直偏移量
javascript
alert(box.offsetLeft)
- scrollWitdth scrollHeight
- 可以获取元素整个滚动区域的宽度和高度
javascript
alert(box.scrollWidth)
- scrollLeft
- 可以获取水平滚动读条的距离
- scrollTop
- 可以获取垂直滚动条滚动的距离
javascript
alert(box.scrollTop)
-
技巧:
- scrollHeight -scrollTop == clientHeight说明垂直滚动条到底了
- scrollWidth - scrollLeft == clientWidth说明水平滚动条到底了
-
代码演示
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
#box {
width: 300px;
height: 500px;
background-color: green;
overflow: auto;
}
</style>
<script>
/**
* 当垂直表单滚动到底时,使表单可选项可用
* onscroll
* 该事件会在元素滚动条滚动时触发
*/
window.onload = function () {
var box = document.getElementById("box");
var inputs = document.getElementsByTagName("input");
box.onscroll = function () {
if (box.scrollHeight - box.scrollTop == box.clientHeight) {
/**
* disabled属性设置一个元素是否可以
* 如果true,则表示禁用
* 如果使false,则表示启用
* @type {boolean}
*/
inputs[0].disabled = false;
inputs[1].disabled = false;
}
};
};
</script>
</head>
<body>
<div >
<h3>注册</h3>
<p id="box">年少轻狂的岁月沉淀下来的是哪些再也回不到的过去,而总让人感叹的则是未能珍惜而失去的那些,
但这些也恰恰是我们让你去体会的,因为年少轻狂的岁月,一生也只有一次。世间最珍贵的不是得不到或已失去的,而是现在能把握的。
我们生活在一个复杂又充满无奈的世界,身上背负着太多太多的责任和使命,
有时我们处理不当,就会不堪重负,难以忍受。最宽阔的是海洋,比海洋更宽阔的是天空,
比天空更宽阔的是人的胸怀。当你紧握双手,里面什么也没有,
当你打开双手,世界就在你手中。
年少轻狂的岁月沉淀下来的是哪些再也回不到的过去,而总让人感叹的则是未能珍惜而失去的那些,
但这些也恰恰是我们让你去体会的,因为年少轻狂的岁月,一生也只有一次。世间最珍贵的不是得不到或已失去的,而是现在能把握的。
我们生活在一个复杂又充满无奈的世界,身上背负着太多太多的责任和使命,
有时我们处理不当,就会不堪重负,难以忍受。最宽阔的是海洋,比海洋更宽阔的是天空,
比天空更宽阔的是人的胸怀。当你紧握双手,里面什么也没有,
当你打开双手,世界就在你手中。
年少轻狂的岁月沉淀下来的是哪些再也回不到的过去,而总让人感叹的则是未能珍惜而失去的那些,
但这些也恰恰是我们让你去体会的,因为年少轻狂的岁月,一生也只有一次。世间最珍贵的不是得不到或已失去的,而是现在能把握的。
我们生活在一个复杂又充满无奈的世界,身上背负着太多太多的责任和使命,
有时我们处理不当,就会不堪重负,难以忍受。最宽阔的是海洋,比海洋更宽阔的是天空,
比天空更宽阔的是人的胸怀。当你紧握双手,里面什么也没有,
当你打开双手,世界就在你手中。
</p>
</div>
<input type="checkbox" disabled="disabled"/>已阅读协议,我一定遵守
<input type="submit" value="注册" disabled="disabled" />
</body>
</html>
- 总结:
- 在写这个的时候,我常常发现一个问题:
- getElementsByName与getElementsByTagName区别:
- 前者获得名字name属性;后者为标签名
13.4. 事件
13.4.1. 事件
- 事件
- 就是文档或浏览器窗口中发生一些特定的交互瞬间
- JavaScript与HTML之间的交互是通过事件实现的
- 对于Web应用来说,有下面这些代表性事件:
- 点击按钮
- 将鼠标移动至某个元素的上方
- 按下键盘上某个键
- 关闭窗口
- ......
- 代码实现
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件</title>
</head>
<body>
<button id="btn">我是一个按钮</button>
<script>
var btn=document.getElementById("btn");
/*
可以为按钮的对应事件绑定处理函数的形式来响应事件
这样当事件被触发时,其对应的函数将会被调用
*/
//绑定一个单击事件
//想这种为单击事件绑定的函数,我们称为单击响应函数
btn.onclick =function (){
alert("你好帅!~~")
};
</script>
</body>
</html>
- 注意:
- 浏览器在加载一个页面时,是按照自上而下的顺序加载的,读取到一行运行一行,如果将script标签写在页面是上面,在代码执行时,页面还没有加载,页面没有加载DOM对象会导致无法获取DOM 对象。
- 为了解决上述问题,可以引入onload
- onload事件会在整个页面加载完成之后才触发,为window绑定一个onload事件,该事件对应的响应函数将会在页面加载完成之后执行,这样可以确保我们的代码执行的所有DOM对象加载完毕了!
13.4.2. 事件对象
- 当事件的响应函数被触发时,浏览器每次都会将一个事件对象作为实参传递进响应函数,在事件对象中封装了当前事件相关的一切信息,比如:鼠标的坐标、键盘哪个键被按下、鼠标滚轮滚动 方向......
- onmousemove该事件将会在鼠标在元素中移动时被触发
- clientX可以获取鼠标指针的水平位置
- clientY可以获取鼠标指针的垂直坐标
- 注意:
- 在IE8,响应函数被触发时,浏览器不会传递事件对象,在IE8及以下的浏览器中,是将事件对象作为window对象的属性保存
- 代码演示
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件对象</title>
<style>
#agrsDiv {
width: 600px;
height: 500px;
border: solid;
}
#showDiv {
width: 600px;
height: 200px;
border: solid;
}
</style>
<script>
window.onload = function () {
var agrs = document.getElementById("agrsDiv");
var show = document.getElementById("showDiv");
agrs.onmousemove = function (event) {
event = event || window.event;
var x = event.clientX;
var y = event.clientY;
show.innerHTML = "x=" + x + ",y =" + y;
};
};
</script>
</head>
<body>
<div id="agrsDiv"></div>
<p></p>
<div id="showDiv"></div>
</body>
</html>
- 练习:div随鼠标移动
javascript
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
#box1{
width: 100px;
height: 100px;
background-color: red;
/*
* 开启box1的绝对定位
*/
position: absolute;
}
</style>
<script type="text/javascript">
window.onload = function(){
/*
* 使div可以跟随鼠标移动
*/
//获取box1
var box1 = document.getElementById("box1");
//绑定鼠标移动事件
document.onmousemove = function(event){
//解决兼容问题
event = event || window.event;
//获取滚动条滚动的距离
/*
* chrome认为浏览器的滚动条是body的,可以通过body.scrollTop来获取
* 火狐等浏览器认为浏览器的滚动条是html的,
*/
var st = document.body.scrollTop || document.documentElement.scrollTop;
var sl = document.body.scrollLeft || document.documentElement.scrollLeft;
//var st = document.documentElement.scrollTop;
//获取到鼠标的坐标
/*
* clientX和clientY
* 用于获取鼠标在当前的可见窗口的坐标
* div的偏移量,是相对于整个页面的
*
* pageX和pageY可以获取鼠标相对于当前页面的坐标
* 但是这个两个属性在IE8中不支持,所以如果需要兼容IE8,则不要使用
*/
var left = event.clientX;
var top = event.clientY;
//设置div的偏移量
box1.style.left = left + sl + "px";
box1.style.top = top + st + "px";
};
};
</script>
</head>
<body style="height: 1000px;width: 2000px;">
<div id="box1"></div>
</body>
</html>
- 注意点:
- document.onmousemove =function (event){};
- 为什么给onmousemove绑定的对象是整个文档呢,因为他是相对于整个文档来移动的。经常会把这个东西绑定给div,但这是错的,一但你的鼠标离开div的范围,那div就不会跟着它移动了。所有这个时候,它只能斜向下方向移动,所有我们针对的是整个文档页面,即为document。
- 滚条问题
javascript
var st =document.body.scrollTop || document.documentElement.scrollTop;
var sl =document.body.scrollLeft || document.documentElement.scrollLeft;
-
- 如果你没有加这两个,因为div的偏移量时相对于整个页面来说,而clientX和clientY的偏移是对当前可见页面来说的,当实际页面比当前页面要大,就会出现滚条,当你滑动滚条时,div会出现于鼠标分离的情况,就因为这两件事物偏移所对应的对象所不同,所有你必须让div的移动加上滚条的移动,就实现了对当前可见窗的移动了。
13.4.3. 事件的冒泡
- 所谓的冒泡指的就是事件向上传导,当后代元素上的事件被触发时,其祖先元素的相同事件也会被触发
- 在开发中的大部分情况中,冒泡都是有用的,如果不希望发生事件冒泡可以通过事件对象来取消冒泡
javascript
cancelBubble
- 可以将事件对象的cancelBubble设置为true,即可取消冒泡
- true着取消,false则启用
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件的冒泡</title>
<style>
#box{
width: 500px;
height: 500px;
background-color: green;
}
span{
width: 200px;
height: 100px;
background-color: yellow;
}
</style>
<script>
window.onload =function (){
var box =document.getElementById("box");
box.onclick =function (event){
event = event||window.event;
alert("我是div函数");
event.cancelBubble =true;
};
var span =document.getElementById("spanBox");
span.onclick =function (event){
event = event||window.event;
alert("我是span函数");
event.cancelBubble =true;
};
document.body.onclick =function (){
alert("我是body函数");
};
};
</script>
</head>
<body>
<div id="box">我是div<span id="spanBox">我是span</span></div>
</body>
</html>
13.4.4. 事件的委派
- 我们希望,只绑定一次事件,即可应用到多分元素上,即使元素是后添加的,我们可以尝试将其绑定给元素的共同祖先元素。
- 事件的委派指将事件统一绑定给元素的共同祖先,这样当后代元素的事件被触发时,会一直冒泡到祖先元素,从而通过祖先元素的响应函数来处理事件。
- 事件的委派是利用了冒泡,通过委派可以减少事件的绑定次数,挺高程序性能。
javascript
target
- event中的target表示的触发事件的对象
- 代码演示
javascript
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script type="text/javascript">
window.onload = function(){
var u1 = document.getElementById("u1");
//点击按钮以后添加超链接
var btn01 = document.getElementById("btn01");
btn01.onclick = function(){
//创建一个li
var li = document.createElement("li");
li.innerHTML = "<a href='javascript:;' class='link'>新建的超链接</a>";
//将li添加到ul中
u1.appendChild(li);
};
/*
* 为每一个超链接都绑定一个单击响应函数
* 这里我们为每一个超链接都绑定了一个单击响应函数,这种操作比较麻烦,
* 而且这些操作只能为已有的超链接设置事件,而新添加的超链接必须重新绑定
*/
//获取所有的a
var allA = document.getElementsByTagName("a");
//遍历
/*for(var i=0 ; i<allA.length ; i++){
allA[i].onclick = function(){
alert("我是a的单击响应函数!!!");
};
}*/
/*
* 我们希望,只绑定一次事件,即可应用到多个的元素上,即使元素是后添加的
* 我们可以尝试将其绑定给元素的共同的祖先元素
*
* 事件的委派
* - 指将事件统一绑定给元素的共同的祖先元素,这样当后代元素上的事件触发时,会一直冒泡到祖先元素
* 从而通过祖先元素的响应函数来处理事件。
* - 事件委派是利用了冒泡,通过委派可以减少事件绑定的次数,提高程序的性能
*/
//为ul绑定一个单击响应函数
u1.onclick = function(event){
event = event || window.event;
/*
* target
* - event中的target表示的触发事件的对象
*/
//alert(event.target);
//如果触发事件的对象是我们期望的元素,则执行否则不执行
if(event.target.className == "link"){
alert("我是ul的单击响应函数");
}
};
};
</script>
</head>
<body>
<button id="btn01">添加超链接</button>
<ul id="u1" style="background-color: #bfa;">
<li>
<p>我是p元素</p>
</li>
<li><a href="javascript:;" class="link">超链接一</a></li>
<li><a href="javascript:;" class="link">超链接二</a></li>
<li><a href="javascript:;" class="link">超链接三</a></li>
</ul>
</body>
</html>
13.4.5. 事件的绑定
- 就目前而言,事件的绑定有三种
- 一:赋值绑定
- 这种方式后者会对前者进行覆盖,所以它只会弹出2
javascript
window.onload = function () {
var button = document.getElementById("button");
button.onclick = function () {
alert(1);
};
button.onclick = function () {
alert(2);
};
};
- 二:addEventListener
- 通过这个方法也可以为元素绑定响应函数
- 参数:
- 事件的字符串
- 回调函数,当时间触发时该函数会被调用
- 是否在捕获阶段触发事件,需要一个布尔值,一般情况下,都传false
javascript
var button = document.getElementById("button");
button.addEventListener("click", function () {
alert(1);
}, false);
button.addEventListener("click", function () {
alert(2);
}, false);
-
优点:
- 可以同时为一个元素的相同事件同时绑定多个响应函数,这样当事件触发时,响应函数将会按照绑定的顺序执行
- 一些特定的事件也只能使用该方法绑定
-
缺点:
- 兼容性问题,IE8及以下没有这个方法
-
attachEvent()
- 在IE8中可以使用attachEvent()来绑定事件
- 参数:
- 事件的字符串,要on
- 回调函数
javascript
button.attachEvent("onclick",function (){
alert(1);
});
button.attachEvent("onclick",function (){
alert(2);
});
- 这个只有IE8及以下的时候采用,但我们考虑到兼容性问题,需要对浏览器做兼容-=》bind()函数
- 值得注意的是:
- 这个方法也可以同时为一个事件绑定多个处理函数
- 不同的是它是后绑定先执行,执行顺序和addEventListener()想反
13.4.6. bind()函数
- 定义一个函数,用来为指定元素绑定响应函数
- addEventListener()中的this,是绑定事件的对象
- attachEvent()中的this,是window
- 需要统一两个方法的this
- 参数:
- obj 要绑定事件的对象
- eventStr 事件的字符串(不要on)
- callback 回调函数
- 参数:
javascript
/**
*
* @param obj 绑定事件的对象
* @param eventStr 事件的字符串(不要on)
* @param callback 回调函数
*/
function bind(obj,eventStr,callback){
if(obj.addEventListener){
//大部分浏览器
obj.addEventListener(eventStr,callback,false);
}else {
/**
* this是由谁调的方式决定
* callback().call(obj);
*/
//IE8及以下浏览器
obj.attachEvent("on"+eventStr,function (){
callback.call(obj);
});
}
}
13.4.7. 事件的传播
- 关于事件的传播网景公司和微软有不同的理解
- 微软认为事件一个是由内向外传播,也就是当事件触发时,应该先触发当前元素上的事件,然后再向当前元素的祖先元素传播,也就说事情应该再在冒泡阶段执行
- 网景公司认为事件应该时由外向内传播的,也就是当事件触发时,应该先触发当前元素最外层的祖先元素,然后再向内传播给后代元素
- W3C综合了两个公司的方案,将事件传播分成了三个阶段
- 捕获阶段
- 在捕获阶段时,从最外层的祖先元素向目标元素进行事件的捕获,但是默认此时不会触发事件
- 目标阶段
- 事件捕获到目标元素,捕获结束开始在目标元素上触发事件
- 冒泡阶段
- 事件从目标元素向他的祖先元素传递,依次触发祖先元素的事件
- 捕获阶段
- 注意:
- 如果希望在捕获阶段就触发事件,可以将addEventListener()的第三个参数设置为true
- IE8及以下的浏览器中没有捕获阶段
- 图示

- 代码演示
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件的传播</title>
<style>
#box1{
height: 300px;
width: 300px;
background-color: yellow;
}
#box2{
height: 150px;
width: 150px;
background-color: green;
}
#box3{
height: 100px;
width: 100px;
background-color: red;
}
</style>
<script>
window.onload =function (){
var box1 =document.getElementById("box1");
var box2 =document.getElementById("box2");
var box3 =document.getElementById("box3");
bind(box1,"click",function (){
alert("我是box1");
});
bind(box2,"click",function (){
alert("我是box2");
});
bind(box3,"click",function (){
alert("我是box3");
});
};
function bind(obj,eventStr,callback){
if(obj.addEventListener){
//大部分浏览器
//这里如果你把obj去掉,那么调用addEventListener的就是window,
// 如果是window调用的话那就是顺序调用了,只有是这个事件调用才是符合事件的传播 obj.addEventListener(eventStr,callback,false);
}else {
/**
* this是由谁调的方式决定
* callback().call(obj);
*/
//IE8及以下浏览器
obj.attachEvent("on"+eventStr,function (){
callback.call(obj);
});
}
}
</script>
</head>
<body>
<div id="box1">
<div id="box2">
<div id="box3"></div>
</div>
</div>
</body>
</html>
- 注意:
- 这里如果你把obj去掉,那么调用addEventListener的就是window,
- 如果是window调用的话那就是顺序调用了,只有是这个事件调用才是符合事件的传播
13.4.8. 拖曳
- 拖曳的流程
- 当鼠标在被拖曳元素上按下时,开始拖曳onmousedown
- 当鼠标移动时被拖曳元素跟随鼠标移动onmousemove
- 当鼠标松开时,被拖曳元素固定在当前位置onmouseup
- 鼠标位置问题:
- 逻辑图解

- 代码演示
javascript
//div的偏移量 鼠标.clientX-box.offsetLeft;
//div的偏移量 鼠标.clientY-box.offsetTop;
var ol =event.clientX -box.offsetLeft;
var ot =event.clientY -box.offsetTop;
var left =event.clientX-ol;
var top =event.clientY-ot;
box.style.left =left+"px";
box.style.top =top+"px";
- 注意:
- 当我们拖曳一个网页中的内容时,浏览器会默认去搜索引擎中搜索内容,此时会导致拖曳功能异常,这个是浏览器所提供的默认行为,如果不希望发生这个行为,则可以通过return false来取消默认行为
- 但是 这对IE8 不管用
- 针对IE8我们使用,捕获函数和释放捕获函数来解决
javascript
obj.setCapture&&obj.setCapture();//捕捉函数
obj.releaseCapture && obj.releaseCapture();//释放函数
- 拖曳代码演示
javascript
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
#box1 {
width: 100px;
height: 100px;
background-color: red;
position: absolute;
}
#box2 {
width: 100px;
height: 100px;
background-color: yellow;
position: absolute;
left: 200px;
top: 200px;
}
</style>
<script type="text/javascript">
window.onload = function () {
/*
* 拖拽box1元素
* - 拖拽的流程
* 1.当鼠标在被拖拽元素上按下时,开始拖拽 onmousedown
* 2.当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove
* 3.当鼠标松开时,被拖拽元素固定在当前位置 onmouseup
*/
//获取box1
var box1 = document.getElementById("box1");
var box2 = document.getElementById("box2");
var img1 = document.getElementById("img1");
//开启box1的拖拽
drag(box1);
//开启box2的
drag(box2);
drag(img1);
};
/*
* 提取一个专门用来设置拖拽的函数
* 参数:开启拖拽的元素
*/
function drag(obj) {
//当鼠标在被拖拽元素上按下时,开始拖拽 onmousedown
obj.onmousedown = function (event) {
//设置box1捕获所有鼠标按下的事件
/*
* setCapture()
* - 只有IE支持,但是在火狐中调用时不会报错,
* 而如果使用chrome调用,会报错
*/
/*if(box1.setCapture){
box1.setCapture();
}*/
obj.setCapture && obj.setCapture();
event = event || window.event;
//div的偏移量 鼠标.clentX - 元素.offsetLeft
//div的偏移量 鼠标.clentY - 元素.offsetTop
var ol = event.clientX - obj.offsetLeft;
var ot = event.clientY - obj.offsetTop;
//为document绑定一个onmousemove事件
document.onmousemove = function (event) {
event = event || window.event;
//当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove
//获取鼠标的坐标
var left = event.clientX - ol;
var top = event.clientY - ot;
//修改box1的位置
obj.style.left = left + "px";
obj.style.top = top + "px";
};
//为document绑定一个鼠标松开事件
document.onmouseup = function () {
//当鼠标松开时,被拖拽元素固定在当前位置 onmouseup
//取消document的onmousemove事件
document.onmousemove = null;
//取消document的onmouseup事件
document.onmouseup = null;
//当鼠标松开时,取消对事件的捕获
obj.releaseCapture && obj.releaseCapture();
};
/*
* 当我们拖拽一个网页中的内容时,浏览器会默认去搜索引擎中搜索内容,
* 此时会导致拖拽功能的异常,这个是浏览器提供的默认行为,
* 如果不希望发生这个行为,则可以通过return false来取消默认行为
*
* 但是这招对IE8不起作用
*/
return false;
};
}
</script>
</head>
<body>
我是一段文字
<div id="box1"></div>
<div id="box2"></div>
<img src="img/an.jpg" id="img1" style="position: absolute;"/>
</body>
</html>
13.4.9. 鼠标滚轮事件
-
火狐滚轮DOMMouseScroll
- 注意该事件需要通过addEventListener()函数来绑定
- 火狐不支持wheelDelta这个属性,其对应用的是detail这个属性来获取滚动的方向,向上滚动 -3,向下滚动3
- 当滚轮滚动时,如果浏览器有滚动条,滚动条会随之滚动,这是浏览器的默认行为,一般用reture false,来取消,但是火狐是用addEventListener(),使用addEventListener()方法来绑定响应函数,取消默认行为不能使用return false。需要使用event来取消默认行为event.preventDefault,但是IE8对此又不支持,如果调用会直接报错,所以我们一般这样写:
event.preventDefault && event.preventDefault()
-
其他浏览器onwheel
- wheelDelta来获取滚轮方向,当向上滚动时,其返回值为120,向下滚动时,其返回值为-120
- 用returen false来取消浏览器滚条随滚条移动的情况。
-
代码演示
javascript
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
#box1{
width: 100px;
height: 100px;
background-color: red;
}
</style>
<script type="text/javascript">
window.onload = function(){
//获取id为box1的div
var box1 = document.getElementById("box1");
//为box1绑定一个鼠标滚轮滚动的事件
/*
* onmousewheel鼠标滚轮滚动的事件,会在滚轮滚动时触发,
* 但是火狐不支持该属性
*
* 在火狐中需要使用 DOMMouseScroll 来绑定滚动事件
* 注意该事件需要通过addEventListener()函数来绑定
*/
box1.onmousewheel = function(event){
event = event || window.event;
//event.wheelDelta 可以获取鼠标滚轮滚动的方向
//向上滚 120 向下滚 -120
//wheelDelta这个值我们不看大小,只看正负
//alert(event.wheelDelta);
//wheelDelta这个属性火狐中不支持
//在火狐中使用event.detail来获取滚动的方向
//向上滚 -3 向下滚 3
//alert(event.detail);
/*
* 当鼠标滚轮向下滚动时,box1变长
* 当滚轮向上滚动时,box1变短
*/
//判断鼠标滚轮滚动的方向
if(event.wheelDelta > 0 || event.detail < 0){
//向上滚,box1变短
box1.style.height = box1.clientHeight - 10 + "px";
}else{
//向下滚,box1变长
box1.style.height = box1.clientHeight + 10 + "px";
}
/*
* 使用addEventListener()方法绑定响应函数,取消默认行为时不能使用return false
* 需要使用event来取消默认行为event.preventDefault();
* 但是IE8不支持event.preventDefault();这个玩意,如果直接调用会报错
*/
event.preventDefault && event.preventDefault();
/*
* 当滚轮滚动时,如果浏览器有滚动条,滚动条会随之滚动,
* 这是浏览器的默认行为,如果不希望发生,则可以取消默认行为
*/
return false;
};
//为火狐绑定滚轮事件
bind(box1,"DOMMouseScroll",box1.onmousewheel);
};
function bind(obj , eventStr , callback){
if(obj.addEventListener){
//大部分浏览器兼容的方式
obj.addEventListener(eventStr , callback , false);
}else{
/*
* this是谁由调用方式决定
* callback.call(obj)
*/
//IE8及以下
obj.attachEvent("on"+eventStr , function(){
//在匿名函数中调用回调函数
callback.call(obj);
});
}
}
</script>
</head>
<body style="height: 2000px;">
<div id="box1"></div>
</body>
</html>
13.4.10. 键盘事件
- 按键被按下onkeydown
- 对于onkeydown来说如果一直按着某个按键不松手,则事件会被一直触发。
- 当onkeydown连续触发时,第一次和第二次之间的间隔稍微长一点,其他的会变得非常快,这种设计是为了防止误操作的发生
- 按键被松开onkeyup
- 键盘事件一般会绑定给一些可以获取焦点的对象或者是document
- keyCode获取按键的unicode编码
- 通过它可以判断哪个按键被按下
- altKey判断alt键是否被按下
- ctrlKey判断ctrl键是否被按下
- shiftKeY判断shift是否被按下
- 练习:键盘移动div
- 相关知识
- 向左的unicode是37
- 向上的unicode是38
- 向右的Unicode是39
- 向下的unicode是40
- 相关知识
- 代码演示
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>键盘移动div</title>
<style>
#box{
width: 100px;
height: 100px;
background-color: red;
border: solid;
position: absolute;
}
</style>
<script>
window.onload =function (){
/**
* 37向左
* 38向上
* 39向右
* 40向下
*/
var box =document.getElementById("box");
document.onkeydown =function (event){
event =event|| window.event;
var speed =10;
if(event.ctrlKey){
speed =50;
}
switch (event.keyCode) {
case 37:
box.style.left =box.offsetLeft -speed +"px";
break;
case 38:
box.style.top =box.offsetTop -speed+"px";
break;
case 39:
box.style.left =box.offsetLeft +speed+"px";
break;
case 40:
box.style.top =box.offsetTop+speed+"px";
break;
}
};
};
</script>
</head>
<body>
<div id="box"></div>
</body>
</html>
14. BOM简介
- BOM浏览器对象模型
- BOM可以使我们通过JS来操作浏览器
- 在BOM中提供了一组对象,用来完成对浏览器的操作
- BOM对象
- Window
- 代表的使整个浏览器的窗口,同时window也是网页中的全局对象
- Navigator
- 代表的是当前浏览器的信息,通过该对象可以识别不同的浏览器
- Location
- 代表的是当前浏览器的地址栏信息,通过Location可以获取地址栏信息,或者操作浏览器跳转页面
- History
- 代表的是浏览器的历史记录,可以通过该对象来操作浏览器的历史记录,由于隐私原因,该对象不能获取到具体的历史记录,只能操作浏览器向前或向后翻页,而且该操作只在当次访问时才有效
- Screen
- 代表用户的屏幕信息,通过该对象可以获取到用户的显示器的相关信息
- Window
- 注意:这些BOM对象在浏览器中都是作为window对象的属性保存的,可以通过window对象来使用,也可直接使用
14.1. Navigator
- Navigator
- 代表的是当前浏览器的信息,通过该对象可以识别不同的浏览器,由于历史原因,Navigator对象中大部分属性都已经不能帮助我们识别浏览器了。
- 一般我们只会使用userAgent来判断浏览器的信息,userAgent是一个字符串,这个字符串中包含用来秒速浏览器信息的内容,不同的浏览器有不同的userAgent。(userAgent等价于浏览器)
- 火狐的userAgent
- Mozilla/5.0 (Windows NT 6.1; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0
- Chrome的userAgent
- Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36
- IE8
- Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
- IE9
- Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
- IE10
- Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
- IE11(Edge)
- Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; rv:11.0) like Gecko
- 在IE11中已经将微软和IE相关的表示都已经去除了,使用我们基本已经不能额通过userAgent来识别一个浏览器是否是IE了
- 但"技高一尺,魔高一丈",我们现在虽然不能通过userAgent不能判断,还可以通过一些浏览器中特有的对象,来判断浏览器的信息,比如ActiveXObject
- 火狐的userAgent
- 代码演示
javascript
var ua =navigator.userAgent;
console.log(ua);
if(/firefox/i.test(ua)) {
alert("你是火狐");
}else if(/Chrome/i.test(ua)){
alert("你是Chrome");
}else if(/msie/i.test(ua)){
alert("你是IE浏览器");
}else if("ActiveXObject" in window){
alert("你是IE11(Edge)")
}
- 这个只是初级的检测代码,在现在的开发过程中,也并没有起到作用,因为现在的Edge已经非常像Chrome了。
14.2. History
- 对象可以用来操作浏览器向前或向后翻转
- length
- 属性,可以获取到当前访问的链接数量
- back()
- 可以退回到上一个页面,作用和浏览器的回退按钮一样
- forward()
- 可以跳转下一个页面,作用和浏览器的前进按钮一样
- go()
- 可以用来跳转到指定的页面,需要一个整数作为参数
- eg:
- 1:向前跳转一个页面,相当于forward()
- 2:向前跳转两个页面
- -1:向后跳转一个页面,相当于back()
- -2:向后跳转两个页面
- length
- 代码演示
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>text1</title>
</head>
<body>
<a href="text2.html">去text2</a>
</body>
</html>
- 这个是test1
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>text1</title>
</head>
<body>
<a href="text2.html">去text2</a>
</body>
</html>
- 这个是text2
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>history</title>
<script>
window.onload = function () {
var butt = document.getElementsByTagName("button")[0];
butt.onclick = function () {
history.go(-2);
}
};
alert(history.length);
</script>
</head>
<body>
<button>后退</button>
</body>
</html>
- 这个是history
14.3. Location
- location
- 该对象封装了浏览器的地址栏信息
- 如果直接打印location,则可以获取到地址栏的信息(当前页面的完整路径)
- 如果直接将location属性修改为一个完整的路径,或相对路径
- 则我们页面会自动跳转到该路径,并且会生成相应的历史记录
- 该对象封装了浏览器的地址栏信息
javascript
location ="https://www.bilibili.com/";
location ="https://v.qq.com/"
- assign()
- 用来跳转到其他页面,作用和直接修改location一样
javascript
location.assign("https://v.qq.com/");
- reload()
- 用来使用一个新的页面替换当前页面,调用完毕也会跳转页面,不会生成历史记录,不能使用回退按钮
- 在括号内加入true即可强制清除缓存,不加则默认为普通的刷新
- 代码演示
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LocationEx</title>
<script>
window.onload =function (){
var butt =document.getElementsByTagName("button")[0];
butt.onclick =function (){
// location ="https://www.bilibili.com/";
// location.assign("https://v.qq.com/");
location.reload(true);
};
};
</script>
</head>
<body>
<button>点一下</button>
<input type="text">
</body>
</html>
14.4. 定时器简介
- 如果希望一段程序,每间隔一段时间执行一次,可以使用定时调用
- setInterval()
- 定时调用,可以将一个函数,每隔一段时间执行一次
- 参数:
- 回调函数,该函数会每隔一段时间被调用一次
- 每次调用间隔的时间,单位是毫秒
- 返回值:返回一个Number类型的数据,这个数字用来作为定时器的唯一标识。
- clearInterval()
- 此方法需要一个定时器标识作为参数,这样来关闭对应的定时器
- 代码演示
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>定时器简介</title>
<script>
window.onload = function () {
var count = document.getElementById("count");
var num = 1;
var timer = setInterval(function () {
count.innerHTML = num++;
if (num == 11) {
clearInterval(timer)
}
}, 1000)
};
</script>
</head>
<body>
<h1 id="count"></h1>
</body>
</html>
14.4.1. 定时器练习
- clearInterval()注意点
- clearInterval()可以接受任意参数
- 如果参数是一个有效的定时器的标识,则关闭该定时器
- 如果参数不是一个有效的标识,则什么也不做,也不会报错
- 其他注意点:
- 如果同一个元素上绑定了多个定时器,那记得每在开启一个的时候,关闭前一个(这个用来防备按了多次,导致切换速度快)
- 注意标识的范围
- 如果右多个相同类型而内容不同的数据,可以用数组来储存,方便操作
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>定时器练习</title>
<script>
window.onload =function (){
//获取img1标签以便修改它的src属性,来达到换图片的效果
var img1 =document.getElementById("img1");
//将图片封装到数组里,方便我们切换图片
var imgArr =["./picture/1.JPG","./picture/2.bmp","./picture/3.bmp","./picture/4.png","./picture/5.jpg"];
//数组下标索引
var index =0;
//定义定时器的标识,以便关闭定时器,
// 如果你不在这里定义,而在按钮1中定义的话,按钮二范围内,它看不到这个标识
var timer;
//为butt1绑定单击响应函数
var butt1 =document.getElementById("butt1");
butt1.onclick =function (){
/**
* 目前,我们每点一次按钮,就会开启一个定时器
* 点击多次就会开启多个定时器,这就导致图片切换的速度过快
* 并且我们只能关闭最后一次定时器
*/
//在开启定时器之前,需要将当前元素上的其他定时器关闭
clearInterval(timer);
//开启一个定时器来自动切换图片
timer =setInterval(function (){
index++;
index =index%imgArr.length;//判断所以是否超过最大索引,将其置为0
//修改img1的src属性,达到切换效果
img1.src =imgArr[index];
},1000);
};
var butt2 =document.getElementById("butt2");
//为bttu2绑定一个单击响应函数
butt2.onclick =function (){
/*
clearInterval()可以接受任意参数
如果参数是一个有效的定时器的标识,则关闭该定时器
如果参数不是一个有效的标识,则什么也不做,也不会报错
*/
clearInterval(timer);
}
}
</script>
</head>
<body>
<img src="./picture/1.JPG" alt="图片" id="img1">
<br/><br/>
<button id="butt1">开始</button>
<button id="butt2">暂停</button>
</body>
</html>
14.4.2. div随键盘移动·改进
- 造成它开始动的那一下,会有些卡动的解决方法,是因为让onkeyCode控制了速度,它有个防误碰机制,所以我们定义一个定时器来控制div移动的速度。
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>键盘移动div改进</title>
<style>
#box {
width: 100px;
height: 100px;
background-color: red;
border: solid;
position: absolute;
}
</style>
<script>
window.onload = function () {
var speed =10;
var dir =0;
//开启一个定时器来控制它移动的速度,不管它的方向,让onkeydown来只控制方向
setInterval(function (){
switch (dir) {
case 37:
box.style.left = box.offsetLeft - speed + "px";
break;
case 38:
box.style.top = box.offsetTop - speed + "px";
break;
case 39:
box.style.left = box.offsetLeft + speed + "px";
break;
case 40:
box.style.top = box.offsetTop + speed + "px";
break;
}
},30)
var box = document.getElementById("box");
document.onkeydown = function (event) {
event = event || window.event;
var speed = 10;
if (event.ctrlKey) {
speed = 50;
}
dir =event.keyCode;
};
document.onkeyup =function (){
dir =0;
speed =10;
}
};
</script>
</head>
<body>
<div id="box"></div>
</body>
</html>
14.5. 延迟调用
- 延迟调用:setTimeout()
- 延迟调用一个函数不马上执行,而是隔一段时间后再执行,而且只会执行一次
- 延迟调用和定时调用的区别:
- 延迟调用只会执行一次,而定时调用会执行多次
- 延迟调用和定时调用实际上可以互相代替,在开发中可以根据自己的需求去选择
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>延迟调用</title>
<script>
window.onload =function (){
var num =1;
var timer =setTimeout(function (){
console.log(num++);
},5000)
//使用clearTimeout来关闭一个延迟调用,因为这里关闭了,使用1不会出来
clearTimeout(timer);
};
</script>
</head>
<body>
</body>
</html>
14.6. 应用
14.6.1. 定时器的应用
- 按钮移动div
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>按钮移动div</title>
<style>
*{
margin: 0;
padding: 0;
}
#box {
height: 100px;
width: 100px;
background-color: red;
border: solid;
position: absolute;
left: 0;
}
</style>
<script>
window.onload = function () {
var box = document.getElementById("box");
var butt = document.getElementsByTagName("button")[0];
var timer;
butt.onclick = function () {
clearInterval(timer);
timer = setInterval(function () {
var oldValue = parseInt(getStyle(box, "left"));
var newValue = oldValue + 10;
if(newValue>1600){
newValue =1600;
}
box.style.left = newValue + "px";
if (newValue >= 1600) {
clearTimeout(timer)
}
}, 30)
};
};
function getStyle(obj, name) {
if (window.getComputedStyle) {
return getComputedStyle(obj, null)[name];
} else {
return obj.currentStyle[name];
}
}
</script>
</head>
<body>
<button>点击按钮向右移动</button>
<br/><br/>
<div id="box"></div>
<div id="line" style="border: 1px solid;height: 10000px;width: 0px;position: absolute;left: 1600px; top: 0px"></div>
</body>
</html>
- 按钮移动div·进阶
- 提取方法
- 但是这个方法现在也是有安全隐患的,定时器的变量是全局变量,他们共用这个定时器,当你想两个事件同时进行的话,那便办不到,原因是你开启第二个事件的定时器时,第一个就被关闭了。
- 提取方法
javascript
/**
* 参数:
* @param obj 要执行动画的对象
* @param target 执行动画的目标位置
* @param speed 移动的速度(正数向右移动,负数向左移动)
*/
function move(obj,target,speed){
clearInterval(timer);
var current =parseInt(getStyle(obj,"left"));
/*
判断速度的正负值
如果从0向1600移动,speed为正
如果从1600向0移动,则speed为负
*/
if(current>target){
//此时速度应为赋值
speed =-speed;
}
timer =setInterval(function () {
var oldValue =parseInt(getStyle(obj,"left"));
var newValue =oldValue+speed;
//向左移动时,需要判断newValue是否小于target
//向右移动时,需要判断newValue是否大于target
if(speed<0 && newValue<target || speed>0 && newValue>target){
newValue =target;
}
obj.style.left =newValue+"px";
if(newValue ==1600){
clearInterval(timer)
}
},30)
}
- 代码演示
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>按钮移动div·进阶</title>
<style>
*{
margin: 0;
padding: 0;
}
#box{
left: 0;
height:100px ;
width: 100px;
position: absolute;
border: solid;
background-color: red;
}
</style>
<script>
var timer;
window.onload =function () {
var butt1 =document.getElementsByTagName("button")[0];
var butt2 =document.getElementsByTagName("button")[1];
var box =document.getElementById("box");
butt1.onclick = function () {
move(box,800,10);
};
butt2.onclick =function (){
move(box,0,10);
};
};
/**
* 参数:
* @param obj 要执行动画的对象
* @param target 执行动画的目标位置
* @param speed 移动的速度(正数向右移动,负数向左移动)
*/
function move(obj,target,speed){
clearInterval(timer);
var current =parseInt(getStyle(obj,"left"));
/*
判断速度的正负值
如果从0向1600移动,speed为正
如果从1600向0移动,则speed为负
*/
if(current>target){
//此时速度应为赋值
speed =-speed;
}
timer =setInterval(function () {
var oldValue =parseInt(getStyle(obj,"left"));
var newValue =oldValue+speed;
//向左移动时,需要判断newValue是否小于target
//向右移动时,需要判断newValue是否大于target
if(speed<0 && newValue<target || speed>0 && newValue>target){
newValue =target;
}
obj.style.left =newValue+"px";
if(newValue ==1600){
clearInterval(timer)
}
},30)
}
function getStyle(obj,name) {
if(window.getComputedStyle){
return getComputedStyle(obj,null)[name];
}else {
return obj.currentStyle[name];
}
}
</script>
</head>
<body>
<button id="butt1">点击按钮向右移动</button>
<button id="butt2">点击按钮向左移动</button>
<br/><br/>
<div id="box"></div>
<div id="line" style="border: 1px solid;height: 10000px;width: 0px;position: absolute;left: 1600px; top: 0px"></div>
</body>
</html>
- 按钮变换div
- 提取方法到JS文件
- 这里的obj.timer避免了上处的安全隐患,且加入了回调函数,让此方法变得更加灵活,且将方向也作为形参传进去,让此方法适应性增强!
- 提取方法到JS文件
javascript
function getStyle(obj,name) {
if(window.getComputedStyle){
return getComputedStyle(obj,null)[name];
}else {
return obj.currentStyle[name];
}
}
/**
* 参数
* @param obj 要执行动画的对象
* @param dir 要执行动画的样式;比如:left top width height
* @param target 执行动画的目标位置
* @param speed 移动的速度
* @param callback 回调函数,这个函数将会再动画执行完毕以后执行
*/
function move(obj,dir,target,speed,callback){
//关闭上一个定时器
clearInterval(obj.timer);
var current =parseInt(getStyle(obj,dir));
if(current>target){
speed =-speed;
}
obj.timer =setInterval(function (){
var oldValue =parseInt(getStyle(obj,dir));
var newValue =oldValue+speed;
if(speed<0 && newValue<target ||speed>0 && newValue>target){
newValue =target;
}
obj.style[dir] =newValue +"px";
if(newValue ==target){
clearInterval(obj.timer);
callback && callback();
}
},30)
}
- 代码演示
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>按钮演播div</title>
<style>
*{
margin: 0;
padding: 0;
}
#box1{
width: 100px;
height: 100px;
background-color: red;
position: absolute;
left: 0;
border: solid;
}
#box2{
width: 100px;
height: 100px;
background-color: yellow;
position: absolute;
left: 0;
top:300px;
border: solid;
}
</style>
<script src="tool.js"></script>
<script>
window.onload =function () {
var box1 = document.getElementById("box1");
var box2 = document.getElementById("box2");
var butt1 = document.getElementById("butt1");
var butt2 = document.getElementById("butt2");
var butt3 = document.getElementById("butt3");
var butt4 = document.getElementById("butt4");
butt1.onclick = function () {
move(box1, "left", 1600, 20);
}
butt2.onclick = function () {
move(box1, "left", 0, 10);
}
butt3.onclick = function () {
move(box2, "left", 1600, 10);
}
butt4.onclick = function () {
move(box2, "width", 1600, 10, function () {
move(box2, "height", 800, 10, function () {
move(box2, "top", 0, 10, function () {
move(box2, "width", 100, 10, function () {
confirm("漂亮吧!");
});
});
});
});
};
};
</script>
</head>
<body>
<button id="butt1">点击按钮以后box1向右移动</button>
<button id="butt2">点击按钮以后box1向左移动</button>
<button id="butt3">点击按钮以后box2向右移动</button>
<button id="butt4">测试按钮</button>
<br /><br />
<div id="box1"></div>
<div id="box2"></div>
<div id="line" style="position: absolute;width: 0;height: 1600px;left: 1600px;border: solid;top:0"></div>
</body>
</html>
14.6.2. 轮播图功能实现
javascript
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
*{
margin: 0;
padding: 0;
}
/*
* 设置outer的样式
*/
#outer{
/*设置宽和高*/
width: 520px;
height: 333px;
/*居中*/
margin: 50px auto;
/*设置背景颜色*/
background-color: greenyellow;
/*设置padding*/
padding: 10px 0;
/*开启相对定位*/
position: relative;
/*裁剪溢出的内容*/
overflow: hidden;
}
/*设置imgList*/
#imgList{
/*去除项目符号*/
list-style: none;
/*设置ul的宽度*/
/*width: 2600px;*/
/*开启绝对定位*/
position: absolute;
/*设置偏移量*/
/*
* 每向左移动520px,就会显示到下一张图片
*/
left: 0px;
}
/*设置图片中的li*/
#imgList li{
/*设置浮动*/
float: left;
/*设置左右外边距*/
margin: 0 10px;
}
/*设置导航按钮*/
#navDiv{
/*开启绝对定位*/
position: absolute;
/*设置位置*/
bottom: 15px;
/*设置left值
outer宽度 520
navDiv宽度 25*5 = 125
520 - 125 = 395/2 = 197.5
* */
/*left: 197px;*/
}
#navDiv a{
/*设置超链接浮动*/
float: left;
/*设置超链接的宽和高*/
width: 15px;
height: 15px;
/*设置背景颜色*/
background-color: red;
/*设置左右外边距*/
margin: 0 5px;
/*设置透明*/
opacity: 0.5;
/*兼容IE8透明*/
filter: alpha(opacity=50);
}
/*设置鼠标移入的效果*/
#navDiv a:hover{
background-color: black;
}
</style>
<!--引用工具-->
<script type="text/javascript" src="js/tools.js"></script>
<script type="text/javascript">
window.onload = function(){
//获取imgList
var imgList = document.getElementById("imgList");
//获取页面中所有的img标签
var imgArr = document.getElementsByTagName("img");
//设置imgList的宽度
imgList.style.width = 520*imgArr.length+"px";
/*设置导航按钮居中*/
//获取navDiv
var navDiv = document.getElementById("navDiv");
//获取outer
var outer = document.getElementById("outer");
//设置navDiv的left值
navDiv.style.left = (outer.offsetWidth - navDiv.offsetWidth)/2 + "px";
//默认显示图片的索引
var index = 0;
//获取所有的a
var allA = document.getElementsByTagName("a");
//设置默认选中的效果
allA[index].style.backgroundColor = "black";
/*
点击超链接切换到指定的图片
点击第一个超链接,显示第一个图片
点击第二个超链接,显示第二个图片
* */
//为所有的超链接都绑定单击响应函数
for(var i=0; i<allA.length ; i++){
//为每一个超链接都添加一个num属性
allA[i].num = i;
//为超链接绑定单击响应函数
allA[i].onclick = function(){
//关闭自动切换的定时器
clearInterval(timer);
//获取点击超链接的索引,并将其设置为index
index = this.num;
//切换图片
/*
* 第一张 0 0
* 第二张 1 -520
* 第三张 2 -1040
*/
//imgList.style.left = -520*index + "px";
//设置选中的a
setA();
//使用move函数来切换图片
move(imgList , "left" , -520*index , 20 , function(){
//动画执行完毕,开启自动切换
autoChange();
});
};
}
//开启自动切换图片
autoChange();
//创建一个方法用来设置选中的a
function setA(){
//判断当前索引是否是最后一张图片
if(index >= imgArr.length - 1){
//则将index设置为0
index = 0;
//此时显示的最后一张图片,而最后一张图片和第一张是一摸一样
//通过CSS将最后一张切换成第一张
imgList.style.left = 0;
}
//遍历所有a,并将它们的背景颜色设置为红色
for(var i=0 ; i<allA.length ; i++){
allA[i].style.backgroundColor = "";
}
//将选中的a设置为黑色
allA[index].style.backgroundColor = "black";
};
//定义一个自动切换的定时器的标识
var timer;
//创建一个函数,用来开启自动切换图片
function autoChange(){
//开启一个定时器,用来定时去切换图片
timer = setInterval(function(){
//使索引自增
index++;
//判断index的值
index %= imgArr.length;
//执行动画,切换图片
move(imgList , "left" , -520*index , 20 , function(){
//修改导航按钮
setA();
});
},3000);
}
};
</script>
</head>
<body>
<!-- 创建一个外部的div,来作为大的容器 -->
<div id="outer">
<!-- 创建一个ul,用于放置图片 -->
<ul id="imgList">
<li><img src="img/1.jpg"/></li>
<li><img src="img/2.jpg"/></li>
<li><img src="img/3.jpg"/></li>
<li><img src="img/4.jpg"/></li>
<li><img src="img/5.jpg"/></li>
<li><img src="img/1.jpg"/></li>
</ul>
<!--创建导航按钮-->
<div id="navDiv">
<a href="javascript:;"></a>
<a href="javascript:;"></a>
<a href="javascript:;"></a>
<a href="javascript:;"></a>
<a href="javascript:;"></a>
</div>
</div>
</body>
</html>
14.7. 类的操作
- 类CSS修改
- 方式一:
box.style.width ="300px";- 通过style属性来修改元素的样式,每修改一个样式,浏览器就需要重新渲染一次页面,这样的执行的性能是比较差,而且这种形式当我们要修改多个样式时,也不太方便
- 方式二:
box.className += " b2";- 我们可以通过修改元素的class属性来简介的修改样式,这样一来,我们只需要修改一次,即可同时修改多个样式,浏览器渲染页面一次,性能比较好,并且这种方式,可以让表现和行为进一步分离。
- 方式三:提取方法
- 方式一:
javascript
//定义一个函数,用来向一个元素中添加指定的class属性值
/*
* 参数:
* obj 要添加class属性的元素
* cn 要添加的class值
*
*/
function addClass(obj , cn){
//检查obj中是否含有cn
if(!hasClass(obj , cn)){
obj.className += " "+cn;
}
}
/*
* 判断一个元素中是否含有指定的class属性值
* 如果有该class,则返回true,没有则返回false
*
*/
function hasClass(obj , cn){
//判断obj中有没有cn class
//创建一个正则表达式
//var reg = /\bb2\b/;
var reg = new RegExp("\\b"+cn+"\\b");
return reg.test(obj.className);
}
/*
* 删除一个元素中的指定的class属性
*/
function removeClass(obj , cn){
//创建一个正则表达式
var reg = new RegExp("\\b"+cn+"\\b");
//删除class
obj.className = obj.className.replace(reg , "");
}
/*
* toggleClass可以用来切换一个类
* 如果元素中具有该类,则删除
* 如果元素中没有该类,则添加
*/
function toggleClass(obj , cn){
//判断obj中是否含有cn
if(hasClass(obj , cn)){
//有,则删除
removeClass(obj , cn);
}else{
//没有,则添加
addClass(obj , cn);
}
}
- 代码演示:
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>类的操作</title>
<style>
*{
margin: 0;
padding: 0;
}
.b1{
height: 100px;
width: 100px;
background-color: red;
border: solid;
}
.b2{
height: 300px;
width: 300px;
border: solid;
}
</style>
<script>
window.onload =function () {
var box =document.getElementById("box");
var butt =document.getElementById("butt1");
box.className +=" b2";
butt.onclick =function (){
// box.style.width ="300px";
//方式二:
// box.className +=" b2";
// addClass(box,"b2");
// removeClass(box,"b2");
toggleClass(box,"b2");
};
};
function addClass(obj,cn){
if(!hasClass(obj,cn)){
obj.className += " "+cn;
}
}
function hasClass(obj,cn) {
var reg =new RegExp("\\b"+cn+"\\b");
return reg.test(obj.className);
}
function removeClass(obj,cn) {
var reg =new RegExp("\\b"+cn+"\\b");
obj.className =obj.className.replace(reg,"");
}
function toggleClass(obj,cn){
if(hasClass(obj,cn)){
removeClass(obj,cn)
}else {
addClass(obj,cn);
}
}
</script>
</head>
<body>
<button id="butt1">点击修改div的类</button>
<br/><br/>
<div class="b1" id="box"></div>
</body>
</html>
15. JSON
- JS中的对象只有JS自己认识,其他的语言都不认识,JSON就是一个特殊格式的字符串,这个字符串可以被任意的语言所识别,并且可以转换为任意语言中的对象,JSON在开发中主要用来数据的交互
- JSON (javaScript Object Notation) JS 对象表示法
- JSON和JS对象的格式一样,只不过JSON字符串中的属性名必须加双引号,不然就会报错!其他的和JS语法一致!

- 创建JSON对象
javascript
var arr ='[1,2,3,"hello",true]';
var obj2 ='{"arr":[1,2,3]}';
var obj ='[{"name":"李白","age":18,"gender":"男",{"name":"美美","age":18,"gender":"女"}]';
- 转换
- JSON对象---> JS对象
- 将JSON字符串转换为JS中的对象,再JS中,为我们提供了一个工具类,就叫JSON,这个对象 可以帮助我们将JSON转换JS对象,也可以将一个JS对象转换为JSON
JSON.parse()- 可以 将JSON字符串转换为JS对象
- 它需要一个JSON字符串作为参数,会将该字符串转换为JS对象并返回。
- JSON对象---> JS对象
javascript
var obj ='[{"name":"李白","age":18,"gender":"男"},{"name":"美美","age":18,"gender":"女"}]';
var jsObj =JSON.parse(obj);
console.log(jsObj);
-
- JS对象---> JSON
JSON.stringify()- 可以将一个JS对象装欢为JSON字符串
- 需要一个JS对象作为参数,会返回一个JSON字符串
- JS对象---> JSON
javascript
var obj3 ={name:"李白",age:18,sex:"男"};
var str =JSON.stringify(obj3);
console.log(str);
-
值得注意的是:
- JSON这个对象在IE7及以下的浏览器中不支持,所以再这些浏览器中调用时会报错。
-
eval()
- 这个函数可以用来执行一段字符串形式的JS代码,并将执行结果返回,但是如果使用eval()执行的字符串中含有{},它会将{}当成是代码块,如果不希望将其当成代码块解析,则需要在字符串前后各加一个()
- eval()这个函数的功能十分强大,可以直接执行一个字符串的JS代码,但是在开发中尽量不要使用,首先它的执行性能比较差,然后它害具有安全隐患。
-
那要怎么去兼容IE7及以下的浏览器呢!
- 直接引进JSON文件!~

