JavaScript基础
JavaScript基础
1- 初识JavaScript
1.1 JavaScript 是什么
-
JavaScript是一种运行在客户端的脚本语言,现基于Node.js技术进行服务端编程;
所谓脚本(Script)语言:是运行时不需要编译,运行过程中由 js 解释器( js 引擎)逐行来进行解释并执行。读到一行,执行一行;
-
目的是实现逻辑业务与页面控制,相当于动作;
所谓逻辑性:就是 实现这个要求的思路 先怎么做后怎么做;
1.2 JavaScript的作用
-
表单动态校验(密码强度检测) ( JS 产生最初的目的 )
-
网页特效
-
服务端开发(Node.js)
-
桌面程序(Electron)
-
App(Cordova)
-
控制硬件-物联网(Ruff)
-
游戏开发(cocos2d-js)
1.3 HTML/CSS/JS 的关系
HTML 和 CSS 属于描述类语言;JS 属于 编程类语言;
1.4 浏览器执行 JS 简介
浏览器分成两部分:渲染引擎和 JS 引擎
-
渲染引擎:用来解析HTML和CSS,俗称内核,比如 chrome浏览器的 blink,老版webkit等;
-
JS 引擎:也称 JS 解释器。用来读取网页中的 JavaScript代码,处理后运行,如chrome的V8;
浏览器本身并不会执行JS代码,而是通过内置 JavaScript 引擎(解释器) 来执行 JS 代码 。JS 引擎执行代码时逐行解释每一句源码(转换为机器语言),然后由计算机去执行,所以 JavaScript 语言归为脚本语言,会逐行解释执行。
1.5 JS 的组成
-
ECMAScript
ECMAScript:规定了JS的编程语法和基础核心知识,是所有浏览器厂商共同遵守的一套JS语法工业标准。
更多参看MDN: MDN手册
-
DOM——文档对象模型
文档对象模型(DocumentObject Model,简称DOM),是W3C组织推荐的处理可扩展标记语言的标准编程接口。通过 DOM 提供的接口可以对页面上的各种元素进行操作(大小、位置、颜色等)——元素对象;
-
BOM——浏览器对象模型
浏览器对象模型(Browser Object Model,简称BOM) 是指浏览器对象模型,它提供了独立于内容的、可以与浏览器窗口进行互动的对象结构。通过BOM可以操作浏览器窗口,比如弹出框、控制浏览器跳转、获取分辨率等——浏览器窗口;
1.6 JS 书写位置
JS 有3种书写位置,分别为行内、内嵌和外部。
1.行内式
<input type="button" value="点我" onclick="alert('Hello World')" />
-
可以将单行或少量 JS 代码写在HTML标签的事件属性中(以 on 开头的属性),如:onclick
-
注意单双引号的使用:在HTML中我们推荐使用双引号, JS 中我们推荐使用单引号
-
可读性差, 在html中编写JS大量代码时,不方便阅读;
2.内嵌式
<script> alert('Hello World~!'); </script>
-
可以将多行JS代码写到 script 标签中
-
内嵌 JS 是学习时常用的方式
3.外部JS文件
<script src="my.js"></script>
-
利于HTML页面代码结构化,把大段 JS代码独立到 HTML 页面之外,既美观,也方便文件级别的复用
-
引用外部 JS文件的 script 标签中间不可以写代码
-
适合于JS 代码量比较大的情况
<head> <meta charset="UTF-8"> <title>Document</title> <!-- 2.内嵌式的js --> <script> alert('这是我的第一个js'); </script> // 3.外部js的写法,开始和结束标签间不能写字 <script src="script.js"> </script> </head> <body> <!-- 1.行内式的js 直接写到元素内部,以on开头的属性 外双内单引号 --> <input type="button" value="提交" onclick="alert('提交成功')"> </body>
2 - JavaScript注释
JS中的注释主要有两种,分别是单行注释和多行注释。
1. 单行注释 // 用来注释单行文字( 快捷键 ctrl + / ) 2. 多行注释 /* */ 用来注释多行文字( 默认快捷键 alt + shift + a )
更改快捷键:vscode → 首选项按钮 → 键盘快捷方式 → 查找 原来的快捷键 → 修改为新的快捷键 → 回车确认
3 - JavaScript输入输出语句
为了方便信息的输入输出,JS中提供了一些输入输出语句,其常用的语句如下:
方法 | 说明 | 面向对象 |
---|---|---|
alert(msg) | 浏览器弹出警示框 | 用户 |
console.log(msg) | 浏览器控制台打印输出信息 | 程序员 |
prompt(info) | 浏览器弹出输入框,用户可以输入 | 用户 |
<script> // 1.弹出输入框 输入内容后默认弹出输入的内容 prompt('请输入你的年龄'); // 2.alert 弹出警示框 输出的 展示给用户的 alert('这是我的第一个js'); // 3.console 控制台输出打印信息 给程序员测试用的 浏览器f12控制台左手第二个 console.log('这是程序员能看到的'); </script>
程序设计基础
1 - 变量概述
1.1 什么是变量
-
为什么需要变量?有些数据需要保存,所以需要变量;
-
变量是什么?变量相当一个容器,用来存储数据;
-
本质?变量的本质是程序在内存中的一块存储空间;
-
通过变量名找到变量,访问内存;
-
变量的命名规范:见名知意-驼峰命名法;
1.2 - 变量的使用
-
变量的声明
-
变量的赋值
-
变量的初始化
1.声明变量
var age; // 声明一个名称为 age 的变量;本质是 在内存中申请一块存储空间
-
var 是一个 JS关键字,用来声明变量( variable 变量的意思 )。使用该关键字声明变量后,计算机会自动为变量分配内存空间,不需要程序员管;
-
age 是程序员定义的变量名,我们要通过 变量名来访问内存中分配的空间;
2.赋值
age = 10; // 给 age 这个变量赋值为 10
-
= 表示赋值,用来把右边的值赋给左边的变量空间
-
变量值是程序员保存到变量空间里的值
3.变量的初始化
声明一个变量的同时并赋值, 我们称之为变量的初始化。
var age = 18; // 声明变量同时赋值为 18
案例:
-
弹出一个输入框,提示用户输入姓名;
-
弹出一个对话框,输入 用户刚才输入的姓名;
<script> // 1.用户输入姓名 存储到一个myname的变量里 变量是存储容器 var myname = prompt('请输入姓名'); // 2.输出这个用户名 alert(myname); // alert('myname');加了单引号就显示不出变量名了 </script>
1.3 变量语法扩展
1.更新变量
变量被重新复赋值后,它原有的值就会被覆盖,变量值将以最后一次赋的值为准。
var age = 18; age = 81; // 最后的结果就是81 因为18 被覆盖掉了
2.同时声明多个变量
同时声明多个变量时,只需要写一个 var, 多个变量名之间使用英文逗号隔开。
var age = 10, name = 'zs', sex = 2;
3.声明变量特殊情况
情况 | 说明 | 结果 |
---|---|---|
var age ; console.log (age); | 只声明 不赋值 | undefined |
console.log(age) | 不声明 不赋值 直接使用 | 报错 |
age = 10; console.log (age); | 不声明 只赋值 | 10 可运行 |
案例:变量的语法扩展
<script> // 1.更新变量 变量被重新赋值后,以最新一次为准 var myname = '卡卡西'; console.log(myname); myname = '火影'; console.log(myname);//最新一次显示 火影 但之前的因为也输出了,也会有历史显示 // 2.声明多个变量,可简写 只需写一个var,变量名间逗号隔开,分号表结束 // var age = 18; // var address = '通辽'; // var sex = 'nv'; var age = 18, address = '通辽', sex = 'nv'; // 3. 声明变量的特殊情况 // 3.1 只声明 不赋值 结果是?undefined var sex; console.log(sex); // undefined // 3.2 不声明 不赋值 直接使用某个变量会报错 console.log('tel'); // 3.3 不声明直接赋值 js 可以使用 qq = 110; console.log(qq); // 110 </script>
案例:交换两个变量的值
js 是编程语言有很强的逻辑性在里面: 实现这个要求的思路 先怎么做后怎么做
// 思路:引入一个临时变量temp <script> var temp; var apple1 = '青苹果'; var apple2 = '红苹果'; temp = apple1; apple1 = apple2; apple2 = temp; console.log(apple1); console.log(apple2); </script>
1.4 变量命名规范
-
由字母(A-Za-z)、数字(0-9)、下划线(_)、美元符号( $ )组成,如:usrAge, num01, _name
-
严格区分大小写。var app; 和 var App; 是两个变量
-
不能 以数字开头。 18age 是错误的
-
不能 是关键字、保留字。例如:var、for、while
-
变量名必须有意义。 MMD BBD nl → age
-
遵守驼峰命名法。首字母小写,后面单词的首字母需要大写。
2 - 数据类型
2.1 数据类型简介
1.为什么需要数据类型?
在计算机中,不同的数据所需占用的存储空间是不同的,为了便于把数据分成内存所需的大小,充分利用存储空间,于是定义了不同的数据类型。
2.变量的数据类型?
变量的数据类型决定了以什么样的类型存储到计算机的内存中。JavaScript 是一种弱类型或者说动态语言。这意味着不用提前声明变量的类型;在程序运行过程中,变量的数据类型是由 JS引擎根据 = 右边变量值的数据类型来判断的。
var age = 10;// 这是一个数字型 var areYouOk = '是的';// 这是一个字符串
JavaScript 拥有动态类型,同时也意味着相同的变量可用作不同的类型:
var x = 6;// x 为数字 var x = "Bill";// x 为字符串
3.数据类型的分类
-
简单数据类型 (Number,String,Boolean,Undefined,Null)
-
复杂数据类型 (object)
2.2 简单数据类型
简单数据类型(基本数据类型)
简单数据类型 | 说明 | 默认值 |
---|---|---|
Number | 数字型,包含整形和浮点型,如21和0.21 | 0 |
String | 字符串型,加了引号的都是字符串 | “ ”、‘ ’ |
Boolean | 布尔值型,返回值true、false,等价于1和0 | false |
Undefined | var a;声明变量确没给值,此时a = undefined | undefined |
Null | var a = null;声明了变量a为空值 | null |
1、数字型 Number
<script> // 1.存储整形和浮点型 var age = 21; // 整数 var Age = 21.3747; // 小数 // 2.存储各进制数值 var num1 = 010; // 八进制 var num2 = 0xff; // 十六进制 // 3.数字型范围 三个特殊值 alert(Number.MAX_VALUE); // 最大值 alert(Number.MIN_VALUE); // 最小值 alert(Infinity); // 无穷大 alert(-Infinity); // 无穷小 alert(NaN); // not a number,代表一个非数值 console.log('Number.MAX_VALUE * 2'); // Infinity 无穷大 console.log('-Number.MAX_VALUE * 2'); // -Infinity 无穷小 console.log('pink老师' - 100);// NaN 非数值 // 4.isNaN() 判断 非数字类型 并且返回一个值 // 是数字返回 false 不是返回true console.log(isNaN(12)); // false console.log(isNaN(userName)); // true </script>
2、字符串型 String
(1)字符串型是引号内的任意文本,内部换行需要用转义字符 如 \ n
<script> // 嵌套原则:外双内单 或 外单内双; var str = '我是一个"高富帅"的程序员'; console.log(str); // 字符串转义字符 都是用 \ 开头 但是这些转义字符写到引号里面 var str1 = "我是一个'高富帅'的\n程序员"; console.log(str1); </script>
(2)字符串转义符
转义符 | 解释说明 |
---|---|
\n | 换行符,n 是 newline 的意思 |
\ \ | 斜杠 \ |
' | ' 单引号 |
" | ”双引号 |
\t | tab 缩进 |
\b | 空格 ,b 是 blank 的意思 |
(3)字符串拼接:
-
多个字符串之间可以使用 + 进行拼接, 字符串 + 任何类型 = 新字符串类型
-
+ 号总结口诀:数值相加 ,字符相连
<script> // 1. 检测获取字符串的长度 length var str = 'my name is andy'; console.log(str.length); // 15 // 2. 字符串的拼接 + 不同类型也可拼接 但最后是字符串型 // 数字型是结果 即:数值相加、字符相连 console.log('沙漠' + '骆驼'); // 字符串的 沙漠骆驼 console.log('pink老师' + 18); // 'pink老师18' console.log('pink' + true); // pinktrue console.log(12 + 12); // 24 console.log('12' + 12); // '1212' </script>
(4)字符串拼接加强
-
经常会将字符串和 变量 来拼接,变量可以很方便地修改里面的值
-
变量是不能添加引号的,因为加引号的变量会变成字符串
-
如果变量两侧都有字符串拼接,口诀“引引加加 ”,删掉数字,变量写加中间
<script> console.log('pink老师 18 岁'); //先写此句,然后删除18 引引加加 中间加变量 var age = 18; console.log('pink老师' + age + '岁');// 引引加加 </script>
案例:交互编程的三个基本要素
-
用户输入:弹出一个输入框prompt,让用户输入年龄;
-
程序内部处理:把用户输入的值作为变量保存起来,把刚才输入的年龄与所要输出的字符串拼接;
-
输出结果:使用alert语句弹出警示框;
案例:显示年龄案例
<script> var age = prompt('请输入你的年龄'); var str = '你今年已经' + age + '岁了'; alert(str); </script>
3、布尔型Boolean
-
布尔类型有两个值:true 和 false ,其中 true 表示真,而 false 表示假;
-
布尔型和数字型相加的时候, true 的值为 1 ,false 的值为 0;
console.log(true + 1); // 2 console.log(false + 1); // 1
4、Undefined 和 Null
-
一个声明后没有被赋值的变量会有一个默认值undefined ( 如果进行相连或者相加时,注意结果)
var variable; console.log(variable); // 只声明未赋值 输出 undefined console.log('你好' + variable); // 你好undefined console.log(11 + variable); // undefined 和数字相加 输出 NaN console.log(true + variable); // NaN
-
一个声明变量给 null 值,里面存的值为空(学习对象时,我们继续研究null)
var vari = null; console.log('你好' + vari); // 你好null console.log(11 + vari); // 11 console.log(true + vari); // 1
2.3 获取变量数据类型
1.typeof 获取检测变量的数据类型
<script> var num = 18; console.log(typeof num); // number var str = 'pink'; console.log(typeof str); // string var flag = true; console.log(typeof flag); // boolean var vari = undefined; console.log(typeof vari); // undefined var timer = null; console.log(typeof timer); // object // prompt 取过来的值是 字符型的 var age = prompt('请输入您的年龄'); console.log(age); console.log(typeof age); // string </script>
也可以通过控制台的颜色判断数据类型;黑色是字符串;
2.字面量
字面量表示如何表达这个值,一眼看上去知道这个属于什么类型的值。
<script> console.log(18);// 数字字面量 console.log('18');// 字符串字面量 console.log(true);// 布尔字面量 console.log(undefined); console.log(null); </script>
2.4 数据类型转换
什么是数据类型转换?就是把一种数据类型的变量转换成另一种数据类型,通常会实现3种方式的转换:
-
转换为字符串类型
-
转换为数字型
-
转换为布尔型
1.转换为字符串
方式 | 说明 | 案例 |
---|---|---|
加号拼接字符串 | 和字符串拼接的结果都是字符串 | var num = 1;alert(num + '我是字符串');也称隐式转换 |
toString( ) | 转成字符串 | var num = 1;alert(num.toString( )); |
String( )强制转换 | 转成字符串 | var num = 1;alert(String(num)); |
<script> // 1. 把数字型转换为字符串型变量 .toString() var num = 10; var str = num.toString(); console.log(str); console.log(typeof str); // 2. 我们利用 String(变量) console.log(String(num)); // 3. 利用 + 拼接字符串的方法实现转换效果 隐式转换 console.log(num + ''); </script>
2.转换为数字型(重点)
方式 | 说明 | 案例 |
---|---|---|
parseInt(string)函数 | 将string类型转换成整数数值型 | parseInt('78') |
parseFloat(string)函数 | 将string类型转换成浮点数值型 | parseFloat('78.21') |
Number()强制转换函数 | 将string类型转换成数值型 | Number('12') |
js隐式转换(- * /) | 利用算数运算隐式转换为数值型 | '12' - 0 |
<script> var age = prompt('请输入你的年龄'); // 1. parseInt(变量) 可以把字符型的转换成数字型 得到的是整数 console.log(parseInt(age)); console.log(parseInt('3.14')); // 整数 3 console.log(parseInt('120px')); // 整数 120 单位px被去掉 console.log(parseInt('rem120px')); // NaN 首字母检测不是数字 // 1. parseFloat(变量) 可以把字符型的转换成浮点型 得到的是浮点数 console.log(parseFloat('3.14')); // 3.14 console.log(parseFloat('120px')); // 单位也会去掉 // 3. Number(变量) var str = '123'; console.log(Number(str)); console.log(Number('12')); // 4. 利用了算术运算 - * / 隐式转换(不能 +) console.log('12' - 0); // 数字型 12,先把数字转为数字型在- console.log('123' - '120'); // 3 console.log('123' + '120'); // 123120 + 是字符串拼接, </script>
案例:输出年龄
思路:
-
弹出一个输入框(prompt),让用户输入出生年份(用户输入)
-
把用户输入的值用变量保存起来,用今年年份减去变量值,就是现在的年龄(程序内部处理)
-
弹出警示框(alert),把计算的结果输出(输出结果)
<script> var year = prompt('请输入你的出生年份'); var age = 2020 - year;// year是字符串 减法隐式转换 成数字型 alert('你今年已经 ' + age + ' 岁了'); </script>
案例:简单加法器
要求:计算两个数的值,用户输入第一个值后,继续弹出第二个输入框并输入第二个值,最后弹出窗口显示两次输入值相加的结果。
<script> var num1 = prompt('请输入第一个值:'); var num2 = prompt('请输入第二个值:'); var result = parseFloat(num1) + parseFloat(num2); alert('结果是:' + result); </script>
3.转换为布尔型
-
代表空、否定的值会被转换为 false ,如 ''、0、NaN、null、undefined ;
-
其余值都会被转换为 true;
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
3 - 标识符、关键字、保留字
3.1 标识符
标识(zhi)符:就是指开发人员 为变量、属性、函数、参数取的名字。 标识符不能是关键字或保留字。
3.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 等。
3.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 等。 注意:如果将保留字用作变量名或函数名,那么除非将来的浏览器实现了该保留字,否则很可能收不到任何错误消息。当浏览器将其实现后,该单词将被看做关键字,如此将出现关键字错误。
3.4 标识符命名规范
-
变量、函数的命名必须要有意义
-
变量的名称一般用名词
-
函数的名称一般用动词
-
操作符(=)、括号、左右各留一个空格;
注释后面打一个空格;
4 - 运算符(操作符)
4.1 运算符的分类
运算符(operator)也被称为操作符,是用于实现赋值、比较和执行算数运算等功能的符号。
JavaScript中常用的运算符有: - 算数运算符 + - * / % - 递增和递减运算符 ++ -- - 比较运算符 > < >= <= != == - 逻辑运算符 && || ! - 赋值运算符 =
4.2 算数运算符
1.算术运算符概述
概念:算术运算使用的符号,用于执行两个变量或值的算术运算。
运算符 | 描述 | 实例 |
---|---|---|
+ | 加 | 10+20=30 |
- | 减 | 10-20=-10 |
* | 减 | 10*20=200 |
/ | 除 | 10/20=0.5 |
% | 取余数(取模) | 返回除法的余数 9%2=1 |
2.浮点数的精度问题
浮点数值的最高精度是 17 位小数,但在进行算术计算时其精确度远远不如整数。
var result = 0.1 + 0.2; // 结果是:0.30000000000000004 console.log(0.07 * 100); // 结果是:7.000000000000001 // 所以:不要直接判断两个浮点数是否相等 !
3.表达式和返回值
表达式:是由数字、运算符、变量等组成的式子
表达式最终都会有一个结果,返回给开发者,称为返回值
4.3 递增和递减运算符
如果需要反复给数字变量+1或-1可以使用递增(++)和递减(--)运算符来完成。 在 JavaScript 中,递增(++)和递减(--)既可放在变量前,也可以放变量后面 前置递增和后置递增。 注意:前置递增和后置递增在单独使用时,效果是一样的;在表达式里,有所不同;
递增运算符
-
前置递增运算符 “++变量”:
使用口诀:先自加,后返回值 ++num——num = num + 1;
var num = 10; alert(++num + 10); // num = 11 11+10=21
-
后置递增运算符 “变量++”:
使用口诀:先原值运算,后自加 num++ —— num = num + 1 ;
var num = 10; alert(10 + num++); // num = 11 10+10=20
案例:递增运算符:
<script> var a = 10; ++a; // ++a 11 a = 11 var b = ++a + 2; // a = 12 console.log(b); // 14 var c = 10; c++; // c++ 11 var d = c++ + 2; // c++ = 11+2 c = 12 console.log(d); // 13 var e = 10; var f = e++ + ++e; // 1. e++ = 10 e = 11 2. e = 12 ++e = 12 console.log(f); // 10 + 12 = 22 // 后置自增 先表达式返回原值 后面变量再自加1 </script>
4.4 比较运算符
-
比较运算符概述
概念:比较运算符(关系运算符)是两个数据进行比较时所使用的运算符,比较运算后,会返回一个布尔值(true / false)作为比较运算的结果。
运算符名称 说明 案例 结果 < 小于号 1<2 true > 大于号 1>2 false >= 大于等于号 2>=2 true <= 小于等于号 2<=3 false == 判断号(会转型) 37==37 true != 不等号 37!=37 false === !== 全等 要求值和数据类型都一致 37==='37' false -
等号比较
符号 作用 用法 = 赋值 等号右侧的值赋给左侧 == 判断 判断两边的值是否相等(注意隐式转换) === 全等 判断两边的值和数据类型是否完全相同 实例:比较运算符
//1. 我们程序里面的 == 是判断两边值是否相等 console.log(3 == 5); // false console.log('pink老师' == '刘德华'); // flase console.log(18 == 18); // true console.log(18 == '18'); // true console.log(18 != 18); // false // 2. 我们程序里面有全等 一模一样 要求 两侧的值 还有 数据类型完全一致才可以 true console.log(18 === 18); console.log(18 === '18'); // false
4.5 逻辑运算符
-
逻辑运算符概述
逻辑运算符是用来进行布尔值运算的运算符,其返回值也是布尔值。
逻辑运算符 说明 案例 && "逻辑与" ’与‘ and true && false || "逻辑或" ’或‘ or true || false ! "逻辑非" ’非‘ not ! true 案例:逻辑运算符
<script> // 1. 逻辑与 && and 两侧都为true 结果才是 true 只要有一侧为false 结果就为false console.log(3 > 5 && 3 > 2); // false console.log(3 < 5 && 3 > 2); // true // 2. 逻辑或 || or 两侧都为false 结果才是假 false 只要有一侧为true 结果就是true console.log(3 > 5 || 3 > 2); // true console.log(3 > 5 || 3 < 2); // false // 3. 逻辑非 not ! console.log(!true); // false </script>
-
短路运算(逻辑中断)
逻辑运算符左边的表达式值可以确定结果时,就不再继续运算右边的表达式的值;
// 1.逻辑与 短路运算 //如果第一个表达式为真,则返回表达式2;如果第一个为假,则返回表达式1; console.log(123 && 456);//456 console.log(0 && 456 + 1 && 2);// 0 console.log('' && 1 + 2 && 456 * 56789); // '' // 空或者否定的为假 其余是真 0 ‘’ null undefined NaN 为假; // 2.逻辑或 短路运算 //如果表达式1 结果为真 则返回表达式1 如果结果为假,则返回表达式2 console.log(123 || 456);//123 console.log(0 && 456 + 1 && 2);//456 继续向后运行
4.6 赋值运算符
概念:用来把数据赋值给变量的运算符。
赋值运算符 | 说明 | 案例 |
---|---|---|
= | 直接赋值 | var name = '值'; |
+=、-= | 加、减一个数后在赋值 | var age = 10; age+=5; // 15 |
*=、/=、%= | 乘、除、取模后再赋值 | var age = 2; age*=5; // 10 |
案例:赋值运算符
var age = 10; age += 5; // 相当于 age = age + 5; age -= 5; // 相当于 age = age - 5; age *= 10; // 相当于 age = age * 10;
4.7 运算符优先级
优先级 | 运算符 | 顺序 |
---|---|---|
1 | 小括号 | ( ) |
2 | 一元运算符 | ++ -- ! |
3 | 算术运算符 | 先 * / % 后 + - |
4 | 关系运算符 | > >= < <= |
5 | 相等运算符 | == != === !== |
6 | 逻辑运算符 | 先 && 后 || |
7 | 赋值运算符 | = |
8 | 逗号运算符 | , |
-
一元运算符里面的逻辑非优先级很高
-
逻辑与比逻辑或优先级高
5 - 流程控制
5.1 流程控制概念
流程控制就是来控制代码按照一定结构顺序来执行 流程控制主要有三种结构:顺序结构、分支结构、循环结构
5.2 顺序流程控制
特点:从上到下,依次执行
5.3 分支流程控制
特点:根据不同的条件,执行不同的路径代码(多选一的过程)得到不同的结果;
JS 语言提供了两种分支结构语句:if 语句、switch 语句
5.4 if 语句
// 1. if语句 // 条件表达式成立 则执行代码,否则什么也不做 if (条件表达式) { // 条件成立执行的代码语句 } // 2. if else 双分支语句 // 分支语句 2选1过程 最终只有一条语句执行 if (条件表达式) { 语句1;//如果条件成立则执行语句1 } else { 语句2 };//条件不成立执行语句2 // 3. 多分支语句 // 最后也是只有一个语句执行 else if任意多,都不成立执行 else if (条件表达式1) { 语句1; } else if (条件表达式2) { 语句2; } else { 最后的语句; } // 4. 三元表达式 条件表达式 ?表达式1 :表达式2 // 如果条件表达式为真,则返回表达式1,否则返回表达式2,表达式有返回值 var num = 10; var result = num > 5 ? '是的' : '不是的'; // 我们知道表达式是有返回值的 console.log(result); // if (num > 5) { // result = '是的'; // } else { // result = '不是的'; // }
案例:判断是否闰年 (if ...else...)
// 算法:能被4整除且不能整除100的为闰年,或者能够被400整除的就是闰年 <script> var year = prompt('请您输入年份:'); if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) { alert('您输入的年份是闰年'); } else { alert('您输入的年份是平年'); } </script>
案例:判断成绩级别 (if ...else if ...else...)
// 思路:从大到小的顺序,否则 就都输出了 <script> var score = prompt('请您输入分数:'); if (score >= 90) { alert('宝贝,你是我的骄傲'); } else if (score >= 80) { alert('宝贝,你已经很出色了'); } else if (score >= 70) { alert('你要继续加油喽'); } else if (score >= 60) { alert('孩子,你很危险'); } else { alert('熊孩子,我不想和你说话,我只想用鞭子和你说话'); </script>
案例:数字补0案例 (条件表达式 ? 表达式1 : 表达式2)
// 思路:用户输入一个0-59之间的数字,如果小于10,在这个数字前面补0(加0 拼接) <script> var time = prompt('请您输入一个 0 ~ 59 之间的一个数字'); // 三元表达式 表达式 ? 表达式1 :表达式2 var result = time < 10 ? '0' + time : time; alert(result); </script>
5.5 switch分支流程控制
-
switch :开关 转换 , case :小例子 选项
-
关键字 switch 后面括号内可以是表达式或值, 通常是一个变量,不用数值;
-
如果表达式与case后面得值 存在匹配全等(===) ,则与该 case 关联的代码块会被执行,并在遇到 break 时停止,整个 switch 语句代码执行结束
-
如果所有的 case 的值都和表达式的值不匹配,则执行 default 里的代码
-
注意: 执行case 里面的语句时,如果没有break,则继续执行下一个case,不会退出switch
特点:switch后面的表达式是 固定值,通常是变量,优点是可以直接跳转到特定的case语句;
// 思路:利用我们的表达式的值 和 case 后面的选项值相匹配 如果匹配上,就执行该case 里面的语句 如果都没有匹配上,那么执行 default里面的语句 switch(表达式) { case value1: 执行语句1; break; case value2: 执行语句2; break; default: 最后的语句; }
案例:查询水果价格 switch()
// 弹出 prompt 输入框,让用户输入水果名称,把这个值取过来保存到变量中。 // 将这个变量作为 switch 括号里面的表达式。 // case 后面的值写几个不同的水果名称,注意一定要加引号 ,因为必须是全等匹配。 // 弹出不同价格即可。 var fruit = prompt('请您输入查询的水果:'); switch (fruit) { case '苹果': alert('苹果的价格是 3.5/斤'); break; case '榴莲': alert('榴莲的价格是 35/斤'); break; default: alert('没有此水果'); }
5.5 switch 语句和 if else if 语句的区别
-
一般情况下,它们两个语句可以相互替换
-
switch用于处理case比较确定的情况,如固定值的;进行条件判断后直接执行到程序的条件语句,效率更高;
-
if else更加灵活,常用于范围判断(大于 小于);但if else有几种条件就判断多少次;分支较少时效率较高;
6 - 循环
循环的目的:可以重复执行某些代码
JS三种循环结构:
-
for循环:常用于 计数
-
while循环:复杂一点的条件判断,比for灵活
-
do...while循环:比while严谨
三个循环很多情况可以相互转换;
6.1 for循环
重复执行某些代码,通常和计数有关系
// 1. 语法结构 for (初始化变量; 条件表达式; 操作表达式) { //循环体 } //1.初始化变量 就是用 var声明一个普通变量,常用于作为计数器 //2.条件表达式 用来决定每一次循环是否继续执行 终止的条件 //3.操作表达式 每次循环最后执行的代码 常用于计数器变量递增减 for (var i = 1; i <= 100; i++) { console.log('你好吗'); } //1.先赋初值 var i = 1 整个循环只执行一次 //2.在执行 i <= 100 条件成立执行循环语句 不成立跳出循环 //3.条件成立的话 接下来执行console.log('') //4.最后执行i++ i++是单独写的代码 递增 第一轮结束 //5.接着执行 i <= 100 如果满足条件 就去执行循环体 不满足条件退出循环 第二轮
for循环执行方式
<script> // 1.for循环 重复执行相同代码 // 让用户 控制 输入的次数 var num = prompt('请输入次数'); for (var i = 1; i <= num; i++) { alert('hello world'); // console.log('hello world'); } // 2.for循环 重复执行不同的代码 因为我们有计数器变量 i 的存在 i每次循环值都会变化 // 计数器 输出一个人 1~100岁 for (var i = 1; i <= 100; i++) { console.log('这个人今年' + i + '岁了'); } </script>
案例:有关for循环的算法
<script> // 1. 求 1~100 之间的整数累加和 算法:sum = sum + i 5050; var sum = 0;// 求和变量 初始值为0 for (var i = 1; i <= 100; i++) { // sum = sum + i; sum += i; } console.log(sum); // 2. 求1~100间的所有数的平均值 需要一个 sum 和的变量 还需要一个平均值 average 的变量 50.5 var sum = 0; var average = 0; for (var i = 1; i <= 100; i++) { sum = sum + i; // sum += i; } average = sum / 100; console.log(average); // 3. 求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); </script>
案例:求学生成绩案例
<script> // 思路: // 1. 弹出输入框输入总得班级人数(num) // 2. 依次输入学生成绩并保存(score) // 3. for循环 弹出的次数与班级总人数之间的关系 i <= num // 4. 先求总成绩 sum ,之后求平均成绩 average 弹出结果 var num = prompt('请输入班级的总人数');// num 总的班级人数 var sum = 0; var average = 0; for (var i = 1; i <= num; i++) { var score = prompt('请输入第' + i + '个学生成绩'); sum = sum + parseFloat(score); } average = sum / num; alert('班级总成绩是' + sum); alert('班级的平均分是' + average); </script>
案例:打印五角星
<script> // 一行打印五个星星 // console.log('★★★★★'); // 循环打印5次 // for (var i = 1; i <= 5; i++) { // console.log('★'); // } // 1.一行打印五颗星星 追加字符串的方法-是一行打印多少个,不是循环多少次一行一个 // var str = ''; // for (i = 1; i <= 5; i++) { // str = str + '★'; // } // 2.取决于用户输入 var num = prompt('请输入星星的个数'); var str = ''; for (i = 1; i <= num; i++) { str = str + '★'; } console.log(str); </script>
双重for循环
双重for循环:
<script> // 1.语法结构 for (外层的初始化变量; 外层的条件表达式; 外层的操作表达式) { for (里层的初始化变量; 里层的条件表达式; 里层的操作表达式) { 执行语句; } } // 内层循环可以看做外层循环的循环体语句 // 外层循环执行一次,内层循环 执行全部 // 总共执行了 i*j 次 for (var i = 1; i <= 3; i++) { console.log('这是外层循环第' + i + '次'); for (var j = 1; j <= 3; j++) { console.log('这是内层循环第' + j + '次'); } } </script>
案例:打印n行n列五角星
<script> var rows = prompt('请你输入行数:'); var cols = prompt('请你输入列数:'); var str = ''; for (var i = 1; i <= rows; i++) { // 外层循环负责 打印i行 for (var j = 1; j <= cols; j++) { // 内层循环负责 一行打印j个 str = str + '★'; } // 如果一行打印完毕j个星星就要另起一行 加 \n str = str + '\n'; // 字符串拼接 追加字符串 } console.log(str); </script>
案例:打印 倒三角
<script> var str = ''; for (var i = 1; i <= 10; i++) { //外层循环控制行数 for (var j = i; j <= 10; j++) { //内层循环打印个数不一样 j=i=1,从1~10打印10个 str = str + '★'; } // 如果一行打印完毕j个星星就要另起一行 加 \n str = str + '\n'; } console.log(str); </script>
案例:打印九九乘法表(正三角)
// 一共有9行,但是每行的个数不一样,因此需要用到双重 for 循环 // 外层的 for 循环控制行数 i ,循环9次 ,可以打印 9 行 // 内层的 for 循环控制每行公式 j // 核心算法:每一行 公式的个数正好和行数一致, j <= i; // 每行打印完毕,都需要重新换一行
<script> str = ''; for (i = 1; i <= 9; i++) { for (j = 1; j <= i; j++) { // str = str + '★'; // str += i + 'x' + j + '=' + i * j; str += j + 'x' + i + '=' + i * j + '\t'; //为了符合列匹配关系 } str = str + '\n'; } console.log(str); </script>
for 循环小结
-
for 循环可以重复执行某些相同代码
-
for 循环可以重复执行些许不同的代码,因为我们有计数器
-
for 循环可以重复执行某些操作,比如算术运算符加法操作
-
双重 for 循环,外层循环一次,内层 for 循环全部执行
-
for 循环是循环条件和数字直接相关的循环
断点调试:
-
浏览器中f12打开调试器窗口
-
单击某条语句设置断点,并刷新浏览器
-
右上角 步进 进行一步步调试,看程序怎样运行的
6.2 while循环
while语句的语法结构如下:
使用 while 循环时一定要注意,它必须要有退出条件,否则会成为死循环
<script> // 1. while 循环语法结构 while 当...的时候 // 2.执行思路 当条件表达式为true时 执行循环体 否则 退出循环 while (条件表达式) { 循环体 } // 3.代码验证 var num = 1;// 初始化变量 计数器 while (num <= 100) { console.log('hello'); num++; // 操作表达式 完成计数器的更新 防止死循环 不加限制会变成死循环 一定要有退出条件 } // 转换写法 for (num = 1; num <= 100; num++) { console.log('hello'); } </script>
案例:while循环 输出人的年龄
<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 = sum + j; j++; } console.log(sum); // 3.弹出一个提示框,你喜欢我么? 如果输入喜欢,就提示结束,否则 一直询问 var message = prompt('你喜欢我么?'); while (message !== '喜欢') { message = prompt('你喜欢我么'); } alert('我也喜欢你啊'); </script>
6.3 do-while循环
比while更简单一些;
while是先判断后循环;do...while是先执行,后判断,至少执行一次;
<script> // 1.语法结构 先循环,在判断,至少执行一次 do { //循环体 } while (条件判断); // 2.代码 var i = 1; do { console.log('how are you'); i++; } while (i <= 100) do { var message = prompt('你喜欢我么?'); } while (message !== '喜欢') alert('我也喜欢你啊'); </script>
6.4 continue、break
1.continue 关键字用于立即跳出本次循环
继续下一次循环(本次循环体中 continue 之后代码会少执行一次)
案例:吃5个包子,第3个有虫子,就扔掉第3个,继续吃第4个第5个包子,代码实现如下
for (var i = 1; i <= 5; i++) { if (i == 3) { console.log('这个包子有虫子,扔掉'); continue; // 跳出本次循环,跳出的是第3次循环 } console.log('我正在吃第' + i + '个包子呢'); } //1. 求 1~100 之间,除了能被7整除之外的 整数和 var sum = 0; for (var i = 1; i <= 100; i++) { if (i % 7 == 0) { continue;// 退出本次循环 直接跳到 i++ } sum += i; console.log(sum); } </script>
2.break 关键字用于立即跳出整个循环(循环结束)
案例:吃5个包子,吃到第3个发现里面有半个虫子,其余的不吃了,其代码实现如下
for (var i = 1; i <= 5; i++) { if (i == 3) { break; // 直接退出整个for 循环,跳到整个for下面的语句 } console.log('我正在吃第' + i + '个包子呢'); }
7 - 数组
为什么需要数组?
普通变量一次只能存一个值;数组(Array)是一组数据的集合,一次可以存多个值;
7.1 数组的概念
数组是指一组数据的集合,其中的每个数据被称作元素,在数组中可以存放任意类型的元素。
7.2 创建数组
JS 中创建数组有两种方式:
-
利用new 关键字 创建数组(对象)
var 数组名 = new Array() ; var arr = new Array(); // 创建一个新的空数组
-
利用数组字面量创建数组
var 数组名 = []; // 使用数组字面量方式创建带初始值的数组 数组类型不限 var 数组名 = [1,'pink',true];// 数组的初始化
7.3 获取数组中的元素
索引 (下标) :用来访问数组元素的序号(数组下标从 0 开始)。
数组可以通过索引来访问、设置、修改对应的数组元素,可以通过“数组名[索引]”的形式来获取数组中的元素。
// 4. 我们数组里面的数据一定用逗号分隔 // 5. 数组里面的数据 比如1,2, 我们称为数组元素 // 6. 获取数组元素 格式 数组名[索引号] 索引号从 0开始 console.log(arr1); console.log(arr1[1]); // pink老师 console.log(arr1[2]); // true
注意:如果访问时数组没有和索引值对应的元素,则得到的值是undefined
7.4 遍历数组
把数组中的每个元素 从头到尾 都访问一次(类似学生的点名)称为遍历数组;
for循环中的 i 是计数器,当索引号使用,arr[i] 是数组元素 第i个数组元素,索引号从0开始
<script> // 1.数组索引 访问数组中某个元素 var arr = ['red', 'green', 'blue']; console.log(arr[0]);// red // 2.遍历数组 通过for循环访问数组所有元素 // 因为数组索引号从0开始,所以i必须从0开始 i < 3 // 输出的时候 arr[i] i 计数器 当索引号来用 var arr = ['red', 'green', 'blue']; for (var i = 0; i < arr.length; i++) { console.log(arr[i]); } // 数组名.length 可以直接获取数组长度 动态监测数组元素的个数 console.log(arr.length);// 此处数组的长度是数组元素的个数,并非索引 </script>
案例:求数组里面所有元素的和及平均值
<script> // 1.声明一个求和变量 sum // 2.遍历这个数组,把里面每个数组元素 加到sum 里 // 3.用求和变量 sum 除以数组的长度得到数组的平均值 var arr = [2, 4, 1, 7, 4]; var sum = 0; var average = 0; for (i = 0; i < arr.length; i++) { // sum+=i;// 加的不是计数器,是数组里的元素 sum += arr[i]; } average = sum / arr.length; console.log('这组数的和是:' + sum); console.log('这组数的平均值是:' + average); console.log(sum, average); // 想要输出多个变量,用逗号分隔即可 </script>
案例:求数组 [2,6,1,77,52,25,7] 中的最大值
<script> // 1.声明一个求和变量 max 默认最大值可以取数组中的第一个元素 // 2.遍历这个数组,把里面每个数组元素和 max 相比较 // 3.如果这个数组元素大于max 就把这个数组元素存到 max 里面,否则继续下一轮比较。 var arr = [2, 6, 1, 77, 52, 25, 7]; var max = arr[0];// 将数组第一个值赋值给max for (i = 1; i < arr.length; i++) { if (arr[i] > max) { max = arr[i]; } } console.log('该数组里最大的是:' + max); </script>
案例:将数组元素转换为字符串,中间用任意字符相连
// 将数组 ['red', 'green', 'blue', 'pink'] 转换为字符串,并且用 | 或其他符号分割 // 1.需要一个新变量用于存放转换完的字符串 str。 // 2.遍历原来的数组,分别把里面数据取出来,加到字符串里面。 // 3.同时在后面多加一个分隔符 <script> var arr = ['red', 'green', 'blue', 'pink']; var str = ''; var sep = '|'; for (i = 1; i < arr.length; i++) { str += arr[i] + sep; } console.log(str); </script>
注意:
-
此处数组的长度是数组元素的个数 ,不是数组的索引号(下标号)。
-
当我们数组里面的元素个数发生了变化,这个 length 属性跟着一起变化;数组的length属性可以被修改:
-
如果设置的length属性值大于数组的元素个数,则会在数组末尾出现空白元素;
-
如果设置的length属性值小于数组的元素个数,则会把超过该值的数组元素删除
7.5 数组中新增元素
1、通过修改length长度新增数组元素,通过length长度实现数组的扩容
2、通过修改数组索引新增数组元素,追加数组元素
<script> // 1.新增数组元素 修改length长度 var arr = ['red', 'green', 'blue']; console.log(arr.length); arr.length = 5;// 数组长度修改为5 里面应该有5个元素 console.log(arr);// 后面两个是空的 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>
案例:数组存放0~10个值,循环追加的方式输出
<script> var arr = [];// 定义一个空数组 for (var i = 0; i < 10; i++) {// 遍历数组 // arr=i;// 不要直接给数组名赋值 否则以前的元素都没了 arr[i] = i + 1;// i是数组下标 下标为0的数组对应着 第一个数组元素 } console.log(arr); </script>
案例:筛选数组 筛选数组中大于10的数存入新数组
<script> // 方法一 var arr = [1, 2, 3, 4, 5, 6, 7, 8, 19, 10]; var newArr = [];// 声明一个新的数组存放新数据 var j = 0;// 方法1 声明一个新变量 for (var i = 0; i < arr.length; i++) { if (arr[i] >= 10) { // 新数组索引号应该从0开始 依次递增 newArr[j] = arr[i]; // 在旧数组里找出大于等于10的元素 依次追加给新数组 j++; } } console.log(newArr); // 方法二 var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; var newArr = [];// 声明一个新的数组存放新数据 // 刚开始 newArr.length 就是0 for (var i = 0; i < arr.length; i++) { if (arr[i] >= 10) { // 新数组索引号应该从0开始 依次递增 newArr[newArr.length] = arr[i]; } } console.log(newArr); </script>
案例:删除数组指定元素,数组去重 删除数组中的0
// 1、需要一个新数组用于存放筛选之后的数据。 // 2、遍历原来的数组, 把不是 0 的数据添加到新数组里面(此时要注意采用数组名 + 索引的格式接收数据)。 // 3、新数组里面的个数, 用 length 不断累加。 <script> var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; var newArray = []; for (var i = 0; i < arr.length; i++) { if (arr[i] != 0) { newArray[newArray.length] = arr[i]; } } console.log(newArray); </script>
案例:翻转数组 将数组中的内容反过来存放
// 1、声明一个新数组 newArr // 2、把旧数组索引号第4个取过来(arr.length - 1),给新数组索引号第0个元素 (newArr.length) // 3、我们采取 递减的方式 i-- // 思路:把 旧数组 的 最后一个元素 取出来给 新数组 作为第一个 (递减) <script> var arr = ['red', 'green', 'blue', 'pink', 'purple']; var newArr = []; for (var i = arr.length - 1; i >= 0; i--) { newArr[newArr.length] = arr[i]; } console.log(newArr); </script>
案例:数组排序 交换相邻两个变量(冒泡排序)
冒泡排序:一种算法,把一系列数据按照一定的顺序排列,依次比较相邻两个元素;
<script> var arr = [5, 4, 3, 2, 1]; for (var i = 0; i <= arr.length - 1; i++) { // 外层交换趟数 5个元素交换4趟 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>
8 - 函数
8.1 函数的概念
函数:就是封装了一段可被重复调用执行的代码块。
通过此代码块可以实现大量代码的重复使用。
8.2 函数的使用
函数使用分为两步: 声明函数 和 调用函数;
// 1.声明函数 函数名 命名为动词 // (1) function 声明函数的关键字 全部小写 // (2) 函数是做某件事情,函数名一般是动词 sayHi // (3) 函数不调用自己不执行 function 函数名() { //函数体代码 }
// 2.调用函数 函数名(); // 通过调用函数名来执行函数体代码 函数不调用 自己不执行 function sayHi() { console.log('hi~~'); } sayHi();
注意:声明函数本身并不会执行代码,只有调用函数时才会执行函数体代码。
案例:利用函数封装计算1-100累加和
// 1.声明函数 function getSum(num1,num2) { var sum = 0;// 准备一个变量,保存数字和 for (var i = num1; i <= num2; i++) { sum += i;// 把每个数值 都累加 到变量中 } alert(sum); } // 2.调用函数 getSum(1,100);
8.3 函数的参数
-
形参:形式上的参数 声明函数时定义 可看做不用声明的变量
-
实参:实际上的参数 函数调用时传递的 最终实参传递给形参
函数参数的运用:
// 1.函数声明 声明形参 function 函数名(形参1, 形参2, 形参3...) { // 函数体 } // 2.函数调用 调用实参 函数名(实参1, 实参2, 实参3...); // 声明函数 function getSum(num1, num2) { console.log(num1 + num2); } // 调用函数 getSum(1, 3); // 4 先将实参传递给形参 在执行函数体 getSum(6, 5); // 11
函数形参和实参数量不匹配时
参数个数 | 说明 |
---|---|
实参个数等于形参个数 | 输出正确结果 |
实参个数多于形参个数 | 值取到形参个数 |
实参个数小于形参个数 | 多的形参定义为undefined,结果NaN |
注意:在JavaScript中,形参的默认值是undefined。
案例:函数的执行
// 1.函数可以重复相同的代码 function cook() { console.log('hello'); } cook(); // 2.也可以利用函数的参数 实现函数重复不同的代码 function 函数名(形参1,形参2...) { // 声明的小括号里是形参 形式上的 } 函数名(实参1,实参2...);// 函数调用的小括号里是实参 实际的 function cook(aru) { // 形参是接收实参的 aru='hello' 相当于一个不用声明的变量 console.log(aru); } cook('hello');// 形参和实参个数尽量相匹配 // 1.利用函数求任意两个数之间的和 function getSum(num1,num2) { console.log(num1 + num2); } getSum(1, 3); getSum(2, 6);
// 2.利用函数求任意两个数之间的累加和 function getSum(start, end) { var sum = 0; for (var i = start; i <= end; i++) { sum += i; } console.log(sum); } getSum(1, 100);
8.4 函数的返回值return
return 语句
函数只是用来做某件事或实现某种功能,最终的结果需要返回给函数的调用者; 只要函数遇到return 就把后面的结果 返回给函数的调用者 函数名()= return + 后面
// 声明函数 function 函数名(){ ... return 需要返回的值; } // 调用函数 函数名();// 此时调用函数就可以得到函数体内return 后面的值 // 声明函数 function sum(){ ... return 666; } // 调用函数 sum(); // 此时sum = 666,return 语句会把自身后面的值返回给调用者
-
在使用 return 语句时,函数会停止执行,并返回指定的值
-
如果函数没有 return ,返回的值是 undefined
// 1.利用函数求任意两个数之和 function getResult(num1,num2) { return num1 + num2; } //getResult();// getResult = num1+num2 console.log(getResult(1,2)); // 2.利用函数求两个数中最大值 function getMax(num1,num2) { // if (num1 > num2) { // return num1; // } else { // return num2; return num1 > num2 ? num1 : num2; } console.log(getMax(1, 3)); // 3.利用函数求数组中的最大值 function getArrMax(arr) { // arr接收一个数组 var max = arr[0]; for (var i = 1; i<=arr.length; i++) { if (arr[i] > max) { max = arr[i]; } } return max; } // getArrMax([1,2,3,4,5]);// 实参是一个数组 // 实际开发中,常用一个变量 来接收 函数的返回结果 var re = getArrMax([1,2,3,4,5]); console.log(re);
return函数注意事项:
// 1.return 终止函数 function getSum(num1, num2) { return num1 + num2; alert('这条语句不被执行');//return结束,后面的代码不被执行 } // 2.return 只能返回一个值 function fn(num1, num2) { return num1, num2;// return返回的结果是最后一个值 num2 } console.log(fn(1, 2)); // 3.求任意两个数的 加减乘除结果 function getResult(num1, num2) { // 想要输出多个值return 可以返回数组 return [num1 + num2, num1 - num2, num1 * num2, num1 / num2]; } var re = getResult(1, 2); console.log(re); // 4. 我们的函数如果有return 则返回的是 return 后面的值,如果函数么有 return 则返回 undefined console.log(fun1()); // 返回 666 function fun2() { } console.log(fun2()); // 函数返回的结果是 undefined
退出循环
break ,continue ,return 的区别
-
break :结束当前的循环体(如 for、while)
-
continue :跳出本次循环,继续执行下次循环(如 for、while)
-
return :不仅可以退出循环,还能够返回 return 语句中的值,同时还可以结束当前的函数体内的代码
8.5 arguments的使用
当不确定有多少个参数传递的时候,可以用 arguments 来获取。
arguments对象中存储了传递的所有实参,是当前函数的一个内置对象,函数独有的;
<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); // 伪数组 并不是真正意义上的数组 // 1. 具有数组的 length 属性 // 2. 按照索引的方式进行存储的 // 3. 它没有真正数组的一些方法 pop() push() 等等 </script>
注意:在函数内部使用该对象,用此对象获取函数调用时传的实参。
案例:利用函数求任意个数的最大值
<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> // 1.利用函数封装方法 翻转任意数组 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, 2, 3, 4, 5]); console.log(arr1); // 2.利用函数封装的方法,对数组排序--冒泡排序 function sort(arr) { for (var i = 0; i < arr.length - 1; i++) { for (var j = 0; j < arr.length - i - j; j++) { if (arr[j] > arr[j + 1]) { var temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } return arr; } var arr2 = sort([1, 2, 3, 4, 5]); console.log(arr2); // 3.判断闰年 function isRunYear(year) { // 如果是闰年返回 true 否则返回false var flag = flase; if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) { flag = true; } return flag; } console.log(isRunYear(2000)); console.log(isRunYear(1999)); </script>
函数之间可以相互调用:
函数内部可以调用另一个函数;
<script> // 函数是可以相互调用的 // function fn1() { // console.log(11); // fn2(); // 在fn1 函数里面调用了 fn2 函数 // } // fn1(); // function fn2() { // console.log(22); // } </script>
在同一作用域代码中,函数名即代表封装的操作,使用函数名加括号即可以将封装的操作执行。
案例:输出当年年的2月份天数
<script> // 用户输入年份,输出当年年的2月份天数 function backDay() { var year = prompt('请您输入年份'); if (isRunYear(year)) { alert('当前年份是闰年 2月份有29天'); } else { alert('当前年份是平年 2月份有28天'); } } backDay(); // 判断是否为闰年的函数 function isRunYear(year) { var flag = false; if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) { flag = true; } return flag; } </script>
8.6 函数的两种声明方式
1、自定义函数方式(命名函数)
利用函数关键字 function 自定义函数方式
// 声明定义方式 function fn() {...} // 调用 调用函数的代码既可以放到声明函数的前面,也可以放在声明函数的后面 fn();
2、函数表达式方式(匿名函数)
// var 变量名 = function () { } var fun = function () { console.log('我是函数表达式'); } fun();
-
fun是变量名 不是函数名
-
函数表达式 声明方式和 声明变量差不多,只不过变量里存的是值 而 函数表达式里存的是函数
-
函数调用的代码必须写到函数体后面
-
函数表达式也可以进行传递参数
9 - 作用域
9.1 作用域概述
作用域:变量能够起作用和效果的 某个范围 目的:为了提高程序的可靠性 更重要的作用是减少命名冲突 全局作用域和局部作用域命名不冲突
9.2 作用域的分类
JavaScript(es6前)中的作用域有两种:
-
全局作用域
-
局部作用域(函数作用域)
1.全局作用域
作用于所有代码执行的环境(整个script标签内部)或独立的js文件,或者var声明的。 如果在函数内部没有声明,直接赋值的变量也属于全局变量,一般不用console.log(); 全局变量只有浏览器关闭时才会结束,占资源;
2.局部作用域
作用于函数内的代码环境,就是局部作用域(函数作用域) 在函数内部的作用域,这个代码名字只在函数内部起作用 function fn { 局部作用域 }; 函数的形参也可以看做局部变量;局部变量在代码执行完毕后就结束;
3.es6新增块级作用域
js在es6中新增块级作用域,块作用域由 { } 包括 如if{} for{}等 在其他编程语言中(如 java、c#等),在 if 语句、循环语句中创建的变量,仅仅只能在当前 if 语句、当前循环语句中使用
-
java有块级作用域:
if(true){ int num = 123; system.out.print(num); // 123 } system.out.print(num); // 报错
以上java代码会报错,是因为代码中 { } 即一块作用域,其中声明的变量 num,在 “{ }” 之外不能使用;
而与之类似的JavaScript代码,则不会报错。
-
js中没有块级作用域(在ES6之前)
if(true){ var num = 123; console.log(123); //123 } console.log(123); //123
9.3 - 变量的作用域
在JavaScript中,根据作用域的不同,变量可以分为两种:
-
全局变量
-
局部变量
1.全局变量
在全局作用域下声明的变量叫做全局变量(在函数外部定义的变量)。 注意 如果在函数内部 没有声明直接赋值的变量也属于全局变量
-
全局变量在代码的任何位置都可以使用
-
在全局作用域下 var 声明的变量 是全局变量
-
特殊情况下,在函数内不使用 var 声明的变量也是全局变量(不建议使用)
2.局部变量
在局部作用域下声明的变量叫做局部变量(在函数内部定义的变量) 注意: 函数的形参也可以看做是局部变量
-
局部变量只能在该函数内部使用
-
在函数内部 var 声明的变量是局部变量
-
函数的形参实际上就是局部变量
3.全局变量和局部变量的区别
-
全局变量:在任何一个地方都可以使用,只有在浏览器关闭时才会被销毁,因此比较占内存;
-
局部变量:只在函数内部使用,当其所在的代码块被执行时,会被初始化;当代码块运行结束后,就会被销毁,因此更节省内存空间;
9.4 - 作用域链
根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作作用域链。
案例分析1:
function f1() { // 外部函数 var num = 123; function f2() { console.log( num );// 站在目标出发,一层一层的往外查找 } f2(); // 内部函数 } var num = 456; f1();
案例:
作用域链:采取就近原则的方式来查找变量最终的值 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的值 ? console.log(b); //b的值 ? } } } fn1(); // 作用域链 var num = 10; function fn() { var num = 20;// 根据作用域链机制 先调用上一级的 function fun() { console.log(num);// 内部函数可以调用外部函数 属于子集 } } function f1() { var num = 123; function f2() { console.log(num);// 站在目标出发一层层往外查找 num=123 近 } f2(); } var num = 456; f1();
预解析
1.1 预解析的相关概念
JavaScript 代码是由浏览器中的 JavaScript 解析器来执行的。 JavaScript 解析器在运行 JavaScript 代码的时候分为两步:预解析和代码执行。 预解析: js引擎会把js里所有的 var 还有 function 提升到当前作用域的最前面,预解析也叫做变量、函数提升。 代码执行: 按照代码抒写的顺序从上到下执行
注意:预解析会把变量和函数的声明在代码执行之前执行完成。
1.2 预解析分类
预解析分为变量预解析(变量提升) 和 函数预解析(函数提升) 变量提升:变量的声明会被提升到当前作用域的最上面,变量的 赋值 不会提升。 函数提升:函数的声明会被提升到当前作用域的最上面,但是不会调用函数。
预解析分为变量预解析(变量提升) 和 函数预解析(函数提升)
// 1.未声明 直接调用 报错 console.log(num); // 2.先调用 后声明 undefined 坑1 // 变量预解析(变量提升)声明提升,赋值不提 console.log(num); var num = 10; // 预解析后相当于: var num; // 只声明 未赋值 undefine console.log(num); num = 10; // 3.利用关键字定义函数 函数先调用后声明 或 先声明后调用 无影响 // 函数预解析(函数提升) fn(); function fn() { console.log(11); } // 预解析后相当于:把函数提升到最前面 // 4.利用函数表达式定义函数 只能先声明后调用 否则会报错 // 解决函数表达式声明调用问题 var fun = function () { console.log(22); } // 预解析后相当于: var fun; fun(); fun = function() { console.log(22); }
案例:
// 1. var num = 10; fun(); function fun() { console.log(num); var num = 20; } // 函数提升后 相当于以下代码 输出undefined var num; function fun() { var num; // 只声明 未赋值 undefined console.log(num); num = 20; } num = 10; fun(); // 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 = b = c = 9; // 相当于 var a = 9;b = 9;c = 9;//b c 直接赋值 没有var声明 相当于全局变量 // 集体声明应该是 var a =9,b = 9,c = 9; var a; a = b = c = 9; console.log(c);// 9 console.log(b);// 9 console.log(a);// 报错 a当局部变量看 只声明 }
对象
1.1 对象的相关概念
1、什么是对象?
对象是指具体的事物,如字符串、数值、数组函数等;万物皆对象;
对象是由属性和方法组成的:
-
属性:事物的特征,在对象中用属性来表示(常用名词)
-
方法:事物的行为,在对象中用方法来表示(常用动词)
2、为什么需要对象?
保存一个值用变量;保存多个值,可以使用数组;保存一个人的完整信息可以用对象(相当于C语言结构体);
-
对象可以让代码结构更清晰
-
对象属于复杂数据类型object。
-
本质:对象就是一组无序的相关属性和方法的集合。
-
构造函数泛指某一大类,比如苹果,不管是红色苹果还是绿色苹果,都统称为苹果。
-
对象实例特指一个事物,比如这个苹果、正在给你们讲课的pink老师等。
-
for...in 语句用于对对象的属性进行循环操作。
变量、属性、函数、方法的区别
相同点 他们都是用来存储数据的;
-
变量:单独声明赋值,使用的时候直接写变量名 单独存在
-
属性:对象里面的变量称为属性,不需要声明,用来描述对象特征 对象.属性;
属性是对象的一部分,而变量不是对象的一部分,变量是单独存储数据的容器
-
函数:单独存在的,通过“函数名()”的方式就可以调用
-
方法:对象里面的函数称为方法,方法不需要声明,使用“对象.方法名()”的方式就可以调用;
方法是对象的一部分,函数是单独封装操作的容器
函数和方法的相同点 都是实现某种功能 做某件事
// 变量和属性的相同点 都是用来存储数据的 // 1.变量 单独声明并赋值 使用的时候直接写变量名 单独存在 var name = 10; // 2.属性 在对象里不需要声明 调用的时候必须是 对象.属性 var obj = { age: 18 } console.log(obj.age); // 函数和方法的相同点 都是实现某种功能 做某件事 // 3.函数是单独声明 并且调用的 函数名() 单独存在的 function fn() { } // 4.方法 在对象里面 调用的时候 对象.方法() var obj = { age: 18 fn: function () { } }
小括号()优先级;中括号[ ]数组;花括号{ }对象
1.2 创建对象的三种方式
-
利用字面量创建对象;
-
利用new object创建对象;
-
利用构造函数创建对象;
1、利用字面量创建对象
<script> // 1.利用 字面量 创建对象 利用键值对形式 属性名 :属性值 ,中间 逗号 隔开 var obj = {}; var obj = { uname: '张三疯', // 里面的属性或方法采取键值对的形式 键 属性名 :值 属性值 age: '18', // 多个属性或者方法中间用逗号隔开 sex: '男', sayHi: function () { // 方法冒号后面跟的是一个匿名函数 function console.log('hi~'); } } // 2.调用对象 console.log(obj.name); // 调用对象的属性 采用 对象名.属性名 理解为 的 console.log(obj['age']); // 调用属性还有一种方法 对象名['属性名'] obj.sayHi(); // 调用对象的方法 sayHi 对象名.方法名() </script>
2、利用 new Object 创建对象
// 利用 new Object 创建对象 利用 等号 = 赋值的方法 添加对象的属性和方法 var obj = new Object();// 创建一个空的对象 obj.uname = '张三疯'; // 利用 等号 = 赋值的方法 添加对象的属性和方法 obj.age = 18; // 每个属性和方法之间用分号结束 obj.sayHi = function () { console.log('hi~'); } console.log(obj.uname); console.log(obj['sex']); obj.sayHi();
3、利用构造函数创建对象
因为前面两种方式一次只能创建一个对象;
-
构造函数就是把 我们对象里一些相同的属性和方法抽象出来封装到函数中;
-
构造函数用于创建某一类函数,首字母要大写;与关键字 new 一起使用;
-
利用构造函数创建对象的过程称为对象的实例化
<script> // 利用构造函数创建对象 // 需要创建四大天王的对象 相同的属性: 名字 年龄 性别 相同的方法:唱歌 function 构造函数名() { this.属性 = 值; this.方法 = function () { } } new 构造函数名(); // 1.构造函数 泛指一大类 function Star(uname, age, sex) { // 构造函数首字母大写 this.name = uname; this.age = age; this.sex = sex; this.sing = function (sang) { console.log(sang); } } // 2.对象 特指某一个 对象的实例化 var ldh = new Star('刘德华', 18, '男'); // 多了个 this 和new 不需要 return 就可以返回结果 // console.log(typeof ldf); // object console.log(ldh.name); console.log(ldh['sex']); ldh.sing('冰雨'); </script> // 1. 构造函数名字首字母要大写 // 2. 我们构造函数不需要return 就可以返回结果 // 3. 我们调用构造函数 必须使用 new // 4. 我们只要new Star() 调用函数就创建一个对象 ldh {} // 5. 我们的属性和方法前面必须添加 this
构造函数和对象的区别:
-
构造函数 如明星 泛指一大类 类似于java语言中的类
-
对象 特指 是一个具体的事物
我们利用构造函数创建对象的过程我们也称为对象的实例化
new关键字:
-
new 构造函数可以 在内存中创建了一个空的新对象;
-
让this就会指向刚才的空对象
-
执行构造函数里面的代码 给这个空对象添加属性和方法
-
返回这个新对象(所以不需return)
var ldh = new Star('刘德华', 18, '男');
1.3 遍历对象
for...in 语句用于对数组或者对象的属性进行循环操作。
for (变量 in 对象名字) { // 在此执行代码 }
变量通常用 k 或者 key
// for (变量 in 对象) { } for (var k in obj) { console.log(k);// k变量输出 得到的是 属性名 console.log( obj[k] );// 得到的是 属性值 }
1.4 内置对象
1.41内置对象的概念
-
JavaScript 中的对象分为3种:自定义对象 、内置对象、 浏览器对象
-
前面两种对象是JS 基础 内容,属于 ECMAScript; 第三个浏览器对象属于我们 JS 独有的, 我们JS API 讲解
-
内置对象就是指 JS 语言自带的一些对象,这些对象供开发者使用,并提供了一些常用的或是最基本而必要的功能(属性和方法)
-
内置对象最大的优点就是帮助我们快速开发
-
JavaScript 提供了多个内置对象:Math、 Date 、Array、String等
1.42 MDN文档查阅!
查找文档:学习一个内置对象的使用,只要学会其常用成员的使用即可,我们可以通过查文档学习,可以通过MDN/W3C来查询。 Mozilla 开发者网络(MDN)提供了有关开放网络技术(Open Web)的信息,包括 HTML、CSS 和万维网及 HTML5 应用的 API。 MDN:https://developer.mozilla.org/zh-CN/
Math对象
1.Math 概述
Math 对象不是构造函数,所以我们不需要new 来调用 而是直接使用里面的属性和方法即可,它具有数学常数和函数的属性和方法。跟数学相关的运算(求绝对值,取整、最大值等)可以使用 Math 中的成员。
属性、方法名 | 功能 |
---|---|
Math.PI | 圆周率 |
Math.floor() | 向下取整 |
Math.ceil() | 向上取整 |
Math.round() | 四舍五入版 就近取整 注意 -3.5 结果是 -3 |
Math.abs() | 绝对值 |
Math.max()/Math.min() | 求最大和最小值 |
Math.random() | 获取范围在[0,1)内的随机值 |
注意:上面的方法使用时必须带括号
// Math 三个取整的方式 // (1) Math.floor() 地板 向下取整 往小了取值 console.log(Math.floor(1.9));// 1 // (2) Math.ceil() 天花板 向上取整 往大了取值 console.log(Math.ceil(1.1));// 2 // (3) Math.round() 四舍五入 其他数字都是四舍五入 5往大了取 console.log(Math.round(1.1));// 1 console.log(Math.round(1.5));// 2 console.log(Math.round(-1.1));// -1 console.log(Math.round(-1.5));// -1 // Math 数学对象 不是一个构造函数,不需要 new 调用 直接使用里面的属性和方法 console.log(Math.PI);// 一个属性 圆周率 console.log(Math.abs(-1));// 1 绝对值 console.log(Math.max(1, 33, 99));// 99 console.log(Math.max('pink'));// NaN console.log(Math.max());// // 利用对象封装自己的数学对象 里面有PI最大值和最小值 var myMath = { PI: 3.1415926, 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));
2. 随机数方法 random()
random() 方法可以随机返回一个小数,其取值范围是 [0,1),左闭右开 0 <= x < 1 ;
得到一个两数之间的随机整数,包括两个数在内。
获取指定范围内的随机整数算法:
function getRandom(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }
案例:Math对象随机数方法
// 想要得到两个数之间的随机整数 并且包括这2个数 // Math.floor(Math.random() * (max - min +1)) + min function getRandom(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } console.log(getRandom(1, 10)); // 随机点名 var arr = ['张三', '张三疯', '张三疯子', '李四', '李思思']; // console.log(arr[0]); console.log(arr[getRandom(0, arr.length - 1)]);
案例:猜数字游戏
程序随机生成一个 1~ 10 之间的数字,并让用户输入一个数字,
案例分析
① 随机生成一个1~10 的整数 我们需要用到 Math.random() 方法。
② 需要一直猜到正确为止,所以一直循环。
③ 用while 循环合适更简单。
④ 核心算法:使用 if else if 多分支语句来判断大于、小于、等于。
<script> 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;// 退出整个循环 一定要写结束循环条件 } } </script>
如果限定猜的次数,可以在条件判断改为for
日期对象
Date 对象和 Math 对象不一样, Date是一个构造函数,使用时需要实例化后(new)才能使用其中具体方法和属性 Date 实例用来处理日期和时间
1.使用Date实例化日期对象
-
获取当前时间必须实例化:
var now = new Date(); console.log(now);
-
获取指定时间的日期对象
var future = new Date('2019/5/1'); 如果Date()不写参数,就返回当前时间 如果Date()里面写参数,就返回括号里面输入的时间
注意:如果创建实例时并未传入参数,则得到的日期对象是当前时间对应的日期对象
// 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 date1 = new Date('2019-10-1 8:8:8'); console.log(date2);
2.使用Date实例的方法和属性 日期格式化
方法名 | 说明 | 代码 |
---|---|---|
getFullYear() | 获取当年 | getFullYear() |
getMonth() | 获取当月(0-11) | getMonth() |
getDate() | 获取当前日期 | getDate() |
getDay() | 获取星期几(周日为0) | getDay() |
getHours() | 获取当前小时 | getHours() |
getMinutes() | 获取当前分钟 | getMinutes() |
getSeconds() | 获取当前秒钟 | getSeconds() |
案例: 输出当前日期
请写出这个格式的日期:2019年5月1日 星期三
<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 周日返回的是0 // 写一个 2019年 5月 1日 星期三 var year = date.getFullYear(); var month = date.getMonth(); var dates = date.getDate(); var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']; var day = date.getDay(); console.log('今天是:' + year + '年' + month + '月' + dates + '日' + arr[day]); </script>
案例: 输出当前时间
写一个函数,格式化日期对象,成为 HH:mm:ss 的形式 比如 00:10:45
<script> // 格式化日期 时分秒 var date = new Date(); console.log(date.getHours());// 时 console.log(date.getMinutes()); // 分 console.log(date.getSeconds()); // 秒 // 要求封装一个函数返回当前的时分秒 格式 08:08:08 function getTime() { 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(getTime()); </script>
3.通过Date实例获取总毫米数
总毫秒数的含义:基于1970年1月1日(世界标准时间)起的毫秒数
毫秒数也叫时间戳,永远不会重复;
案例:获取总毫秒数
<script> // 获得 Date总的毫秒数 不是当前时间的毫秒数 而是距离1970年1月1日 var date = new Date();// 实例化Date对象 // 1. 通过 valueOf() getTime() 用于获取对象的原始值 console.log(date.valueOf());// 距离 1970 过了多少毫秒 console.log(date.getTime()); // 2. 简单的写法(常用) var date1 = +new Date();// +new Date() 返回的是总毫秒数 console.log(date1); // 3. HTML5新增的的方法,有兼容性问题 console.log(Date.now()); </script>
案例:倒计时效果
案例分析
① 核心算法:输入的时间减去现在的时间就是剩余的时间,即倒计时 ,但是不能拿着时分秒相减,比如 05 分减去25分,结果会是负数的。
② 用时间戳(毫秒)来做。用户输入时间总的毫秒数减去现在时间的总的毫秒数,得到的就是剩余时间的毫秒数。
③ 把剩余时间总的毫秒数转换为天、时、分、秒 (时间戳转换为时分秒)
转换公式如下:
d = parseInt(总秒数/ 60/60 /24); // 计算天数
h = parseInt(总秒数/ 60/60 %24) // 计算小时
m = parseInt(总秒数 /60 %60 ); // 计算分数
s = parseInt(总秒数%60); // 计算当前秒数
<script> function countDown(time) { var nowTime = +new Date();// 返回的是当前时间的总毫秒数 var inputTime = +new Date(time);// 返回的是用户输入事件的总毫秒数 var times = (inputTime - nowTime) / 1000; // times是剩余时间总的秒数 1s=1000ms 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>
数组对象
1.创建数组的两种方式
-
字面量方式
var arr = [1, 2, 3]; console.log(arr[0]);
-
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);
注意:上面代码中arr创建出的是一个空数组,如果需要使用构造函数Array创建非空数组,可以在创建数组时传入参数
参数传递规则如下:
-
如果只传入一个参数,则参数规定了数组的长度
-
如果传入了多个参数,则参数称为数组的元素
-
2.检测是否为数组
-
instanceof 运算符
instanceof 可以判断一个对象是否是某个构造函数的实例
var arr = [1, 23]; var obj = {}; console.log(arr instanceof Array); // true arr是数组 console.log(obj instanceof Array); // false obj是对象
-
Array.isArray()
Array.isArray()用于判断一个对象是否为数组,isArray() 是 HTML5 中新增的方法 ie9以上不支持
var arr = [1, 23]; var obj = {}; console.log(Array.isArray(arr)); // true console.log(Array.isArray(obj)); // false
翻转数组:
// 翻转数组 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));
3.添加删除数组元素的方法
数组中有进行增加、删除元素的方法,部分方法如下表
方法名 | 说明 | 返回值 |
---|---|---|
push(参数1...) | 末尾添加一个或多个元素,注意修改原数组 | 并返回新的长度 |
pop() | 删除数组最后一个元素,把数组长度减1 无参数、修改原数组 | 返回他删除的元素的值 |
unshift(参数1...) | 向数组的开头添加一个或多个元素,注意修改原数组 | 并返回新的长度 |
shift() | 删除数组的第一个元素,数组长度减1无参数,修改原数组 | 并返回第一个元素得值 |
注意:push、unshift为增加元素方法;pop、shift为删除元素的方法
案例:添加删除数组元素
<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) 原数组也会发生变化 // 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> </head>
案例: 筛选数组
有一个包含工资的数组[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);
4.数组排序
数组中有对数组本身排序的方法,部分方法如下表
方法名 | 说明 | 是否修改原数组 |
---|---|---|
reverse() | 颠倒数组中元素的熟悉怒,无参数 | 改变原来数组 返回新数组 |
sort() | 对数组的元素进行排序 | 改变原数组 返回新数组 |
注意:sort方法需要传入参数来设置升序、降序排序
-
如果传入“function(a,b){ return a-b;}”,则为升序
-
如果传入“function(a,b){ return b-a;}”,则为降序
// 数组排序 // 1. 翻转数组 var arr = ['pink', 'red', 'blue']; arr.reverse(); console.log(arr); // 2. 数组排序(冒泡排序) var arr1 = [17, 4, 71, 6, 9]; // arr1.sort();// 只能对单位数字排序 arr1.sort(function (a, b) { return a - b;// 按照升序排列 return b - a;// 按照降序排序 }); console.log(arr1);
5.数组索引方法
数组中有获取数组指定元素索引值的方法,部分方法如下表
方法名 | 说明 | 返回值 |
---|---|---|
indexOf() | 数组中查找给定元素的第一个索引 | 存在返回索引,不存在,返回-1 |
lastIndexOf() | 在数组中的最后一个索引 | 存在返回索引,不存在,返回-1 |
获取数组指定元素索引值
<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>
案例: 数组去重(重点案例)
有一个数组[‘c’, ‘a’, ‘z’, ‘a’, ‘x’, ‘a’, ‘x’, ‘c’, ‘b’],要求去除数组中重复的元素
案例分析
① 目标:把旧数组里面不重复的元素选取出来放到新数组中,重复的元素只保留一个,放到新数组中去重。
② 核心算法:我们遍历旧数组,然后拿着旧数组元素去查询新数组,如果该元素在新数组里面没有出现过,我们就添加,否则不添加。
③ 我们怎么知道该元素没有存在? 利用 新数组.indexOf(数组元素) 如果返回时 -1 就说明 新数组里面没有该元素
旧数组['c', 'a', 'z', 'a', 'x', 'a', 'x', 'c', 'b']
新数组 [ ]
<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>
6.数组转换为字符串
数组中有把数组转化为字符串的方法,部分方法如下表
方法名 | 说明 | 返回值 |
---|---|---|
toString() | 把数组转换成字符串 逗号分割每一项 | 返回一个字符串 |
join('分隔符') | 方法用于把数组中的所有元素转换为一个字符串 | 返回一个字符串 |
注意:join方法如果不传入参数,则按照 “ , ”拼接元素
// 数组转换成字符串 // 1. toString() var arr = [1, 2, 3]; console.log(arr.toString());// 1,2,3 // 2. join(分隔符) var arrr1 = ['green', 'blue', 'pink']; console.log(arr1.join());// green,blue,pink console.log(arr1.join('-'));// green-blue-pink console.log(arr1.join('&'));// green&blue&pink
其他方法
-
数组中还有其他操作方法,同学们可以在课下自行查阅学习
-
slice() 和 splice() 目的基本相同,建议同学们重点看下 splice()
方法名 | 说明 | 返回值 |
---|---|---|
concat() | 连接两个或多个数组 不影响原数组 | 返回一个新的数组 |
slice() | 数组截取 slice(begin,end) | 返回被截取项目的新数组 |
splice() | 数组删除splice(第几个开始,要删除个数) | 返回被删除项目的新数组 影响原数组 |
字符串对象
1.基本包装类型
为了方便操作基本数据类型,JavaScript 还提供了三个特殊的引用类型:String、Number和 Boolean。
基本包装类型就是把 简单数据类型 包装成为 复杂数据类型,这样基本数据类型就有了属性和方法。
// 下面代码有什么问题? var str = 'andy'; console.log(str.length);
按道理简单数据类型是没有属性和方法的,而对象才有属性和方法,但上面代码却可以执行,这是因为js 会把基本数据类型包装为复杂数据类型,其执行过程如下 :
// 对象 才有 属性和方法 复杂数据类型才有 属性和方法 // 简单数据类型为什么会有length 属性呢? // 基本包装类型: 就是把简单数据类型 包装成为了 复杂数据类型 // 1. 生成临时变量,把简单类型包装为复杂数据类型 var temp = new String('andy'); // 2. 赋值给我们声明的字符变量 str = temp; // 3. 销毁临时变量 temp = null;
2.字符串的不可变
指的是里面的值不可变,虽然看上去可以改变内容,但只是地址变了,在内存中新开辟了一个内存空间。 原来的值还是有的; 当重新给字符串变量赋值的时候,变量之前保存的字符串不会被修改,依然在内存中重新给字符串赋值,会重新在内存中开辟空间,这个特点就是字符串的不可变。
由于字符串的不可变,在大量拼接字符串的时候会有效率问题
var str = 'abc'; str = 'hello'; // 当重新给 str 赋值的时候,常量'abc'不会被修改,依然在内存中 // 重新给字符串赋值,会重新在内存中开辟空间,这个特点就是字符串的不可变 // 由于字符串的不可变,在大量拼接字符串的时候会有效率问题 var str = ''; for (var i = 0; i < 100000; i++) { str += i; } console.log(str); // 这个结果需要花费大量时间来显示,因为需要不断的开辟新的空间
3.根据字符返回位置
字符串的所有方法,都不会修改字符本身(字符串是可变的),操作完成后会发挥成以个新的字符串;
字符串通过基本包装类型可以调用部分方法来操作字符串,以下是返回指定字符的位置的方法:
方法名 | 说明 |
---|---|
indexOf('要查找的字符',开始的位置) | 返回指定内容在元字符串中的位置,如果找不到返回-1,开始的位置是index索引号 |
lastIndexOf() | 从后往前找,值找第一个匹配的 |
// 字符串对象 根据字符返回位置 str.indexOf('要查找的字符',[起始位置]) var str = '改革春风吹满地,春天来了'; console.log(str.indexOf('春'));// 2 console.log(str.indexOf('春', 3));// 从索引号是 3的位置开始往后查找 8
案例:返回字符位置
查找字符串"abcoefoxyozzopp"中所有o出现的位置以及次数
① 核心算法:先查找第一个o出现的位置
② 然后 只要indexOf 返回的结果不是 -1 就继续往后查找
③ 因为indexOf 只能查找到第一个,所以后面的查找,利用第二个参数,当前索引加1,从而继续查找
<script> var str = "abcoefoxyozzopp"; var index = str.indexOf('o'); // 从第一个o开始查找,返回 索引号 3 var num = 0; // console.log(idnex); while (index !== -1) { console.log(index); num++; // 开始寻找第二个 o index = str.indexOf('o', index + 1); } console.log('o出现的次数是:' + num); </script>
4.根据位置返回字符
字符串通过基本包装类型可以调用部分方法来操作字符串,以下是根据位置返回指定位置上的字符:
方法名 | 说明 | 使用 |
---|---|---|
charAt(index) | 返回指定位置的字符(index字符串的索引号) | str.charAt(0) |
charCodeAt(index) | 获取指定位置处字符的ASII码(index索引号) | str.charCodeAt(0) |
str[index] | 获取指定位置处字符 | html/ie8+支持 |
在上述方法中,charCodeAt方法返回的是指定位置上字符对应的ASCII码,ASCII码对照表如下:
// 根据位置返回字符 // 1. charAt(index) 根据位置返回字符 var str = 'andy'; console.log(str.charAt(3));// y // 遍历所有字符 for (var i = 0; i < str.length; i++) { console.log(str.charAt(i)); } // 2. charCodeAt(index) 反应相应索引号的字符ASII值 目的:判断用户按下了哪个键 console.log(str.charCodeAt(0));//97 // 2. str[index] H5 新增的 console.log(str[0]); // a
案例:返回字符位
统计出现最多的字符和次数
判断一个字符串 'abcoefoxyozzopp' 中出现次数最多的字符,并统计其次数
1.核心算法:利用 charAt() 遍历这个字符串
2.把每个字符都存储给对象, 如果对象没有该属性,就为1,如果存在了就 +1
3.遍历对象,得到最大值和该字符
注意:在遍历的过程中,把字符串中的每个字符作为对象的属性存储在对象总,对应的属性值是该字符出现的次数
<script> 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); </script> <script> // 有一个对象 来判断是否有该属性 对象['属性名'] var o = { age: 18 } if (o['sex']) { console.log('里面有该属性'); } else { console.log('没有该属性'); } // 判断一个字符串 '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); </script>
5.字符串操作方法
字符串通过基本包装类型可以调用部分方法来操作字符串,以下是部分操作方法:
方法名 | 说明 |
---|---|
concat(str1,str2,str3...) | 用于连接两个或多个字符串,拼接字符串,等效于+(+常用) |
substr(start,length) | 从start位置开始(索引号),length取个数 |
slice(start,end) | 从start位置开始,截取到end位置,end取不到(都是索引号) |
substring(start,end) | 从start位置开始,截取到end,end取不到,基本和slice相同,但不接收负值 |
// 字符串操作方法 // 1.concat('字符串1','字符串2'...) var str ='andy'; console.log(str.concat('red'));// andyred // 2. substr('截取的起始位置','截取几个字符'); var str1 = '改革春风吹满地'; console.log(str1.substr(2,2));// 春风 // 第一个2 是索引号的2 从第几个开始 第二个2 是取几个字符
replace()方法
replace() 方法用于在字符串中用一些字符替换另一些字符,其使用格式如下:
字符串.replace(被替换的字符串, 要替换为的字符串); var str = 'andyandy'; console.log(str.replace('a')); //只替换第一个a
split()方法
split()方法用于切分字符串,它可以将字符串切分为数组。在切分完毕之后,返回的是一个新数组。
字符串.split("分割字符") var str = 'a,b,c,d'; console.log(str.split(',')); // 返回的是一个数组 [a, b, c, d] <script> // 1. 替换字符 replace('被替换的字符','替换为的字符') 只替换第一个 var str = 'andyandy'; console.log(str.replace('a', 'b'));// bndyandy // 替换里面所有选中的字符串 var str1 = 'andyandy'; while (str1.indexOf('a') !== -1) { str1 = str1.replace('a', '*'); } console.log(str1); // 2. 字符串转换为数组 split('分隔符') join 把数组转为字符串 var str2 = 'red,pink,blue'; console.log(str2, split(','));// ['red','pink','blue'] console.log(str2, split('&'));// ['red'&'pink'&'blue'] </script>
课下查阅
toUpperCase() //转换大写
toLowerCase() //转换小写
数据类型
1.1 简单数据类型
简单类型(基本数据类型、值类型):
在存储时变量中存储的是值本身,包括string ,number,boolean,undefined,null
null返回的是object,如果有个变量,以后打算存储为对象,可以用;
<script> // 简单数据类型 null 返回的是一个空的对象 object var timer = null; console.log(typeof timer); // 如果有个变量我们以后打算存储为对象,暂时没想好放啥, 这个时候就给 null // 1. 简单数据类型 是存放在栈里面 里面直接开辟一个空间存放的是值 // 2. 复杂数据类型 首先在栈里面存放地址 十六进制表示 然后这个地址指向堆里面的数据 </script>
1.2 复杂数据类型
复杂数据类型(引用类型):在存储时变量中存储的仅仅是地址(引用),通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等;
1.3 堆栈
-
堆栈空间分配区别:
1、栈(操作系统):由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈;简单数据类型存放到栈里面;
2、堆(操作系统):存储 复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收
js中没有堆栈概念
-
简单数据类型的存储方式
值类型变量的数据直接存放在变量(栈空间)中,存储的是值
-
复杂数据类型的存储方式
引用类型变量(栈空间)里存放的是地址,地址指向堆里面的数据,真正的对象实例存放在堆空间中
1.4 简单类型传参
函数的形参也可以看做是一个变量,当我们把一个值类型变量作为参数传给函数的形参时,其实是把变量在栈空间里的值复制了一份给形参,那么在方法内部对形参做任何修改,都不会影响到的外部变量。
function fn(a) { a++; console.log(a); } var x = 10; fn(x); console.log(x);
运行结果如下:
1.5 复杂数据类型传参
函数的形参也可以看做是一个变量,当我们把引用类型变量传给形参时,其实是把变量在栈空间里保存的堆地址复制给了形参,形参和实参其实保存的是同一个堆地址,所以操作的是同一个对象。
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. 这个输出什么 ? 张学友