一、JavaScript基础语法
HTML
:标记语言JavaScript
:编程语言
1、序言
JavaScript发展历史(JS)
1. 1994年,网景公司(Netscape)发布了Navigator浏览器0.9版,这是世界上第一款比较成熟的网络浏览器,轰动一时。但是这是一款名副其实的浏览器--只能浏览页面,浏览器无法与用户互动,当时解决这个问题有两个办法,一个是采用现有的语言,许它们直接嵌入网页。另一个是发明一种全新的语言。
liveScript ==> javaScript ==> ECMAscript
2. 1995年Sun公司将Oak语言改名为Java,正式向市场推出。Sun公司大肆宣传,许诺这种语言可以"一次编写,到处运 行"(Write Once, Run Anywhere),它看上去很可能成为未来的主宰。
3. 网景公司动了心,决定与Sun公司结成联盟
4. 34岁的系统程序员Brendan Eich登场了。1995年4月,网景公司录用了他,他只用10天时间就把Javascript设计出来了。(多态语言)
5. (1)借鉴C语言的基本语法; (2)借鉴Java语言的数据类型和内存管理; (3)借鉴Scheme语言,将函数提升到"第一等公民"(first class)的地位; (4)借鉴Self语言,使用基于原型(prototype)的继承机制。
js概念
概念:支持面向对象的跨平台脚本语言。
理解:
1. 脚本语言:依赖别的语言才能运行
html必须在浏览器中才能运行,js嵌套在html中才能运行
2. 跨平台:可以在不同的平台上运行
windows、linux、安卓。。。
3. 支持面向对象 使用面向对象的思想编程
JS和H5的关系
h5,是html的下一个版本,很强大,就目前而言,我们知道的h5只是一些标签,并不能完美的展示出他的强大 之处,加入js后,才能激活这些标签深层次的功能。
随着h5应用越来越多,js的使用方式和各种框架及插件也越来越多,甚至已经从前端语言可以实现后台服务器的功 能。js的发展已经成为一种潮流。
JavaScript能干什么
1. 常见的网页效果【表单验证,轮播图。。。】
2. 与H5配合实现游戏【水果忍者: http://www.jq22.com/demo/html5-fruit-ninja/】
3. 实现应用级别的程序【http://naotu.baidu.com】
4. 实现统计效果【http://echarts.baidu.com/examples/】
5. 地理定位等功能【http://lbsyun.baidu.com/jsdemo.htm#i4_5】
6. 在线学编程【https://codecombat.163.com/play/】
7. js可以实现人工智能【面部识别】
8. 。。。
应用场景
1. 表单验证:规范用户输入数据,和后台数据进行交互
2. 网页特效:给页面内容加行为,让页面动起来
3. 游戏开发:飞机大战、打砖块
4. 物联网:https://zhuanlan.zhihu.com/p/45509947
JavaScript的组成
1. ECMASCRIPT: 定义了javascript的语法规范,描述了语言的基本语法和数据类型
2. BOM (Browser Object Model): 浏览器对象模型
- 有一套成熟的可以操作浏览器的 API,通过 BOM 可以操作浏览器。比如: 弹出框、浏览器跳转、获取分辨率等
3. DOM (Document Object Model): 文档对象模型
- 有一套成熟的可以操作页面元素的 API,通过 DOM 可以操作页面中的元素。比如: 增加个 div,减少个 div,给div 换个位置等
总结: JS 就是通过固定的语法去操作 浏览器 和 标签结构 来实现网页上的各种效果
2、JavaScript代码的书写位置
- 和
css
一样,我们的js
也可以有多种方式书写在页面上让其生效 js
也有多种方式书写,分为 行内式, 内嵌式,外链式
行内式 JS 代码(不推荐)
- 写在标签上的 js 代码需要依靠事件(行为)来触发
<!-- 写在 a 标签的 href 属性上 -->
<a href="javascript:alert('Hello World!');">点击一下试试</a>
<!-- 写在其他元素上 -->
<div onclick="alert('Hello World!')">点一下试试看</div>
<!--
注:onclick 是一个事件(点击事件),当点击元素的时候执行后面的 js 代码
-->
内嵌式 JS 代码
- 内嵌式的 js 代码会在页面打开的时候直接触发
<!-- 在 html 页面书写一个 script 标签,标签内部书写 js 代码 -->
<script type="text/javascript">
alert('Hello World!')
</script>
<!--
注:script 标签可以放在 head 里面也可以放在 body 里面
-->
外链式 JS 代码(推荐)
- 外链式 js 代码只要引入了 html 页面,就会在页面打开的时候直接触发
- 新建一个
.js
后缀的文件,在文件内书写 js 代码,把写好的 js 文件引入 html 页面
// 我是 index.js 文件
alert('我是一个弹出层')
<!-- 我是一个 html 文件 -->
<!-- 通过 script 标签的 src 属性,把写好的 js 文件引入页面 -->
<script src="index.js"></script>
<!-- 一个页面可以引入多个 js 文件 -->
<script src="index1.js"></script>
<script src="index2.js"></script>
<script src="index3.js"></script>
【注】前期推荐将js放在和之间
3、JS 中的注释
- 学习一个语言,先学习一个语言的注释,因为注释是给我们自己看的,也是给开发人员看的
- 写好一个注释,有利于我们以后阅读代码
单行注释
- 一般就是用来描述下面一行代码的作用
- 可以直接写两个
/
,也可以按ctrl + /
// 我是一个单行注释
// 下面代码表示在浏览器里面出现一个弹出层
alert('我是一个弹出层')
多行注释
- 一般用来写一大段话,或者注释一段代码
- 可以直接写
/**/
然后在两个星号中间写注释,也可以按shift + alt + a
/*
我是一个多行注释
*/
/*
注释的代码不会执行
alert('我是一个弹出层')
alert('我是一个弹出层')
*/
alert('我是一个弹出层')
4、js的输出
以弹窗的形式显示(给用户做提示)
alert(11);
以文本的形式显示
document.write(123456);
可输入内容的弹窗
prompt(12345)
可判断的弹窗(常用作在敏感操作时给用户做提示)
confirm(12345)
调试工具中输出(常用-调试代码)
console.log(123);
【注】注意:在js代码中,每行结束可以加分号,也可以不加分号,但是建议加上。
5、变量(重点)
- 变量指的是在程序中保存数据的一个容器
- 变量是计算机内存中存储数据的标识符,根据变量名称可以获取到内存中存储的数据
- 也就是说,我们向内存中存储了一个数据,然后要给这个数据起一个名字,为了是我们以后再次找到他
- 语法:
var 变量名 = 值;
定义变量及赋值
// 声明 (定义)变量
var x; 在内存中开辟了一个空间,给这个空间起名叫x,里面没有放内容
var a,b; 一次性声名多个变量
// 给变量赋值
num = 100;
// 声明变量并赋值-初始化
var y = 10; 在内存中开辟了一个空间,这个空间的名字叫y,把10存了进去
var a=1,b=2; 一次性声明多个变量并赋值
- 注意:
- 一个变量名只能存储一个值
- 当再次给一个变量赋值的时候,前面一次的值就没有了
- 变量名称区分大小写(JS 区分大小写)
变量的命名规则和命名规范
-
规则: 必须遵守的,不遵守就是错
- 一个变量名称可以由 数字、字母、英文下划线(_)、美元符号($) 组成
- 严格区分大小写
- 不能由数字开头,不要使用中文汉字命名
- 不能是 保留字 或者 关键字
- 不要出现空格
-
规范: 建议遵守的(开发者默认),不遵守不会报错
- 变量名尽量有意义(语义化)
- 遵循驼峰命名规则,由多个单词组成的时候,从第二个单词开始首字母大写
6、数据类型(重点)
- 是指我们存储在内存中的数据的类型
- 我们通常分为两大类 基本数据类型 和 复杂数据类型
基本数据类型
-
数值类型(number)
-
一切数字都是数值类型(包括二进制,十进制,十六进制等)
var a = 010; // 8进制 var b = 0xA; // 16进制 var c = 0xb; // 小写字母和大写字母都可以 console.log(a); // 8 console.log(b); // 10 console.log(c); // 11
-
NaN(not a number),表示一个非数字
在js中,NaN用来表示一个非数字的特殊值,当发现无法进行运算时,js不会报错,而是会返回一个NaN NaN的注意事项: - NaN的类型是number类型的,表示一个非数字 - NaN不等于任何值,包括NaN本身 - 通过isNaN()可以判断是否是一个数字,返回false的时候,表示是一个数字。 var a = 123; var b = "abc"; console.log(isNaN(a)); // false console.log(isNaN(b)); // true
-
小数
- 科学计数法
//当一次数字很大的时候,可以用科学计数法来表示 var num = 5e+5; //5乘以10的5次方 var num = 3e-3;//3乘以10的-3次方
- 浮点数精度丢失问题
//在进行浮点数运算的时候,可能会出现精度丢失的问题 0.1 + 0.2 = 0.30000000000000004; 0.2 + 0.2 = 0.4; //尽量少用浮点数进行运算,不要让浮点数进行比较。 解决办法 : 根据小数点后面的位数量 乘以对应的整数; 0.1 + 0.2 ==> (0.1*10+0.2*10) / 10 = 0.3
-
数值范围
最小值:Number.MIN_VALUE,这个值为: 5e-324 最大值:Number.MAX_VALUE,这个值为: 1.7976931348623157e+308 无穷大:Infinity 1/0 无穷小:-Infinity
-
-
字符串类型(string)
-
被引号包裹的所有内容(可以是单引号也可以是双引号)
分析: 1. 引号可以嵌套,但是不能嵌套自己,需要交叉嵌套(单引号嵌套双引号或者双引号嵌套单引号)。 2. 使用转义符 console.log('大家好,我姓"熏",我叫孙悟空'); console.log('选择"好看"的外表,还\\是\'有趣\'的灵魂');
-
一些带有特殊含义的字符需要进行转义,例:
符号 意义 \n 换行 \t 制表符 \b 空格 \ 斜杠 ’ 单引号 " 双引号 -
注意:js可以输出标签,让页面中的元素具备标签的特性,但是在输出标签的时候一定要将标签当做字符串输出。
-
字符串里面的字符个数:字符串.length
-
布尔类型(boolean)
- 只有两个(true 或者 false)
-
对象类型(object)
- null,表示空的意思
- 数组 var a = [1,2,3];
- 结构体 var a = {name=“张三”,age=18;}
-
undefined类型(undefined)
- 只有一个,就是 undefined,表示没有值的意思
复杂数据类型
类型 | 示例 | 备注 |
---|---|---|
数字型(number) | 1 -2 3.14 300 | 包括整数、小数、负数 |
字符串型(string) | “你好吗?” ‘今天嫁给我’ | 用引号引起来的一串字符,单引号和双引号都行 |
布尔型(boolean) | true false | 代表事物的两面性,真和假 |
未定义型(undefined) | var a | 代表定义过未赋值的变量 |
对象(object) | null [1,2,3] {name:张三} | 代表一个集合 |
7、判断数据类型
- 既然已经把数据分开了类型,那么我们就要知道我们存储的数据是一个什么类型的数据
- 使用
typeof
关键字来进行判断
【注】typeof(x) 可以写成 typeof x 。使用小括号和空格都可以。
// 第一种使用方式
var n1 = 100;
console.log(typeof n1);
// 第二种使用方式
var s1 = 'abcdefg';
console.log(typeof(s1));
判断一个变量是不是数字
- 可以使用
isNaN
这个方法来判断一个变量是不是数字 isNaN
:is not a number
// 如果变量是一个数字
var n1 = 100;
console.log(isNaN(n1)); //=> false
// 如果变量不是一个数字
var s1 = 'Jack'
console.log(isNaN(s1)); //=> true
8、数据类型转换
- 数据类型之间的转换,比如数字转成字符串,字符串转成布尔,布尔转成数字等
强制转换
-
转换为布尔型
语法: Boolean(arg)
- 非0数字转换为布尔型为true,0转换为布尔型为false
- 非空字符串转换为布尔型为true,空字符串转换为布尔型为false
- undefined转换为布尔型为false
- null转换为布尔型为false
- NaN转换为布尔型为false
-
转换为字符串
语法: String(arg)
- true转换为字符串仍为 true,false转换为字符串仍为false
- null转换为字符串扔为null
- undefined转换为字符串仍为undefined
-
转换为数字
语法: Number(str)
- NaN代表不是数字,但是他是数字类型(没有意义的数字)
- 非数字字符串转换后都是NaN(NaN是一个不是数字的数字类型)
- true转为数字为1,false转为数字为0
- undefined转换为数字为NaN
- null转化为数字为0
-
使用函数强制转换为数字
语法: parseInt(arg) # 强制转换为整数 parseFloat(arg) # 强制转换为小数
-
小数转换为整数只取整数,向下取整
-
首位非数字的字符串强转为整数为NaN,首位是数字的字符串强转为整数是首位的数字
-
布尔型强转为数字为NaN
-
undefined强转为数字为NaN
-
null强转为数字为NaN
-
-
使用
toString()
方法强制转换为字符串,转换结果和String()函数一样var a = 123456; b = true; var c = a.toString(); var d = b.toString(); console.log(c); console.log(typeof c); console.log(d); console.log(typeof d);
注意:这个方法不能给undefined和null使用
-
如果是复杂数据类型转换,会调用内置的[ToPrimitive]函数
隐形转换
a、+号左右有一个是字符串,另一个也会转成字符串
b、除了+法的数学运算都会将两边的数据转为数字
c、比较时,左右有一个是数字,另一个也会转为数字
9、运算符
- 就是在代码里面进行运算的时候使用的符号,不光只是数学运算,我们在 js 里面还有很多的运算方式
数学运算符
运算符 | 示例 | 备注 |
---|---|---|
+(求和) | var a = 1; var b = 2; var c = a + b; | 数学中的加法 |
-(求差) | var a = 2; var b = 1; var c = a - b; | 数学中的减法 |
*(求积) | var a = 1; var b = 2; var c = a * b; | 数学中的乘法 |
/(求商) | var a = 1; var b = 2; var c = a / b; | 数学中的除法 |
%(求余) | var a = 5; var b = 2; var c = a % b; | 数学中的求余数 |
字符串的拼接运算
上面的+
,如果两边都是数字,那进行的是数学中的加法运算。但是两边只要一边是字符串的话,那是将两边的值连接成一个。也就是所谓的字符串的拼接。
var a = 12345;
var b = "上山打老虎"
var c = a + b;
console.log(c); // 结果:12345上山打老虎
也就是将a变量和b变量拼接在一块,组成一个新的字符串,赋值给了c变量。
拼接运算的+
左右两边,只要有一边是字符串就进行拼接运算,具体情况有:数字+字符串、字符串+数字、字符串+字符串。
赋值运算符
-
=
在编程中
=
不叫“等于号”,叫“赋值符”,**作用是将右边的值赋值给左边的变量,反过来讲,赋值符右边是值,左边是变量 **var x = 1 // 将右边的数字1赋值给左边的变量x
其实就是将右边的数字1放到叫做x的那个内存空间中。
注意:变量是可变的,也就是说同一个变量可以多次赋值,后面的值覆盖前面的值。
var x = 1; // 声明变量x并给他赋值1 x = 10; // 给变量x重新赋值为10 alert(x); // 现在x变量的值就是10
第二次赋值的时候,是纯赋值操作,不是声明变量,所以就不用var关键字了。
-
赋值运算符(2)
符号 | 描述 | 示例 |
---|---|---|
+= | 自己先加后,再赋值给自己 | var a = 1; a += 2; 相当于a先加2,结果赋值给a |
-= | 自己先减后,再赋值自己 | var a = 1; a -= 1; 相当于a先减1,结果赋值给a |
*= | 自己先乘后,再赋值自己 | var a = 1; a *= 3; 相当于a先乘3,结果赋值给a |
/= | 自己先除后,再赋值自己 | var a = 4; a /= 2; 相当于a先除2,结果赋值给a |
%= | 自己先余后,再赋值自己 | var a = 5; a %= 2; 相当于a先余2,结果赋值给a |
比较运算符
运算符 | 描述 |
---|---|
> | 大于 |
>= | 大于等于 |
< | 小于 |
<= | 小于等于 |
== | 等于(主要用于判断两边的值是否相等) |
=== | 全等于(先判断两边的类型是否相等,类型相等再判断值是否相等) |
!= | 不等于(主要用于判断两边的值是否不相等) |
!== | 不全等于(先判断两边的类型是否不相等,类型相等再判断值是否不相等) |
关系运算最后的结果只有两种,一种是真,一种是假,也就是布尔型的true
和false
console.log(2>3); // false
var a = 2>1;
console.log(a); // true
等于和全等于
var a = 123;
var b = "123";
console.log(a==b); // true
console.log(a===b); // false
运行结果 |
---|
![]() |
a变量和b变量在内存中占用大小一样,里面的存的内容也一样,所以是相等的
但类型不一样,所以不全等。
逻辑运算符
运算符 | 描述 |
---|---|
&&(与,并且) | 左右两边都为true,最后结果才为true,否则就是false |
||(或者) | 左右两边只要有一个true,最后结果就为true,否则就是false |
!(非,取反) | 将true处理为false,将false处理为true |
逻辑运算最后得出的结果也是布尔型。
-
&&
- 进行 且 的运算
- 符号左边必须为 true 并且右边也是 true,才会返回 true
- 只要有一边不是 true,那么就会返回 false
true && true
truetrue && false
falsefalse && true
falsefalse && false
false
-
||
- 进行 或 的运算
- 符号的左边为 true 或者右边为 true,都会返回 true
- 只有两边都是 false 的时候才会返回 false
true || true
truetrue || false
truefalse || true
truefalse || false
false
-
!
- 进行 取反 运算
- 本身是 true 的,会变成 false
- 本身是 false 的,会变成 true
!true
false!false
true
自增自减运算符(一元运算符)
运算符 | 描述 |
---|---|
x++ | 先把值返回,再自增 |
++x | 先把值自增,再返回值 |
x– | 先把值返回,再自减 |
–x | 先把值自减,再返回值 |
-
++
-
进行自增运算
-
分成两种,前置++ 和 后置++
-
前置++,会先把值自动 +1,再返回值
var a = 10; console.log(++a); // 会返回 11,并且把 a 的值变成 11
-
后置++,会先把值返回,再自动+1
var a = 10; console.log(a++); // 会返回 10,然后把 a 的值变成 11
-
-
--
- 进行自减运算
- 分成两种,前置– 和 后置–
- 和
++
运算符道理一样
二、分支结构
- 我们的 js 代码都是顺序执行的(从上到下)
- 逻辑分支就是根据我们设定好的条件来决定要不要执行某些代码
1、IF 条件分支结构
if 语句(单分支)
-
通过一个 if 语句来决定代码执行与否
-
语法:
if (条件) { 要执行的代码 }
-
通过
()
里面的条件是否成立来决定{}
里面的代码是否执行// 条件为 true 的时候执行 {} 里面的代码 if (true) { alert('因为条件是 true,我会执行') } // 条件为 false 的时候不执行 {} 里面的代码 if (false) { alert('因为条件是 false,我不会执行') }
if else 语句(双分支)
-
通过 if 条件来决定,执行哪一个
{}
里面的代码 -
语法:
if (条件) { 条件为 true 的时候执行 } else { 条件为 false 的时候执行 }
-
两个
{}
内的代码一定有一个会执行// 条件为 true 的时候,会执行 if 后面的 {} if (true) { alert('因为条件是 true,我会执行') } else { alert('因为条件是 true,我不会执行') } // 条件为 false 的时候,会执行 else 后面的 {} if (false) { alert('因为条件为 false,我不会执行') } else { alert('因为条件为 false,我会执行') }
if else if … 语句(多分支一)
-
可以通过 if 和 else if 来设置多个条件进行判断
-
语法:
if (条件1) { 条件1为 true 的时候执行 } else if (条件2) { 条件2为 true 的时候执行 }
-
会从头开始依次判断条件
- 如果第一个条件为 true 了,那么就会执行后面的
{}
里面的内容 - 如果第一个条件为 false,那么就会判断第二个条件,依次类推
- 如果第一个条件为 true 了,那么就会执行后面的
-
多个
{}
,只会有一个被执行,一旦有一个条件为 true 了,后面的就不在判断了// 第一个条件为 true,第二个条件为 false,最终会打印 “我是代码段1” if (true) { alert('我是代码段1') } else if (false) { alert('我是代码段2') } // 第一个条件为 true,第二个条件为 true,最终会打印 “我是代码段1” // 因为只要前面有一个条件满足了,就不会继续判断了 if (true) { alert('我是代码段1') } else if (true) { alert('我是代码段2') } // 第一个条件为 false,第二个条件为 true,最终会打印 “我是代码段2” // 只有前一个条件为 false 的时候才会继续向后判断 if (false) { alert('我是代码段1') } else if (true) { alert('我是代码段2') } // 第一个条件为 false,第二个条件为 false,最终什么也不会发生 // 因为当所有条件都为 false 的时候,两个 {} 里面的代码都不会执行 if (false) { alert('我是代码段1') } else if (false) { alert('我是代码段2') }
if else if … else 语句(多分支二)
-
和之前的
if else if ...
基本一致,只不过是在所有条件都不满足的时候,执行最后 else 后面的{}
// 第一个条件为 false,第二个条件为 false,最终会打印 “我是代码段3” // 只有前面所有的条件都不满足的时候会执行 else 后面的 {} 里面的代码 // 只要前面有一个条件满足了,那么后面的就都不会执行了 if (false) { alert('我是代码段1') } else if (false) { alert('我是代码段2') } else { alert('我是代码段3') }
分支结构的简写方式
如果单分支或双分支以及多分支的大括号中只有一行代码的时候,大括号可以省略。
// 单分支的简写
var age;
if(age>18)
alert("已经成年了");
// 双分支的简写
if(age>18)
alert("成年了");
else
alert("未成年")
// 多分支的简写
var score = Number(prompt("请输入考试成绩:"));
var score = Number(prompt("请输入考试成绩:"));
if(isNaN(score))
alert("输入不正确");
else{
if(score>=0 && score<60)
alert("不及格");
else if(score>=60 && score<70)
alert("及格了");
else if(score>=70 && score<80)
alert("丙");
else if(score>=80 && score<90)
alert("乙");
else if(score>=90 && score<=100)
alert("甲");
else
alert("输入不正确");
}
分支结构的嵌套
例:定义三个变量,求出三个值中的最大值。
var a,b,c;
if(a>b){
if(a>c){
alert("变量a最大");
}else{
alert("变量c最大");
}
}else{
if(b>c){
alert("变量b最大");
}else{
alert("变量c最大");
}
}
2、SWITCH 条件分支结构
-
也是条件判断语句的一种
-
是对于某一个变量的判断
-
语法:
switch (要判断的变量) { case 情况1: 情况1要执行的代码 break case 情况2: 情况2要执行的代码 break case 情况3: 情况3要执行的代码 break default: 上述情况都不满足的时候执行的代码 }
-
使用说明:
- break表示当前分支执行后就结束switch的运行,后续代码不再运行
- default可以理解为判断语句中的else
- case理解为if来判断这个变量是否全等于某个值
-
注意:使用多路判断的时候,能使用switch进行判断,就尽量使用switch,因为switch的判断都是确定的值,条件比较简单,所以效率高。
使用场景:
- 如果判断的条件比较复杂,使用if
- 条件是确定的值,分两种情况:
- 如果判断的分支小于等于3个,就使用if,这时候的效率和switch一样
- 如果大于3个,就使用switch。
- switch判断使用的是全等于(===)
-
switch 穿透写法
如果case后面不写break,那当前case执行后,会继续执行后面的case中的代码
3、三元运算(扩展)
-
三元运算,就是用 两个符号 组成一个语句
-
三元运算只是对 if else 语句的一个简写形式
-
语法:
条件 ? 条件为 true 的时候执行 : 条件为 false 的时候执行
-
三元运算有个特点:可以将整个表达式当做一个值,可以赋值给一个变量,也可以输出
var max = a>b?a:b; // 将a与b中较大的数赋值给变量max console.log(a>b?a:b); // 将a与b中较大的数输出
三、循环结构
- 循环结构,就是根据某些给出的条件,重复的执行同一段代码
- 循环必须要有某些固定的内容组成
- 初始化
- 条件判断
- 要执行的代码
- 自身改变
1、WHILE 循环
-
while
,中文叫 当…时,其实就是当条件满足时就执行代码,一旦不满足了就不执行了 -
语法
while (条件) { 满足条件就执行 }
-
因为满足条件就执行,所以我们写的时候一定要注意,就是设定一个边界值,不然就一直循环下去了
// 1. 初始化条件 var num = 0; // 2. 条件判断 while (num < 10) { // 3. 要执行的代码 console.log('当前的 num 的值是 ' + num); // 4. 自身改变 num++; }
- 如果没有自身改变,那么就会一直循环不停了
2、DO WHILE 循环
-
是一个和
while
循环类似的循环 -
while
会先进行条件判断,满足就执行,不满足直接就不执行了 -
但是
do while
循环是,先不管条件,先执行一回,然后在开始进行条件判断 -
语法:
do { 要执行的代码 } while (条件)
// 下面这个代码,条件一开始就不满足,但是依旧会执行一次 do 后面 {} 内部的代码 var num = 10 do { console.log('我执行了一次') num++; } while (num < 10)
3、FOR 循环
-
和
while
和do while
循环都不太一样的一种循环结构 -
道理是和其他两种一样的,都是循环执行代码的
-
语法:
for (var i = 0; i < 10; i++) { 要执行的代码 }
// 把初始化,条件判断,自身改变,写在了一起 for (var i = 1; i <= 10; i++) { // 这里写的是要执行的代码 console.log(i); } // 控制台会依次输出 1 ~ 10
-
这个只是看起来不太舒服,但是用起来比较好用
-
使用for循环对数组进行遍历:
var arr = [10,20,30,40,50];
var sum = 0;
for (var i in arr){
sum += arr[i];
}
alert(sum);
【注】
for循环中的初始值和变化可以不放在小括号中
在循环中,变量i的变化规律可以不是递增,也可以递减,也可以不是递增(值也不一定都为1)
4、BREAK 终止循环
-
在循环没有进行完毕的时候,因为我设置的条件满足,提前终止循环
-
比如:我要吃五个包子,吃到三个的时候,不能在吃了,我就停止吃包子这个事情
-
要终止循环,就可以直接使用
break
关键字for (var i = 1; i <= 5; i++) { // 没循环一次,吃一个包子 console.log('我吃了一个包子') // 当 i 的值为 3 的时候,条件为 true,执行 {} 里面的代码终止循环 // 循环就不会继续向下执行了,也就没有 4 和 5 了 if (i === 3) { break } }
5、CONTINUE 结束本次循环
-
在循环中,把循环的本次跳过去,继续执行后续的循环
-
比如:吃五个包子,到第三个的时候,第三个掉地下了,不吃了,跳过第三个,继续吃第四个和第五个
-
跳过本次循环,就可以使用
continue
关键字for (var i = 1; i <= 5; i++) { // 当 i 的值为 3 的时候,执行 {} 里面的代码 // {} 里面有 continue,那么本次循环后面的代码就都不执行了 // 自动算作 i 为 3 的这一次结束了,去继续执行 i = 4 的那次循环了 if (i === 3) { console.log('这个是第三个包子,掉地下了,我不吃了') continue } console.log('我吃了一个包子') }
四、函数(上)
- 我们代码里面所说的函数和我们上学的时候学习的什么三角函数、二次函数之类的不是一个东西
1、函数的概念
-
对于 js 来说,函数就是把任意一段代码放在一个 盒子 里面
-
在我想要让这段代码执行的时候,直接执行这个 盒子 里面的代码就行
-
先看一段代码
// 这个是我们以前写的一段代码 for (var i = 0; i < 10; i++) { console.log(i) } // 函数,这个 {} 就是那个 “盒子” function fn() { // 这个函数我们以前写的代码 for (var i = 0; i < 10; i++) { console.log(i) } }
2、函数的两个阶段(重点)
- 按照我们刚才的说法,两个阶段就是 放在盒子里面 和 让盒子里面的代码执行
函数定义阶段
- 定义阶段就是我们把代码 放在盒子里面
- 我们就要学习怎么 放进去,也就是书写一个函数
- 我们有两种定义方式 声明式 和 赋值式
声明式
-
使用
function
这个关键字来声明一个函数 -
语法:
function fn() { // 一段代码 } // function: 声明函数的关键字,表示接下来是一个函数了 // fn: 函数的名字,我们自己定义的(遵循变量名的命名规则和命名规范) // (): 必须写,是用来放参数的位置(一会我们再聊) // {}: 就是我们用来放一段代码的位置(也就是我们刚才说的 “盒子”)
赋值式
-
其实就是和我们使用
var
关键字是一个道理了 -
首先使用
var
定义一个变量,把一个函数当作值直接赋值给这个变量就可以了 -
语法:
var fn = function () { // 一段代码 } // 不需要在 function 后面书写函数的名字了,因为在前面已经有了
函数调用阶段
- 就是让 盒子里面 的代码执行一下
- 让函数执行
- 两种定义函数的方式不同,但是调用函数的方式都以一样的
调用一个函数
-
函数调用就是直接写
函数名()
就可以了// 声明式函数 function fn() { console.log('我是 fn 函数') } // 调用函数 fn() // 赋值式函数 var fn2 = function () { console.log('我是 fn2 函数') } // 调用函数 fn()
- 注意: 定义完一个函数以后,如果没有函数调用,那么写在 {} 里面的代码没有意义,只有调用以后才会执行
调用上的区别
-
虽然两种定义方式的调用都是一样的,但是还是有一些区别的
-
声明式函数: 调用可以在 定义之前或者定义之后
// 可以调用 fn() // 声明式函数 function fn() { console.log('我是 fn 函数') } // 可以调用 fn()
-
赋值式函数: 调用只能在 定义之后
// 会报错 fn() // 赋值式函数 var fn = function () { console.log('我是 fn 函数') } // 可以调用 fn()
3、函数的参数(重点)
-
我们在定义函数和调用函数的时候都出现过
()
-
现在我们就来说一下这个
()
的作用 -
就是用来放参数的位置
-
参数分为两种 行参 和 实参
// 声明式 function fn(行参写在这里) { // 一段代码 } fn(实参写在这里) // 赋值式函数 var fn = function (行参写在这里) { // 一段代码 } fn(实参写在这里)
行参和实参的作用
-
行参
-
就是在函数内部可以使用的变量,在函数外部不能使用
-
每写一个单词,就相当于在函数内部定义了一个可以使用的变量(遵循变量名的命名规则和命名规范)
-
多个单词之间以
,
分隔// 书写一个参数 function fn(num) { // 在函数内部就可以使用 num 这个变量 } var fn1 = function (num) { // 在函数内部就可以使用 num 这个变量 } // 书写两个参数 function fun(num1, num2) { // 在函数内部就可以使用 num1 和 num2 这两个变量 } var fun1 = function (num1, num2) { // 在函数内部就可以使用 num1 和 num2 这两个变量 }
-
如果只有行参的话,那么在函数内部使用的变量是没有值的,也就是
undefined
-
行参的值是在函数调用的时候由实参决定的
-
-
实参
-
在函数调用的时候给行参赋值的
-
也就是说,在调用的时候是给一个实际的内容的
function fn(num) { // 函数内部可以使用 num } // 这个函数的本次调用,书写的实参是 100 // 那么本次调用的时候函数内部的 num 就是 100 fn(100) // 这个函数的本次调用,书写的实参是 200 // 那么本次调用的时候函数内部的 num 就是 200 fn(200)
-
函数内部的行参的值,由函数调用的时候传递的实参决定
-
多个参数的时候,是按照顺序一一对应的
function fn(num1, num2) { // 函数内部可以使用 num1 和 num2 } // 函数本次调用的时候,书写的参数是 100 和 200 // 那么本次调用的时候,函数内部的 num1 就是 100,num2 就是 200 fn(100, 200)
-
参数个数的关系
-
行参比实参少
-
因为是按照顺序一一对应的
-
行参少就会拿不到实参给的值,所以在函数内部就没有办法用到这个值
function fn(num1, num2) { // 函数内部可以使用 num1 和 num2 } // 本次调用的时候,传递了两个实参,100 200 和 300 // 100 对应了 num1,200 对应了 num2,300 没有对应的变量 // 所以在函数内部就没有办法依靠变量来使用 300 这个值 fn(100, 200, 300)
-
-
行参比实参多
-
因为是按照顺序一一对应的
-
所以多出来的行参就是没有值的,就是
undefined
function fn(num1, num2, num3) { // 函数内部可以使用 num1 num2 和 num3 } // 本次调用的时候,传递了两个实参,100 和 200 // 就分别对应了 num1 和 num2 // 而 num3 没有实参和其对应,那么 num3 的值就是 undefined fn(100, 200)
-
3.获取函数的实参
函数中还有一个关键字arguments可以获取到所有的实参
function css(){
// 打印实参
console.log(arguments);
// 打印实参的个数
console.log(arguments.length);
// 遍历实参
for(var i in arguments){
console.log(arguments[i]);
}
}
css("width","100px");
4、匿名函数(赋值式的函数)
概念:顾名思义,匿名函数就是没有名字的函数。
定义:
语法:
function(){
代码段
}
当然匿名函数也可以传递参数。
调用:
定义的时候调用
语法:
//(封装一个库的时候会用)
//推荐使用小括号
(function(形参){
代码段
})(实参)
//后面两种不推荐使用(容易产生未知错误)
~function(){
}()
!function(){
}()
很简单,就是在大括号后面加小括号就是调用。
(function(a,b){
var c = a + b;
document.write(c);
})(1,2);
将匿名函数赋值给变量,调用的时候使用变量名来调用
语法:
# 定义
var fun = function(){
代码段
}
# 调用
fun()
例:
var fun = function(a,b){
var c = a + b;
document.write(c);
}
fun(1,2);
通过事件来调用匿名函数
<style>
#myid{
width:200px;
height:200px;
background:#f00;
}
</style>
<body>
<div id="myid"></div>
</body>
<script>
var oDiv = document.getElementById("myid");
oDiv.onclick=function(){
alert(123);
}
</script>
5、函数的return(重点)
- return 返回的意思,其实就是给函数一个 返回值 和 终断函数
终断函数
-
当我开始执行函数以后,函数内部的代码就会从上到下的依次执行
-
必须要等到函数内的代码执行完毕
-
而
return
关键字就是可以在函数中间的位置停掉,让后面的代码不在继续执行function fn() { console.log(1) console.log(2) console.log(3) // 写了 return 以后,后面的 4 和 5 就不会继续执行了 return console.log(4) console.log(5) } // 函数调用 fn()
返回值
-
函数调用本身也是一个表达式,表达式就应该有一个值出现
-
现在的函数执行完毕之后,是不会有结果出现的
// 比如 1 + 2 是一个表达式,那么 这个表达式的结果就是 3 console.log(1 + 2) // 3 function fn() { // 执行代码 } // fn() 也是一个表达式,这个表达式就没有结果出现 console.log(fn()) // undefined
-
return
关键字就是可以给函数执行完毕一个结果function fn() { // 执行代码 return 100 } // 此时,fn() 这个表达式执行完毕之后就有结果出现了 console.log(fn()) // 100
- 我们可以在函数内部使用
return
关键把任何内容当作这个函数运行后的结果
- 我们可以在函数内部使用
6、函数的优点
- 函数就是对一段代码的封装,在我们想调用的时候调用
- 函数的几个优点
- 封装代码,使代码更加简洁
- 复用,在重复功能的时候直接调用就好
- 代码执行时机,随时可以在我们想要执行的时候执行
7、预解析(重点)
- 预解析 其实就是聊聊 js 代码的编译和执行
- js 是一个解释型语言,就是在代码执行之前,先对代码进行通读和解释,然后在执行代码
- 也就是说,我们的 js 代码在运行的时候,会经历两个环节 解释代码 和 执行代码
预解析js代码
预解析的过程,就是查找代码中的var和function这两个关键字,找到以后,将变量和函数存到了一个地方,就叫仓库吧,并给他们赋一个初始值,变量的初始值为undefined,函数的初始值为代码段。
开始按顺序一行一行解读代码
解读代码的时候,仓库中的变量和函数的值会随着代码的解读而发生变化,也就是变量的赋值和函数的调用。
预解析分为变量的预解析和函数的预解析,也就是代码在执行之前先进行解析,将变量和函数的声名放在当前作用域的最前面。
console.log(a); // 因为变量a没有声名过,所以会报错
test(); // 函数未定义,所以报错
但是在打印之后声名过变量的话,情况就不一样了。
// 变量预解析
console.log(a); // 因为变量a在执行之前进行了预解析,也就是已经放到内存中了,只是没有值,所以是undefined
var a = 1;
/* 预解析相当于下面的过程 */
var a; // 将变量的声名放到当前作用域的最前面
console.log(a);
a = 1;
// 函数预解析
test(); // 结果:123 代码在执行之前经过预解析,将函数的内容放到了内存了,所以在下面的定义函数也能调用执行
function test(){
console.log(123);
}
/* 预解析过程如下: */
function test(){ // 将函数声名放到当前作用域的最前面
console.log(123);
}
test();
案例:
// 1.匿名函数赋值给变量
fn();
var fn = function(){
console.log(123);
}
// 2.函数内部的变量预解析
function test(){
console.log(a);
var a = 10;
}
test();
总结:
1. 用var关键字声名的变量,将变量的声名提升到当前作用域的最前面,赋值不提升
2. 自定义的函数整体提升到当前作用域的最前面
3. 函数同名,后面的会覆盖前面的
4. 变量和函数同名,函数优先提升
五、函数(下)
1、作用域(重点)
- 什么是作用域,就是一个变量可以生效的范围
- 变量不是在所有地方都可以使用的,而这个变量的使用范围就是作用域
全局作用域
-
全局作用域是最大的作用域
-
在全局作用域中定义的变量可以在任何地方使用
-
页面打开的时候,浏览器会自动给我们生成一个全局作用域 window
-
这个作用域会一直存在,直到页面关闭就销毁了
// 下面两个变量都是存在在全局作用域下面的,都是可以在任意地方使用的 var num = 100 var num2 = 200
局部作用域
-
局部作用域就是在全局作用域下面有开辟出来的一个相对小一些的作用域
-
在局部作用域中定义的变量只能在这个局部作用域内部使用
-
在 JS 中只有函数能生成一个局部作用域,别的都不行
-
每一个函数,都是一个局部作用域
// 这个 num 是一个全局作用域下的变量 在任何地方都可以使用 var num = 100 function fn() { // 下面这个变量就是一个 fn 局部作用域内部的变量 // 只能在 fn 函数内部使用 var num2 = 200 } fn()
2、变量使用规则(重点)
- 有了作用域以后,变量就有了使用范围,也就有了使用规则
- 变量使用规则分为两种,访问规则 和 赋值规则
访问规则
-
当我想获取一个变量的值的时候,我们管这个行为叫做 访问
-
获取变量的规则:
- 首先,在自己的作用域内部查找,如果有,就直接拿来使用
- 如果没有,就去上一级作用域查找,如果有,就拿来使用
- 如果没有,就继续去上一级作用域查找,依次类推
- 如果一直到全局作用域都没有这个变量,那么就会直接报错(该变量 is not defined)
var num = 100 function fn() { var num2 = 200 function fun() { var num3 = 300 console.log(num3) // 自己作用域内有,拿过来用 console.log(num2) // 自己作用域内没有,就去上一级,就是 fn 的作用域里面找,发现有,拿过来用 console.log(num) // 自己这没有,去上一级 fn 那里也没有,再上一级到全局作用域,发现有,直接用 console.log(a) // 自己没有,一级一级找上去到全局都没有,就会报错 } fun() } fn()
-
变量的访问规则 也叫做 作用域的查找机制
-
作用域的查找机制只能是向上找,不能向下找
function fn() { var num = 100 } fn() console.log(num) // 发现自己作用域没有,自己就是全局作用域,没有再上一级了,直接报错
赋值规则
-
当你想给一个变量赋值的时候,那么就先要找到这个变量,在给他赋值
-
变量赋值规则:
- 先在自己作用域内部查找,有就直接赋值
- 没有就去上一级作用域内部查找,有就直接赋值
- 在没有再去上一级作用域查找,有就直接赋值
- 如果一直找到全局作用域都没有,那么就把这个变量定义为全局变量,在给他赋值
function fn() { num = 100 } fn() // fn 调用以后,要给 num 赋值 // 查看自己的作用域内部没有 num 变量 // 就会向上一级查找 // 上一级就是全局作用域,发现依旧没有 // 那么就会把 num 定义为全局的变量,并为其赋值 // 所以 fn() 以后,全局就有了一个变量叫做 num 并且值是 100 console.log(num) // 100
3、递归函数
-
什么是递归函数
-
在编程世界里面,递归就是一个自己调用自己的手段
-
递归函数: 一个函数内部,调用了自己,循环往复
// 下面这个代码就是一个最简单的递归函数 // 在函数内部调用了自己,函数一执行,就调用自己一次,在调用再执行,循环往复,没有止尽 function fn() { fn() } fn()
-
其实递归函数和循环很类似
-
需要有初始化,自增,执行代码,条件判断的,不然就是一个没有尽头的递归函数,我们叫做 死递归
4、简单实现一个递归
-
我们先在用递归函数简单实现一个效果
-
需求: 求 1 至 5 的和
- 先算 1 + 2 得 3
- 再算 3 + 3 得 6
- 再算 6 + 4 得 10
- 再算 10 + 5 得 15
- 结束
-
开始书写,写递归函数先要写结束条件(为了避免出现 “死递归”)
function add(n) { // 传递进来的是 1 // 当 n === 5 的时候要结束 if (n === 5) { return 5 } } add(1)
-
再写不满足条件的时候我们的递归处理
function add(n) { // 传递进来的是 1 // 当 n === 5 的时候要结束 if (n === 5) { return 5 } else { // 不满足条件的时候,就是当前数字 + 比自己大 1 的数字 return n + add(n + 1) } } add(1)
5、简单了解对象
-
对象是一个复杂数据类型
-
其实说是复杂,但是没有很复杂,只不过是存储了一些基本数据类型的一个集合
var obj = { num: 100, str: 'hello world', boo: true }
-
这里的
{}
和函数中的{}
不一样 -
函数里面的是写代码的,而对象里面是写一些数据的
-
对象就是一个键值对的集合
-
{}
里面的每一个键都是一个成员 -
也就是说,我们可以把一些数据放在一个对象里面,那么他们就互不干扰了
-
其实就是我们准备一个房子,把我们想要的数据放进去,然后把房子的地址给到变量名,当我们需要某一个数据的时候,就可以根据变量名里面存储的地址找到对应的房子,然后去房子里面找到对应的数据
6、事件
概念
事件就是用户在网页上的动作,例如:鼠标点击、鼠标移动、键盘按下…
事件三要素 : 事件源 + 事件名称 + 事件处理程序
- 事件源 : 谁触发这个事件 (按钮 btn)
- 事件名称 : 触发了什么事件 (点击click事件)
- 事件处理程序 : 事件触发后要执行的代码(函数形式)
初体验:
<input type="button" value="按钮" onclick="dian" id="btn">
<script type="text/javascript">
function dian(){
alert("点击了按钮!");
}
</script>
注意:事件处理程序(函数)并不是立马执行,而是当事件触发的时候在会执行(浏览器会自动调用)
事件列表
事件 | 备注 |
---|---|
onclick | 当鼠标左键单击 |
ondblclick | 当鼠标左键双击 |
onmouseover | 当光标在指定的内容上面 |
onmouseout | 当光标离开指定的内容 |
onkeydown | 当键盘按下的那一刻 |
onkeyup | 当键盘抬起的那一刻 |
onfocus | 当输入框得到焦点 |
onblur | 当输入框失去焦点 |
onchange | 当指定的标签里面内容有变化的时候 |
onsubmit | 提交事件 |
onload | 当整个网页加载完成后 |
通常使用事件来驱动函数:
对象.事件=function(){}
对象.事件=函数名;// 调用自定义函数,不能加小括号,否则会提前执行
<标签名 事件名="函数调用"></标签名>
键盘事件可以区分按下的是哪个键,每个键都由按键码
window.onkeydown = function(e){
var keyNum = e.keyCode
if(keyNum == "13"){
alert("回车键");
}else if(keyNum == "8"){
alert("BackSpace键");
}
}
事件中的this
当在事件中表示当前元素的时候,可以使用this
document.getElementsByTagName("img")[0].onclick=function(){
this.src="images/2.jpg";
}
7、对象
引入
表现形式:
var arr = [];
var obj = {};
var none = null;
这三种不同的表现形式指的都是对象。今天重点学习第二种,使用大括号定义的对象。
概念
将一系列的数据存入一个变量中,这个变量就是对象。
对象的创建
// 创建了一个空对象
var obj = {};
var obj = new Object();
这是两种定义对象的方式,定义的对象都是空的。要给对象中放入值,需要知道对象存储数据的格式 - 键值对。
语法:
var obj = {
键:值,
键:值,
...
};
# 或
var obj = new Object({
键:值,
键:值,
...
});
语法规则:
- 键,也叫作对象的属性,必须是字符串,但是这个字符串在不包含连字符的时候,可以不加引号 - 建议加上
- 值可以是任意类型,包括:数字、字符串、布尔、对象、函数…
- 键值对之间使用逗号隔开
- 键值对之间没有顺序,先写哪个后写哪个没有关系
例:对象可以用来存储一个人的信息
var obj = {
"name":"张三",
age:12,
height:180,
"province-name":"山东省"
};
console.log(obj);
访问
获取这个对象中的某个属性:
对象.属性名 # 这种方式的属性名不用加引号
# 或
对象[属性名] # 这种方式的属性名必须加引号
例:
var obj = {
name:"张三",
age:12
};
console.log(obj.name);
console.log(obj["age"]);
对象的属性名类似于变量名,只不过是定义在大括号中的变量,不会被大括号外部的变量名覆盖 - 不会被外部的变量污染。
遍历对象
遍历的意思就是将每一个值都访问一遍。
js提供了专门用来遍历对象的操作语法:
for(var attr in obj){
# 这里的attr代表对象属性名
# obj表示这个对象
}
例:
var obj = {
name:"张三",
age:12,
height:180
};
for(var i in obj){ // 这里的i表示对象的属性名,是一个字符串
console.log(obj[i]); // 必须使用中括号来输出
}
方法
对象是一种复杂类型变量,里面可以说是很多变量的集合。之前我们在学习函数的时候,可以将一个函数赋值给一个变量,那么,在对象中,是否可以这样操作。
var obj2 = {
name:'王五',
study:function(){
console.log("在学习");
}
}
console.log(obj2);
说明也是可以的。其实对象具备两个内容,一个是属性,一个是方法,属性用来描述一个对象的特征,方法用来描述一个人的行为。就跟人也是一个对象,人可以有特征,也可以有行为,行为可以做一件事情,所以用来描述对象行为的,是函数。在对象中,把值是函数的属性,就叫做方法。
方法的访问和属性是一样的:
obj2.study(); // 因为函数执行需要调用,所以需要加小括号
操作
对象的属性和方法除了可以访问之外,还可以赋值:
var obj2 = {
name:'王五',
study:function(){
console.log("在学习");
}
}
obj2.age = 15;
console.log(obj2);
obj2.eat = function(){
console.log("在吃饭");
}
obj2.eat();
如果赋值的属性名不存在,则是给对象增加属性,如果对象的属性存在,则是给对象修改属性。
#增
//对不存在的属性进行赋值,即为增
对象.键=值;
对象[键]=值;
#删
//删除已存在的属性
delete 对象.键;
delete 对象[键];
#改
//对已存在的属性进行修改
对象.键=值;
对象[键]=值;
#查
8、构造函数
引入
思考:普通类型的数据能不能添加属性和方法?
var num = 90;
num.index = 12;
console.log(num.index);
报错了,也就是说,普通类型的变量不能添加属性和方法。
我来换一种写法:
var num = new Number(90); // 定义一个数字的另一种方法
num.index = 12;
console.log(num.index);
结果可以访问出来,说明,这种方式定义的数字可以添加属性和方法。
那么,直接定义和new来定义有什么不同?类型不同:
var num = 90;
var num1 = new Number(90);
console.log(typeof num); // number
console.log(typeof num1); // object
其实字符串也可以这样来定义,定义后的字符串也可以有属性和方法。
我们发现一个规律,用new创建出来的数据都可以有属性和方法, 因为用new创建出来的变量都是对象。我们把能用new创建对象的这种函数,叫做构造函数。
构造函数没有我们想象中的那个高大上,其实任何函数都可以是构造函数:
function fn(){
}
var o = new fn();
console.log(o); // object
也就是说,当我们使用new来创建一个对象的时候,这个函数就成了构造函数。
使用new关键来创建对象的函数,叫做构造函数。
我们可以为这个对象添加属性和方法。
六、数组
-
什么是数组?
-
字面理解就是 数字的组合
-
其实不太准确,准确的来说数组是一个 数据的集合
-
也就是我们把一些数据放在一个盒子里面,按照顺序排好
[1, 2, 3, 'hello', true, false]
-
这个东西就是一个数组,存储着一些数据的集合
1、数据类型分类
number
/string
/boolean
/undefined
/null
/object
/function
/array
/ …- 数组也是数据类型中的一种
- 我们简单的把所有数据类型分为两个大类 基本数据类型 和 复杂数据类型
- 基本数据类型:
number
/string
/boolean
/undefined
/null
- 复杂数据类型:
object
/function
/array
/ …
2、创建一个数组
- 数组就是一个
[]
- 在
[]
里面存储着各种各样的数据,按照顺序依次排好
字面量创建一个数组
-
直接使用
[]
的方式创建一个数组var arr = []; # 创建了一个空数组 var arr = ["张三","李四","王五"]; # 创建了一个数组,里面存了三个姓名
内置构造函数创建数组
-
使用 js 的内置构造函数
Array
创建一个数组var arr = new Array(); # 创建了一个空数组 var arr = new Array(3); # 创建了一个长度为3的数组 var arr = new Array("张三","李四","王五"); # 创建了一个数组,里面存了三个姓名
使用构造函数的方式创建数组的时候,如果其中只有一个整数,表示数组的长度,如果是多个值,代表是数组中的多个值,如果只有一个值,但不是整数,要报错。
数组的 length
-
length: 长度的意思
-
length 就是表示数组的长度,数组里面有多少个成员,length 就是多少
-
length属性可以读,也可以写。也就是说可以查看长度,也可以修改长度。
// 创建一个数组 var arr = [1, 2, 3] console.log(arr.length) // 3
数组的索引
-
索引,也叫做下标,是指一个数据在数组里面排在第几个的位置
-
注意: 在所有的语言里面,索引都是从 0 开始的
-
在 js 里面也一样,数组的索引从 0 开始
// 创建一个数组 var arr = ['hello', 'world']
-
上面这个数组中,第 0 个 数据就是字符串
hello
,第 1 个 数据就是字符串world
-
想获取数组中的第几个就使用 数组[索引] 来获取
-
数组也是对象
var arr = ['hello', 'world'] console.log(arr[0]) // hello console.log(arr[1]) // world
数组操作(增删改查)
增/改
数组[下标] = 值;
如果下标不存在,就是给数组增加元素
如果下标已经存在,就是将数组中的元素修改。
删:
清空数组:
删:
arr = [1,2,3,4,5];
arr = [];
或
arr.length = 0;
通常,数组中的元素可以是任意类型的数据。一般情况,在数组中的每个元素都是同样的类型,但从语法上来说,数组中的每个元素的类型可以不一样。
var arr = [1,3.14,"Rose",true,null];
console.log(arr); // (5) [1, 3.14, "Rose", true, null]
arr[4] = "Jack";
conole.log(arr); // (5) [1, 3.14, "Rose", true, "赵六"]
delete:清除数组元素的值,将其改成undefined,但是不会改变数组的长度(length),需要使用其他方法消除空间
var arr = [1,2,3];
delete arr[1]; // 将值改成undefined
console.log(arr);
for(var i in arr){
document.write(arr[i]);
}
查:
// 根据下标查询
var arr = [1,2,3,4];
console.log(arr[0]);
// 查询数组长度
var len = arr.length;
// 遍历(for循环,for in)
for(var i in arr){
console.log(arr[i]);
}
总结规律:
数组中第一个元素的下标是0。
数组中最后一个元素的下标是数组元素的个数减1。
数组的空间是可扩展的。可以在其后面继续添加元素。
3、数据类型之间存储的区别(重点)
- 既然我们区分了基本数据类型和复杂数据类型
- 那么他们之间就一定会存在一些区别
- 他们最大的区别就是在存储上的区别
- 我们的存储空间分成两种 栈 和 堆
- 栈: 主要存储基本数据类型的内容
- 堆: 主要存储复杂数据类型的内容
- 简单类型传递值,复杂类型传递地址
基本数据类型在内存中的存储情况
-
简单数据类型:number、string、boolean、undefined、null
-
var num = 100
,在内存中的存储情况 -
值传递过程 引用传递时将值改变了,但是地址没有改变
-
直接在 栈空间 内有存储一个数据
复杂数据类型在内存中的存储情况
-
复杂数据类型:Array、function, object
-
下面这个 对象 的存储
var obj = { name: 'Jack', age: 18, gender: '男' }
-
引用传递过程
-
复杂数据类型的存储
- 在堆里面开辟一个存储空间
- 把数据存储到存储空间内
- 把存储空间的地址赋值给栈里面的变量
-
这就是数据类型之间存储的区别
-
总结:简单类型存储的是值本身,复杂类型存储的是地址,引入如果把第一个对象赋值给另一个变量,此时两个变量会指向同一个对象。
数据类型之间的比较
-
基本数据类型是 值 之间的比较
var num = 1 var str = '1' console.log(num == str) // true
-
复杂数据类型是 地址 之间的比较
var obj = { name: 'Jack' } var obj2 = { name: 'Jack' } console.log(obj == obj2) // false
- 因为我们创建了两个对象,那么就会在 堆空间 里面开辟两个存储空间存储数据(两个地址)
- 虽然存储的内容是一样的,那么也是两个存储空间,两个地址
- 复杂数据类型之间就是地址的比较,所以
obj
和obj2
两个变量的地址不一样 - 所以我们得到的就是
false
4、数组的常用方法
-
数组是一个复杂数据类型,我们在操作它的时候就不能再想基本数据类型一样操作了
-
比如我们想改变一个数组
// 创建一个数组 var arr = [1, 2, 3] // 我们想把数组变成只有 1 和 2 arr = [1, 2]
- 这样肯定是不合理,因为这样不是在改变之前的数组
- 相当于新弄了一个数组给到 arr 这个变量了
- 相当于把 arr 里面存储的地址给换了,也就是把存储空间换掉了,而不是在之前的空间里面修改
- 所以我们就需要借助一些方法,在不改变存储空间的情况下,把存储空间里面的数据改变了
数组常用方法之 push
-
push
是用来在数组的末尾追加一个元素,并返回新数组的lengthvar arr = [1, 2, 3] // 使用 push 方法追加一个元素在末尾,并将其返回的长度赋值给a var a = arr.push(4) console.log(arr) // [1, 2, 3, 4] console.log(a) // 4
-
可以插入多个元素
var arr = [1, 2, 3] // 使用 push 方法追加一个元素在末尾 arr.push(4, 5, 6) console.log(arr) // [1, 2, 3, 4 , 5 , 6]
-
可插入其他数组或对象,但数组长度不会叠加,只会将插入数组或对象作为一个元素
var arr = [1, 2, 3]; var arr1 = [2,3,4] // 使用 push 方法追加一个元素在末尾 arr.push(arr1) console.log(arr) // [1, 2, 3, arr1]
数组常用方法之 pop
-
pop
是用来删除数组末尾的一个元素,并返回删除的那个元素var arr = [1, 2, 3] // 使用 pop 方法删除末尾的一个元素,并将其赋值给a var a = arr.pop() console.log(arr) // [1, 2] console.log(a) // 3
数组常用方法之 unshift
-
unshift
是在数组的最前面添加一个元素,并返回新数组的长度 -
可以插入多个元素
-
可插入其他数组或对象,但数组长度不会叠加,只会将插入数组或对象作为一个元素
-
使用方法与push类似
var arr = [1, 2, 3] // 使用 unshift 方法想数组的最前面添加一个元素 arr.unshift(4) console.log(arr) // [4, 1, 2, 3]
数组常用方法之 shift
-
shift
是删除数组最前面的一个元素,并返回删除的那个元素 -
使用方法与pop类似
var arr = [1, 2, 3] // 使用 shift 方法删除数组最前面的一个元素 arr.shift() console.log(arr) // [2, 3]
增删总结
总结:
1. shift 在前面 ,所以处理数组前面的
2. p+ 在后面,所以是处理后面的
3. unshift 比 shift 多个un,,所以就是加
4. 添加的都是返回长度
5. 删除的都是返回删除的元素
6. 添加要说明添加什元素,,删除直接删除
数组常用方法之 splice
-
splice
是截取数组中的某些内容,按照数组的索引来截取 -
语法:
splice(从哪一个索引位置开始,截取多少个,替换的新元素)
(第三个参数可以不写)var arr = ['zs','ls','ww','zl','xmg']; // 原来的数组影响 //- splice(start, deletedCount) 删除元素 // - start 开始 // - deletedCount 删除个数 //- splice(start, deletedCount , item) 删除+添加, 第三个参数是在原来删除的位置上新加"几个"元素 //- 特殊 : // splice(start, 0 , item) 就是在某个位置新加元素 var arr = [1, 2, 3, 4, 5] // 使用 splice 方法截取数组 arr.splice(1, 2) console.log(arr) // [1, 4, 5]
arr.splice(1, 2)
表示从索引 1 开始截取 2 个内容- 第三个参数没有写,就是没有新内容替换掉截取位置(第三个参数可为多个值)
var arr = [1, 2, 3, 4, 5] // 使用 splice 方法截取数组 arr.splice(1, 2, '我是新内容','我是新内容2') console.log(arr) // [1, '我是新内容','我是新内容2', 4, 5]
arr.splice(1, 2, '我是新内容','我是新内容2')
表示从索引 1 开始截取 2 个内容- 然后用第三个参数把截取完空出来的位置填充
- 【注】splice(start, 0 , item) 就是在某个位置新加元素,即插入元素操作
数组常用方法之 reverse
-
reverse
是用来反转数组使用的var arr = [1, 2, 3] // 使用 reverse 方法来反转数组 arr.reverse() console.log(arr) // [3, 2, 1]
数组常用方法之 sort
-
sort
是用来给数组排序的array.sort();//数组的排序,默认按照 字母/首字符 顺序排序 => 1 11 2 3,按照字符串的比较方法进行比较的 var arr1 = ['a','d','b','c']; var arr2 = [3, 6, 1, 5, 10, 2,11]; arr1.sort();//[a,b,c,d] arr2.sort();//[1,10,11,2,3,5,6] //按照别的顺序进行排序,就必须提供比较函数,该函数要比较两个值,然后返回一个用于说明这两个值的相对顺序的数字。比较函数应该具有两个参数a和b,其返回值如下: //如果根据你的评判标准,a小于b,在排序后的数组中a应该出现在b之前,就返回一个小于0的值。 //如果a等于b,就返回0。 //如果a大于b,就返回一个大于0的值。 arr.sort(function(a, b){ //如果返回值>0,则交换位置 return a - b; }); //【注】数组中undefined的元素都排列在数组末尾。即使你提供了自定义的排序函数也是这样,因为undefined值不会被传递给你提供的orderfunc。
- 这个只是一个基本的简单用法
数组常用方法之 concat
-
concat
是把多个数组进行拼接 -
和之前的方法有一些不一样的地方,就是
concat
不会改变原始数组,而是返回一个新的数组var arr = [1, 2, 3] // 使用 concat 方法拼接数组 var newArr = arr.concat([4, 5, 6]) console.log(arr) // [1, 2, 3] console.log(newArr) // [1, 2, 3, 4, 5, 6]
- 注意: concat 方法不会改变原始数组
数组常用方法之 join
-
join
是把数组里面的每一项内容链接起来,变成一个字符串 -
可以自己定义每一项之间链接的内容
join(要以什么内容链接)
-
不会改变原始数组,而是把链接好的字符串返回
-
arr.join();不传参数,默认按【,】进行拼接
var arr = [1, 2, 3] // 使用 join 链接数组 var str = arr.join('-') console.log(arr) // [1, 2, 3] console.log(str) // 1-2-3
- 注意: join 方法不会改变原始数组,而是返回链接好的字符串
数组常用方法之 split
-
split
:将字符串分割成数组 -
功能和数组的join正好相反
-
不会改变原始字符串,而是把拆分好的数组返回
var str = "张三,李四,王五"; var arr = str.split(","); console.log(str); //张三,李四,王五 console.log(arr); //[张三,李四,王五]
5、for 和 for in 循环
-
因为数组的索引就可以获取数组中的内容
-
数组的索引又是按照 0 ~ n 顺序排列
-
我们就可以使用 for 循环来循环数组,因为 for 循环我们也可以设置成 0 ~ n 顺序增加
-
我们把这个行为叫做 遍历
var arr = [1, 2, 3, 4, 5] // 使用 for 循环遍历数组 for (var i = 0; i < arr.length; i++) { console.log(arr[i]) } // 会在控制台依次打印出 1, 2, 3, 4, 5
i < arr.length
因为 length 就是数组的长度,就是一个数字,所以我们可以直接用它来决定循环次数console.log(arr[i])
因为随着循环,i 的值会从 0 开始依次增加- 所以我们实际上就相当于在打印
arr[0]
/arr[1]
/ …
-
因为 对象 是没有索引的,所以我们没有办法使用 for 循环来遍历
-
这里我们使用 for in 循环来遍历对象
-
先来看一段代码
var obj = { name: 'Jack', age: 18 } for (var key in obj) { console.log(key) } // 会在控制台打印两次内容,分别是 name 和 age
- for in 循环的遍历是按照对象中有多少成员来决定了
- 有多少成员,就会执行多少次
key
是我们自己定义的一个变量,就和 for 循环的时候我们定义的 i 一个道理- 在每次循环的过程中,key 就代表着对象中某一个成员的 属性名
- 注意:for in不会遍历空元素
- 注意:for in中的i变量类型是字符串,而不是数字类型,所以for in专门用来遍历对象,for in不会遍历空元素
6、数组的排序
- 排序,就是把一个乱序的数组,通过我们的处理,让他变成一个有序的数组
- 今天我们讲解两种方式来排序一个数组 冒泡排序 和 选择排序
冒泡排序
-
先遍历数组,让挨着的两个进行比较,如果前一个比后一个大,那么就把两个换个位置
-
数组遍历一遍以后,那么最后一个数字就是最大的那个了
-
然后进行第二遍的遍历,还是按照之前的规则,第二大的数字就会跑到倒数第二的位置
-
以此类推,最后就会按照顺序把数组排好了
-
我们先来准备一个乱序的数组
var arr = [3, 1, 5, 6, 4, 9, 7, 2, 8]
- 接下来我们就会用代码让数组排序
-
先不着急循环,先来看数组里面内容换个位置
// 假定我现在要让数组中的第 0 项和第 1 项换个位置 // 需要借助第三个变量 var tmp = arr[0] arr[0] = arr[1] arr[1] = tmp
-
第一次遍历数组,把最大的放到最后面去
for (var i = 0; i < arr.length; i++) { // 判断,如果数组中的当前一个比后一个大,那么两个交换一下位置 if (arr[i] > arr[i + 1]) { var tmp = arr[i] arr[i] = arr[i + 1] arr[i + 1] = tmp } } // 遍历完毕以后,数组就会变成 [3, 1, 5, 6, 4, 7, 2, 8, 9]
- 第一次结束以后,数组中的最后一个,就会是最大的那个数字
- 然后我们把上面的这段代码执行多次。数组有多少项就执行多少次
-
按照数组的长度来遍历多少次
for (var j = 0; j < arr.length; j++) { for (var i = 0; i < arr.length; i++) { // 判断,如果数组中的当前一个比后一个大,那么两个交换一下位置 if (arr[i] > arr[i + 1]) { var tmp = arr[i] arr[i] = arr[i + 1] arr[i + 1] = tmp } } } // 结束以后,数组就排序好了
-
给一些优化
-
想象一个问题,假设数组长度是 9,第八次排完以后
-
后面八个数字已经按照顺序排列好了,剩下的那个最小的一定是在最前面
-
那么第九次就已经没有意义了,因为最小的已经在最前面了,不会再有任何换位置出现了
-
那么我们第九次遍历就不需要了,所以我们可以减少一次
for (var j = 0; j < arr.length - 1; j++) { for (var i = 0; i < arr.length; i++) { // 判断,如果数组中的当前一个比后一个大,那么两个交换一下位置 if (arr[i] > arr[i + 1]) { var tmp = arr[i] arr[i] = arr[i + 1] arr[i + 1] = tmp } } }
-
第二个问题,第一次的时候,已经把最大的数字放在最后面了
-
那么第二次的时候,其实倒数第二个和最后一个就不用比了
-
因为我们就是要把倒数第二大的放在倒数第二的位置,即使比较了,也不会换位置
-
第三次就要倒数第三个数字就不用再和后两个比较了
-
以此类推,那么其实每次遍历的时候,就遍历当前次数 - 1 次
for (var j = 0; j < arr.length - 1; j++) { for (var i = 0; i < arr.length - 1 - j; i++) { // 判断,如果数组中的当前一个比后一个大,那么两个交换一下位置 if (arr[i] > arr[i + 1]) { var tmp = arr[i] arr[i] = arr[i + 1] arr[i + 1] = tmp } } }
-
-
至此,一个冒泡排序就完成了
-
选择排序
-
先假定数组中的第 0 个就是最小的数字的索引
-
然后遍历数组,只要有一个数字比我小,那么就替换之前记录的索引
-
知道数组遍历结束后,就能找到最小的那个索引,然后让最小的索引换到第 0 个的位置
-
再来第二趟遍历,假定第 1 个是最小的数字的索引
-
在遍历一次数组,找到比我小的那个数字的索引
-
遍历结束后换个位置
-
依次类推,也可以把数组排序好
-
准备一个数组
var arr = [3, 1, 5, 6, 4, 9, 7, 2, 8]
-
假定数组中的第 0 个是最小数字的索引
var minIndex = 0
-
遍历数组,判断,只要数字比我小,那么就替换掉原先记录的索引
var minIndex = 0 for (var i = 0; i < arr.length; i++) { if (arr[i] < arr[minIndex]) { minIndex = i } } // 遍历结束后找到最小的索引 // 让第 minIndex 个和第 0 个交换 var tmp = arr[minIndex] arr[minIndex] = arr[0] arr[0] = tmp
-
按照数组的长度重复执行上面的代码
for (var j = 0; j < arr.length; j++) { // 因为第一遍的时候假定第 0 个,第二遍的时候假定第 1 个 // 所以我们要假定第 j 个就行 var minIndex = j // 因为之前已经把最小的放在最前面了,后面的循环就不需要判断前面的了 // 直接从 j + 1 开始 for (var i = j + 1; i < arr.length; i++) { if (arr[i] < arr[minIndex]) { minIndex = i } } // 遍历结束后找到最小的索引 // 第一堂的时候是和第 0 个交换,第二趟的时候是和第 1 个交换 // 我们直接和第 j 个交换就行 var tmp = arr[minIndex] arr[minIndex] = arr[j] arr[j] = tmp }
-
一些优化
-
和之前一样,倒数第二次排序完毕以后,就已经排好了,最后一次没有必要了
for (var j = 0; j < arr.length - 1; j++) { var minIndex = j for (var i = j + 1; i < arr.length; i++) { if (arr[i] < arr[minIndex]) { minIndex = i } } var tmp = arr[minIndex] arr[minIndex] = arr[j] arr[j] = tmp }
-
在交换变量之前,可以判断一下,如果我们遍历后得到的索引和当前的索引一直
-
那么就证明当前这个就是目前最小的,那么就没有必要交换
-
做一我们要判断,最小作引和当前作引不一样的时候,才交换
for (var j = 0; j < arr.length - 1; j++) { var minIndex = j for (var i = j + 1; i < arr.length; i++) { if (arr[i] < arr[minIndex]) { minIndex = i } } if (minIndex !== j) { var tmp = arr[minIndex] arr[minIndex] = arr[j] arr[j] = tmp } }
-
-
至此,选择排序完成
-
7、函数参数传递基本数据类型和复杂数据类型的区别
-
之前我们知道了,基本数据类型和复杂数据类型在存储上是有区别的
-
那么他们在赋值之间也是有区别的
-
基本数据类型之间的赋值
var num = 10 var num2 = num num2 = 200 console.log(num) // 100 console.log(num2) // 200
- 相当于是把 num 的值复制了一份一摸一样的给了 num2 变量
- 赋值以后两个在没有关系
-
复杂数据类型之间的赋值
var obj = { name: 'Jack' } var obj2 = obj obj2.name = 'Rose' console.log(obj.name) // Rose console.log(obj2.name) // Rose
- 因为复杂数据类型,变量存储的是地址,真实内容在 堆空间 内存储
- 所以赋值的时候相当于把 obj 存储的那个地址复制了一份给到了 obj2 变量
- 现在 obj 和 obj2 两个变量存储的地址一样,指向一个内存空间
- 所以使用 obj2 这个变量修改空间内的内容,obj 指向的空间也会跟着改变了
函数的参数
-
函数的参数也是赋值的之中,在函数调用的时候,实参给行参赋值
-
和之前变量赋值的规则是一样的
-
函数传递基本数据类型
function fn(n) { n = 200 console.log(n) // 200 } var num = 100 fn(num) console.log(num) // 100
- 和之前变量赋值的时候一样,在把 num 的值复制了一份一摸一样的给到了函数内部的行参 n
- 两个之间在没有任何关系了
-
函数传递复杂数据类型
function fn(o) { o.name = 'Rose' console.log(o.name) // Rose } var obj = { name: 'Jack' } fn(obj) console.log(obj.name) // Rose
- 和之前变量赋值的时候一样,把 obj 内存储的地址复制了一份一摸一样的给到函数内部的行参 o
- 函数外部的 obj 和函数内部的行参 o,存储的是一个地址,指向的是一个存储空间
- 所以两个变量操作的是一个存储空间
- 在函数内部改变了空间内的数据
- obj 看到的也是改变以后的内容
8、二维数组
var arr = [
"Jack",
"Rose",
["王宝强","马蓉"],
["贾乃亮","李小璐"]
];
console.log(arr);
console.log(arr[2]);
console.log(arr[2][1]);
包含数组的数组,叫做多维数组,我们用的最多的就是二维数组。
var arr = [arr0,arr1,arr2,...,arrn];
// arr0,arr1,arr2,...,arrn都是一位数组
利用二维数组加载网页内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<style>
*{
padding: 0;
margin: 0;
list-style: none;
}
.container{
width: 1200px;
margin:auto;
}
li{
float:left;
width: 200px;
margin:20px;
border:1px solid #ccc;
}
li img{
width: 100%;
height: 100%;
}
</style>
<body>
</body>
<script type="text/javascript">
var arr = [
{
image_url:"http://www.leawo.cn/attachment/201404/16/1433365_1397624557Bz7w.jpg",
introudce:"这是小米手机,很好用,很便宜",
price:"¥20元",
},
{
image_url:"http://imgfs.oppo.cn/uploads/thread/attachment/2017/10/04/15070507024870.jpg",
introudce:"这是华硕电脑,好用",
price:"¥60元",
},
{
image_url:"http://www.cphoto.com.cn/dz/attachments/month_1204/12042913298163d0a39dcf0c11.jpg",
introudce:"华为手机,死贵,摄像头好",
price:"¥88.8元",
},
{
image_url:"http://hbimg.b0.upaiyun.com/11eb40ac428374964b24948a000ff1b2a18d2e518afa4-v4kiLD_fw658",
introudce:"苹果手机,垃圾",
price:"¥99.9元",
},
{
image_url:"http://img3.imgtn.bdimg.com/it/u=671482448,2533267591&fm=26&gp=0.jpg",
introudce:"这是女朋友,漂亮",
price:"¥30元",
},
];
document.write("<div class='container'>");
document.write("<ul>");
for(var i=0;i<arr.length;i++){
document.write("<li>");
document.write("<img src='"+ arr[i].image_url +"'>");
document.write("<div>"+arr[i].introudce+"</div>");
document.write("<p>价格:"+arr[i].price+"</p>");
document.write("</li>");
}
document.write("</ul>");
document.write("</div>");
</script>
</html>
随机点名系统
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
h1{
text-align:center;
}
#box{
width:350px;
height:150px;
font-size:100px;
border:#abcdef 5px solid;
line-height:150px;
margin:auto;
text-align:center;
}
#btn{
display:block;
margin:0 auto;
width:350px;
height:80px;
font-size:50px;
background: yellowgreen;
}
</style>
</head>
<body>
<h1>点名程序</h1>
<div id="box"></div>
<input type="button" value="开始" id="btn">
</body>
<script type="text/javascript">
// 定时器 每隔多长时间做什么事情
// setInterval(function(){
// console.log(1);
// },1000);
// 随机数
// console.log(Math.random()); // >=0 <1的随机数
// console.log(parseInt(Math.random()*11));
var arr = ["张三","李四","王五","赵六","孙七","周八","吴九","郑九"];
var timerId;
btn.onclick=function(){
// 使用this代表触发当前事件的那个事件源
// input的值都使用value可以获取到
// 标签内容:innerText
if(this.value == "开始"){
this.value = "停止";
timerId = setInterval(function(){
box.innerText = arr[parseInt(Math.random()*11)];
},30);
}else{
this.value = "开始";
// 结束定时器 clearInterval(定时器的变量)
clearInterval(timerId);
}
}
</script>
</html>
9、补充
// 判断一个元素是不是数组
a instanceof Array
是-->返回true,否-->返回false
七、ES5/String
1、严格模式
- 我们都知道 js 是一个相对不很严谨的语言
- 而且开发的时候,一些代码也不是很严格要求
- 而严格模式就是对开发的时候写的一些内容做了要求
开启严格模式
-
想开启严格模式,直接在代码最开始的位置写上字符串
use strict
<script> 'use strtic' // 下面代码书写就要按照严格模式来书写 </script>
严格模式的规则
-
声明变量必须有
var
关键字'use strtic' var num = 100 num2 = 200 // 这个就会报错
- 之前了解过,在声明变量的时候,如果没有 var 关键字,就是隐式声明变量,按照作用域的规则会自动定义成全局变量
- 严格模式下不可以,会报错
-
函数的行参不可以重复
'use strtic' function fn(p1, p1) {} // 直接就会报错
- 在非严格模式下,函数两个行参一样,是不会报错的,只不过就是相当于在函数内部只有一个变量了
- 但是在严格模式下会报错
-
声明式函数调用的时候函数内部没有 this
'use strtic' function fn() { console.log(this) // undefined } fn()
- 本身,全局声明式函数在调用的时候,函数内部的 this 是指向 window 的
- 在严格模式下,是没有 this 的
-
arguments对象不允许被动态改变
<script>
function fn1(a){
a = 2;
return [a, arguments[0]];
}
console.log(fn1(1)); //正常模式为[2,2];
function fn2(a){
“use strict”;
a = 2;
return [a, arguments[0]];
}
console.log(fn2(1)); //严格模式为[2,1];
</script>
5.新增保留字:implements, interface, let, package, private, protected, public, static, yield
严格模式的优点
- 可以让代码更加规范
- 可以让代码运行起来更快,提高运行效率
注意:当合并文件时,第一行的严格模式代码会失效,建议包在一个自执行函数中
2、ES5 中常见的数组常用方法
- 之前我们讲过的数组常用方法都是 ES3 的方法
- 今天来说一些 ES5 中的方法
indexOf方法
查找某个元素在数组中第一次出现的位置
语法:
arr.indexOf(item,[index]);
# 参数1:将要查找的元素
# 参数2:可选项。从哪个下标开始往后查找
# 返回值:如果找到了,就返回这个元素在数组中的下标,如果没有找到,就返回-1
例:
var arr = [1,3,5,7,7,5,3,1];
console.log(arr.indexOf(5)); //2
console.log(arr.lastIndexOf(5)); //5
console.log(arr.indexOf(5,2)); //2
console.log(arr.lastIndexOf(5,4)); //2
console.log(arr.indexOf("5")); //-1
forEach方法
用于遍历数组
和 for 循环一个作用,就是用来遍历数组的
语法:
arr.forEach(function(item, index, arr){
// 代码段
});
# 在这个方法中需要传入一个函数参数,这个函数的参数说明如下:
# 参数1:数组遍历出来的每个值
# 参数2:可选项。数组遍历出来的每个值对应的下标
# 参数3:可选项。被遍历的当前数组
例:
var arr = [1, 2, 3, 4, 5];
arr.forEach(function(x, index, a){
console.log(x + '|' + index + '|' + (a === arr));
});
// 输出为:
// 1|0|true
// 2|1|true
// 3|2|true
// 4|3|true
// 5|4|true
使用说明:
这个方法没有返回值,返回值为undefined,不会改变原来数组的值。
forEach() 的时候传递的那个函数,会根据数组的长度执行
数组的长度是多少,这个函数就会执行多少回
map方法
-
和 forEach 类似,只不过可以对数组中的每一项进行操作,返回一个新的数组
-
遍历数组,并将每个元素传入回掉函数中处理后,组成新的数组并返回
var arr = [1, 2, 3] // 使用 map 遍历数组 var newArr = arr.map(function (item, index, arr) { // item 就是数组中的每一项 // index 就是数组的索引 // arr 就是原始数组 return item + 10 }) console.log(newArr) // [11, 12, 13]
例:
var arr = [1, 2, 3, 4, 5]; var arr2 = arr.map(function(item){ return item*item; }); console.log(arr2); //[1, 4, 9, 16, 25]
filter方法
-
和 map 的使用方式类似,按照我们的条件来筛选数组
-
把原始数组中满足条件的筛选出来,组成一个新的数组返回
var arr = [1, 2, 3] // 使用 filter 过滤数组 var newArr = arr.filter(function (item, index, arr) { // item 就是数组中的每一项 // index 就是数组的索引 // arr 就是原始数组 // 函数体-->筛选条件 return item > 1 }) console.log(newArr) // [2, 3]
- 使用方法和功能跟map方法很像,只是运行规则不一样。map方法中的函数,用于返回新的元素,而filter方法中的函数,根据返回true或false来筛选元素
some方法
-
按照我们的条件来筛选数组
-
找到第一个符合条件的元素就返回true,否则返回false
var arr = [1, 2, 3]
// 使用 some 过滤数组
var newArr = arr.some(function (item, index, arr) {
// item 就是数组中的每一项
// index 就是数组的索引
// arr 就是原始数组
// 函数体-->筛选条件
return item > 1
})
console.log(newArr) //true
every方法
-
按照我们的条件来筛选数组
-
如果全部元素都符合条件的元素就返回true,否则返回false
var arr = [1, 2, 3]
// 使用 every 过滤数组
var newArr = arr.every(function (item, index, arr) {
// item 就是数组中的每一项
// index 就是数组的索引
// arr 就是原始数组
// 函数体-->筛选条件
return item > 1
})
console.log(newArr) //true
reduce方法
归并,其中调用回掉函数,回掉函数中有两个参数,第一个参数是上一次操作的返回值,第二个参数是从第二个元素开始到最后一个元素
语法:
arr.reduce(function(prev,next){
// 逻辑代码
});
例:
var arr = [1,2,3,4,5,6];
document.write("prev------next<br>");
var res = arr.reduce(function(prev,next){
document.write(prev + "------" + next + "<br>");
// prev 表示上一次操作返回的结果,第一次是第一个数
// next 表示是下一个数,第一次是第二个数
return prev + next; // 将每一次操作的结果返回给下一次的prev(数组求和)
});
console.log(res);
效果:
归并示意图 |
---|
![]() |
3、创建字符串
-
我们创建字符串也分为两种方法 字面量 和 构造函数
-
字面量:
var str = 'hello'// typeof---->String
-
构造函数创建
var str = new String('hello')// typeof---->object
4、ASCII 字符集
- 我们都知道,计算机只能存储
0101010
这样的二进制数字 - 那么我们的
a ~ z
/A ~ Z
/ ``/@
/… 之类的内容也有由二进制数字组成的 - 我们可以简单的理解为,
a ~ z
/A ~ Z
/ ``/@
/… 之类的内容都有一个自己的编号,然后在计算机存储的时候,是存储的这些编号,我们看的时候,也是通过这些编号在解析成我们要看到的内容给我们看到 - ASCII码计算机中用得最广泛的字符集及其编码,是由**美国国家标准局(ANSI)**制定的ASCII码(American Standard Code for Information Interchange,美国标准信息交换码)。所以对于英文字母和符号的支持是很全面的。
- 两个字符串也是可以比较大小的,比较的规则是逐字符进行比较,字符的大小由字符对应的阿斯克码决定。
5、unicode 编码
- 我们看到了,ASCII 只有这 128 个字符的编码结构
- 但是因为 ASCII 出现的比较早,而且是美国发明的,早起时候这些内容就够用了
- 因为存储一些英文的内容,传递一些英文的文章什么的都够用了
- 那么对于这个世界来说肯定是不够用的
- 因为我们的汉字没有办法存储,包括一些其他国家的语言也没有办法存储
- 所以就出现了 unicode 编码,也叫(万国码,统一码)
- unicode 对照表就是一个和 ASCII 一样的对照表,只不过变得很大很大,因为存储的内容特别的多
- 而且包含了世界上大部分国家的文字,所以我们的文字和字符现在在存储的时候,都是按照 unicode 编码转换成数字进行存储
- 我们的 UTF-8 就是一种 8 位的unicode字符集
6、字符串的比较
我们曾经碰到过一个问题,接收到文本框的两个值,一个是"3",另一个是"10",这两个值进行大小比较的时候,结果是:"3">"10" === true
,出现这个结果的原因是,两个字符串进行比较的时候,是逐字符进行比较,也就是字符"3"先和字符"1"进行比较,如果第一个字符相等再进行第二个字符的比较。
从ASCII码表中,可以找到字符"3"和字符"1"相对应的值,很明显,字符"3"是要大于字符"1"的。
通过阿斯克码表,我们可以得出一些字符串比较的规律:
- 字母比数字大
- 小写字母比大写字母大
- 字母越靠后越大
var str1 = "2";
var str2 = "11";
console.log(str1 > str2) // true
//先取第一位进行比较str1取2,str2取1,2>1,所以后面的比较不会再进行,从而得到2>11
【注】汉字等其他字符的比较也类似,只是用的是Unicode编码(更大的ASCII编码)
7、字符串常见API(应用程序接口)
- 我们操作字符串,也有一堆的方法来帮助我们操作
- 字符串和数组有一个一样的地方,也是按照索引来排列的
通过下标获取字符操作
例:
var str = '你好吗';
// 输出下标为1的字符
console.log(str[1]); // 好
每个字符都有对应的下标,所以,字符串也可以进行遍历。
字符串是只读数据类型,不能添加新字符,不能修改字符串中的字符,不能删除某个字符
例:
var str = '你好吗';
// 修改下标为1的字符
str[1] = "帅"
console.log(str); // 你好吗
length属性
求字符串中字符的个数 - 字符串的长度
语法:
字符串.length
例:
var str = 'asdfvczx';
// 输出字符串的长度
console.log(str.length);//8
charAt方法
-
charAt(索引)
是找到字符串中指定索引位置的内容返回var str = 'Jack' // 使用 charAt 找到字符串中的某一个内容 var index = str.charAt(2) console.log(index) // c
- 因为字符串也是按照索引进行排列的,也是同样从 0 开始
- 所以索引 2 的位置就是 c
-
如果没有对应的索引,那么就会返回 空字符串
var str = 'Jack' // 使用 charAt 找到字符串中的某一个内容 var index = str.charAt(10) console.log(index) // ''
- 这个字符串根本没有索引 10 的位置
- 所以就会返回一个空字符串
''
- 而通过索引查找的方式(str[i]),没找到的话会返回undefined
charCodeAt方法
-
charCodeAt(索引)
就是返回对应索引位置的 unicode 编码var str = 'Jack' // 使用 charCodeAt 返回索引位置的unicode 编码 var index = str.charCodeAt(0) console.log(index) // 74
- 因为
J
在 unicode 对照表里面存储的是 74,所以就会返回 74 - 且返回值是一个number值
- 若对应索引不存在,则返回NaN
- 因为
String.fromCharCode方法
根据指定的ASCII码得到对应的字符
语法:
String.fromCharCode(ASCII码)
例:
// 获取98对应的字符
var res = String.fromCharCode(98);
console.log(res); // b
indexOf方法
查找字符或子字符串在大字符串中第一次出现的位置
语法:
大字符串.indexOf(字符/子字符串[,开始查找的下标])
例:
var str = 'i love you';
// 找到o字符在str中第一次出现的位置
var res = str.indexOf('o');
console.log(res); // 3
var str = 'i love you';
// 找到o字符在str中第一次出现的位置(从下标4开始查找)
var res = str.indexOf('o',4);
console.log(res); // 8
使用说明:
- 如果找到这个字符在字符串中的位置,就返回这个字符对应的下标,如果找不到,就返回-1
- 第二个参数可选项。表示从哪个下标开始查找
- 索引小于0仍会从前到后搜索,等于或大于字符串长度则会返回-1
lastIndexOf方法
查找字符或子字符串在大字符串中最后一次出现的位置
语法:
大字符串.lastIndexOf(字符/子字符串[,开始查找的下标])
例:
var str = 'i love you';
// 找到o字符在str中最后一次出现的位置
var res = str.lastIndexOf('o');
console.log(res); // 8
使用说明:
- 如果找到这个字符在字符串中的位置,就返回这个字符对应的下标,如果找不到,就返回-1
- 第二个参数可选项。表示从哪个下标开始查找(【注】从后往前查找)
search()方法
正则匹配(返回出现的位置)
语法:
大字符串.search()(字符/子字符串)
例:
var str = 'i love you';
// 找到o字符在str中最后一次出现的位置
var res = str.search(/O/i);
console.log(res); // 8
使用说明:
- 如果找到这个字符在字符串中的位置,就返回这个字符对应的下标,如果找不到,就返回-1
- 第二个参数可选项。表示从哪个下标开始查找(【注】从后往前查找)
substr方法
-
substr
也是用来截取字符串的 -
语法:
substr(从哪个索引开始,截取多少个)
例:
var str = '你的头发还好吗'; // 从下标2开始截取2个字符 var res = str.substr(2,2); console.log(res); // 头发
使用说明:
- 第二个参数是可选项。如果省略掉第二个参数,默认截取到字符串末尾。
- 开始下标可以使用负数表示,从右往左的下标依次是-1,-2,。。。
- 截取字符的时候都是从左向右截取的
例:
var str = '你的头发还好吗'; // 从下表2开始截取 var res = str.substr(2); console.log(res); // 头发还好吗 // 从下标-5开始截取2个字符 var res = str.substr(-5,2); console.log(res); // 头发 // 从下标-1开始截取2个字符 var res = str.substr(-1,2); console.log(res);// 吗
使用说明:截取到最后也不满足长度的时候,就返回能截取到的所有字符
substring方法
截取字符串
语法:
字符串.substring(开始下标[,结束下标])
例:
var str = '你的头发还好吗';
// 从下标2开始截取到下标4
var res = str.substr(2,4);
console.log(res); // 头发
使用说明:
- 第二个参数是可选项。如果省略掉第二个参数的话,默认截取到字符串末尾。
- 截取的结果包含开始下标对应的字符,不包含结束下标对应的字符
- 如果开始下标和结束下标相等,则返回空字符串;如果开始下标大于结束下标,则先交换两个参数,然后再截取;如果开始下标或结束下标为负数,则先将负数替换成0,然后再截取,如果下标大于length-1,则先将下标替换成length-1,然后截去
例:
var str = '你的头发还好吗';
// 从下标2开始截取
var res = str.substring(2);
console.log(res); // 头发还好吗
// 从下标2截取到下标-2
var res = str.substring(2,-2);
console.log(res); // 你的
/*
过程分析:
首先开始下标大于结束下标,所以先交换两个参数,相当于: str.substring(-2,2);
开始下标为负数,所以替换成0,相当于: str.substring(0,2);
所以结果为:你的
*/
slice方法
截取字符串
语法:
字符串.slice(开始下标[,结束下标]);
例:
var str = '你的头发还好吗';
// 从下标2截取到下标4
var res = str.slice(2,4);
console.log(res); // 头发
使用说明:
- 第二个参数是可选项。如果省略第二个参数默认截取到字符串的末尾
- 返回的结果包含开始下标对应的字符,不包含结束下标对应的字符
- 截取的时候,下标可以使用负数表示
- 开始下标对应的字符一定要在结束下标对应的字符左边,否则返回空字符串。因为截取的顺序是从左向右的
例:
var str = '你的头发还好吗';
// 从下标2开始截取
var res = str.slice(2);
console.log(res); // 头发还好吗
// 从下标-5开始截取到下标4
var res = str.slice(-5,4);
console.log(res); // 头发
// 从下标-1截取到下标-3
var res = str.slice(-1,-3);
console.log(res); // 空
split方法
使用指定的分隔符将字符串分割成多部分组成数组
语法:
字符串.split([分隔符,[最后数组中要保留的个数]])
例:
var str = 'open_door_now';
// 以下划线为分隔符,分割字符串为数组
var arr = str.split("_");
console.log(arr); // ["open", "door", "now"]
使用说明:
- 分隔符是可选项。如果省略了分隔符,则将整个字符串当做数组的元素,如果是空字符串,则会在每个字符中间进行分割
- 要保留的个数是可选项。如果省略了个数,则返回全部的个数,如果加上个数,则是设置了数组中元素的个数。
例:
var str = 'open_door_now';
// 省略分隔符将字符串分割为数组
var arr = str.split();
console.log(arr); // ["open_door_now"]
// 以空字符串进行分割字符串
var arr = str.split("");
console.log(arr); // ["o", "p", "e", "n", "_", "d", "o", "o", "r", "_", "n", "o", "w"]
// 以空字符串分割字符串,并在数组中保留4个元素
var arr = str.split("",4);
console.log(arr); // ["o", "p", "e", "n"]
replace方法
使用新的字符或子字符串替换原来在字符串中的一部分
语法:
字符串.replace(将要被替换的部分,要替换进来的新内容);
例:
var str = '你的头发还好吗';
// 使用"眉毛"将"头发"替换掉
var res = str.replace("头发","眉毛");
console.log(res); // 你的眉毛还好吗
使用说明:
如果第一个参数是空字符串,则会将新内容拼接到原字符串前面
【注】只会替换一次,替换最前面出现的替换部分
例:
var str = '你的头发还好吗';
// 使用"眉毛"将""替换掉
var res = str.replace("","眉毛");
console.log(res); // 眉毛你的头发还好吗
trim方法
去除字符串左右两边的空白
语法:
字符串.trim();
例:
var str = ' ab c ';
// 取出str左右两边的空白
var res = str.trim();
console.log(res); // 'ab c'
使用说明:
- 去除的是左右两边的空白,不会去除字符串中间的空白
- 只去除左边的空白使用:
trimLeft
方法;只去除右边的空白使用:trimRight
方法
toLowerCase 和 toUpperCase
将字符串中所有小写字母转为大写字母,使用:toUpperCase
方法
将字符串中所有小写字母转为大写字母,使用:toLowerCase
方法
语法:
字符串.toUpperCase(); # 转为大写
字符串.toLowerCase(); # 转为小写
var str = "hello"
// 使用 toUpperCase 转换成大写
var upper = str.toUpperCase()
console.log(upper) // HELLO
// 使用 toLowerCase 转换成小写
var lower = upper.toLowerCase()
console.log(lower) // hello
字符串的方法(了解)格式:字符串.函数名()
big() 用大号字体显示字符串
blink() 显示闪动字符串(IE下无效)
bold() 使用粗体显示字符串
fixed() 以打字机文本显示字符串
strike() 使用删除线来显示字符串
fontcolor() 使用指定颜色来显示字符串
fontsize() 使用指定尺寸来显示字符串
link() 将字符串显示为链接
sub() 把字符串显示为下标
sup() 把字符串显示为上标
document.write()中使用,用特殊的样式输出该字符串。
八、Math 和 Date
- Math 是 js 的一个内置对象,提供了一堆的方法帮助我们操作 数字
- Date 是 js 的一个内置对象,提供了一堆的方法帮助我们操作 时间
1、Math
- 没有什么多余的东西,就是一堆的方法来操作数字
random(生成随机数)
-
Math.random()
这个方法是用来生成一个0 ~ 1
之间的随机数 -
每次执行生成的数字都不一样,但是一定是
0 ~ 1
之间的 -
生成的数字包含 0 ,但是不包含 1
var num = Math.random() console.log(num) // 得到一个随机数
round(四舍五入)
-
Math.round()
是将一个小数 四舍五入 变成一个整数,并返回,原数据不发生改变var num = 10.1 console.log(Math.round(num)) // 10 console.log(num) // 10.1 var num2 = 10.6 console.log(Math.round(num2)) // 11 console.log(num2) // 10.6
abs(绝对值)
-
Math.abs()
是返回一个数字的绝对值,原数据不发生改变var num = -10 console.log(math.abs(num)) // 10 console.log(num) // -10
ceil(向上取整)
-
Math.ceil()
是将一个小数 向上取整 得到的整数返回,原数据不发生改变var num = 10.1 console.log(Math.ceil(num)) // 11 console.log(num) // 10.1 var num2 = 10.9 console.log(Math.ceil(num2)) // 11 console.log(num2) // 10.9
floor(向下取整)
-
Math.floor()
是将一个小数 向下取整 的到的整数返回,原数据不发生改变var num = 10.1 console.log(Math.floor(num)) // 10 console.log(num) // 10.1 var num2 = 10.9 console.log(Math.floor(num2)) // 10 console.log(num2) // 10.9
max(最大值)
-
Math.max()
得到的是你传入的几个数字之中最大的那个数字返回console.log(Math.max(1, 2, 3, 4, 5)) // 5
min(最小值)
-
Math.min()
得到的是你传入的几个数字之中最小的那个数字返回console.log(Math.min(1, 2, 3, 4, 5)) // 1
pow(幂运算)
-
Math.pow(x,y)
得到x的y次方console.log(Math.pow(2,3)) // 2的3次幂->8
sqrt(幂运算)
-
Math.sqrt(x,y)
得到x的y次根号幂console.log(Math.sqrt(8,3)) // 8的3次根号幂->2
PI(π)
-
Math.PI
得到的是π
的值,也就是3.1415936...
console.log(Math.PI) // 3.141592653589793
- 因为计算机的计算精度问题,只能得到小数点后 15 位
- 使用 Math.PI 的时候,是不需要加 () 的
数字转换进制
-
toString()
方法可以在数字转成字符串的时候给出一个进制数-
语法:
toString(你要转换的进制)
-
转换结果作为字符串类型返回,且原数据不发生改变
var num = 100 console.log(num.toString(2)) // 1100100 console.log(num.toString(8)) // 144 console.log(num.toString(16)) // 64
-
-
parseInt()
方法可以在字符串转成数字的时候把字符串当成多少进制转成十进制-
语法:
parseInt(要转换的字符串,当作几进制来转换)
-
转换结果作为数字类型返回,且原数据不发生改变,第二个参数可省略,默认值为10
var str = 100 console.log(parseInt(str, 8)) // 64 把 100 当作一个 八进制 的数字转换成 十进制 以后得到的 console.log(parseInt(str, 16)) // 256 把 100 当作 十六进制 的数字转换成 十进制 以后得到的 console.log(parseInt(str, 2)) // 4 把 100 当作 二进制 的数字转换成 十进制 以后得到的
-
2、Date
- js 提供的内置构造函数,专门用来获取时间的
new Date()
-
new Date()
在不传递参数的情况下是默认返回当前时间,构造函数创建时间,是一个对象类型var time = new Date() console.log(time) // 当前时间 Fri Mar 01 2019 13:11:23 GMT+0800 (中国标准时间)
-
new Date()
在传入参数的时候,可以获取到一个你传递进去的时间var time = new Date('2019-03-03 13:11:11') console.log(time) // Sun Mar 03 2019 13:11:11 GMT+0800 (中国标准时间)
-
new Date()
传递的参数有多种情况-
传递一个数字,表示毫秒数(从1970 年 1 月 1 日午夜(零时)开始计算)
// 类型使用自 CUT(Coordinated Universal Time,国际协调时间)1970 年 1 月 1 日午夜(零时)开始经过的毫秒数来保存 日期。Date 类型保存的日期能够精确到 1970 年 1 月 1 日之前或之后的 285616 年。 // 中国是东八区,所以在标准时间的基础上+8(中国标准时间)
var time = new Date(1000) // 从1970 年 1 月 1 日午夜(零时)开始计算经过1ms
console.log(time) // Thu Jan 01 1970 08:00:01 GMT+0800 (中国标准时间)-
传递两个数字,第一个表示年,第二个表示月份
var time = new Date(2019, 00) // 月份从 0 开始计数,0 表示 1月,11 表示 12月 console.log(time) // Tue Jan 01 2019 00:00:00 GMT+0800 (中国标准时间)
-
传递三个数字,前两个不变,第三个表示该月份的第几天,从 1 到 31
var time = new Date(2019, 00, 05) console.log(time) // Sat Jan 05 2019 00:00:00 GMT+0800 (中国标准时间)
-
传递四个数字,前三个不变,第四个表示当天的几点,从 0 到 23
var time = new Date(2019, 00, 05, 22) console.log(time) // Sat Jan 05 2019 22:00:00 GMT+0800 (中国标准时间)
-
传递五个数字,前四个不变,第五个表示的是该小时的多少分钟,从 0 到 59
var time = new Date(2019, 00, 05, 22, 33) console.log(time) // Sat Jan 05 2019 22:33:00 GMT+0800 (中国标准时间)
-
传递六个数字,前五个不变,第六个表示该分钟的多少秒,从 0 到 59
var time = new Date(2019, 00, 05, 22, 33, 55) console.log(time) // Sat Jan 05 2019 22:33:55 GMT+0800 (中国标准时间)
-
传入字符串的形式
console.log(new Date('2019')) // Tue Jan 01 2019 08:00:00 GMT+0800 (中国标准时间) console.log(new Date('2019-02')) // Fri Feb 01 2019 08:00:00 GMT+0800 (中国标准时间) console.log(new Date('2019-02-03')) // Sun Feb 03 2019 08:00:00 GMT+0800 (中国标准时间) console.log(new Date('2019-02-03 13:')) // Sun Feb 03 2019 13:00:00 GMT+0800 (中国标准时间) console.log(new Date('2019-02-03 13:13:')) // Sun Feb 03 2019 13:13:00 GMT+0800 (中国标准时间) console.log(new Date('2019-02-03 13:13:13')) // Sun Feb 03 2019 13:13:13 GMT+0800 (中国标准时间)
-
注意事项
1、若传入参数是数字,则需要用","隔开 2、若传入参数是字符串,则需要分隔符分开("-",","," "等) 3、若日期输入不合法,系统会自定转换为合法日期,如:4月31日 -》5月1日
-
+new Date()
// 变量名 = +new Date();获取毫秒值
var date = +new Date("2020-8-7"); //1596729600000
将日期字符串格式化成指定内容
- 比如我们得到的时间字符串是
Sun Feb 03 2019 13:13:13 GMT+0800 (中国标准时间)
- 我指向得到这个日期中是那一年,我们就要靠截取字符串的形式得到
- 但是现在 js 为我们提供了一系列的方法来得到里面的指定内容
- 返回值为数字类型
getFullYear
-
getFullYear()
方式是得到指定字符串中的哪一年var time = new Date(2019, 03, 03, 08, 00, 22) console.log(time.getFullYear()) // 2019
getMonth
-
getMonth()
方法是得到指定字符串中的哪一个月份var time = new Date(2019, 03, 03, 08, 00, 22) console.log(time.getMonth()) // 3
- 这里要有一个注意的地方
- 月份是从 0 开始数的
- 0 表示 1月,1 表示 2月,依此类推
getDate
-
getDate()
方法是得到指定字符串中的哪一天var time = new Date(2019, 03, 03, 08, 00, 22) console.log(time.getDate()) // 3
getHours
-
getHours()
方法是得到指定字符串中的哪小时var time = new Date(2019, 03, 03, 08, 00, 22) console.log(time.getHours()) // 8
getMinutes
-
getMinutes()
方法是得到指定字符串中的哪分钟var time = new Date(2019, 03, 03, 08, 00, 22) console.log(time.getMinutes()) // 0
getSeconds
-
getSeconds()
方法是得到指定字符串中的哪秒钟var time = new Date(2019, 03, 03, 08, 00, 22) console.log(time.getSeconds()) // 22
getMilliseconds
-
getMilliseconds()
方法是得到指定字符串中的哪毫秒var time = new Date() console.log(time.getMilliseconds())
getDay
-
getDay()
方法是得到指定字符串当前日期是一周中的第几天(周日是 0,周六是 6)var time = new Date(2019, 03, 08, 08, 00, 22) console.log(time.getDay()) // 1
getTime
-
getTime()
方法是得到执行时间到格林威治时间
的毫秒数var time = new Date(2019, 03, 08, 08, 00, 22) console.log(time.getTime()) // 1554681622000
获取时间差(getTime)
- 是指获取两个时间点之间相差的时间
- 在 js 中是不能用时间直接做 减法 的
- 我们需要一些特殊的操作
- 在编程的世界里面,有一个特殊的时间,是
1970年01月01日00时00分00秒
- 这个时间我们叫做
格林威治时间
- 所有的编程世界里面,这个时间都是一样的,而且
格林威治时间
的数字是 0 - 从
格林威治时间
开始,每经过1毫秒,数字就会 + 1 - 所以我们可以获取到任意一个时间节点到
格林威治时间
的毫秒数 - 然后在用两个毫秒数相减,就能得到两个时间点之间相差的毫秒数
- 我们在通过这个毫秒数得到准确的时间
计算时间差
- 例如:我们现在计算一下
2019-01-01 00:00:00
到2019-01-03 04:55:34
的时间差
-
先获取两个时间点到
格林威治时间
的毫秒数var time1 = new Date('2019-01-01 00:00:00') var time2 = new Date('2019-01-03 04:55:34') time1 = time1.getTime() time2 = time2.getTime() console.log(time1) // 1546272000000 console.log(time2) // 1546462534000
-
两个时间相减,得到两个时间点之间相差的毫秒数
var differenceTime = time2 - time1 console.log(differenceTime) // 190534000
- 现在我们计算出了两个时间点之间相差的毫秒数
-
把我们计算的毫秒数换算成时间
-
先计算出有多少天
-
以为一天是
1000 * 60 * 60 * 24
毫秒 -
用总的毫秒数除以一天的毫秒数,就能得到多少天了
var time1 = new Date('2019-01-01 00:00:00') var time2 = new Date('2019-01-03 04:55:34') time1 = time1.getTime() time2 = time2.getTime() var differenceTime = time2 - time1 // 计算整的天数 var day = differenceTime / (1000 * 60 * 60 * 24) // 2.20525462962963 day = Math.ceil(day) // 2
- 因为得到的是有小数的天数,我们向下取整,得到有多少个整的天数
-
使用
differenceTime
减去两天所包含的毫秒数,剩下的就是不够一天的毫秒数 -
用不够一天的毫秒数计算出有多少个小时
-
因为一个小时是
1000 * 60 * 60
毫秒 -
用不够一天的毫秒数除以一小时的毫秒数,就能得到多少小时了
var time1 = new Date('2019-01-01 00:00:00') var time2 = new Date('2019-01-03 04:55:34') time1 = time1.getTime() time2 = time2.getTime() var differenceTime = time2 - time1 // 计算整的天数 var day = differenceTime / (1000 * 60 * 60 * 24) // 2.20525462962963 day = Math.floor(day) // 2 // 计算整的小时数 var afterHours = differenceTime - (1000 * 60 * 60 * 24 * 2) var hours = afterHours / (1000 * 60 * 60) hours = Math.floor(hours) // 4
- 和刚才一样的道理,我们需要向下取整
-
同理,使用
afterHours
- 4个小时包含的毫秒数,剩下的就是不够一个小时的毫秒数 -
用不够一个小时的毫秒数计算出有多少分钟
-
因为一分钟是
1000 * 60
毫秒 -
用不够一个小时的毫秒数除以一分钟的毫秒数就能得到多少分钟了
var time1 = new Date('2019-01-01 00:00:00') var time2 = new Date('2019-01-03 04:55:34') time1 = time1.getTime() time2 = time2.getTime() var differenceTime = time2 - time1 // 计算整的天数 var day = differenceTime / (1000 * 60 * 60 * 24) // 2.20525462962963 day = Math.floor(day) // 2 // 计算整的小时数 var afterHours = differenceTime - (1000 * 60 * 60 * 24 * 2) var hours = afterHours / (1000 * 60 * 60) hours = Math.floor(hours) // 4 // 计算整分钟数 var afterMinutes = afterHours - (1000 * 60 * 60 * 4) var minutes = afterMinutes / (1000 * 60) minutes = Math.floor(minutes) // 55
-
和之前一样的道理计算出秒
var time1 = new Date('2019-01-01 00:00:00') var time2 = new Date('2019-01-03 04:55:34') time1 = time1.getTime() time2 = time2.getTime() var differenceTime = time2 - time1 // 计算整的天数 var day = differenceTime / (1000 * 60 * 60 * 24) // 2.20525462962963 day = Math.floor(day) // 2 // 计算整的小时数 var afterHours = differenceTime - (1000 * 60 * 60 * 24 * 2) var hours = afterHours / (1000 * 60 * 60) hours = Math.floor(hours) // 4 // 计算整分钟数 var afterMinutes = afterHours - (1000 * 60 * 60 * 4) var minutes = afterMinutes / (1000 * 60) minutes = Math.floor(minutes) // 55 // 计算整秒数 var afterSeconds = afterMinutes - (1000 * 60 * 55) var seconds = afterSeconds / 1000 seconds = Math.floor(seconds) // 34
-
最后,同理减去整秒的数,剩下的就是毫秒数
var time1 = new Date('2019-01-01 00:00:00') var time2 = new Date('2019-01-03 04:55:34') time1 = time1.getTime() time2 = time2.getTime() var differenceTime = time2 - time1 // 计算整的天数 var day = differenceTime / (1000 * 60 * 60 * 24) // 2.20525462962963 day = Math.floor(day) // 2 // 计算整的小时数 var afterHours = differenceTime - (1000 * 60 * 60 * 24 * 2) var hours = afterHours / (1000 * 60 * 60) hours = Math.floor(hours) // 4 // 计算整分钟数 var afterMinutes = afterHours - (1000 * 60 * 60 * 4) var minutes = afterMinutes / (1000 * 60) minutes = Math.floor(minutes) // 55 // 计算整秒数 var afterSeconds = afterMinutes - (1000 * 60 * 55) var seconds = afterSeconds / 1000 seconds = Math.floor(seconds) // 34 // 计算毫秒数 var milliSeconds = afterSeconds - (1000 * 34) // 0
-
最后我们把结果输出一下就可以了
document.write('2019-01-01 00:00:00 和 2019-01-03 04:55:34 之间相差') document.write(day + '天' + hours + '小时' + minutes + '分钟' + seconds + '秒' + milliSeconds + '毫秒')
-
日期格式化
date.toLocalString();//本地风格的日期格式
date.toLocaleDateString(); // 获取日期
date.toLocaleTimeString(); // 获取时间
date.toDateString();//以特定的格式显示星期几、月、日和年
date.toTimeString();//以特定的格式显示时、分、秒和时区
date.toUTCString();//以特定的格式显示完整的 UTC 日期
设置时间
date.setFullYear(2016) // 将日期对象中的年份设置为2016
date.setMonth(3) // 将日期对象中的月份设置为4月份
date.setDate(15) // 将日期对象中的日期设置为15号
date.setHours(12) // 将日期对象中的小时设置为12点
date.setMinutes(56) // 将日期对象中的分钟设置为56分
date.setSeconds(23) // 将日期对象中的描述设置为23秒
date.setTime(0) // 将日期对象设置为0的时间戳
3、补充
// innerText属性 不识别html标签 非标准 去除空格和换行(仅保留一个空格)
// box.innerText = '<strong>今天是:</strong> 2019';
// setInterval按照指定的周期(以毫秒计)来调用函数或计算表达式。刷新
setInterval(showNowTime,1000);//showNowTime函数,每1000毫秒(1秒)调用一次
JSON格式
所有对象的属性名必须是字符串,必须加引号
对象的最后一个元素后面不允许加逗号
js中对象:
var obj = {
name:"张三",
}
json中的对象:
{
“name“:”张三”
}
例:
[
{
"name":"手机",
"price":"¥1999",
"color":"red"
},
{
"name":"电脑",
"price":"¥3998",
"color":"green"
}
]