JavaScript基础

前提

编程语言

编程:就是让计算机为解决某个问题而使用某种程序设计语言编写程序代码,并最终得到结果的过程。

计算机程序:就是计算机所执行的一系列的指令集合,而程序全部都是用我们所掌握的语言来编写的,所以人们要控制计算机一定要通过计算机语言向计算机发出命令。

计算机语言指用于人与计算机之间通讯的语言,它是人与计算机之间传递信息的媒介

  • 计算机语言的种类非常的多,总的来说可以分成机器语言汇编语言高级语言三大类。
  • 实际上计算机最终所执行的都是机器语言,它是由“0”和“1”组成的二进制数,二进制是计算机语言的基础

如今通用的编程语言有两种形式:汇编语言和高级语言。

  • 汇编语言和机器语言实质是相同的,都是直接对硬件操作,只不过指令采用了英文缩写的标识符,容易识别和记忆。
  • 高级语言主要是相对于低级语言而言,它并不是特指某一种具体的语言,而是包括了很多编程语言,常用的有C语言、C++、Java、C#、Python、PHP、JavaScript、Go语言、Objective-C、Swift等。
1
2
3
4
C语言:puts("你好");
PHP:echo "你好";
Java:System.out.println("你好");
JavaScript: alert("你好");

初识JavaScript

是什么

  • JavaScript 是世界上最流行的语言之一,是一种运行在客户端的脚本语言 (Script 是脚本的意思)
  • 脚本语言:不需要编译,运行过程中由 js 解释器( js 引擎)逐行来进行解释并执行
  • 现在也可以基于 Node.js 技术进行服务器端编程

作用

  • 表单动态校验(密码强度检测)( JS 产生最初的目的
  • 网页特效
  • 服务端开发(Node.js)
  • 桌面程序(Electron)
  • App(Cordova)
  • 控制硬件-物联网(Ruff)
  • 游戏开发(cocos2d-js)

组成

JavaScript: ECMAScript(语法)、DOM(页面文档对象模型)、BOM(浏览器对象模型)

  • ECMAScript: ECMAScript 规定了JS的编程语法和基础核心知识,是所有浏览器厂商共同遵守的一套JS语法工业标准。
  • 文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标记语言的标准编程接口。 通过 DOM 提供的接口可以对页面上的各种元素进行操作(大小、位置、颜色等)。
  • BOM (Browser Object Model,简称BOM) 是指浏览器对象模型,它提供了独立于内容的、可以与浏览器窗口进行 互动的对象结构。通过BOM可以操作浏览器窗口,比如弹出框、控制浏览器跳转、获取分辨率等。

书写方式

JS 有3种书写位置,分别为行内、内嵌和外部。

行内式JS

1
<input type="button" value="点我试试" onclick="alert('Hello World')" />
  • 可以将单行或少量 JS 代码写在HTML标签的事件属性中(以 on 开头的属性),如:onclick
  • 注意单双引号的使用:在HTML中我们推荐使用双引号, JS 中我们推荐使用单引号
  • 可读性差, 在html中编写JS大量代码时,不方便阅读;
  • 引号易错,引号多层嵌套匹配时,非常容易弄混;
  • 特殊情况下使用

内嵌 JS

1
2
3
<script>
alert('Hello World~!');
</script>
  • 可以将多行JS代码写到 <script> 标签中
  • 内嵌 JS 是学习时常用的方式

外部 JS文件

1
<script src="my.js"></script>
  • 利于HTML页面代码结构化,把大段 JS代码独立到 HTML 页面之外,既美观,也方便文件级别的复用
  • 引用外部 JS文件的 script 标签中间不可以写代码
  • 适合于JS 代码量比较大的情况

注释

为了提高代码的可读性,JS与CSS一样,也提供了注释功能。JS中的注释主要有两种,分别是单行注释和多行注释。

单行注释

1
// 我是一行文字,不想被JS引擎执行,所以注释起来 

// 用来注释单行文字( vscoad快捷键 ctrl + / )

多行注释

1
2
3
4
/*
获取用户年龄和姓名
并通过提示框显示出来
*/

/* */ 用来注释多行文字( 默认快捷键 alt + shift + a )

快捷键修改为: ctrl + shift + /

vscode → 首选项按钮 → 键盘快捷方式 → 查找 原来的快捷键 → 修改为新的快捷键→ 回车确认

输入输出语句

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

方法 说明 归属
alert(msg) 浏览器弹出警示框 浏览器
console.log(msg) 浏览器控制台打印输出信息 浏览器
prompt(info) 浏览器弹出输入框,用户可以输入 浏览器

例如:

1
2
3
4
5
6
7
8
9
<script>
// 这是一个输入框
prompt('请输入您的年龄');
// alert 弹出警示框 输出的 展示给用户的
alert('计算的结果是');
// console 控制台输出 给程序员测试用的
console.log('我是程序员能看到的');
</script>

变量

概述

白话:变量就是一个装东西的盒子。

通俗:变量是用于存放数据的容器。 我们通过 变量名 获取数据,甚至数据可以修改。

变量在内存中的存储:本质:变量是程序在内存中申请的一块用来存放数据的空间。(类似我们酒店的房间,一个房间就可以看做是一个变量)

使用

变量在使用时分为两步:

  1. 声明变量

  2. 赋值

1
2
3
4
5
6
7
8
9
10
11
<script>
// 1. 声明了一个age 的变量
var age;
// 2. 赋值 把值存入这个变量中
age = 18;
// 3. 输出结果
console.log(age);
// 4. 变量的初始化
var myname = 'Cyan';
console.log(myname);
</script>

声明变量

1
var age;   // 声明一个名称为age的变量
  • var 是一个 JS关键字,用来声明变量( variable 变量的意思 )。使用该关键字声明变量后,计算机会自动为变量分配 内存空间,不需要程序员管
  • age 是程序员定义的变量名,我们要通过变量名来访问内存中分配的空间

赋值

1
age = 18;   // 给 age 这个变量赋值为 18
  • = 用来把右边的值赋给左边的变量空间中 此处代表赋值的意思
  • 变量值是程序员保存到变量空间里的值

变量的初始化

1
2
3
4
var age = 18;      // 声明变量同时赋值为 18
// 例如:
var myname = 'Cyan';
console.log(myname);

声明一个变量并赋值, 我们称之为变量的初始化

案例1

  1. 弹出一个输入框,提示用户输入姓名。
  2. 弹出一个对话框,输出用户刚才输入的姓名。
1
2
3
4
5
6
<script>
// 1. 用户输入姓名 存储到一个 myname的变量里面
var myname = prompt('请输入您的名字');
// 2. 输出这个用户名
alert(myname);
</script>

语法拓展

更新变量

一个变量被重新复赋值后,它原有的值就会被覆盖,变量值将以最后一次赋的值为准。

1
2
var age = 18;
age = 81; // 最后的结果就是81,把18覆盖掉
同时声明多个变量

同时声明多个变量时,只需要写一个 var, 多个变量名之间使用英文逗号隔开。

1
var age = 10, name = 'zs', sex = 2; 
声明变量特殊情况
情况 说明 结果
var age ; console.log (age); 只声明 不赋值 undefined
console.log(age) 不声明 不赋值 直接使用 报错
age = 10; console.log (age); 不声明 只赋值 10

命名规范

  • 由字母(A-Za-z)、数字(0-9)、下划线(_)、美元符号( $ )组成,如:usrAge, num01, _name
  • 严格区分大小写。var app; 和 var App; 是两个变量
  • 不能 以数字开头。 18age 是错误的
  • 不能 是关键字、保留字。例如:var、for、while
  • 变量名必须有意义。 MMD BBD nl → age
  • 遵守驼峰命名法。首字母小写,后面单词的首字母需要大写。 myFirstName

案例2

要求:交换两个变量的值 ( 实现思路:使用一个 临时变量 用来做中间存储 )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script>
// js 是编程语言有很强的逻辑性在里面: 实现这个要求的思路 先怎么做后怎么做
// 1. 我们需要一个临时变量帮我们
// 2. 把apple1 给我们的临时变量 temp
// 3. 把apple2 里面的苹果给 apple1
// 4. 把临时变量里面的值 给 apple2
var temp; // 声明了一个临时变量为空
var apple1 = '青苹果';
var apple2 = '红苹果';
temp = apple1; // 把右边给左边
apple1 = apple2;
apple2 = temp;
console.log(apple1);
console.log(apple2);
</script>

数据类型

简介

在计算机中,不同的数据所需占用的存储空间是不同的,为了便于把数据分成所需内存大小不同的数据,充分利用存储空间,于是定义了不同的数据类型。

简单来说,数据类型就是数据的类别型号。比如姓名“张三”,年龄18,这些数据的类型是不一样的。

变量是用来存储值的所在处,它们有名字和数据类型。变量的数据类型决定了如何将代表这些值的位存储到计算机的 内存中。JavaScript 是一种弱类型或者说动态语言。这意味着不用提前声明变量的类型,在程序运行过程中,类型会被自动确定。

1
2
var age = 10;     // 这是一个数字型
var areYouOk = '是的'; // 这是一个字符串

JS 的变量数据类型是只有程序在运行过程中,根据等号右边的值来确定的

JavaScript 拥有动态类型,同时也意味着相同的变量可用作不同的类型

1
2
var x = 6;     // x 为数字
var x = "Bill"; // x 为字符串

分类

JS 把数据类型分为两类:

  • 简单数据类型 (Number,String,Boolean,Undefined,Null)
  • 复杂数据类型 (object)
简单数据类型(基本数据类型)

JavaScript 中的简单数据类型及其说明如下:

简单数据类型 说明 默认值
Number 数字型,包含整型值和浮点型值,如21、0.21 0
Boolean 布尔值类型,如true、false,等价于1和0 false
String 字符串类型,如“张三”注意咱们JS里面,字符串都带引号 “”
Undefined var a;声明了变量a但是没有给值,此时a=undefined undefined
Null var a=null; 声明了变量a为空值 null
数字型 Number

JavaScript 数字类型既可以用来保存整数值,也可以保存小数(浮点数)。

1
2
var age = 21;    // 整数
var Age = 21.3747; // 小数

1.进制:(八进制:数字前面加0 十六进制:数字的前面加 0x)

1
2
3
4
5
6
7
8
9
10
11
// 1. 八进制 0 ~ 7 我们程序里面数字前面加0 表示八进制
var num1 = 010;
console.log(num1); // 010 是八进制 转换为 10进制 就是 8
var num2 = 012;
console.log(num2); //10

// 2. 十六进制 0 ~ 9 a ~ f 数字的前面加 0x 表示十六进制
var num3 = 0x9;
console.log(num3); //9
var num4 = 0xa;
console.log(num4); //10

2.范围:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 3. 数字型的最大值
console.log(Number.MAX_VALUE); // 1.7976931348623157e+308

// 4. 数字型的最小值
console.log(Number.MIN_VALUE); // 5e-324

// 5. 无穷大
console.log(Number.MAX_VALUE * 2); // Infinity 无穷大

// 6. 无穷小
console.log(-Number.MAX_VALUE * 2); // -Infinity 无穷大

// 7. 非数字
console.log('pink老师' - 100); // NaN

3.判断:(isNaN() )

1
2
3
// isNaN() 这个方法用来判断非数字 并且返回一个值 如果是数字返回的是 false 如果不是数字返回的是true
console.log(isNaN(12)); // false
console.log(isNaN('pink老师')); // true
字符串型String

字符串型可以是引号中的任意文本,其语法为 双引号 “” 和 单引号’’

因为 HTML 标签里面的属性使用的是双引号,JS 这里我们更推荐使用单引号。

1.字符串转义符

JS 可以用单引号嵌套双引号 ,或者用双引号嵌套单引号 (外双内单,外单内双)

1
2
var str = '今天"也"在学习';
console.log(str); //今天"也"在学习

2.字符串转义符

类似HTML里面的特殊字符,字符串中也有特殊字符,我们称之为转义符。

转义符都是 \ 开头的,常用的转义符及其说明如下:

转义符 解释说明
\n 换行符,n 是 newline 的意思
\\ 斜杠 \
\' ‘ 单引号
\" ”双引号
\t tab 缩进
\b 空格 ,b 是 blank 的意思
1
2
3
// 字符串转义字符 都是用 \ 开头 但是这些转义字符写道引号里面
var str1 = '今天"也"在\n学习';
console.log(str1);

3.字符串长度

字符串是由若干字符组成的,这些字符的数量就是字符串的长度。通过字符串的 length 属性可以获取整个字符串的长度。

1
2
var strMsg = '今天也在学习';
alert(strMsg.length); // 显示 6
  1. 字符串拼接
  • 多个字符串之间可以使用 + 进行拼接,其拼接方式为 字符串 + 任何类型 = 拼接之后的新字符串
  • 拼接前会把与字符串相加的任何类型转成字符串,再拼接成一个新的字符串
1
2
3
4
5
6
// 2. 字符串的拼接 + 只要有字符串和其他类型相拼接 最终的结果是字符串类型
console.log('沙漠' + '骆驼'); // 字符串的 沙漠骆驼
console.log('今天' + 18); // '今天18' 字符串 + 数值
console.log('pink' + true); // pinktrue
console.log(12 + 12); // 24 数值相加
console.log('12' + 12); // '1212' 数值字符串 + 数值

+ 号总结口诀:数值相加 ,字符相连

1
2
3
4
5
console.log('pink老师' + 18 + '岁');  //pink老师18岁

// 我们变量不要写到字符串里面,是通过和 字符串相连的方式实现的
var age = 19;
console.log('pink老师' + age + '岁');
案例1

弹出一个输入框,需要用户输入年龄,之后弹出一个警示框显示“您今年 xx 岁啦”(xx 表示刚才输入的年龄)

这是利用 JS 编写的一个非常简单的交互效果程序。

1
2
3
4
5
6
7
// 弹出一个输入框(prompt),让用户输入年龄(用户输入):prompt('请输入您的年龄')
// 把用户输入的值用变量保存起来:var age = prompt('请输入您的年龄'),把刚才输入的年龄与所要输出的字符串拼接 (程序内部处理):var str = '您今年已经' + age + '岁了'
// 使用alert语句弹出警示框(输出结果):alert(str)

var age = prompt('请输入您的年龄');
var str = '您今年已经' + age + '岁了';
alert(str);
布尔型 Boolean

布尔类型有两个值:true 和 false ,其中 true 表示真(对),而 false 表示假(错)。

布尔型和数字型相加的时候, true 的值为 1 ,false 的值为 0。

1
2
3
4
var flag = true; // flag 布尔型
var flag1 = false; // flag1 布尔型
console.log(flag + 1); // true 参与加法运算当1来看
console.log(flag1 + 1); // false 参与加法运算当 0来看
Undefined 和 Null

一个声明后没有被赋值的变量会有一个默认值 undefined ( 如果进行相连或者相加时,注意结果)

1
2
3
4
5
var str;
console.log(str); // undefined
var variable = undefined;
console.log(variable + 'pink'); // undefinedpink
console.log(variable + 1); // NaN undefined和数字相加最后的结果是 NaN

一个声明变量给 null 值,里面存的值为空(学习对象时,我们继续研究null)

1
2
3
4
// null 空值
var space = null;
console.log(space + 'pink'); // nullpink
console.log(space + 1); // 1
获取检测变量的数据类型

typeof 可用来获取检测变量的数据类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var num = 10;
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

也可以根据控制台的颜色分辨

1
2
3
4
5
console.log(18);  //number
console.log('18'); //string
console.log(true); //boolean
console.log(undefined); //undefined
console.log(null); //null

数据类型转换

1.转换为字符串

方式 说明 案例
toString() 转成字符串 var num=1;alert(num.toString());
String()强制转换 转成字符串 var num=1;alert(String(num));
加号拼接字符串 和字符串拼接的结果都是字符串 var num=1;alert(num+”我是字符串”);
  • toString() 和 String() 使用方式不一样。
  • 三种转换方式,我们更喜欢用第三种加号拼接字符串转换方式, 这一种方式也称之为隐式转换。
1
2
3
4
5
6
7
8
9
// 1. 把数字型转换为字符串型 变量.toString()
var num = 10;
var str = num.toString();
console.log(str); // 10
console.log(typeof str); // string
// 2. 我们利用 String(变量)
console.log(String(num)); // 10
// 3. 利用 + 拼接字符串的方法实现转换效果 隐式转换
console.log(num + ''); // 10

2.转换为数字型(重点)

方式 说明 案例
parselnt(string)函数 将string类型转成整数数值型 parselnt(‘78’)
parseFloat(string)函数 将string类型转成浮点数数值型 parseFloat(‘78.21’)
Number()强制转换函数 将string类型转换为数值型 Number(‘12’)
js隐式转换(-*/) 利用算术运算隐式转换为数值型 ‘12’-0
  • 注意 parseInt 和 parseFloat 单词的大小写,这2个是重点
  • 隐式转换是我们在进行算数运算的时候,JS 自动转换了数据类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var age = prompt('请输入您的年龄');
// 1. parseInt(变量) 可以把 字符型的转换为数字型 得到是整数
console.log(parseInt(age));
console.log(parseInt('3.14')); // 3 取整
console.log(parseInt('3.94')); // 3 取整
console.log(parseInt('120px')); // 120 会去掉这个px单位
console.log(parseInt('rem120px')); // NaN

// 2. parseFloat(变量) 可以把 字符型的转换为数字型 得到是小数 浮点数
console.log(parseFloat('3.14')); // 3.14
console.log(parseFloat('120px')); // 120 会去掉这个px单位
console.log(parseFloat('rem120px')); // NaN

// 3. 利用 Number(变量)
var str = '123';
console.log(Number(str)); // 123
console.log(Number('12')); // 12

// 4. 利用了算数运算 - * / 隐式转换
console.log('12' - 0); // 12
console.log('123' - '120'); // 3
console.log('123' * 1); // 123

3.案例1——计算年龄

要求在页面中弹出一个输入框,我们输入出生年份后, 能计算出我们的年龄。

1
2
3
var year = prompt('请输入你的出生年份');
var age = '2023' - year;
alert('你的年龄是:' + age + '岁');

4.案例2——简单加法器

计算两个数的值, 用户输入第一个值后,继续弹出第二个输入框并输入第二个值,最后通过弹出窗口显示出两 次输入值相加的结果。

1
2
3
4
var dyz = prompt('请输入第一个值:');
var dez = prompt('请输入第二个值:');
var jsz = parseFloat(dyz) + parseFloat(dez); // 转换为数字型再相加
alert('结果是:' + jsz);
  1. 转换为布尔型
方式 说明 案例
Boolean()函数 其他类型转成布尔值 Boolean(’‘true);
  • 代表否定的值会被转换为 false ,如 ‘’、0、NaN、null、undefined
  • 其余值都会被转换为 true
1
2
3
4
5
6
7
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
课后作业

依次询问并获取用户的姓名、年龄、性别

1
2
3
4
var dys = prompt('请输入您的姓名:');
var dyz = prompt('请输入您的年龄:');
var dez = prompt('请输入您的性别:');
alert('您的姓名是:' + dys + '\n' + '您的年龄是:' + dyz + '\n' + '您的性别是:' + dez);

运算符

运算符(operator)也被称为操作符,是用于实现赋值、比较和执行算数运算等功能的符号。

JavaScript中常用的运算符有:

  • 算数运算符
  • 递增和递减运算符
  • 比较运算符
  • 逻辑运算符
  • 赋值运算符

算术运算符

算术运算使用的符号,用于执行两个变量或值的算术运算。

算术运算符优先级:先乘除后加减,有小括号先算小括号里面的

判断一个数是能被整除:它的余数是0就说明这个数能被整除,这就是%取余运算符的主要用途。

运算符 描述 实例
+ 10 + 20 = 30
- 10 - 20 = -10
* 10 * 20 = 200
/ 10 / 20 = 0.5
% 取余数(取模) 返回除法的余数 9 % 2 = 1
1
2
3
4
5
6
7
8
console.log(1 + 1); // 2
console.log(1 - 1); // 0
console.log(1 * 1); // 1
console.log(1 / 1); // 1
// 1. % 取余 (取模)
console.log(4 % 2); // 0
console.log(5 % 3); // 2
console.log(3 % 5); // 3

浮点数的精度问题:浮点数值的最高精度是 17 位小数,但在进行算术计算时其精确度远远不如整数。

所以:不要直接判断两个浮点数是否相等 !

1
2
3
4
5
6
7
// 2. 浮点数 算数运算里面会有问题(转换成二进制计算后会有误差)
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(0.07 * 100); // 7.000000000000001

// 3. 我们不能直接拿着浮点数来进行相比较 是否相等
var num = 0.1 + 0.2;
console.log(num == 0.3); // false

递增和递减运算符

如果需要反复给数字变量添加或减去1,可以使用递增(++)和递减( – )运算符来完成。

在 JavaScript 中,递增(++)和递减( – )既可以放在变量前面,也可以放在变量后面。放在变量前面时,我 们可以称为前置递增(递减)运算符放在变量后面时,我们可以称为后置递增(递减)运算符

注意:递增和递减运算符必须和变量配合使用。

1
2
3
4
5
// 想要一个变量自己加1 num = num + 1 比较麻烦
var num = 1;
num = num + 1; // ++num
num = num + 1;
console.log(num); // 3

前置递增运算符

++num 前置递增,就是自加1,类似于 num = num + 1,但是 ++num 写起来更简单。

使用口诀:先自加,后返回值

1
2
3
4
5
6
7
8
// 前置递增运算符 ++ 写在变量的前面
var age = 10;
++age; // 类似于 age = age + 1
console.log(age); // 11

// 先加1 后返回值
var p = 10;
console.log(++p + 10); // 21 11 + 10 = 21

后置递增运算符

num++ 后置递增,就是自加1,类似于 num = num + 1 ,但是 num++ 写起来更简单。

使用口诀:先返回原值,后自加

1
2
3
4
5
6
7
8
var num = 10;
num++; // num = num + 1 ;
console.log(num);
// 1. 前置自增和后置自增如果单独使用 效果是一样的
// 2. 后置自增 口诀:先返回原值 后自加1
var age = 10;
console.log(age++ + 10); //20 先返回原值10 然后再+10(参与运算) 所以等于20
console.log(age); // 11 后自加1

练习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var a = 10;
++a; // 11
var b = ++a + 2; // 12 + 2 = 14
console.log(b); // 14

var c = 10;
c++; // 11
var d = c++ + 2; // 10 + 2 = 12
console.log(d); // 12 +1 = 13(运算后再加1)

var e = 10;
var f = e++ + ++e; // e++ = 10 代码从左往右算,e++已经返回原值,再+1,所以现在e=11,所以 ++e = 12
console.log(f); // 22
// 后置自增 先表达式返回原值 后面变量再自加1

比较运算符

比较运算符(关系运算符)是两个数据进行比较时所使用的运算符,比较运算后,会返回一个布尔值 (true / false)作为比较运算的结果。

运算符名称 说明 案例 结果
< 小于号 1 < 2 true
> 大于号 1 > 2 false
>= 大于等于号(大于或者等于) 2 >= 2 true
<= 小于等于号(小于或者等于) 3 <=2 false
== 判等号(会转型) 37 == 37 true
!= 不等号 37 !=37 false
=== !== 全等 要求值和数据类型都一致 37 === ‘37’ false
1
2
3
4
5
6
7
8
9
10
11
12
13
14
console.log(3 >= 5); // false
console.log(2 <= 4); // true

// 1. 我们程序里面的等于符号 是 ==
console.log(3 == 5); // false
console.log('pink老师' == '刘德华' ); // flase
// 默认转换数据类型 会把字符串型的数据转换为数字型 只要求值相等就可以
console.log(18 == 18); // true
console.log(18 == '18' ); // true '18'是字符串,会自动转换为数字型
console.log(18 != 18); // false

// 2. 我们程序里面有全等 一模一样 要求 两侧的值 还有 数据类型完全一致才可以 true
console.log(18 === 18);
console.log(18 === '18' ); // false
符号 作用 用法
= 赋值 把右边给左边
== 判断 判断两边值是否相等(注意此时有隐式转换)
=== 全等 判断两边的值和数据类型是否完全相同

逻辑运算符

逻辑运算符是用来进行布尔值运算的运算符,其返回值也是布尔值。后面开发中经常用于多个条件的判断。

1
2
3
4
5
6
7
8
9
// 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
console.log(!false); // true

短路运算(逻辑中断)

短路运算的原理:当有多个表达式(值)时,左边的表达式值可以确定结果时,就不再继续运算右边的表达式的值;

逻辑与

语法: 表达式1 && 表达式2

  • 如果第一个表达式的值为真,则返回表达式2
  • 如果第一个表达式的值为假,则返回表达式1
1
2
3
4
5
6
7
8
// 1. 用我们的布尔值参与的逻辑运算 true && false == false
// 2. 123 && 456 是值 或者是 表达式 参与逻辑运算?
// 3. 逻辑与短路运算 如果表达式1 结果为真 则返回表达式2 如果表达式1为假 那么返回表达式1
console.log(123 && 456); // 456 123是数字,所以为真,返回表达式2,除了0之外所有数字都是真的
console.log(0 && 456); // 0 0是假的,所以返回表达式1
console.log(0 && 1 + 2 && 456 * 56789); // 0
console.log('' && 1 + 2 && 456 * 56789); // ''
// 如果有空的或者否定的为假 其余是真的 0 '' null undefined NaN
逻辑或

语法: 表达式1 || 表达式2

  • 如果第一个表达式的值为真,则返回表达式1
  • 如果第一个表达式的值为假,则返回表达式2
1
2
3
4
5
6
7
8
// 4. 逻辑或短路运算 如果表达式1 结果为真 则返回的是表达式1 如果表达式1 结果为假 则返回表达式2
console.log(123 || 456); // 123
console.log(123 || 456 || 456 + 123); // 123
console.log(0 || 456 || 456 + 123); // 456
// 逻辑中断很重要 它会影响我们程序运行结果
var num = 0;
console.log(123 || num++); // 123
console.log(num); // 0

赋值运算符

用来把数据赋值给变量的运算符。

赋值运算符 说明 案例
= 直接赋值 var usrName = ‘我是值’;
+= 加、减一个数后再赋值 var age=10; age += 5; // 15
*=、/=、%= 乘、除、取模后再赋值 var age=2; age *= 5; // 10
1
2
3
4
var age = 10;
age += 5; // 相当于 age = age + 5;
age -= 5; // 相当于 age = age - 5;
age *= 10; // 相当于 age = age * 10;

运算符优先级

优先级 运算符 顺序
1 小括号 ()
2 一元运算符 ++ – !
3 算术运算符 先 * / % 后 + -
4 关系运算符 > >= < <=
5 相等运算符 == != === !==
6 逻辑运算符 先&& 后
7 赋值运算符 =
8 逗号运算符 ,
  • 一元运算符里面的逻辑非优先级很高
  • 逻辑与比逻辑或优先级高
1
2
3
console.log(4 >= 6 || '人' != '阿凡达' && !(12 * 2 == 144) && true)
// 4>=6 false , '人' != '阿凡达' true , !(12 * 2 == 144) true , true true
//先&&后||,后面三个都为true,所以true,false||true,(||有一个为true结果就为true),最终结果为true

流程控制

在一个程序执行的过程中,各条代码的执行顺序对程序的结果是有直接影响的。很多时候我们要通过控制代码的执行 顺序来实现我们要完成的功能。

简单理解:流程控制就是来控制代码按照一定结构顺序来执行

流程控制主要有三种结构,分别是顺序结构分支结构循环结构,代表三种代码执行的顺序。

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

分支流程控制

分支结构:由上到下执行代码的过程中,根据不同的条件,执行不同的路径代码(执行代码多选一的过程),从而得到 不同的结果。

JS 语言提供了两种分支结构语句:if 语句、switch 语句

if 语句

语法结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 1. if 的语法结构 如果if
if (条件表达式) {
// 执行语句
}

// 例如1:
if (3 < 5) {
alert('沙漠骆驼');
} // 弹出“沙漠骆驼”警示框

// 例如2:
if (3 > 5) {
alert('沙漠骆驼');
} // 什么都没有
执行思路
  • 如果 if 里面的条件表达式结果为真 true, 则执行大括号{}里面的执行语句
  • 如果if 条件表达式结果为假,则不执行大括号里面的语句,则执行if 语句后面的代码

案例

弹出一个输入框,要求输入年龄,如果年龄大于等于18岁,允许进网吧。

1
2
3
4
5
6
7
// 弹出 prompt 输入框,用户输入年龄, 程序把这个值取过来保存到变量中
// 使用 if 语句来判断年龄,如果年龄大于18,就执行 if 大括号里面的输出语句

var age = prompt("请输入您的年龄");
if (age >= 18) {
alert("允许")
}

if else 语句(双分支语句)

语法结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 1. 语法结构 if 如果 else 否则
if (条件表达式) {
// 执行语句1
} else {
// 执行语句2
}

// 例如:
var age = prompt("请输入您的年龄");
if (age >= 18) {
alert("允许")
} else{
alert("拒绝")
}
执行思路
  • 如果表达式结果为真,那么执行语句1,否则执行语句2。

  • if里面的语句1 和 else 里面的语句2,最终只能有一个语句执行,2选1

  • else 后面直接跟大括号

案例

1.接收用户输入的年份,如果是闰年就弹出闰年,否则弹出平年

算法:能被4整除不能整除100的为闰年(如2004年就是闰年,1901年不是闰年)或者能够被 400 整除的就是闰年

1
2
3
4
5
6
7
8
9
10
// 弹出prompt 输入框,让用户输入年份,把这个值取过来保存到变量中
// 使用 if 语句来判断是否是闰年,如果是闰年,就执行 if 大括号里面的输出语句,否则就执行 else里面的输出语句
// 一定要注意里面的且 && 还有或者 || 的写法,同时注意判断整除的方法是取余为 0

var year = prompt("请您输入要检测的年份:");
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
alert("您输入的年份是闰年")
} else{
alert("您输入的年份是平年")
}

2.判断是否中奖:接收用户输入的姓名,来判断是否中奖,如果输入的是刘德华,则提示中了5块钱,否则提示没有中奖。

1
2
3
4
5
6
var name = prompt("请输入您的姓名:");
if (name == '刘德华') {
alert("恭喜您中了5块钱")
} else{
alert("谢谢参与")
}

if else if 语句(多分支语句)

语法结构
1
2
3
4
5
6
7
8
9
10
11
// 1. 多分支语句   就是利用多个条件来选择不同的语句执行 得到不同的结果  多选1 的过程
// 2. if else if语句是多分支语句
if (条件表达式1) {
// 语句1;
} else if (条件表达式2) {
// 语句2;
} else if (条件表达式3) {
// 语句3;
} else {
// 最后的语句;
}
执行思路
  • 如果条件表达式1满足,就执行语句1,执行完毕后,退出整个if 分支语句。
  • 如果条件表达式1不满足,则判断条件表达式2,满足的话,执行语句2,以此类推。
  • 如果上面的所有条件表达式都不成立,则执行else 里面的语句。

注意
  • 多分支语句还是多选1,最后只能有一个语句执行。
  • else if 里面的条件理论上是可以任意多个的。
  • else if 中间有个空格了。
案例

判断成绩等级

要求:接收用户输入的分数,根据分数输出对应的等级字母A、B、C、D、E.。

其中:

  1. 90分(含)以上,输出:A
  2. 80分(含)~90分(不含),输出:B
  3. 70分(含)~80分(不含),输出:C
  4. 60分(含)~70分(不含),输出:D
  5. 60分(不含),输出:E
1
2
3
4
5
6
7
8
9
10
11
12
var fs = prompt("请输入您的分数:");
if (fs >= 90) {
alert("A")
} else if (fs >= 80 && fs < 90) {
alert("B")
} else if (fs >= 70 && fs < 80) {
alert("C")
} else if (fs >= 60 && fs < 70) {
alert("D")
} else {
alert("E")
}

三元表达式

三元表达式也能做一些简单的条件选择。有三元运算符组成的式子我们称为三元表达式。

一元:++num 二元: 3 + 5

语法结构
1
2
3
4
5
条件表达式 ? 表达式1 : 表达式2

var num = 10;
var result = num > 5 ? '是的' : '不是的' // 我们知道表达式是有返回值的
console.log(result); // 是的
执行思路

如果条件表达式结果为真,则返回表达式1的值,如果条件表达式结果为假,则返回表达式2的值。

案例

数字补0:用户输入数字,如果数字小于10,则在前面补0,比如01,09,如果数字大于10,则不需要补0,例如20。

1
2
3
4
5
6
7
// 用户输入0~59之间的一个数字
// 如果数字小于10,则在这个数字前面补0,(加0 拼接) 否则 不做操作
// 用一个变量接受这个返回值,输出

var num = prompt("请您输入0~59之间的一个数字");
var result = num < 10 ? '0' + num : num;
alert(result);

switch 语句

switch 语句也是多分支语句,它用于基于不同的条件来执行不同的代码。当要针对变量设置一系列的特定值的选项时,就可以使用 switch。

语法结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 1. switch 语句也是多分支语句 也可以实现多选1
// 2. 语法结构 switch 转换、开关
switch(表达式) {
case value1:
执行语句1;
break;
case value2:
执行语句2;
break;
...
default:
执行最后的语句;
}

// 例如:
switch (2) {
case 1:
console.log('这是1');
break;
case 2:
console.log('这是2');
break;
case 3:
console.log('这是3');
break;
default:
console.log('没有匹配结果');
} // 这是2
执行思路

利用我们的表达式的值和 case 后面的选项值相匹配,如果匹配上,就执行该case 里面的语句,如果都没有匹配上,那么执行 default里面的语句。

注意
  1. 我们开发里面,表达式我们经常写成变量。
  2. 我们num 的值 和 case 里面的值相匹配的时候是全等,必须是值和数据类型一致才可以 num === 1。
  3. break 如果当前的case里面没有break,则不会退出switch,是继续执行下一个case。
案例

查询水果:用户在弹出框里面输入一个水果,如果有就弹出该水果的价格,如果没有该水果就弹出“没有此水果”。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 弹出 prompt 输入框,让用户输入水果名称,把这个值取过来保存到变量中。
// 将这个变量作为 switch 括号里面的表达式。
// case 后面的值写几个不同的水果名称,注意一定要加引号 ,因为必须是全等匹配。
// 弹出不同价格即可。同样注意每个 case 之后加上 break ,以便退出 switch 语句。
// 将 default 设置为没有此水果。

var fruit = prompt('请您输入查询的水果:');
switch (fruit) {
case '苹果':
alert('苹果的价格是 3.5/斤');
break;
case '榴莲':
alert('榴莲的价格是 35/斤');
break;
default:
alert('没有此水果');
}

区别

switch 语句和 if else if 语句的区别:

  • 一般情况下,它们两个语句可以相互替换。
  • switch…case 语句通常处理 case为比较确定值的情况, 而 if…else…语句更加灵活,常用于范围判断(大于、等于某个范围)。
  • switch 语句进行条件判断后直接执行到程序的条件语句,效率更高。而if…else 语句有几种条件,就得 判断多少次。
  • 当分支比较少时,if… else语句的执行效率比 switch语句高。
  • 当分支比较多时,switch语句的执行效率比较高,而且结构更清晰。

作业

①判断时间阶段。

通过弹出框提示用户输入时间信息,根据用户输入的时间弹出问候信息;

如: 用户输入的时间在6-12之间 弹出“上午好”; 用户输入的时间在13-18之间 弹出“下午好”; 用户输入的时间在19-23之间 弹出“晚上好”; 用户输入的时间在0-5之间 弹出“这是休息时间,不要说话!”;

1
2
3
4
5
6
7
8
9
10
11
12
var time = prompt('请输入时间点:');
if (time >= 6 && time <= 12) {
alert("上午好");
} else if (time >= 13 && time <= 18) {
alert("下午好");
} else if (time >= 19 && time <= 23) {
alert("晚上好");
} else if (time >= 0 && time <= 5) {
alert("这是休息时间,不要说话!");
} else{
alert("请输入0-24之间的数字表示时间点")
}

②比较两个数的最大值(用户依次输入2个值,最后弹出最大的那个值)

1
2
3
4
5
6
7
8
9
10
11
12
//  var num=Number(prompt('请输入一个数')):使用Number()转换数据类型。因为prompt输入的数据默认是字符串类型,要变成数字类型,就要转换数据类型;而不知道是转换成什么数据类型,就用Number().
var num1 = Number(prompt('请输入第一个数'));
var num2 = Number(prompt('请输入第二个数'));
if (num1 > num2) {
alert("最大值:" + num1);
} else {
alert("最大值:" + num2);
}

// parseInt()是转换成整数型
// parseFloat()是转换成浮点数
// Number()是转换成数字型。

③用户输入一个数,来判断是奇数还是偶数。(偶数能被2整除)

1
2
3
4
5
6
var num = Number(prompt('请输入一个数'));
if (num % 2 == 0) {
alert(num + '为偶数!');
} else {
alert(num + '为奇数。');
}

④假设这个月1号是星期一,提示用户输入本月的日期(即1日-31日),返回用户输入日期是星期几。(利用%和7取余,再判定是星期几)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var date = prompt('请输入日期数');
if (date == 1 || date % 7 == 1) {
alert("今天是星期一");
} else if (date == 2 || date % 7 == 2) {
alert("今天是星期二");
} else if (date == 3 || date % 7 == 3) {
alert("今天是星期三");
} else if (date == 4 || date % 7 == 4) {
alert("今天是星期四");
} else if (date == 5 || date % 7 == 5) {
alert("今天是星期五");
} else if (date == 6 || date % 7 == 6) {
alert("今天是星期六");
} else if (date == 7 || date % 7 == 0) {
alert("今天是星期天");
}

⑤接收班长口袋里的钱数?若大于等于2000,请大家吃西餐。若小于2000,大于等于1500,请大家吃快餐。若小于1500,大于等于1000,请大家喝饮料。若小于1000,大于等于500,请大家吃棒棒糖。否则提醒班长下次把钱带够。

1
2
3
4
5
6
7
8
9
10
11
12
var money = Number(prompt('请输入一个数'));        
if (money >= 2000) {
alert("请大家吃西餐");
} else if (money >= 1500 && money < 2000) {
alert("请大家吃快餐");
} else if (money >= 1000 && money < 1500) {
alert("请大家喝饮料");
} else if (money >= 500 && money < 1000) {
alert("请大家吃棒棒糖");
} else {
alert("班长下次把钱带够");
}

⑥分数转换,给一个分数,判定等级。大于等于90A,大于等于80小于90B,大于等于70小于80 C,大于等于60小于70D,小于60E

1
2
3
4
5
6
7
8
9
10
11
12
var fs = prompt("请输入您的分数:");
if (fs >= 90) {
alert("A")
} else if (fs >= 80 && fs < 90) {
alert("B")
} else if (fs >= 70 && fs < 80) {
alert("C")
} else if (fs >= 60 && fs < 70) {
alert("D")
} else {
alert("E")
}

循环

循环的目的:在实际问题中,有许多具有规律性的重复操作,因此在程序中要完成这类操作就需要重复执行某些语句

JS 中的循环,主要有三种类型的循环语句:

  • for 循环
  • while 循环
  • do…while 循环

for 循环

在程序中,一组被重复执行的语句被称之为循环体,能否继续重复执行,取决于循环的终止条件。由循环体及循环的终止条件组成的语句,被称之为循环语句

语法结构
1
2
3
4
5
6
for (初始化变量; 条件表达式; 操作表达式) {
//循环体
}
// 初始化变量 就是用var 声明的一个普通变量, 通常用于作为计数器使用
// 条件表达式 就是用来决定每一次循环是否继续执行 就是终止的条件
// 操作表达式 是每次循环最后执行的代码 经常用于我们计数器变量进行更新(递增或者递减)
1
2
3
4
5
6
7
8
// 代码体验 我们重复打印100局 你好
for (var i = 1; i <= 100; i++) {
console.log('你好吗');
}
// 1. 首先执行里面的计数器变量 var i = 1 .但是这句话在for 里面只执行一次
// 2. 去 i <= 100 来判断是否满足条件, 如果满足条件 就去执行 循环体(console.log('你好吗');) 不满足条件退出循环
// 3. 最后去执行 i++ i++是单独写的代码 递增 第一轮结束
// 4. 接着去执行 i <= 100 如果满足条件 就去执行 循环体 不满足条件退出循环 第二轮

断点调试

断点调试是指自己在程序的某一行设置一个断点,调试时,程序运行到这一行就会停住,然后你可以一步一步往下调试,调试过程中可以看各个变量当前的值,出错的话,调试到出错的代码行即显示错误,停下。

断点调试可以帮我们观察程序的运行过程

浏览器中按F12–> sources –>找到需要调试的文件–>在程序的某一行设置断点

Watch: 监视,通过watch可以监视变量的值的变化,非常的常用。

F11: 程序单步执行,让程序一行一行的执行,这个时候,观察watch中变量的值的变化。

代码调试的能力非常重要,只有学会了代码调试,才能学会自己解决bug的能力。初学者不要觉得调试代码麻烦就不去调试,知识点花点功夫肯定学的会,但是代码调试这个东西,自己不去练,永远都学不会。

for 循环重复相同的代码
1
2
3
4
5
6
7
8
9
10
//  基本写法
for(var i = 1; i <= 10; i++){
console.log('学习!');
}

// 用户输入次数
var num = prompt('请输入次数:');
for ( var i = 1 ; i <= num; i++) {
console.log('学习!');
}
for 循环重复不相同的代码

for 循环可以重复执行不同的代码 因为我们有计数器变量 i 的存在 i每次循环值都会变化

例如:我们想要输出1个人 1~100岁

1
2
3
for (var i = 1; i <= 100; i++) {
console.log('这个人今年' + i + '岁了');
}
1
2
3
4
5
6
7
8
9
10
// 多分支
for (var i = 1; i <= 100; i++) {
if (i == 1) {
console.log('这个人今年1岁了,他出生了');
} else if (i == 100) {
console.log('这个人今年100岁了,他');
} else {
console.log('这个人今年' + i + '岁了');
}
}
for 循环重复某些相同操作

1-100之间所有整数的累加和

分析:

  • 需要循环100次,我们需要一个计数器 i
  • 我们需要一个存储结果的变量 sum ,但是初始值一定是 0
  • 核心算法:1 + 2 + 3 + 4 …. ,sum = sum + i ;
1
2
3
4
5
6
var sum = 0; // 求和 的变量
for (var i = 1; i <= 100; i++) {
// sum = sum + i;
sum += i;
}
console.log(sum); // 5050
案例
  1. 求1-100之间所有数的平均值
1
2
3
4
5
6
7
8
var sum = 0; // 求和 的变量
var average = 0;
for (var i = 1; i <= 100; i++) {
// sum = sum + i;
sum += i;
}
average = sum / 100;
console.log(average);
  1. 求1-100之间所有偶数和奇数的和
1
2
3
4
5
6
7
8
9
10
11
12
// 我们需要一个偶数的和变量 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);
  1. 求1-100之间所有能被3整除的数字的和
1
2
3
4
5
6
7
8
var result = 0;
for (var i = 1; i <= 100; i++) {
if (i % 3 == 0) {
// result = result + i;
result += i;
}
}
console.log('1~100之间能够被3整数的数字的和是:' + result);
  1. 求学生成绩

要求用户输入班级人数,之后依次输入每个学生的成绩,最后打印出该班级总的成绩以及平均成绩。

  • 弹出输入框输入总的班级人数(num)
  • 依次输入学生的成绩( 保存起来 score), 此时我们需要用到for 循环, 弹出的次数跟班级总人数有关系 条件表达式 i <= num
  • 进行业务处理: 计算成绩。 先求总成绩( sum), 之后求平均成绩( average)
  • 弹出结果
1
2
3
4
5
6
7
8
9
10
11
var num = prompt('请输入班级的总人数:'); // num 总的班级人数
var sum = 0; // 求和的变量
var average = 0; // 求平均值的变量
for (var i = 1; i <= num; i++) {
var score=prompt('请您输入第' + i + '个学生成绩' );
// 因为从prompt取过来的数据是 字符串型的需要转换为数字型 sum=sum +
parseFloat(score);
}
average=sum / num;
alert('班级总的成绩是' + sum);
alert('班级平均分是:' + average);
  1. 一行打印五个星星

采取追加字符串的方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 一行5个星星
var str = '';
for (var i = 1; i <= 5; i++) {
str = str + '★'
}
console.log(str);


// 自己设定多少个星星
var num = prompt('请输入星星的个数');
var str = '';
for (var i = 1; i <= num; i++) {
str = str + '★'
}
console.log(str);

双重for 循环

很多情况下,单层 for 循环并不能满足我们的需求,比如我们要打印一个 5 行 5 列的图形、打印一个倒直角三角形等,此时就可以通过循环嵌套来实现。

循环嵌套是指在一个循环语句中再定义一个循环语句的语法结构,例如在for循环语句中,可以再嵌套一个for 循环,这样的 for 循环语句我们称之为双重for循环。

语法结构
1
2
3
4
5
6
7
8
for (外层的初始化变量; 外层的条件表达式; 外层的操作表达式) {
for (里层的初始化变量; 里层的条件表达式; 里层的操作表达式) {
// 执行语句;
}
}

// 我们可以把里面的循环看做是外层循环的语句
// 外层循环循环一次, 里面的循环执行全部
1
2
3
4
5
6
7
8
// 代码验证
for (var i = 1; i <= 3; i++) {
console.log('这是外层循环第' + i + '次');
for (var j = 1; j <= 3; j++) {
console.log('这是里层的循环第' + j + '次');

}
}

打印五行五列星星

核心:

  • 内层循环负责一行打印五个星星
  • 外层循环负责打印五行
1
2
3
4
5
6
7
8
9
10
// 打印五行五列星星
var str = '';
for (var i = 1; i <= 5; i++) { // 外层循环负责打印五行
for (var j = 1; j <= 5; j++) { // 里层循环负责一行打印五个星星
str = str + '★';
}
// 如果一行打印完毕5个星星就要另起一行 加 \n
str = str + '\n';
}
console.log(str);
案例
  1. 打印n行n列的星星
1
2
3
4
5
6
7
8
9
10
var hang = prompt('请输入您打印几行星星:');
var lie = prompt('请输入您打印几列星星:');
var str = '';
for (var i = 1; i <= hang; i++) {
for (var j = 1; j <= lie; j++) {
str = str + '⭐';
}
str = str + '\n';
}
console.log(str);
  1. 打印倒三角形
1
2
3
4
5
6
7
8
9
10
11
var str = '';
for (var i = 1; i <= 10; i++) { // 外层循环控制行数
for (var j = i; j <= 10; j++) { // 里层循环打印的个数不一样 j = i
str = str + '⭐';
}
str = str + '\n';
}
console.log(str);

// i=1表示第一行,外循环,然后j=i即j=1,但后面有j小于等于10,因为有外层循环循环一次, 里面的循环执行全部,所以内循环要全部执行,然后j是从1开始的,即执行10次,所以有10颗星星。
//
  1. 打印正三角形
1
2
3
4
5
6
7
8
var str = '';
for (var i = 1; i <= 10; i++) { // 外层循环控制行数
for (var j = 1; j <= i; j++) {
str = str + '⭐';
}
str = str + '\n';
}
console.log(str);
  1. 打印九九乘法表
1
2
3
4
5
6
7
8
var str = '';
for (var i = 1; i <= 9; i++) { // 外层循环控制行数
for (var j = 1; j <= i; j++) {
str += j + '×' + i + '=' + i * j + '\t';
}
str = str + '\n';
}
console.log(str);

i =1时,j <= 1所以 j 只循坏一次,然后 j = 1,j 只能等于1,所以就是第一行1 x 1 = 1;

i =2时,j <= 2所以 j 循坏两次,然后 j = 1,j 可取数:1、2,所以就是第二行1 x 1 = 1 1 x 2 = 2;

以此类推

while 循环

while 语句可以在条件表达式为真的前提下,循环执行指定的一段代码,直到表达式不为真时结束循环。

语法结构
1
2
3
4
5
6
// while 当... 的时候
while (条件表达式) {
// 循环体代码
}

// 执行思路:当条件表达式结果为true 则执行循环体 否则 退出循环
1
2
3
4
5
6
7
8
9
// 代码验证
var num = 1;
while (num <= 100) {
console.log('学习');
num++;
}

// 里面应该也有计数器 初始化变量
// 里面应该也有操作表达式 完成计数器的更新 防止死循环
案例
  1. 打印人的一生,从1岁到100岁。
1
2
3
4
5
var i = 1;
while (i <= 100) {
console.log('这个人今年' + i + '岁了');
i++;
}
  1. 计算 1 ~ 100 之间所有整数的和
1
2
3
4
5
6
7
var sum = 0;
var j = 1;
while (j <= 100) {
sum += j;
j++
}
console.log(sum);
  1. 弹出一个提示框, 你爱我吗? 如果输入我爱你,就提示结束,否则,一直询问。
1
2
3
4
5
var message = prompt('你爱我吗?');
while (message !== '我爱你') {
message = prompt('你爱我吗?');
}
alert('我也爱你啊!');

do while 循环

do… while 语句其实是 while 语句的一个变体。该循环会先执行一次代码块,然后对条件表达式进行判断,如果条件为真,就会重复执行循环体,否则退出循环。

语法结构
1
2
3
4
5
do {
// 循环体
} while (条件表达式)

// 执行思路 跟while不同的地方在于 do while 先执行一次循环体 在判断条件 如果条件表达式结果为真,则继续执行循环体,否则退出循环
1
2
3
4
5
6
7
// 代码验证
var i = 1;
do {
console.log('how are you?');
i++;
} while (i <= 100)
// 我们的do while 循环体至少执行一次
案例
  1. 打印人的一生,从1岁到100岁。
1
2
3
4
5
var i = 1;
do {
console.log('这个人今年' + i + '岁了');
i++;
} while (i <= 100)
  1. 计算 1 ~ 100 之间所有整数的和
1
2
3
4
5
6
7
var sum = 0;
var j = 1;
do {
sum += j;
j++;
} while (j <= 100)
console.log(sum);
  1. 弹出一个提示框, 你爱我吗? 如果输入我爱你,就提示结束,否则,一直询问。
1
2
3
4
do {
message = prompt('你爱我吗?');
} while (message !== '我爱你')
alert('我也爱你啊!');

continue

continue 关键字用于立即跳出本次循环继续下一次循环(本次循环体中 continue 之后的代码就会少执行一次)。

例如,吃5个包子,第3个有虫子,就扔掉第3个,继续吃第4个第5个包子,其代码实现如下:

1
2
3
4
5
6
7
8
// continue 关键字   退出本次(当前次的循环)  继续执行剩余次数循环

for (var i = 1; i <= 5; i++) {
if (i == 3) {
continue; // 当i=3时,退出本次循环,不跳到下面的代码,回到i++上,然后进行其他的循环。
}
console.log('我正在吃第' + i + '个包子');
}
1
2
3
4
5
6
7
8
9
// 求1~100 之间, 除了能被7整除之外的整数和 
var sum = 0;
for (var i = 1; i <= 100; i++) {
if (i % 7 == 0) {
continue;
}
sum += i;
}
console.log(sum);

break

break 关键字用于立即跳出整个循环(循环结束)。

例如,吃5个包子,吃到第3个发现里面有半个虫子,其余的不吃了,其代码实现如下:

1
2
3
4
5
6
7
8
// break 退出整个循环

for (var i = 1; i <= 5; i++) {
if (i == 3) {
break;
}
console.log('我正在吃第' + i + '个包子');
}

作业

  1. 求1-100之间所有数的总和与平均值
1
2
3
4
5
6
7
8
var sum = 0;
var average = 0;
for (var i = 1; i <= 100; i++) {
sum += i;
}
average = sum / 100;
console.log(sum);
console.log(average);
  1. 求1-100之间所有偶数的和
1
2
3
4
5
6
7
var sum = 0;
for (var i = 1; i <= 100; i++) {
if (i % 2 == 0) {
sum += i;
}
}
console.log(sum);
  1. 求100以内7的倍数的总和
1
2
3
4
5
6
7
var sum = 0;
for (var i = 1; i <= 100; i++) {
if (i % 7 == 0) {
sum += i;
}
}
console.log(sum);
  1. 使用for 循环打印矩形,要求每次只能输出一个☆

    ☆☆☆☆☆

    ☆☆☆☆☆

    ☆☆☆☆☆

    ☆☆☆☆☆

1
2
3
4
5
6
7
8
var str = '';
for (var i = 1; i <= 5; i++) {
for (var j = 1; j <= 5; j++) {
str = str + '★'
}
str = str + '\n'
}
console.log(str);
  1. 使用for循环打印三角形

    ☆☆

    ☆☆☆

    ☆☆☆☆

    ☆☆☆☆☆

1
2
3
4
5
6
7
8
var str = '';
for (var i = 1; i <= 5; i++) {
for (var j = 1; j <= i; j++) {
str = str + '★'
}
str = str + '\n'
}
console.log(str);
  1. 使用for循环打印99乘法表
1
2
3
4
5
6
7
8
var sum = '';
for (var i = 1; i <= 9; i++) {
for (var j = 1; j <= i; j++) {
sum = sum + j + 'x' + i + '=' + j * i + '\t';
}
sum = sum + '\n'
}
console.log(sum);
  1. 接收用户输入的用户名和密码,若用户名为 “admin” ,密码为 “123456” ,则提示用户登录成功! 否则,让用户一直输入。
1
2
3
4
5
6
7
var message1 = prompt('请输入用户名');
var message2 = prompt('请输入密码');
while (message1 !== 'admin' && message2 !== '123456') {
var message1 = prompt('请输入用户名');
var message2 = prompt('请输入密码');
}
alert('登录成功!');
  1. 求整数1~100的累加值,但要求跳过所有个位为3的数【用continue实现】。
1
2
3
4
5
6
7
8
var sum = 0;
for (var i = 1; i <= 100; i++) {
if (i % 10 == 3) { // 除以10的余数为3,即个位数为3
continue;
}
sum += i;
}
console.log(sum);

简易ATM

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// while(true)就是无限循环语句。因为括号中的条件为true,所以永远不会跳出循环,除非语句块中有break语句才都能跳出循环。
var yue = 100;
while (true) {
var message = prompt('请输入您要的操作:\n 1.存钱 \n 2.取钱 \n 3.显示余额 \n 4.退出');
if (message == '1') {
var cunqian = parseFloat(prompt('请您输入存的钱数:'));
yue += cunqian;
alert('您现在的钱数是:' + yue);
} else if (message == '2') {
var quqian = parseFloat(prompt('请您输入取的钱数:'));
yue -= quqian;
alert('您现在的钱数是:' + yue);
} else if (message == '3') {
alert('您现在的钱数是:' + yue);
} else if (message == '4') {
alert('正在退出');
break
}
}

数组

数组是指一组数据的集合,其中的每个数据被称作元素,在数组中可以存放任意类型的元素。数组是一种将一组数据存储在单个变量名下的优雅方式。

1
2
3
4
// 普通变量一次只能存储一个值
var num = 10;
// 数组一次可以存储多个值
var arr = [1,2,3,4,5];

数组的创建方式

JS 中创建数组有两种方式:

  • 利用 new 创建数组
  • 利用数组字面量创建数组

利用 new 创建数组

1
2
var 数组名 = new Array() ;
var arr = new Array(); // 创建一个新的空数组
  • 这种方式暂且了解,等学完对象再看
  • 注意 Array () ,A 要大写

利用数组字面量创建数组

1
2
3
4
// 1. 使用数组字面量方式创建空的数组
var 数组名 = [];
// 2. 使用数组字面量方式创建带初始值的数组
var 数组名 = ['小白','小黑','大黄','瑞奇'];
  • 数组的字面量是方括号 [ ]
  • 声明数组并赋值称为数组的初始化
  • 这种字面量方式也是我们以后最多使用的方式

数组中可以存放任意类型的数据,例如字符串,数字,布尔值等。

1
2
3
4
var arr = []; //创建了一个空的数组
var arr1 = [1,2,'学习',true];
// 我们数组里面的数据一定用逗号分隔
// 数组里面的数据 比如1,2, 我们称为数组元素

数组的索引

索引 (下标) :用来访问数组元素的序号(数组下标从 0 开始)。

1
2
var  arr = ['小白','小黑','大黄','瑞奇'];
索引号: 0 1 2 3

数组可以通过索引来访问、设置、修改对应的数组元素,我们可以通过“数组名[索引]”的形式来获取数组中的元素。
这里的访问就是获取得到的意思

1
2
3
4
5
var arr1 = [1,2,'学习',true];
console.log(arr1);
console.log(arr1[2]); // 学习
console.log(arr1[3]); // true
console.log(arr1[4]); // 因为没有这个数组元素 所以输出的结果是 undefined

练习:定义一个数组,里面存放星期一、星期二…… 直到星期日(共7天),在控制台输出:星期日,请同学们自己动手完成。

1
2
var arr = ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日',];
console.log(arr[6]);

遍历数组

遍历: 就是把数组中的每个元素从头到尾都访问一次(类似我们每天早上学生的点名)。
我们可以通过 for 循环索引遍历数组中的每一项

1
2
3
4
5
6
var arr = ['red', 'green', 'blue'];
for (var i = 0; i < 3; i++) {
console.log(arr[i]);
}
// 1. 因为我们的数组索引号从0开始 ,所以 i 必须从 0开始 i < 3
// 2. 输出的时候 arr[i] i 计数器当索引号来用

数组长度

使用“数组名.length”可以访问数组元素的数量(数组长度)。

1
2
var arr = ['关羽', '张飞', '马超', '赵云', '黄忠', '刘备', '姜维'];
console.log(arr.length);
1
2
3
4
5
6
7
8
9
var arr = ['关羽', '张飞', '马超', '赵云', '黄忠', '刘备', '姜维', 'pink'];
// for (var i = 0; i < 7; i++) {
// console.log(arr[i]);
// }
// console.log(arr.length);

for (var i = 0; i < arr.length; i++) {
console.log(arr[i]);
}

注意:

  1. 数组的长度是元素个数 ,不要跟索引号混淆

  2. arr.length 动态监测数组元素的个数

案例

1.数组求和及平均值

求数组 [2,6,1,7, 4] 里面所有元素的和以及平均值。

1
2
3
4
5
6
7
8
var arr = [2, 6, 1, 7, 4];
var sum = 0;
var average = 0;
for (var i = 0; i < arr.length; i++) {
sum += arr[i]; // 我们加的是数组元素 arr[i] 不是计数器 i
}
average = sum / arr.length;
console.log(sum, average); // 想要输出多个变量,用逗号分隔即可

2.数组最大值

求数组[2,6,1,77,52,25,7]中的最大值。

思路:

①声明一个保存最大元素的变量 max。

②默认最大值可以取数组中的第一个元素。

③遍历这个数组,把里面每个数组元素和 max 相比较。

④如果这个数组元素大于max 就把这个数组元素存到 max 里面,否则继续下一轮比较。

⑤最后输出这个 max。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var arr = [2, 6, 1, 77, 52, 25, 7];
var max = arr[0];
for (var i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
console.log('该数组里面的最大值是:' + max);

// 最小值
var arr = [2, 6, 1, 77, 88, 25, 7];
var min = arr[0];
for (var i = 1; i < arr.length; i++) {
if (arr[i] < min) {
min = arr[i];
}
}
console.log('该数组里面的最小值是:' + min);

3.数组转换为字符串

要求:将数组 [‘red’, ‘green’, ‘blue’, ‘pink’] 里面的元素转换为字符串,并且用|或其他符号分割。

输出: ‘red|green|blue|pink’

1
2
3
4
5
6
7
8
9
10
// 将数组 ['red', 'green', 'blue', 'pink'] 转换为字符串,并且用 | 或其他符号分割
// 1.需要一个新变量用于存放转换完的字符串 str。
// 2.遍历原来的数组,分别把里面数据取出来,加到字符串里面。
// 3.同时在后面多加一个分隔符
var arr = ['red', 'green', 'blue', 'pink'];
var str = arr[0];
for (var i = 1; i < arr.length; i++) {
str = str + '|' + arr[i];
}
console.log(str);

数组中新增元素

通过修改 length 长度新增数组元素

  • 可以通过修改 length 长度来实现数组扩容的目的
  • length 属性是可读写的
1
2
3
4
5
6
7
var arr = ['red', 'green', 'blue'];
console.log(arr.length); // 3
arr.length = 5; // 把我们数组的长度修改为了 5 里面应该有5个元素
console.log(arr);
console.log(arr[3]); // undefined
console.log(arr[4]); // undefined
// 其中索引号是 3,4的空间没有给值,就是声明变量未给值,默认值就是 undefined。

通过修改数组索引新增数组元素

  • 可以通过修改数组索引的方式追加数组元素
  • 不能直接给数组名赋值,否则会覆盖掉以前的数据
1
2
3
4
5
6
7
8
9
10
var arr1 = ['red', 'green', 'blue'];
arr1[3] = 'pink';
console.log(arr1); // ['red', 'green', 'blue', 'pink']
arr1[4] = 'hotpink';
console.log(arr1); // ['red', 'green', 'blue', 'pink', 'hotpink']
arr1[0] = 'yellow'; // 这里是替换原来的数组元素
console.log(arr1); // ['yellow', 'green', 'blue', 'pink', 'hotpink']
arr1 = '有点意思';
console.log(arr1); // 有点意思 之前的数据都没有了
// 不要直接给 数组名赋值 否则里面的数组元素都没有了

案例

1.数组新增元素

新建一个数组,里面存放10个整数( 1~10), 要求使用循环追加的方式输出: [1,2,3,4,5,6,7,8,9,10]

1
2
3
4
5
var arr = [];
for (var i = 0; i < 10; i++) {
arr[i] = i + 1;
}
console.log(arr);

2.筛选数组

要求:将数组 [2, 0, 6, 1, 77, 0, 52, 0, 25, 7] 中大于等于 10 的元素选出来,放入新数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 将数组 [2, 0, 6, 1, 77, 0, 52, 0, 25, 7] 中大于等于 10 的元素选出来,放入新数组。
// 1、声明一个新的数组用于存放新数据newArr。
// 2、遍历原来的旧数组, 找出大于等于 10 的元素。
// 3、依次追加给新数组 newArr。
// 方法1
var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7];
var newArr = [];
var j = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i] >= 10) {
// 新数组索引号应该从0开始 依次递增
newArr[j] = arr[i];
j++;
}
}
console.log(newArr);

// 方法2
var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7];
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);

数组案例

删除指定数组元素

要求:将数组[2, 0, 6, 1, 77, 0, 52, 0, 25, 7]中的 0 去掉后,形成一个不包含 0 的新数组。

1
2
3
4
5
6
7
8
var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7];
var newArr = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i] >= 1) { // 或者 (arr[i] != 0)
newArr[newArr.length] = arr[i];
}
}
console.log(newArr);

翻转数组

要求: 将数组 [‘red’, ‘green’, ‘blue’, ‘pink’, ‘purple’] 的内容反过来存放。

输出: [‘purple’, ‘pink’, ‘blue’, ‘green’, ‘red’]。

1
2
3
4
5
6
7
8
9
// 1、声明一个新数组 newArr
// 2、把旧数组索引号第4个取过来(arr.length - 1),给新数组索引号第0个元素 (newArr.length)
// 3、我们采取 递减的方式 i--
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);

数组排序(冒泡排序)

冒泡排序:是一种算法,把一系列的数据按照一定的顺序进行排列显示(从小到大或从大到小)。

例如,我们可以将数组 [5, 4, 3, 2, 1]中的元素按照从小到大的顺序排序,输出: 1,2,3,4,5。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var arr = [5, 4, 3, 2, 1];
// var arr = [4, 1, 2, 3, 5]; 也是可以排序的
for (var i = 0; i <= arr.length - 1; i++) { // 外层循环管趟数
for (var j = 0; j <= arr.length - i - 1; j++) { // 里面的循环管 每一趟的交换次数
// 内部交换2个变量的值 前一个和后面一个数组元素相比较
if (arr[j] < arr[j + 1]) { // 降序(arr[j] > arr[j + 1])
var temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}

}
}
console.log(arr);

函数

在 JS 里面,可能会定义非常多的相同代码或者功能相似的代码,这些代码可能需要大量重复使用。

虽然 for循环语句也能实现一些简单的重复操作,但是比较具有局限性,此时我们就可以使用 JS 中的函数

函数:就是封装了一段可被重复调用执行的代码块。通过此代码块可以实现大量代码的重复使用。

封装:函数的封装是把一个或者多个功能通过函数的方式封装起来,对外只提供一个简单的函数接口。(简单理解:封装类似于将电脑配件整合组装到机箱中 ( 类似快递打包))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 1. 求 1~100的累加和
var sum = 0;
for (var i = 1; i <= 100; i++) {
sum += i;
}
console.log(sum);

// 2. 求 10~50的累加和
var sum = 0;
for (var i = 10; i <= 50; i++) {
sum += i;
}
console.log(sum);

// 3. 函数就是封装了一段可以被重复执行调用的代码块 目的: 就是让大量代码重复使用
function getSum(num1, num2) {
var sum = 0;
for (var i = num1; i <= num2; i++) {
sum += i;
}
console.log(sum);
}
getSum(1, 100);
getSum(10, 50);
getSum(1, 1000);

函数的使用

函数在使用时分为两步:声明函数和调用函数。

声明函数

1
2
3
4
5
6
7
8
9
// 语法结构
function 函数名() {
// 函数体
}

// 例如:
function sayHi() {
console.log('hi~~');
}

(1) function 声明函数的关键字 全部小写

(2) 函数是做某件事情,函数名一般是动词 sayHi

(3) 函数不调用自己不执行

调用函数

1
2
3
4
5
// 语法结构
函数名();

// 例如:
sayHi();

调用函数的时候千万不要忘记加小括号

案例

1.利用函数计算1-100之间的累加和

1
2
3
4
5
6
7
8
9
10
// 1.声明函数
function getSum() {
var sum = 0;
for (var i = 1; i <= 100; i++) {
sum += i;
}
console.log(sum);
}
// 2.调用函数
getSum(); // 5050

函数的参数

1
2
3
4
5
6
7
// 1. 函数可以重复相同的代码
function cook() {
console.log('酸辣土豆丝');

}
cook();
cook();

形参和实参

1
2
3
4
5
6
7
8
9
10
11
12
13
// 2. 我们可以利用函数的参数实现函数重复不同的代码
function 函数名(形参1,形参2...) { // 在声明函数的小括号里面是 形参 (形式上的参数)
}
函数名(实参1,实参2...); // 在函数调用的小括号里面是实参(实际的参数)

// 3. 形参和实参的执行过程
function cook(aru) { // 形参是接受实参的 aru = '酸辣土豆丝' 形参类似于一个变量
console.log(aru);
}
cook('酸辣土豆丝');
cook('大肘子');

// 4. 函数的参数可以有,也可以没有个数不限

在声明函数时,可以在函数名称后面的小括号中添加一些参数,这些参数被称为形参,而在调用该函数时,同样也需要传递相应的参数,这些参数被称为实参

参数的作用 : 在函数内部某些值不能固定,我们可以通过参数在调用函数时传递不同的值进去。

案例

1.利用函数求任意两个数的和

1
2
3
4
5
function getSum(num1, num2) {
console.log(num1 + num2);
}
getSum(1, 3); // 4
getSum(3, 8); // 11

2.利用函数求任意两个数之间的和

1
2
3
4
5
6
7
8
9
function getSums(start, end) {
var sum = 0;
for (var i = start; i <= end; i++) {
sum += i;
}
console.log(sum);
}
getSums(1, 100); //5050
getSums(1, 10); // 55

3.注意点

  • 多个参数之间用逗号隔开
  • 形参可以看做是不用声明的变量
函数形参和实参个数不匹配问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 函数形参实参个数匹配
function getSum(num1, num2) {
console.log(num1 + num2);

}

// 1. 如果实参的个数和形参的个数一致 则正常输出结果
getSum(1, 2); // 3

// 2. 如果实参的个数多于形参的个数 会取到形参的个数
getSum(1, 2, 3); // 3

// 3. 如果实参的个数小于形参的个数 多于的形参定义为undefined 最终的结果就是 NaN
// 形参可以看做是不用声明的变量 num2 是一个变量但是没有接受值 结果就是undefined
getSum(1); // NaN

// 建议 我们尽量让实参的个数和形参相匹配

函数的返回值

return 语句

有的时候,我们会希望函数将值返回给调用者,此时通过使用 return 语句就可以实现。

return 语句的语法格式如下:

1
2
3
4
function 函数名() {
return 需要返回的结果;
}
函数名();

(1) 我们函数只是实现某种功能,最终的结果需要返回给函数的调用者函数名() 通过return 实现的。

(2) 只要函数遇到return 就把后面的结果 返回给函数的调用者 函数名() = return后面的结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 代码验证
function getResult() {
return 666;
}
getResult(); // 相当于getResult() = 666
console.log(getResult());

// 2.点餐
function cook(aru) {
return aru;
}
console.log(cook('大肘子'));

// 3.求任意两个数的和
function getSum(num1, num2) {
return num1 + num2
}
console.log(getSum(5, 6)); // 11
console.log(getSum(1, 2)); // 3

案例

1.利用函数求任意两个数的最大值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function getBig(num1, num2) {
if (num1 > num2) {
return num1;
} else {
return num2;
}
}

// 或者
function getMax(num1, num2) {
return num1 > num2 ? num1 : num2; // 三元表达式
}

console.log(getBig(1, 8)); //8

2.利用函数求任意一个数组中的最大值

求数组 [5,2,99,101,67,77] 中的最大数值。

1
2
3
4
5
6
7
8
9
10
11
12
13
function getArrMax(arr) { // arr 接受一个数组  arr =  [5,2,99,101,67,77]
var max = arr[0];
for (var i = 1; i <= arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
// getArrMax([5, 2, 99, 101, 67, 77]); // 实参是一个数组送过去
// 在我们实际开发里面,我们经常用一个变量来接受 函数的返回结果 使用更简单
var re = getArrMax([3, 77, 44, 99, 143]);
console.log(re);

return 终止函数

return 语句之后的代码不被执行。

return 只能返回一个值。如果用逗号隔开多个值,以最后一个为准。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 1. return 终止函数
function getSum(num1, num2) {
return num1 + num2; // return 后面的代码不会被执行
alert('我是不会被执行的哦!') //这句并没有被执行!!!
}
console.log(getSum(1, 2));

// 2. return 只能返回一个值
function fn(num1, num2) {
return num1, num2; // 返回的结果是最后一个值
}
console.log(fn(1, 2)); //返回num2的值 2

// 3. 我们求任意两个数的 加减乘数结果
function getResult(num1, num2) {
return [num1 + num2, num1 - num2, num1 * num2, num1 / num2];
}
var re = getResult(1, 2); // 返回的是一个数组
console.log(re);

函数没有 return 返回 undefined

函数都是有返回值的。

  1. 如果有return 则返回 return 后面的值
  2. 如果没有return 则返回 undefined
1
2
3
4
5
6
7
8
function fun1() {
return 666;
}
console.log(fun1()); // 返回 666

function fun2() {
}
console.log(fun2()); // 函数返回的结果是 undefined

作业

① 写一个函数,用户输入任意两个数字的任意算术运算(简单的计算器小功能),并能弹出运算后的结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function getCount() {
var num1 = parseFloat(prompt('请输入第一个数字'));
var num2 = prompt('请输入运算符');
var num3 = parseFloat(prompt('请输入第二个数字'));
if (num2 == '-') {
return num1 - num3;
} else if (num2 == '+') {
return num1 + num3;
} else if (num2 == '*') {
return num1 * num3;
} else if (num2 == '/') {
return num1 / num3;
}
}
var re = getCount();
alert('结果为' + re);

② 写一个函数,用户输入任意两个数字的最大值,并能弹出运算后的结果。

1
2
3
4
5
6
7
var num1 = parseInt(prompt('输入数字'));  //parseInt()强制转换数据类型
var num2 = parseInt(prompt('输入数字'));
function getMax(num1, num2) {
return num1 > num2 ? num1 : num2; // 三元表达式
}
var str = getmax(num1,num2);
alert(str);

③ 写一个函数,用户输入任意三个不同数字的最大值,并能弹出运算后的结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var num1 = parseInt(prompt('请输入第一个数字'));  //parseInt()强制转换数据类型
var num2 = parseInt(prompt('请输入第二个数字'));
var num3 = parseInt(prompt('请输入第三个数字'));
function getMax(num1, num2, num3) {
if (num1 > num2 && num1 > num3) {
return num1;
} else if (num2 > num1 && num2 > num3) {
return num2;
} else if (num3 > num1 && num3 > num2) {
return num3
}
}
var str = getMax(num1, num2, num3);
alert('最大值为' + str);

④ 写一个函数,用户输入一个数判断是否是素数,并返弹出回值。

素数又称质数,一个大于1的正整数,如果除了1它本身以外,不能被其他正整数整除,就叫素数。

1
2
3
4
5
6
7
8
9
10
11
12
var num = parseInt(prompt('请输入一个数字'));  //parseInt()强制转换数据类型
function getSu() {
// 因为 计数器 i 要与 质数num 作比较,而质数是大于 1 的,所以 i 初始值设为 2
for (var i = 2; i < num; i++) {
if (num % i == 0) {
return num + '不是质数'
}
}
return num + '是质数'
}
var str = getSu();
alert(str);

arguments 的使用

当我们不确定有多少个参数传递的时候,可以用 arguments 来获取。在 JavaScript 中,arguments 实际上它是当前函数的一个内置对象。所有函数都内置了一个 arguments 对象,arguments 对象中存储了传递的所有实参

1
2
3
4
5
6
function fn() {
console.log(arguments); // 里面存储了所有传递过来的实参 arguments = [1,2,3]
console.log(arguments.length); // 3
console.log(arguments[2]); // 3
}
fn(1,2,3);

arguments展示形式是一个伪数组,因此可以进行遍历。伪数组具有以下特点:

  • 具有数组的 length 属性
  • 按照索引的方式进行存储的
  • 它没有真正数组的一些方法 pop() push() 等等
1
2
3
4
5
6
7
// 我们可以按照数组的方式遍历arguments
function fn() {
for (var i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}
fn(1,2,3);

只有函数才有 arguments对象 而且是每个函数都内置好了这个arguments

案例

利用函数求任意个数的最大值

1
2
3
4
5
6
7
8
9
10
11
function getMax() { // arguments = [1,2,3]
var max = arguments[0]; // 先把数组里的第一个值取过来默认当最大值
for (var i = 1; i < arguments.length; i++) { // 因为第0个序号已经被默认当成最大值,所以从第1个序号开始
if (arguments[i] > max) { // 循环每个数字与默认的最大值比较,如果大于默认的就输出最大值等于当前,循环
max = arguments[i];
}
}
return max; // 全部比较完后,输出最大值
}
console.log(getMax(1, 2, 3)); // 3
console.log(getMax(1, 2, 3, 4, 5)); // 5

函数案例

1.利用函数封装方式,翻转任意一个数组

1
2
3
4
5
6
7
8
9
10
11
function reverse(arr) {  // reverse翻转  因为是要翻转一个数组,即旧数组arr
var newArr = []; // 需要一个新的空数组
for (var i = arr.length - 1; i >= 0; i--) { //设i初始值为旧数组的长度减一,即从最后一个数开始,遍历旧数组
newArr[newArr.length] = arr[i]; // 把旧数组的最后一个放到新数组的第一个
}
return newArr; // 输出新数组
}
var arr1 = reverse([1, 3, 4, 6, 9]);
console.log(arr1);
var arr2 = reverse(['red', 'pink', 'blue']);
console.log(arr2);

2.利用函数封装方式,对数组排序 – 冒泡排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function sort(arr) { // sort 排序
for (var i = 0; i < arr.length - 1; i++) { // 一共要走(旧数组的长度减一)趟,例如5个数据就要走4趟
for (var j = 0; j < arr.length - i - 1; j++) { // 每一趟要交换的次数,因为我们每一趟交换的次数不一样,例如5个数据的时候,第一趟就交换4次,第二趟的时候交换3次。所以我们不能简单的用旧数组的长度减一,我们注意到i的初始值为0,每一趟都会增加1,所以次数最终为旧数组长度-1-i。
if (arr[j] > arr[j + 1]) { // 交换变量
var temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return arr;
}
var arr1 = sort([1, 4, 2, 9]);
console.log(arr1); // 1, 2, 4, 9
var arr2 = sort([11, 7, 22, 999]);
console.log(arr2); // 7, 11, 22, 999

3.判断闰年

要求:输入一个年份,判断是否是闰年(闰年:能被4整除并且不能被100整除,或者能被400整除)

1
2
3
4
5
6
7
8
9
10
function isRunYear(year) {
// 如果是闰年我们返回 true 否则 返回 false
var flag = false;
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) { // 先&&后||,2000%4=0为true,2000% 100 != 0为false,所以&&为false,但2000% 400 == 0为true,||一true一false为true,所以符合
flag = true;
}
return flag;
}
console.log(isRunYear(2000)); // true
console.log(isRunYear(1999)); // false

4.函数可以调用另外一个函数

因为每个函数都是独立的代码块,用于完成特殊任务,因此经常会用到函数相互调用的情况。

1
2
3
4
5
6
7
8
9
10
11
function fn1() {
console.log(111);
fn2();
console.log('fn1');
}
function fn2() {
console.log(222);
console.log('fn2');
}
fn1();
// 111 222 fn2 fn1

5.用户输入年份,输出当前年份2月份的天数

如果是闰年,则2月份是 29天, 如果是平年,则2月份是 28天。(闰年:能被4整除并且不能被100整除,或者能被400整除)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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;
}

函数的两种声明方式

自定义函数方式(命名函数)

利用函数关键字 function 自定义函数方式。

1
2
3
4
5
// 利用函数关键字自定义函数(命名函数)
function fn() {

}
fn();
  • 因为有名字,所以也被称为命名函数。
  • 调用函数的代码既可以放到声明函数的前面,也可以放在声明函数的后面。

函数表达式方式(匿名函数)

1
2
3
4
5
6
7
// 函数表达式(匿名函数) 
// var 变量名 = function(){};
var fun = function(aru) {
console.log('我是函数表达式');
console.log(aru);
}
fun('pink老师');
  • 因为函数没有名字,所以也被称为匿名函数
  • 这个fn 里面存储的是一个函数
  • 函数表达式方式原理跟声明变量方式是一致的
  • 函数调用的代码必须写到函数体后面

作用域

JavaScript作用域:就是代码名字(变量)在某个范围内起作用和效果,出了这个范围就不起效果,目的是为了提高程序的可靠性,更重要的是减少命名冲突。

JavaScript(es6前)中的作用域有两种:

  • 全局作用域
  • 局部作用域(函数作用域)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 1. 全局作用域: 整个script标签 或者是一个单独的js文件
<script>
var num = 10; // num这个变量名字在整个script标签中但是可用的。
console.log(num);
alert(num);
</script>


// 2. 局部作用域(函数作用域) 在函数内部就是局部作用域 这个代码的名字只在函数内部起效果和作用
function fn() {
// 局部作用域
var num = 20;
console.log(num);

}
fn();

变量的作用域

在JavaScript中,根据作用域的不同,变量可以分为两种:

  • 全局变量
  • 局部变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 1. 全局变量: 在全局作用域下的变量 在全局下都可以使用
// 注意 如果在函数内部 没有声明直接赋值的变量也属于全局变量
var num = 10; // num就是一个全局变量
console.log(num);

function fn() {
console.log(num);
}
fn();
// console.log(aru);

// 2. 局部变量 在局部作用域下的变量 后者在函数内部的变量就是 局部变量
// 注意: 函数的形参也可以看做是局部变量
function fun(aru) {
var num1 = 10; // num1就是局部变量 只能在函数内部使用
num2 = 20;
}
fun();
// console.log(num1);
// console.log(num2);

从执行效率来看全局变量和局部变量:

  1. 全局变量只有浏览器关闭的时候才会销毁,比较占内存资源
  2. 局部变量 当我们程序执行完毕就会销毁, 比较节约内存资源

JS 没有块级作用域

Js的作用域: 全局作用域 局部作用域 现阶段我们Js 没有 块级作用域

块级作用域(用{}包含的) if {} for {}

1
2
3
4
5
6
// 例如java中: 
if(true){
int num = 123;
system.out.print(num); // 123
}
system.out.print(num); // 报错

Js中没有块级作用域(在ES6之前)。

1
2
3
4
if (3 < 5) {
var num = 10;
}
console.log(num); // 10

作用域链

  • 只要是代码,就至少有一个作用域
  • 写在函数内部的局部作用域
  • 如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
  • 根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作作用域链
1
2
3
4
5
6
7
8
9
10
11
12
13
// 作用域链  : 内部函数访问外部函数的变量,采取的是链式查找的方式来决定取那个值 这种结构我们称为作用域链   就近原则
var num = 10;

function fn() { // 外部函数
var num = 20;

function fun() { // 内部函数,内部函数访问外部函数的变量
console.log(num);

}
fun();
}
fn(); // 20

案例

1.结果是几?

1
2
3
4
5
6
7
8
9
function f1() {
var num = 123;
function f2() {
console.log( num );
}
f2();
}
var num = 456;
f1(); // 123,因为123最近

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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(); // 4 22

预解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 1问  
console.log(num); // 报错


// 2问
console.log(num); // undefined 坑 1
var num = 10;


// 3问
// fn(); // 放在上面也是正常输出
function fn() {
console.log(11);
}
fn();


// 4问
fun(); // 放在上面报错 坑2
var fun = function() {
console.log(22);
}

1.JavaScript 代码是由浏览器中的 JavaScript 解析器来执行的。JavaScript 解析器在运行 JavaScript 代码的时候分为两步:预解析和代码执行。

  • 预解析:预解析 js引擎会把js 里面所有的 var 还有 function 提升到当前作用域的最前面。
  • 代码执行: 按照代码书写的顺序从上往下执行。

2.预解析分为 变量预解析(变量提升) 和 函数预解析(函数提升)

  • 变量提升:就是把所有的变量声明提升到当前的作用域最前面,不提升赋值操作。
  • 函数提升:就是把所有的函数声明提升到当前作用域的最前面,不调用函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 2问
console.log(num); // undefined 坑 1
var num = 10;
// 相当于执行了以下代码
var num; // 先变量提升,不提升赋值
console.log(num); // 代码依次执行
num = 10; // 因为var已经被提到前面去了,所以只留下了num=10;


// 4问
fun(); // 放在上面报错 坑2
var fun = function() {
console.log(22);
}
// 函数表达式 调用必须写在函数表达式的下面
// 相当于执行了以下代码
var fun; // 先把var提升到前面
fun(); // 依次执行
fun = function() {
console.log(22);
}
1
2
3
4
5
6
// 3问 
fn(); // 放在上面也是正常输出
function fn() {
console.log(11);
}
// 因为函数提升,将函数提升到当前作用域的最前面。

案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 案例1
var num = 10;
fun();
function fun() {
console.log(num);
var num = 20;
}

// 相当于执行了以下操作
var num;
function fun() {
var num;
console.log(num); // 作用域链,就近原则,所以num=var num;所以undefined
num = 20;
}
num = 10;
fun(); // undefined
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 案例2
var num = 10;
function fn(){
console.log(num);
var num = 20;
console.log(num);
}
fn();

// 相当于执行了以下操作
var num;
function fn(){
var num;
console.log(num);
num = 20;
console.log(num);
}
num = 10;
fn(); // undefined 20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 案例3
var a = 18;
f1();
function f1() {
var b = 9;
console.log(a);
console.log(b);
var a = '123';
}

// 相当于执行了以下操作
var a;
function f1() {
var b;
var a;
b = 9;
console.log(a);
console.log(b);
a = '123';
}
a = 18;
f1(); // undefined 9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 案例4
f1();
console.log(c);
console.log(b);
console.log(a);
function f1() {
var a = b = c = 9;
// 相当于 var a = 9; b = 9; c = 9; b 和 c 直接赋值 没有var 声明 当 全局变量看
// 集体声明是这样写:var a = 9, b = 9, c = 9;
console.log(a);
console.log(b);
console.log(c);
}

// 相当于执行了以下操作
function f1() {
var a;
a = b = c = 9;
console.log(a);
console.log(b);
console.log(c);
}
f1(); // 9 9 9
console.log(c); // 9
console.log(b); // 9
console.log(a); // 报错 因为a是局部变量

对象

现实生活中:万物皆对象,对象是一个具体的事物,看得见摸得着的实物。例如,一本书、一辆汽车、一个人可以是“对象”,一个数据库、一张网页、一个与远程服务器的连接也可以是“对象”。

在 JavaScript 中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字符串、数值、数组、函数等。

对象是由属性方法组成的。

  • 属性:事物的特征,在对象中用属性来表示(常用名词)
  • 方法:事物的行为,在对象中用方法来表示(常用动词)

为什么需要变量?

保存一个值时,可以使用变量,保存多个值(一组值)时,可以使用数组。如果要保存一个人的完整信息呢?

例如,将“张三疯”的个人的信息保存在数组中的方式为:

1
var arr = [‘张三疯’, ‘男', 128,154];

JS 中的对象表达结构更清晰,更强大。张三疯的个人信息在对象中的表达结构如下:

1
2
3
4
5
6
7
8
9
张三疯.姓名 =  ‘张三疯';
张三疯.性别 = ‘男';
张三疯.年龄 = 128;
张三疯.身高 = 154

person.name = ‘张三疯';
person.sex = ‘男';
person.age = 128;
person.height = 154

在 JavaScript 中,现阶段我们可以采用三种方式创建对象(object):

  • 利用字面量创建对象
  • 利用 new Object 创建对象
  • 利用构造函数创建对象

字面量创建对象

对象字面量:就是花括号 { } 里面包含了表达这个具体事物(对象)的属性和方法。

创建对象

1
2
3
4
5
6
7
8
9
// var obj = {};  // 创建了一个空的对象 
var obj = {
uname: '张三疯',
age: 18,
sex: '男',
sayHi: function() {
console.log('hi~');
}
}

1.{ } 里面采取键值对的形式表示

  • 键:相当于属性名
  • 值:相当于属性值,可以是任意类型的值(数字类型、字符串类型、布尔类型,函数类型等)

2.多个属性或者方法中间用逗号隔开的。

3.方法冒号后面跟的是一个匿名函数

使用对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var obj = {
uname: '张三疯',
age: 18,
sex: '男',
sayHi: function() {
console.log('hi~');
}
}

// (1).调用对象的属性 我们采取 对象名.属性名 . 我们理解为 的
console.log(obj.uname);
// (2).调用属性还有一种方法 对象名['属性名']
console.log(obj['age']);
// (3).调用对象的方法 sayHi 对象名.方法名() 千万别忘记添加小括号
obj.sayHi();

练习

请用对象字面量的形式创建一个名字为可可的狗对象。

具体信息如下:

姓名:可可

类型(type):阿拉斯加犬

年龄:5岁,

颜色:棕红色。

技能:汪汪汪(bark) ,演电影 (showFilm)

1
2
3
4
5
6
7
8
9
10
11
12
var obj = {
uname: '可可',
type: '阿拉斯加犬'
age: 5,
color: '棕红色',
skill : '汪汪汪(bark),演电影 (showFilm)'
}
console.log(obj.uname);
console.log(obj.age);
console.log(obj.type);
console.log(obj.color);
console.log(obj.skill);

变量、属性、函数、方法总结

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 1.变量和属性的相同点 他们都是用来存储数据的 
var num = 10;
var obj = {
age: 18,
}
console.log(obj.age); // 18
console.log(age); // 使用的时候没有对象.属性,就会报错
// 变量 单独声明并赋值 使用的时候直接写变量名 单独存在
// 属性 在对象里面的不需要声明的 使用的时候必须是 对象.属性

// 2. 函数和方法的相同点 都是实现某种功能 做某件事
var obj = {
age: 18,
fn: function() { // 方法,在对象里面
}
}

function fn() { // 函数
}
// 函数是单独声明 并且调用的 函数名() 单独存在的
// 方法 在对象里面 调用的时候 对象.方法()

new Object 创建对象

1
2
3
4
5
6
7
8
9
10
11
12
13
// 利用 new Object 创建对象
var obj = new Object(); // 创建了一个空的对象
obj.uname = '张三疯';
obj.age = 18;
obj.sex = '男';
obj.sayHi = function() {
console.log('hi~');
}
// (1) 我们是利用 等号 = 赋值的方法 添加对象的属性和方法
// (2) 每个属性和方法之间用 分号结束
console.log(obj.uname);
console.log(obj['sex']);
obj.sayHi();

练习

请用new Object 形式创建一个鸣人对象。

具体信息如下:

姓名:鸣人

性别:男

年龄:19岁

技能(skill):影分身术

1
2
3
4
5
6
7
8
9
10
var obj = new Object(); // 创建了一个空的对象
obj.uname = '鸣人';
obj.age = 19;
obj.sex = '男';
obj.skill = '影分身术';

console.log(obj.uname);
console.log(obj.age);
console.log(obj.sex);
console.log(obj.skill);

构造函数创建对象

为什么

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var ldh = {
uname: '刘德华',
age: 55,
sing: function() {
console.log('冰雨');
}
}

var zxy = new Object();
obj.uname = '张学友';
obj.age = 58;
obj.sing = function() {
console.log('李香兰');
}

上面的代码可以看出前面两种创建对象的方式一次只能创建一个对象,然后我们一次创建一个对象,里面很多的属性和方法是大量相同的,我们只能复制,因此,我们可以利用函数的方法 重复这些相同的代码,我们就把这个函数称为构造函数

为什么叫构造函数:又因为这个函数不一样,里面封装的不是普通代码,而是对象

所以说:构造函数就是把我们对象里面一些相同的属性和方法抽象出来封装到函数里面。

创建对象

语法格式:

1
2
3
4
5
function 构造函数名() {
this.属性 = 值;
this.方法 = function() {}
}
new 构造函数名();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 创建四大天王的对象  相同的属性: 名字 年龄 性别  相同的方法: 唱歌
function Star(uname, age, sex) {
this.name = uname;
this.age = age;
this.sex = sex;
this.sing = function(sang) {
console.log(sang);
}
}
var ldh = new Star('刘德华', 18, '男'); // 调用函数返回的是一个对象
console.log(typeof ldh); // object,对象
console.log(ldh.name);
console.log(ldh['sex']);
ldh.sing('冰雨');
var zxy = new Star('张学友', 19, '男');
console.log(zxy.name);
console.log(zxy.age);
zxy.sing('李香兰');
  1. 。构造函数名字首字母要大写
  2. 我们构造函数不需要return 就可以返回结果。
  3. 我们调用构造函数 必须使用 new
  4. 我们只要new Star() 调用函数就创建一个对象 ldh {}。
  5. 我们的属性和方法前面必须添加 this

练习

利用构造函数创建两个英雄对象。函数中的公共部分包括:姓名属性(name),类型属性(type),血量属性(blood)和攻击方式(attack)。

英雄对象的信息如下 :

  • 廉颇 力量型 500血量 攻击 :近战
  • 后羿 射手型 100血量 攻击: 远程
1
2
3
4
5
6
7
8
9
10
function Star(uname, type, blood, attack) {
this.name = uname;
this.type = type;
this.blood = blood;
this.attack = attack;
}
var lp = new Star('廉颇', '力量型', '500血量', '近战');
console.log(lp);
var hy = new Star('后羿', '射手型', '100血量', '远程');
console.log(hy);

构造函数和对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 1. 构造函数  明星 泛指的某一大类  它类似于 java 语言里面的  类(class)
function Star(uname, age, sex) {
this.name = uname;
this.age = age;
this.sex = sex;
this.sing = function(sang) {
console.log(sang);
}
}

// 2. 对象 特指 是一个具体的事物 例如刘德华就是对象,刘德华就相当于这段代码:{name: "刘德华", age: 18, sex: "男", sing: ƒ}
var ldh = new Star('刘德华', 18, '男'); // 调用函数返回的是一个对象
console.log(ldh);
// 3. 我们利用构造函数创建对象的过程我们也称为对象的实例化

new关键字

new关键字执行过程:

  1. new 构造函数可以在内存中创建了一个空的对象。

​ 2. this 就会指向刚才创建的空对象。

​ 3. 执行构造函数里面的代码,给这个空对象添加属性和方法。

​ 4. 返回这个对象。

遍历对象

1
2
3
4
5
6
7
8
9
var obj = {
name: 'pink老师',
age: 18,
sex: '男',
}
console.log(obj.name);
console.log(obj.age);
console.log(obj.sex);
// 很麻烦,要一个一个的输出属性

for...in 语句用于对数组或者对象的属性进行循环操作。

其语法如下:

1
2
3
for (变量 in 对象) {

}
1
2
3
4
5
6
7
8
9
var obj = {
name: 'pink老师',
age: 18,
sex: '男',
}
for(var k in obj){
console.log(k); // k 变量 输出 得到的是 属性名 name age sex
console.log(obj[k]); // obj[k] 得到是 属性值 pink老师 18 男
}

我们使用 for in 里面的变量 我们喜欢写 k 或者 key

作业

  1. 创建一个电脑对象

有颜色(color)、重量(weight)、品牌(brand)、型号(type)等属性,

有看电影(watch)、听音乐(listen)、打游戏(play)和敲代码(coding)等方法。

题目描述:

颜色、重量、品牌、型号是属性;看电影、听音乐、打游戏、敲代码是方法,在调用方法时分别打印 “我在看电影/听音乐/打游戏/敲代码”。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var computer = {
color: 'black',
weight: '2.42kg',
brand: 'hp',
type: '光影精灵',
skill: function () {
console.log('我在看电影');
console.log('我在听音乐');
console.log('我在打游戏');
console.log('我在敲代码');
}
};
console.log(computer.color);
console.log(computer.weight);
console.log(computer.brand);
console.log(computer.type);
computer.skill();
  1. 创建一个按钮对象,该对象中需要包含宽,高,背景颜色和点击行为。
1
2
3
4
5
6
7
8
9
10
11
12
var an = {
width: '20cm',
height: '20cm',
color: 'blue',
chick: function (chick) {
console.log('写的代码点击就成功');
}
}
console.log(an.width);
console.log(an.height);
console.log(an.color);
an.chick();
  1. 创建一个车的对象,该对象要有重量、颜色、牌子,可以载人、拉货和耕田。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var car = {
weight: '200kg',
color: 'blue',
paizi: '凯迪拉克',
gn: function (gn) {
console.log('载人');
console.log('拉货');
console.log('耕田');
}
}
console.log(car.weight);
console.log(car.color);
console.log(car.paizi);
car.gn();

内置对象

JavaScript 中的对象分为3种:自定义对象 、内置对象、 浏览器对象。

前面两种对象是JS 基础 内容,属于 ECMAScript;第三个浏览器对象属于我们JS独有的

内置对象就是指 JS 语言自带的一些对象,这些对象供开发者使用,并提供了一些常用的或是最基本而必要的功能(属性和方法),最大的优点就是帮助我们快速开发。

JavaScript 提供了多个内置对象:Math、 Date 、Array、String等。

查文档

学习一个内置对象的使用,只要学会其常用成员的使用即可,我们可以通过查文档学习,可以通过MDN/W3C来查询。

Mozilla 开发者网络(MDN)提供了有关开放网络技术(Open Web)的信息,包括 HTML、CSS 和万维网及 HTML5 应用的 API。

MDN Web Docs (mozilla.org)

  1. 查阅该方法的功能
  2. 查看里面参数的意义和类型
  3. 查看返回值的意义和类型
  4. 通过 demo 进行测试

Math 对象

Math对象不是构造函数,所以我们不需要new 来调用,它具有数学常数和函数的属性和方法。跟数学相关的运算(求绝对值,取整、最大值等)可以使用 Math 中的成员。

1
2
3
4
5
6
Math.PI		 // 圆周率
Math.floor() // 向下取整
Math.ceil() // 向上取整
Math.round() // 四舍五入版 就近取整 注意 -3.5 结果是 -3
Math.abs() // 绝对值
Math.max()/Math.min() // 求最大和最小值

注意:上面的方法必须带括号

圆周率、最大和最小值

1
2
3
4
5
console.log(Math.PI); // 一个属性 圆周率
console.log(Math.max(1, 99, 3)); // 99
console.log(Math.max(-1, -10)); // -1
console.log(Math.max(1, 99, 'pink老师')); // NaN
console.log(Math.max()); // -Infinity 负的无穷大
封装自己的数学对象(案例)

利用对象封装自己的数学对象,里面有 PI、最大值和最小值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var myMath = {
PI: 3.141592653,
max: function() {
var max = arguments[0];
for (var i = 1; i < arguments.length; i++) {
if (arguments[i] > max) {
max = arguments[i];
}
}
return max;
},
min: function() {
var min = arguments[0];
for (var i = 1; i < arguments.length; i++) {
if (arguments[i] < min) {
min = arguments[i];
}
}
return min;
}
}
console.log(myMath.PI); // 3.141592653
console.log(myMath.max(1, 5, 9)); // 9
console.log(myMath.min(1, 5, 9)); // 1

绝对值、三个取整方法

1
2
3
4
5
// 绝对值方法
console.log(Math.abs(1)); // 1
console.log(Math.abs(-1)); // 1
console.log(Math.abs('-1')); // 隐式转换 会把字符串型 -1 转换为数字型
console.log(Math.abs('pink')); // NaN
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 三个取整方法
// (1) Math.floor() 地板 向下取整 往最小了取值
console.log(Math.floor(1.1)); // 1
console.log(Math.floor(1.9)); // 1

// (2) Math.ceil() ceil 天花板 向上取整 往最大了取值
console.log(Math.ceil(1.1)); // 2
console.log(Math.ceil(1.9)); // 2

// (3) Math.round() 四舍五入 其他数字都是四舍五入,但是 .5 特殊 它往大了取
console.log(Math.round(1.1)); // 1
console.log(Math.round(1.5)); // 2
console.log(Math.round(1.9)); // 2
console.log(Math.round(-1.1)); // -1
console.log(Math.round(-1.5)); // 这个结果是 -1

随机数方法 random()

random() 方法可以随机返回一个小数,其取值范围是 [0,1),左闭右开 0 <= x < 1。

1
2
3
// 这个方法里不跟参数
// 代码验证
console.log(Math.random()); // 确实取值在[0,1)之间。

得到一个两数之间的随机整数,包括两个数在内。

1
2
// 我们想要得到两个数之间的随机整数 并且 包含这2个整数
Math.floor(Math.random() * (max - min + 1)) + min; // 公式
1
2
3
4
5
6
7
8
9
10
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
console.log(getRandom(1, 10)); // 取值在1到10之间,包括1,10

// 5. 随机点名
var arr = ['张三', '张三丰', '张三疯子', '李四', '李思思', 'pink老师'];
// console.log(arr[0]);
// console.log(arr[getRandom(0, 4);
console.log(arr[getRandom(0, arr.length - 1)]);
猜数字游戏(案例)

程序随机生成一个 1~ 10 之间的数字,并让用户输入一个数字,

1. 如果大于该数字,就提示,数字大了,继续猜;
2. 如果小于该数字,就提示数字小了,继续猜;
3. 如果等于该数字,就提示猜对了, 结束程序。

分析:

①随机生成一个1~10 的整数 我们需要用到 Math.random() 方法。

②需要一直猜到正确为止,所以一直循环。

③用while 循环合适更简单。

④核心算法:使用 if else if 多分支语句来判断大于、小于、等于。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var random = getRandom(1, 10);
while (true) { // 死循环
var num = prompt('你来猜? 输入1~10之间的一个数字');
if (num > random) {
alert('你猜大了');
} else if (num < random) {
alert('你猜小了');
} else {
alert('你好帅哦,猜对了');
break; // 退出整个循环结束程序
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 要求用户猜 1~50之间的一个数字 但是只有 10次猜的机会
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var random = getRandom(1, 50);
for (i = 1; i <= 10; i++) { // 死循环
var num = prompt('你来猜? 输入1~50之间的一个数字,只有10次机会哦');
if (num > random) {
alert('你猜大了,还有' + (10 - i) + '次机会');
} else if (num < random) {
alert('你猜小了,还有' + (10 - i) + '次机会');
} else {
alert('你好帅哦,猜对了');
break; // 退出整个循环结束程序
}
}

日期对象

Date 对象和 Math 对象不一样,他是一个构造函数,所以我们需要实例化后才能使用。Date 实例用来处理日期和时间。

Date() 日期对象,是一个构造函数,必须使用new 来调用创建我们的日期对象。

1
2
3
// 之前学的Array和Object都是构造函数
var arr = new Array(); // 创建一个数组对象
var obj = new Object(); // 创建了一个对象实例
1
2
3
4
5
6
7
8
9
// 1. 使用Date  如果没有参数 返回当前系统的当前时间
var date = new Date();
console.log(date); // 当前的时间 Wed Aug 09 2023 17:01:30 GMT+0800 (中国标准时间)

// 2. 参数常用的写法 数字型 2023, 08, 09 或者是 字符串型 '2023-8-9 17:03:18'
var date1 = new Date(2023, 8, 09);
console.log(date1); // 返回的是 9月 不是 8月
var date2 = new Date('2023-8-9 17:03:18');
console.log(date2); // 正常

日期格式化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var date = new Date();
console.log(date.getFullYear()); // 返回年份 2023
console.log(date.getMonth()); // 返回月份 7 注意,这个获得的是(0-11),所以获得的少一月,所以我们要+1
console.log(date.getMonth() + 1); // 8 正确的月份
console.log(date.getDate()); // 返回日期
console.log(date.getDay()); // 4 周一返回的是 1 周六返回的是 6 但是 周日返回的是 0

// 我们写一个 2023年 8月 10日 星期四
var year = date.getFullYear();
var month = date.getMonth() + 1;
var date1 = date.getDate();
var day = date.getDay();
var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
console.log('今天是:' + year + '年' + month + '月' + date1 + '日 ' + arr[day]);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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; // 当个数位数时,在前面+0,变成01
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());

获取日期的总的毫秒形式

Date 对象是基于1970年1月1日(世界标准时间)起的毫秒数。

我们经常利用总的毫秒数来计算时间,因为它更精确。

获得Date总的毫秒数(时间戳) ,不是当前时间的毫秒数,而是距离1970年1月1号过了多少毫秒数

1
2
3
4
5
6
7
8
9
// 1. 通过 valueOf()  getTime()
var date = new Date();
console.log(date.valueOf()); // 就是 我们现在时间 距离1970.1.1 总的毫秒数
console.log(date.getTime());
// 2. 简单的写法 (最常用的写法)
var date1 = +new Date(); // +new Date() 返回的就是总的毫秒数
console.log(date1);
// 3. H5 新增的 获得总的毫秒数
console.log(Date.now());

倒计时(案例)

分析:

①核心算法:输入的时间减去现在的时间就是剩余的时间,即倒计时 ,但是不能拿着时分秒相减,比如 05 分减去25分,结果会是负数的。

②用时间戳来做。用户输入时间总的毫秒数减去现在时间的总的毫秒数,得到的就是剩余时间的毫秒数。

③把剩余时间总的毫秒数转换为天、时、分、秒 (时间戳转换为时分秒)

转换公式如下:

  • d = parseInt(总秒数/ 60/60 /24); // 计算天数
  • h = parseInt(总秒数/ 60/60 %24) // 计算小时
  • m = parseInt(总秒数 /60 %60 ); // 计算分数
  • s = parseInt(总秒数%60); // 计算当前秒数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function countDown(time) {
var nowTime = +new Date(); // 返回的是当前时间总的毫秒数
var inputTime = +new Date(time); // 返回的是用户输入时间总的毫秒数
var times = (inputTime - nowTime) / 1000; // times是剩余时间总的秒数
var d = parseInt(times / 60 / 60 / 24); // 天
d = d < 10 ? '0' + d : d;
var h = parseInt(times / 60 / 60 % 24); //时
h = h < 10 ? '0' + h : h;
var m = parseInt(times / 60 % 60); // 分
m = m < 10 ? '0' + m : m;
var s = parseInt(times % 60); // 当前的秒
s = s < 10 ? '0' + s : s;
return d + '天' + h + '时' + m + '分' + s + '秒';
}
console.log(countDown('2023-8-10 23:00:00'));

数组对象

创建数组对象的两种方式

  • 字面量方式
  • new Array()
1
2
3
4
5
6
7
8
9
// 1. 利用数组字面量
var arr = [1, 2, 3];
console.log(arr[0]);

// 2. 利用new Array()
// var arr1 = new Array(); // 创建了一个空的数组
// var arr1 = new Array(2); // 这个2 表示 数组的长度为 2 里面有2个空的数组元素
var arr1 = new Array(2, 3); // 等价于 [2,3] 这样写表示 里面有2个数组元素 是 2和3
console.log(arr1);

检测是否为数组

instanceof 运算符 它可以用来检测是否为数组。

Array.isArray(参数); H5新增的方法 ie9以上版本支持。

1
2
3
4
5
6
7
8
9
// (1) instanceof  运算符 它可以用来检测是否为数组
var arr = [];
console.log(arr instanceof Array); // true
var obj = {};
console.log(obj instanceof Array); // false

// (2) Array.isArray(参数); H5新增的方法 ie9以上版本支持
console.log(Array.isArray(arr)); // true
console.log(Array.isArray(obj)); // false
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
function reverse(arr) {
var newArr = [];
for (var i = arr.length - 1; i >= 0; i--) {
newArr[newArr.length] = arr[i];
}
return newArr;
}
console.log(reverse([1, 2, 3])); // 翻转 3,2,1
console.log(reverse(1, 2, 3)); // 空

// 改造
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));

添加删除数组元素的方法

push()
1
2
3
4
5
6
7
// 1. push() 在我们数组的末尾 添加一个或者多个数组元素   push  推
var arr = [1, 2, 3];
arr.push(4, 'pink');
console.log(arr); // 1,2,3,4,pink
// 也可以这样写
var arr = [1, 2, 3];
console.log(arr.push(4, 'pink'));
  1. push 是可以给数组追加新的元素
  2. push() 参数直接写数组元素就可以了
  3. push完毕之后,返回的结果是新数组的长度
  4. 原数组也会发生变化
unshift()
1
2
3
4
5
6
7
// 2. unshift 在我们数组的开头 添加一个或者多个数组元素
var arr = [1, 2, 3];
arr.unshift('red');
console.log(arr); // red,1,2,3
// 也可以这样写
var arr = [1, 2, 3];
console.log(arr.unshift('red', 'purple'));
  1. unshift是可以给数组前面追加新的元素
  2. unshift() 参数直接写 数组元素就可以了
  3. unshift完毕之后,返回的结果是 新数组的长度
  4. 原数组也会发生变化
pop()
1
2
3
4
5
6
7
// 3. pop() 它可以删除数组的最后一个元素  
var arr = [1, 2, 3];
arr.pop();
console.log(arr); // 1,2

var arr = [1, 2, 3];
console.log(arr.pop()); // 3,删除哪个元素,返回哪个元素
  1. pop是可以删除数组的最后一个元素 记住一次只能删除一个元素
  2. pop() 没有参数
  3. pop完毕之后,返回的结果是 删除的那个元素
  4. 原数组也会发生变化
shift
1
2
3
4
5
6
7
// shift() 它可以删除数组的第一个元素  
var arr = [1, 2, 3];
arr.shift();
console.log(arr); // 2,3

var arr = [1, 2, 3];
console.log(arr.shift()); // 1,删除哪个元素,返回哪个元素
  1. shift是可以删除数组的第一个元素 记住一次只能删除一个元素
  2. shift() 没有参数
  3. shift完毕之后,返回的结果是 删除的那个元素
  4. 原数组也会发生变化
筛选数组(案例)

有一个包含工资的数组[1500, 1200, 2000, 2100, 1800],要求把数组中工资超过2000的删除,剩余的放到新数组里面。

1
2
3
4
5
6
7
8
9
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);

数组排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 1. 翻转数组
var arr = ['pink', 'red', 'blue'];
arr.reverse();
console.log(arr);

// 2. 数组排序(冒泡排序)
var arr = [3, 2, 5, 8];
arr.sort();
console.log(arr); // 2,3,5,8

var arr1 = [13, 4, 77, 1, 7];
arr.sort();
console.log(arr); // 1,13,4,7,77 sort只能识别个位数的
// 解决方法
var arr1 = [13, 4, 77, 1, 7];
arr1.sort(function(a, b) {
// return a - b; 升序的顺序排列
return b - a; // 降序的顺序排列
});
console.log(arr1);

数组索引方法

1
2
3
4
5
6
7
8
9
10
11
// 返回数组元素索引号方法  indexOf(数组元素)  作用就是返回该数组元素的索引号 从前面开始查找
// 它只返回第一个满足条件的索引号
// 它如果在该数组里面找不到元素,则返回的是 -1
var arr = ['red', 'green', 'blue', 'pink'];
console.log(arr.indexOf('blue')); // 2

var arr = ['red', 'green', 'blue', 'pink', 'blue'];
console.log(arr.indexOf('blue')); // 2 即使有多个blue,也只会返回第一个满足条件的索引号

var arr = ['red', 'green', 'pink'];
console.log(arr.indexOf('blue')); // -1 它如果在该数组里面找不到元素,则返回的是 -1
1
2
3
4
5
6
// 返回数组元素索引号方法  lastIndexOf(数组元素)  作用就是返回该数组元素的索引号 从后面开始查找
var arr = ['red', 'green', 'pink'];
console.log(arr.lastIndexOf('blue')); // -1 它如果在该数组里面找不到元素,则返回的是 -1

var arr = ['red', 'green', 'blue', 'pink', 'blue'];
console.log(arr.indexOf('blue')); // 4 即使有多个blue,也只会返回第一个满足条件的索引号(从后面开始)
数组去重(重点案例)

有一个数组[‘c’, ‘a’, ‘z’, ‘a’, ‘x’, ‘a’, ‘x’, ‘c’, ‘b’],要求去除数组中重复的元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 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'])
console.log(demo);

数组转换为字符串

1
2
3
4
5
6
7
8
// 1. toString() 将我们的数组转换为字符串
var arr = [1, 2, 3];
console.log(arr.toString()); // 1,2,3
// 2. join(分隔符)
var arr1 = ['green', 'blue', 'pink'];
console.log(arr1.join()); // green,blue,pink
console.log(arr1.join('-')); // green-blue-pink
console.log(arr1.join('&')); // green&blue&pink

其他

1
2
3
4
5
6
7
8
// 1.concat() 方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。
var arr = ['a', 'b', 'c'];
var arr1 = ['d', 'e', 'f'];
var arr2 = ['你', '学', '习'];
var arr3 = arr.concat(arr1); // 2个数组连接
var arr4 = arr.concat(arr1, arr2); // 3个数组连接
console.log(arr3);
console.log(arr4);
1
2
3
// slice() 方法返回一个新的数组对象,这一对象是一个由 start 和 end 决定的原数组的浅拷贝(包括 start,不包括 end),其中 start 和 end 代表了数组元素的索引。原始数组不会被改变。
var arr = ['a', 'b', 'c', 'd', 'e', 'f'];
console.log(arr.slice(0, 3)); // a,b,c
1
2
3
4
5
// splice() 方法通过移除或者替换已存在的元素和/或添加新元素就地改变一个数组的内容。
// splice(第几个索引号开始,删除几个数,添加的文字)
var arr = ['a', 'b', 'c', 'd'];
arr.splice(1, 1, 'z'); // 从第一个索引号开始,删除一个数,添加一个z
console.log(arr);

字符串对象

1
2
3
4
5
var str = 'andy';
console.log(str.length); // 4

// 对象 才有 属性和方法 复杂数据类型才有 属性和方法
// 简单数据类型为什么会有length 属性呢?

为了方便操作基本数据类型,JavaScript 还提供了三个特殊的引用类型:String、Number和 Boolean。

基本包装类型

基本包装类型就是把简单数据类型包装成为复杂数据类型,这样基本数据类型就有了属性和方法。

步骤(原因):

1
2
3
4
5
6
// (1) 把简单数据类型包装为复杂数据类型 
var temp = new String('andy');
// (2) 把临时变量的值 给 str
str = temp;
// (3) 销毁这个临时变量
temp = null;

字符串的不可变

指的是里面的值不可变,虽然看上去可以改变内容,但其实是地址变了,内存中新开辟了一个内存空间。

1
2
3
4
5
6
7
8
9
10
var str = 'andy';
console.log(str); // andy
str = 'red';
console.log(str); // red
// 因为我们字符串的不可变,所以不要大量的拼接字符串
var str = '';
for (var i = 1; i <= 1000000000; i++) {
str += i;
}
console.log(str); // 这个结果需要花费大量时间来显示,因为需要不断的开辟新的空间

根据字符返回位置

字符串所有的方法,都不会修改字符串本身(字符串是不可变的),操作完成会返回一个新的字符串。

1
2
3
4
// 字符串对象  根据字符返回位置  str.indexOf('要查找的字符', [起始的位置])
var str = '改革春风吹满地,春天来了';
console.log(str.indexOf('春')); // 2,第二个索引号
console.log(str.indexOf('春', 3)); // 8,从索引号是 3的位置开始往后查找
返回字符位置(案例)

查找字符串”abcoefoxyozzopp”中所有o出现的位置以及次数

1
2
3
4
5
6
7
8
9
10
11
12
13
// 核心算法:先查找第一个o出现的位置
// 然后 只要indexOf 返回的结果不是 -1 就继续往后查找(如果在该数组里面找不到元素,则返回的是 -1)
// 因为indexOf 只能查找到第一个,所以后面的查找,一定是当前索引加1,从而继续查找

var str = "abcoefoxyozzopp";
var index = str.indexOf('o');
var num = 0;
while (index !== -1) { // 设定index不等于-1,即找得到o时就执行下面的代码
console.log(index); // 打印index,即打印o的索引号
num++; // 打印一次就num++
index = str.indexOf('o', index + 1); // 因为o被找到了,所以要往下一个索引号开始找
}
console.log('o出现的次数是: ' + num); // o出现的次数是: 4

根据位置返回字符(重点)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 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) 返回相应索引号的字符ASCII值 目的: 判断用户按下了那个键
var str = 'andy';
console.log(str.charCodeAt(0)); // 97 a的ASCII码为97

// 3. str[index] H5 新增的
var str = 'andy';
console.log(str[0]); // a

返回字符位置(案例)
1
2
3
4
5
6
7
8
9
10
// 有一个对象 来判断是否有该属性 对象['属性名']
var o = {
age: 18
}
if (o['age']) { // 如果o里面包含有age这个属性,就执行下面的代码
console.log('里面有该属性');
} else {
console.log('没有该属性');
}
// 里面有该属性

判断一个字符串 ‘abcoefoxyozzopp’ 中出现次数最多的字符,并统计其次数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 核心算法:利用 charAt() 遍历这个字符串
// 把每个字符都存储给对象, 如果对象没有该属性,就为1,如果存在了就 +1
// 遍历对象,得到最大值和该字符
var str = 'abcoefoxyozzopp';
var o = {};
for (var i = 0; i < str.length; i++) {
var chars = str.charAt(i); // chars 是 字符串的每一个字符 第一次遍历:chars={a},第二次遍历chars={a,b},这些都是没有属性值,所以我们后面要写if函数属性值
// o.a = 1,如果后面还有a的话,就o.a+1(o.a++)
if (o[chars]) { // 如果o里面有chars这个属性,比如a,就++
o[chars]++;
} else { // 如果o里面没有这个属性,就=1,相当于,一开始没有a,那就是o.a=1
o[chars] = 1;
}
}
console.log(o); // {a: 1, b: 1, c: 1, e: 1, f: 1, o: 4, p: 2, x: 1, ,y: 1, z: 2}
// 2. 遍历对象
var max = 0;
var ch = '';
for (var k in o) {
// k 得到是 属性名 a,b,e这些就是属性
// o[k] 得到的是属性值,a:1中的1就是属性值
if (o[k] > max) {
max = o[k];
ch = k;
}
}
console.log(max);
console.log('最多的字符是' + ch);

字符串操作方法(重点)

1
2
3
4
5
6
7
// 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() 方法用于在字符串中用一些字符替换另一些字符。其使用格式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 1. 替换字符 replace('被替换的字符', '替换为的字符')  它只会替换第一个字符
var str = 'andy';
console.log(str.replace('a', 'b')); // bndy

var str = 'andyandy';
console.log(str.replace('a', 'b')); // bndyandy,只会替换第一个字符

// 有一个字符串 'abcoefoxyozzopp' 要求把里面所有的 o 替换为 *
var str1 = 'abcoefoxyozzopp';
while (str1.indexOf('o') !== -1) {
str1 = str1.replace('o', '*');
}
console.log(str1); // abc*ef*xy*zz*pp
split()方法

split()方法用于切分字符串,它可以将字符串切分为数组。在切分完毕之后,返回的是一个新数组。例如下面代码:

1
2
3
4
5
// 2. 字符转换为数组 split('分隔符')    前面我们学过 join 把数组转换为字符串
var str2 = 'red, pink, blue';
console.log(str2.split(','));
var str3 = 'red&pink&blue';
console.log(str3.split('&'));

作业

给定一个字符串,如:“abaasdffggghhjjkkgfddsssss3444343”,问题如下:

  1. 字符串的长度
  2. 取出指定位置的字符,如:0,3,5,9等
  3. 查找指定字符是否在以上字符串中存在,如:i,c,b等
  4. 替换指定的字符,如:g替换为22,ss替换为b等操作方法
  5. 截取指定开始位置到结束位置的字符串,如:取得1-5的字符串
  6. 找出以上字符串中出现次数最多的字符和出现的次数
  7. 遍历字符串,并将遍历出的字符两头添加符号“@”
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
var str = 'abaasdffggghhjjkkgfddsssss3444343';

// 1.
console.log(str.length); // 33

// 2.
console.log(str.charAt(0) + str.charAt(3) + str.charAt(5) + str.charAt(9));

// 3.
var index = str.indexOf('i');
// var index = str.indexOf('c');
// var index = str.indexOf('b');
if (index !== -1) {
console.log('存在');
} else {
console.log('不存在');
}

// 4.
while (str.indexOf('g') !== -1) {
str = str.replace('g', '22');
}
// while (str.indexOf('ss') !== -1) {
// str = str.replace('ss', 'b');
// }
console.log(str);

// 5.
console.log(str.substr(1, 5)); //从索引号1开始,截取5个字符串

// 6.
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;
}
}
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);

// 7.
var strArr = str.split(''); //将字符串分割成字符串方法
var newStr = ''; //创建空数组
for (var i = 0; i < strArr.length; i++) { //遍历
var newChar = '@' + strArr[i] + '@';
newStr += newChar; //将newChar一个个字符串相连
}
console.log(newStr);

简单数据类型与复杂类型

简单类型又叫做基本数据类型或者值类型,复杂类型又叫做引用类型

  • 值类型:简单数据类型/基本数据类型,在存储时变量中存储的是值本身,因此叫做值类型

string ,number,boolean,undefined,null

  • 引用类型:复杂数据类型,在存储时变量中存储的仅仅是地址(引用),因此叫做引用数据类型

通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等

1
2
3
4
// 简单数据类型 null  返回的是一个空的对象  object 
var timer = null;
console.log(typeof timer); // object
// 如果有个变量我们以后打算存储为对象,暂时没想好放啥, 这个时候就给 null

堆和栈

堆栈空间分配区别:

  1. 栈(操作系统):由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈;简单数据类型存放到栈里面
  2. 堆(操作系统):存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。复杂数据类型存放到堆里面

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

简单类型的内存分配

  • 值类型(简单数据类型): string ,number,boolean,undefined,null
  • 值类型变量的数据直接存放在变量(栈空间)中
  1. 简单数据类型 是存放在栈里面 里面直接开辟一个空间存放的是值

  2. 复杂数据类型 首先在栈里面存放地址 十六进制表示 然后这个地址指向堆里面的数据

简单类型传参

函数的形参也可以看做是一个变量,当我们把一个值类型变量作为参数传给函数的形参时,其实是把变量在栈空间里的值复制了一份给形参,那么在方法内部对形参做任何修改,都不会影响到的外部变量。

1
2
3
4
var num = 10;
num = 20;
console.log(num);
// 声明一个变量叫num,然后就在内存中开辟一个空间,存放一个值 10,变量num指向10,你重新给num赋值20,这时候,是按照值来存储的,找到num,找到空间,把值改为20

1
2
3
4
5
6
7
8
function fn(a) {
a++;
console.log(a);
}
var x = 10;
fn(x);
console.log(x);

复杂类型传参

函数的形参也可以看做是一个变量,当我们把引用类型变量传给形参时,其实是把变量在栈空间里保存的堆地址复制给了形参,形参和实参其实保存的是同一个堆地址,所以操作的是同一个对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
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. 这个输出什么 ? 张学友