听阳光的猫

道阻且长、望你如一

0%

JavaScript

一. 认识JavaScript

JavaScript作用是和网页进行交互的

JavaScript是一门编程语言

编程语言的发展史:

  1. 机器语言
  2. 汇编语言
  3. 高级语言: JavaScript/C/C++

JavaScript的历史

诞生背景: 1995网景公司 Eich, Scheme, 发明JavaScript

微软公司: JScript

1996年网景公司向ECMA(欧洲计算机制造商协会)提交了提案: ECMA指定这门语言的标准

1997年ECMA指定标准: ECMAScript

JavaScript只是ECMAScript一种实现:

JavaScript: JavaScript + DOM + BOM

JavaScript的特点

解释性语言

高级语言按照其运行的方式, 又可以分为:

  1. 编译型语言:代码需要先编译,再运行 C/C++/Objective-C/Swift等等
  2. 解释型语言:一行行读取,一行行执行 Python/JavaScript/MATLAB等等

动态类型语言

JavaScript可以在执行过程中动态改变变量的类型,非常灵活,但是不安全。

目前前端已经越来越多的转向TypeScript,TypeScript最强大之处就是提供了类型检测。

JavaScript目前可以做哪些工作?

  1. 网页的交互

  2. 服务端开发(Node.js)

  3. 命令行工具(Node.js)

  4. 桌面程序,VSCode使用TypeScript开发的

  5. App(React Native)

  6. 游戏开发(cocos2d-js)

JavaScript编写位置

  • HTML元素中
  • script标签里面
  • 外部引入js文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<body>

<!-- 1.在HTML元素中直接执行JavaScript代码(不推荐) -->
<a href="" onclick="alert('我是一个弹窗')">弹出弹窗</a>
<a href="javascript:alert('我也是弹窗')">弹出弹窗</a>

<h2 style="color: red;"></h2>

<!-- 2.书写到script标签中(学习阶段) -->
<script>
alert('我是直接弹出的弹窗');
</script>

<!-- 3.从外部引入JavaScript文件(真实开发) -->
<script src="./js/test.js"></script>

<script type="text/javascript"></script>
</body>

摆放位置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>

<!-- 这个位置不推荐 -->
<!-- <script>
alert("Hello World");
document.querySelector(".title").onclick = function() {
alert("点击了h2元素")
}
</script> -->
</head>
<body>

<h2 class="title">hahaha </h2>
<H2></H2>
<p></p>
<div class="box">
<a href=""></a>
</div>


<!-- 推荐的位置 -->
<script>
// DOM操作: Document Object Manager
alert("Hello World");

// 严格区分大小写
ALERT("Hello JavaScript");

document.querySelector(".title").onclick = function() {
alert("点击了h2元素");
}
</script>
<script src=""></script>
</body>
</html>
  • 注意点
    1. script标签不能写成单标签:
      在外联式引用js文件时,script标签中不可以写JavaScript代码,并且script标签不能写成单标签
      即不能写成<script src=”index.js”/>
    2. 省略type属性:
      在以前的代码中,<script>标签中会使用 type=”text/javascript”。
      现在可不写这个代码了,因为JavaScript 是所有现代浏览器以及 HTML5 中的默认脚本语言。
    3. 加载顺序:
      作为HTML文档内容的一部分,JavaScript默认遵循HTML文档的加载顺序,即自上而下的加载顺序
      推荐将JavaScript代码和编写位置放在body子元素的最后一行
    4. JavaScript代码严格区分大小写
      HTML元素和CSS属性不区分大小写,但是在JavaScript中严格区分大小写

JavaScript注释使用

  • 单行注释
  • 多行注释
  • 文档注释
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>

<style>
/* 注释的内容 */
</style>
</head>
<body>

<!-- html -->
<h2></h2>

<script>
// 1.JavaScript注释的写法一: 单行注释
alert("hello World");

/* 2.JavaScript注释的写法二: 多行注释 */

// 3.JavaScript注释的写法二: 文档注释(了解)
/**
* 这是一个测试函数
*/
function test() {

}
</script>
</body>
</html>

浏览器交互方式

方式一:弹出弹窗显示内容

alert(内容)

方式二:在控制台打印(使用最多)

console.log(内容1, 内容2)

方式三:将内容输入到界面显示

document.write(写入的内容)

方式四:接收用户输入的内容:

prompt(内容)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<body>

<script>

// 1.交互方式一: 浏览器弹出弹窗
// alert("Hello World");

// 2.交互方式二: 在控制台打印一段内容
console.log("HelloWorld", "coderwhy", 18, 1.88);

// 3.交互方式三: DOM操作时(了解)
document.write("<h2>Hello HTML</h2>");

// 4.交互方式四: 接受用户输入的一个内容(了解)
var age = prompt("请输入您的年龄");
console.log("您的年龄是:", age);

</script>
</body>
</html>

二.JavaScript变量和数据类型

变量的命名格式

变量的声明:在JavaScript中声明一个变量使用var关键字(后续学习ES6还有let、const声明方式)

变量的赋值:使用=给变量进行赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    <script>
// 1.定义变量赋值(常用)
// 1.1.变量的定义同时进行赋值
var name = "why";

// 1.2.给变量重新赋值
name = "kobe";

alert(name);
console.log(name);

// 2.先定义(声明), 但是后面在进行赋值
var age;
age = 20;

// 3.同时定义多个变量
var num1, num2, num3;
num1 = 20;
num2 = 30;
num3 = 40;

var numa = 20, numb = 30, numc = 40;
</script>
</body>

变量命名规则(必须遵守)

第一个字符必须是一个字母、下划线( _ )或一个美元符号( $ )
其他字符可以是字母、下划线、美元符号或数字。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script>
/*
1.变量命名规则
* 首字母(第一个字符), 必须是字母(a-z,A-Z)或者_或者$
* 其他字符可以是字母或下划线或$或数字

2.什么是关键字?
* 关键字: 解析代码时, 这个单词有特殊的含义.
* 保留字: 目前这些保留字还没有成为关键字, 但是作为预留, 以后有可能会升级为关键字
*/
var name = "why";
var num1 = 123;

</script>

变量命名规范(建议遵守)

多个单词使用驼峰标识
赋值=两边都加上一个空格
一条语句结束后加上分号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<script>
// 1.变量的命名规范: 多个单词使用驼峰标识
var firstName;
var lastName;
var userLoginFlag; // 推荐写法
var userloginflag; // 不推荐

// 2.变量的命名规范: 尽量做到见名知意(看到名字就知道这个变量是做什么)
// 不要用拼音
var name = "why";
var age = 18;

// 3.赋值=两边加上空格
var height = 1.88;

// 4.一条语句结束, 后面跟一个;

// 强调变量的使用
var message = "你好啊,王小波";
alert("message")
</script>

两个变量的交换

查看数据类型

常见数据类型

数值型(Number)

Number类型也叫 数字类型或数值类型

1
2
3
4
5
6
7
8
// 1.数字类型的基本使用
var age = 20;
var height = 1.88;
var tel = 110;
console.log(typeof age);
console.log(typeof height);
console.log(typeof tel);

数字的表示方法:十进制(掌握)、十六进制、二进制、八进制

1
2
3
4
5
6
7
8
9
10
11
12
13
// 2.其他进制
// 2.1.十六进制 #ff ff ff
// 2.2.八进制
// 2.3.二进制
var num1 = 100;
var num2 = 0x100;
var num3 = 0o10;
var num4 = 0b10;
console.log(num1);
console.log(num2);
console.log(num3);
console.log(num4);

数字表示的范围

最小值:Number.MIN_VALUE,这个值为: 5e-324

最大值:Number.MAX_VALUE,这个值为: 1.7976931348623157e+308

NaN,即非数值(Not a Number)是一个特殊的数值,JS中当对数值进行计算时没有结果返回,则返回NaN。

isNaN,用于判断是否不是一个数字。不是数字返回true,是数字返回false。

1
2
3
4
5
6
7
    <script>
        // 表示的最大数字
        console.log(Number.MAX_VALUE);
        // 表示的最小数字
        console.log(Number.MIN_VALUE);
        console.log(Number("abc"));
    </script>

字符串型(String)

字符串类型,用于表示一段文字.

字符串的表示可以使用单引号也可以使用双引号。

1
2
3
4
5
6
7
8
<script>
var name = "coderwhy";
var address = "广州市";
var introduce = "认真是一种可怕的力量";

var message = "";

</script>

转义字符

转义字符 表示符号
\‘ 单引号
\“ 双引号
\\ 反斜杠
\n 换行符
\r 回车符
\t 制表符
\b 退格符
1
2
3
4
5
6
<script>
var message = 'fda\tsf\\d\naf\"asd\'ffadsf';
console.log(message);

var name= "coder\"why"
</script>

获取字符串的长度 :length属性

1
2
3
4
<script>
var name = "coderwhy";
console.log(name.length);
</script>

布尔型(Boolean)

布尔类型用于表示真假:

两个取值: true/false

1
2
3
4
<script>
var isLogin = false;
console.log(isLogin);
</script>

空类型(Null)

Null类型也是只有一个值:null

通常当一个对象(Object类型)不再使用时,可以赋值为null

未定义型(Undefined)

Undefined 类型只有一个值:undefined

在使用 var 声明变量但未对其加以初始化时,这个变量的值就是 undefined

typeof对没有初始化和没有声明的变量都会返回undefined

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script>
// 1.undefined(未定义): 当一个变量进行了声明,但是没有赋值, 这个时候它的值就是undefined
var flag;
console.log(flag); // 目前的值是undefined
console.log(typeof flag); // 类型是undefined

// 2.null(空):
var info = {name: "why", age: 18};
info = null;

// 了解
console.log(undefined == null); // true

</script>
  • Null和Undefined的关系:

    undefined值实际上是由null值衍生出来的,所以如果比较undefined和null是否相等,会返回true

    但是转化成数字时,undefined为NaN,null为0

变量存储的本质

内存的分类:栈空间stack和堆空间heap

数据类型的转换

转成数字类型

其他类型转成数值类型的时候,存在有两种可能的值:

  1. 转换成功,获取到对应的数字
  2. 转换失败,结果为NaN

将其他类型转成数字类型的方法:

Number(any)函数 将任意类型转成数字

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
<script>

// 1.将其他转成数字类型
// 1.1.将String转成数字类型
var message1 = "123";
var num1 = Number(message1);
console.log(num1, typeof num1);

var message2 = "abc";
var num2 = Number(message2);
console.log(num2, typeof num2); // NaN: not a number

// 1.2.将Boolean转成数字类型
// true: 1
// false: 0
console.log(Number(true));
console.log(Number(false));

// 1.3.Undefined转成数字类型
console.log(Number(undefined)); // NaN

// 1.4.Null转成数字类型
console.log(Number(null)); // 0

</script>

parseInt(string, radix)函数:将字符串转换成整数类型,radix表示基数,这里可以理解成进制

如果第一个字符是数字或运算符号,那么就开始解析,直到遇到非数字字符,停止解析并得到解析结果;

如果第一个字符是非数字且非运算符号,则不解析并得到结果 NaN。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script>
// parseInt
var str1 = "123";
var num1 = parseInt(str1);
console.log(num1, typeof num1); // 123 number

var str2 = "123.45";
var num2 = parseInt(str2);
console.log(num2, typeof num2); // 123 number

var str3 = "abc";
var num3 = parseInt(str3);
console.log(num3, typeof num3); // NaN number

var str4 = "abc123";
var num4 = parseInt(str4);
console.log(num4, typeof num4); // NaN number

var str5 = "123abc";
var num5 = parseInt(str5);
console.log(num5, typeof num5); // 123 number

</script>

parseFloat(string)函数:将字符串转换成浮点类型(小数类型)

如果第一个字符是数字或运算符号,那么就开始解析,直到遇到非数字字符,停止解析并得到解析结果;

如果第一个字符是非数字且非运算符号,则不解析并得到结果 NaN。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    <script>
// parseFloat
var s1 = "123.45";
var n1 = parseFloat(s1);
console.log(n1, typeof n1); // 123.45 number

var s2 = "123";
var n2 = parseFloat(s2);
console.log(n2, typeof n2); // 123 number

var s3 = "123.45.67";
var n3 = parseFloat(s3);
console.log(n3, typeof n3); // 123.45 number

// parseInt-> radix
var str = "111";
console.log(parseInt(str, 16));

// parseFloat()
// alert()

</script>

转换成字符串类型

方式一: 调用toString()方法

toString()方法只能将数值类型和布尔类型转换成字符串类型

不能将Undefined和Null类型转成字符串类型;

1
2
3
4
5
6
7
8
9
10
11
var num = 123;
var obj = null;
var message = undefined;
var flag = true;

// 1.转换方式一: 变量.toString();
console.log(num.toString());
// console.log(obj.toString()); null不适用
// console.log(message.toString()); undefined不适用
console.log(flag.toString());

方式二: String(内容)

String()函数能将所有基本类型转成字符串类型

1
2
3
4
5
6
7
8
9
10
      var num = 123;
var obj = null;
var message = undefined;
var flag = true;

// 2.转换方式二: String(变量)
console.log(String(num));
console.log(String(obj));
console.log(String(message));
console.log(String(flag));

方式三:字符串拼接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script>
var num = 123;
var obj = null;
var message = undefined;
var flag = true;

// 3.转换方式三: 和字符串进行拼接: 变量 + ""
// 隐式转换: 其他的数据类型再和字符串通过+运算符进行拼接时, 会自动转成字符串类型
console.log(num + "gg");
console.log(obj + "");
console.log(message + "");
console.log(flag + "");

</script>

转换成布尔类型

通常使用Boolean()函数将其他类型转成布尔类型:

转换成false的五种特殊值:””(空字符串)、0(包括 0、-0)、undefined、null、NaN;

如果某个值为 “”(空字符串)、0(包括 0、-0)、undefined、null、NaN时,那么这个值转换成布尔类型之后的值为 false。
否则,其值为 true。(记住五种特殊值)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script>

// 转成布尔类型: Boolean(数据/变量)
// 非五个值: true
console.log(Boolean("123"));
console.log(Boolean(123));

// 五个值: "" 0 null undefined NaN
console.log(Boolean(""));
console.log(Boolean(0));
console.log(Boolean(null));
console.log(Boolean(undefined));
console.log(Boolean(NaN));

</script>

三.JavaScript操作符

算术运算符

算术运算符用在数学表达式中, 它的使用方式和数学中也是一致的.

可以直接对数据进行操作, 也可以操作变量指向的数据.

运算符 运算规则 范例 结果
+ 正号 +3, 和直接写3一样 3
+ 加法 2 + 3 5
+ 连接字符串 ‘中’+ ‘国’ ‘中国’
- 减法 2 - 3 -1
* 乘法 2 * 3 6
/ 除法 5 / 2 2.5
% 取余数 5 % 2 1
++ 自增 3++或++3 4
自减 3–或–3 2
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
<script>
// 1.定义一些变量
var num1 = 20;
var num2 = 6;
var str1 = "hello";
var str2 = "coderwhy";

// 2.+
console.log(+num1);
console.log(num1 + num2);
console.log(str1 + str2);
console.log(str1 + " " + str2);
console.log(str1, str2);

// 字符串和其他类型拼接: 其他类型转成字符串
console.log(str1 + num1);

// 3.-
console.log(num1 - num2);
console.log(str1 - str2); // NaN

// 4.*
console.log(num1 * num2);

// 5./
console.log(num1 / num2);

// 6.%
console.log(20 % 6); // 2

</script>

自增++和自减–

通常都是用在数字变量上

  1. 自增:++ 分为前置自增和后置自增
  2. 自减:– 分为前置自减和后置自减

总结:前置先算后使用,后置先使用后计算

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
<script>
// 1.自增
var num1 = 100;
// num1++; ++后置写法
// ++num1; ++前置写法
console.log(num1);

// 2.自减
var num2 = 100;
// num2 = num2 - 1;
// num2--;
--num2;
console.log(num2);

// 3.前置和后置的区别: 参与运算时有区别
// num++: 先使用, 之后自身再+1
// ++num: 先自身+1, 之后再使用
var num = 100;

// var result = num++ + 10; // 110
// console.log(result);

var result = ++num + 10;
console.log(result);

// 4.练习
var a = 10;
// 10 + 11
// var b = a++ + a++; // 21
// console.log(b);
// console.log(a);

// 11 + 11 = 22
// var b = ++a + a++;
// console.log(b);

// 11 + 12 = 23
// var b = ++a + ++a;
// console.log(b);

// 10 + 11 = 21
var b = a++ + a--;
console.log(b);

</script>

赋值运算符

赋值运算符主要是给某个变量进行赋值

赋值运算符是算术运算符和赋值的一种简便写法.
比如 a = 3; a = a + 1;
第二句可以写成 a += 1;

运算符 运算规则 范例
= 赋值 a = 5 5
+= 加后赋值 a = 5, a += 2 7
-= 减后赋值 a = 5, a -= 2 3
*= 乘后赋值 a = 5; a *= 2 10
/= 除后赋值 a = 5; a /= 2 2.5
%= 取余后赋值 a = 5; a %= 2 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script>
// 1.定义变量
var num1 = 20;
var num2 = 6;

// 2.赋值运算符
// num1 = num1 + num2;
// num1 += num2; // 26
// num1 -= num2; // 14
// num1 *= num2; // 120
// num1 /= num2;
num1 %= num2;

console.log(num1);
</script>

比较运算符

比较运算符,又叫关系运算符

它是用来判断两个操作数的大小关系及是否相等关系的
结果是布尔类型(bool): True或者False
比较运算符经常用在后面学习的if/while语句中
学习if语句的使用

运算符 运算规则 范例 结果
== 相等 4 == 3 false
!= 不等于 4 != 3 true
> 大于 4 > 3 true
< 小于 4 < 3 false
>= 大于等于 4 >=3 true
<= 小于等于 4 <= 3 false
1
2
3
4
5
6
7
8
9
10
11
12
<script>
var num1 = 20;
var num2 = 30;

console.log(num1 == num2); // false

console.log(num1 != num2); // true
console.log(num1 > num2); // false
console.log(num1 < num2); // true
console.log(num1 >= num2); // false
console.log(num1 <= num2); // true
</script>

除了==以外,JS中还提供了===
===表示全等,他和==基本一致,不过==在判断两个值时会进行自动的类型转换,而===不会。
比如”123”==123 会返回true,而”123”===123会返回false;

除了!=以外,JS中还提供了!==
!==也不会进行自动类型转换,比如”123”!=123 会返回false,而”123”!==123会返回true;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script>
// 1.==比较: 会进行隐式转换, 再进行比较
var num1 = 123;
var num2 = "123";

// == 判断, 隐式转换: 将string转成number
console.log(num1 == num2);

var flag1 = true;
var flag2 = "true";
// 隐式转换: 都转成number再比较
// flag1 -> 1
// flag2 -> NaN
console.log(flag1 == flag2); // false

// 2.===全等: 类型相等, 数据相等(更多)
console.log(num1 === num2);

// 2.!=比较: 隐式转换
// 2.!==比较: 不会进行隐式转换
console.log(num1 != num2); // false
console.log(num1 !== num2); // true

</script>

逻辑运算符

逻辑运算符,它是用于将多个条件放在一起进行运算的
逻辑运算符的运算结果也是Boolean类型: true/false
逻辑运算符也应用if/while的判断句中, 并且是多个条件时会使用到

运算符 运算规则 范例 结果
&& 与: 同时为真 false && True false
|| 或: 一个为真 false or frue true
! 非: 取反 !false true
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
<script>
var age = 20;
var money = 2;

// 1.与运算: && -> 两个条件同时满足
if(age >= 18 && money >= 5) {
console.log("开机");
console.log("上网");
console.log("玩游戏");
}

// 2.或运算: || -> 满足一个条件
var profession = "网管";
var flag1 = age >= 18 && money >= 5; // false
var flag2 = profession === "网管"; // true

if (flag1 || flag2) {
console.log("开机");
console.log("上网");
console.log("玩游戏");
}

// 3.取反运算: ! -> 对之前的Boolean类型取反
var flag = true;
if (!flag) {
console.log("Hello World");
}

</script>
  1. 逻辑与补充:

    逻辑与运算符可以应用于任何数据类型,且不一定返回布尔值。

    对于非布尔值运算,会先将非布尔值转换为布尔值。

  2. 逻辑或补充:

    逻辑或运算符可以应用于任何数据类型,且不一定返回布尔值。

    对于非布尔值运算,会先将非布尔值转换为布尔值。

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
<script>
var name = "why";

// 对象中存放的是键值对: key(键): value(值)
var info = {
name: "why",
age: 18,
height: 1.88,

eating: function() {
console.log("吃东西");
}
};

// 1.与运算的特殊用法: 多个条件都为true
// 短路与: 有一个条件为false, 那么后续不再判断
// 条件1 && 条件2 && 条件3
// console.log(info.eating());

// if (info.eating) {
// info.eating()
// }

info.eating && info.eating();
console.log("--------");

// 2.或运算的特殊用法: 只要有一个条件为true
// 短路或: 一旦遇到一个条件为true, 那么后面的条件不再判断
// 条件1 || 条件2 || 条件3
var message = info.name || info.age || info.height;
console.log(message);

</script>

运算符的优先级

image-20201112105701541

1
2
3
4
5
6
7
8
9
10
<script>
// 先算乘除, 再算加减
var result = 20 * (5 + 10) * 2 - 20;
console.log(result);

// 上午练习
var a = 10;
var b = a++ + ++a;

</script>

四. JavaScript分支语句

程序的执行顺序

在程序开发中,程序有三种不同的执行方式:

顺序 —— 从上向下,顺序执行代码

分支 —— 根据条件判断,决定执行代码的 分支

循环 —— 让 特定代码 重复 执行

if分支结构

if分支结构有三种:

  1. 单分支结构 if..
1
2
3
4
5
6
7
8
9
10
11
12
<script>
// 案例一: 小明的例子
// 1.让小明输入自己的分数
var score = prompt("小明, 请输入你的分数:");
console.log(score, typeof score);

// 2.判断分数是否大于90
if (score > 90) {
console.log("去游乐场玩");
}

</script>
  1. 多分支结构 if..else..
1
2
3
4
5
6
7
8
9
10
11
12
13
<script>
// 案例一: 小明去游乐场还是补习班
// 1.小明输入自己的分数
var score = prompt("小明请输入你的分数:");

// 2.条件判断
if (score > 90) {
console.log("游乐场玩");
} else {
console.log("去上补习班");
}

</script>

​ if..else if..else..

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
<script>
/*
小明:
分数大于90分: 去游乐场玩
分数大于80分, 小于等于90: 玩手机游戏一天
分数大于60分, 小于等于80: 优先做家庭作业
小于60分: 天天去上补习班
*/

// 1.小明输入自己的分数
var score = prompt("小明请输入你的分数:");

// 2.小明应该做什么
// > 80 80~90 90以上
if (score > 90) {
console.log("去游乐场玩");
} else if (score > 80) {
console.log("玩手机游戏一天");
} else if (score > 60) {
console.log("优先做家庭作业");
} else {
console.log("天天去上补习班");
}

</script>

三元运算符

有三元运算符或者称之为三目运算符,整个表达式中有三个元素。

三元表达式是一种if else的简便写法。

三元表达式的格式:表达式1 ? 表达式2 : 表达式3

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
<script>
// 1.比较两个数字
var m = 50;
var n = 30;
var max = m > n? m: n;
console.log(max);

// 通过if else
// if (m > n) {
// max = m;
// } else {
// max = n;
// }

// 2.判断一个人是否是成年人
var age = 12;
var result = age >= 18? "成年人": "未成年人";

// if (age >= 18) {
// result = "成年人";
// } else {
// result = "未成年人";
// }
console.log(result);

// 3.判断要执行哪一个函数(了解)
function test1() {
console.log("test1");
}
function test2() {
console.log("test2");
}
var flag = true;
flag? test1(): test2();


</script>

switch分支结构

它是通过判断表达式的结果是否等于case语句的常量,来执行相应的分支体的

与if语句不同的是,switch语句只能做值的相等判断(使用全等运算符 ===),而if语句可以做值的范围判断

case穿透问题:一条case语句结束后,会自动执行下一个case的语句

break关键字,通过在每个case的代码块后添加break关键字来解决这个问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script>
// 1.女朋友输入节日
var holidayName = prompt("请输入今天的节日:");

// 2.判断节日
switch (holidayName) {
case "情人节":
console.log("买玫瑰");
console.log("看电影");
break;
case "平安夜":
console.log("买苹果");
console.log("吃大餐");
break;
case "生日会":
console.log("买蛋糕");
console.log("开Party");
break;
default:
console.log("上班");
console.log("工作");
console.log("喝西北风");
}
</script>

五.JavaScript循环语句

while循环

只有一个判断条件

当条件成立时,执行代码块

当条件不成立时,跳出代码块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<script>
// 练习一: 打印10次Hello World
// var i = 0;
// while (i < 10) {
// console.log("Hello World");
// i++;
// }

// 练习二: 打印0~99的数字
// var i = 0;
// while (i < 100) {
// console.log(i);
// i++;
// }

// 练习三: 打印1-100的数字
// var i = 1;
// while (i < 101) {
// console.log(i);
// i++;
// }
// var i = 0;
// while (i < 100) {
// i++;
// console.log(i);
// }

// 练习四: 计算0~99数字的和
var i = 0;
var total = 0;

while (i < 100) {
console.log(i);
total += i;
i++;
}

console.log(total);

// 练习五: 计算所有奇数的和
// 问题: 如何判断一个数字是奇数还是偶数
// 需求一: 让用户在浏览器中输入一个数字, 打印一下这个数字是奇数还是偶数
var num = prompt("请输入一个数字:");
if (num % 2 === 0) {
console.log("您输入数字是偶数");
} else {
console.log("您输入数字是奇数");
}

// 需求二: 打印所有的奇数, 并且计算它们的和
var i = 0;
var oddTotal = 0;
var evenTotal = 0;
while (i < 100) {
if (i % 2 !== 0) {
console.log("奇数:", i);
oddTotal += i;
} else {
console.log("偶数:", i);
evenTotal += i;
}
i++;
}
console.log("所有奇数的和:", oddTotal);
console.log("所有偶数的和:", evenTotal);

</script>

do..while循环

do..while循环和while循环非常像,二者经常可以相互替代(不常用)

但是do..while的特点是不管条件成不成立,do循环体都会先执行一次

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
<script>
// 1.练习一: 打印10次Hello World
// i=0, 执行一次 判断 i=1
// i=1, 执行一次 判断 i=2
// i=2, 执行一次 判断 i=3
// i=3, 执行一次 判断 i=4
// i=4, 执行一次 判断 i=5
// i=5, 执行一次 判断 i=6
// i=6, 执行一次 判断 i=7
// i=7, 执行一次 判断 i=8
// i=8, 执行一次 判断 i=9
// i=9, 执行一次 判断 i=10
// var i = 0;
// do {
// console.log("Hello World");
// i++;
// } while (i < 10)

// 2.练习二: 打印0~99的数字还需要计算它们的和
var i = 0;
var total = 0;
do {
console.log(i);
total += i;
i++;
} while (i < 100)
console.log(total);

</script>

for循环

for循环是开发中使用最多的循环语句

语句一:初始化表达式:通常会写var i=1

语句二:条件表达式,用于判断进行条件判断

语句三:自增、减表达式,比如i++或i–

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
<script>
// 1.练习一: 打印0~99的数字
// for (var i = 0; i < 100; i++) {
// console.log(i);
// }

// 2.练习二: 打印1~100的数字
// for (var i = 1; i <= 100; i++) {
// console.log(i);
// }

// 3.练习三: 打印100~1的数字
// for (var i = 100; i > 0; i--) {
// console.log(i);
// }

// 4.练习四: 计算0~99的和
// var total = 0;
// for (var i = 0; i < 100; i++) {
// console.log(i);
// total += i;
// }
// console.log(total);

// 5.练习五: 计算0~99的奇数和和偶数和
var oddTotal = 0;
var evenTotal = 0;
for (var i = 0; i < 100; i++) {
if (i % 2 === 0) { // 偶数
evenTotal += i;
} else { // 奇数
oddTotal += i;
}
}
console.log("奇数和:", oddTotal);
console.log("偶数和:", evenTotal);


</script>

for循环嵌套

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
span {
display: inline-block;
width: 80px;
height: 30px;
line-height: 30px;
text-align: center;
border-top: 1px solid #f00;
border-right: 1px solid #f00;
}

div {
display: inline-block;
border-left: 1px solid #f00;
border-bottom: 1px solid #f00;
}
</style>
</head>
<body>

<script>
// 1.在屏幕上显示一个❤矩形
// document.write("❤");
// for (var i = 0; i < 10; i++) {
// // document.write("❤ ❤ ❤ ❤ ❤ ❤");
// for (var j = 0; j < 10; j++) {
// document.write("❤ ");
// }

// document.write("<br>")
// }

// 2.在屏幕上显示一个❤三角形
// for (var i = 0; i < 10; i++) {
// for (var j = 0; j <= i; j++) {
// document.write("❤ ");
// }

// document.write("<br>");
// }

// 3.在屏幕上显示一个九九乘法表
for (var i = 1; i < 10; i++) {
for (var j = 1; j <= i; j++) {
var str = j + "*" + i + "=" + j * i + "&nbsp;&nbsp;&nbsp;";
document.write(str);
}
document.write("<br>");
}

document.write("<div>");
for (var i = 1; i < 10; i++) {
for (var j = 1; j <= i; j++) {
var str = "<span>" + j + "*" + i + "=" + j * i + "</span>";
document.write(str);
}
document.write("<br>");
}
document.write("</div>");

</script>
</body>
</html>

循环的跳转

循环的跳转控制

break: 直接跳出循环, 循环结束

break 某一条件满足时,退出循环,不再执行后续重复的代码

continue: 跳过本次循环次, 执行下一次循环体

continue 某一条件满足时,不执行后续重复的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script>
// 默认情况下, 所有的循环都会按照正常的顺序, 依次执行
// 1.需求一: 5这个数字不打印
// continue: 跳出本次, 执行下一次循环
// for (var i = 0; i < 10; i++) {
// if (i === 5 || i === 8) {
// continue;
// }
// console.log(i);
// console.log("Hello World");
// }

// 2.需求二: 5这个数字, 直接整个循环跳出
// break: 直接跳出循环, 后续所有的循环体都不再执行
for (var i = 0; i < 10; i++) {
if (i === 5) {
break;
}

console.log(i);
console.log("Hello World");
}

</script>

断点调试

可以查看一个变量的变化

断点调试也被称为debug

开启断点调试常见的有两种方式:

方式一:找到自己的源代码,在其中打断点

​ 浏览器 -> source -> 代码 -> 打断点

方式二:在代码中写上debugger

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<script>

var num = 100;
var name = "why";

debugger;

num = num + 25;
name = "kobe";

while (num < 200) {
num += 2;
}

num = 55;

// ...1000行

</script>

六.JavaScript数组基础

数组的常见操作

数组有一个length属性,所以可以直接通过length获取数组的长度

获取数组某个位置的数据:通过索引值

索引值也被称为下标值index

索引值是从0开始的(注意,不是从1开始的)

注意:在JavaScript中获取一个不存在的索引值,不会报错,结果为undefined

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script>
// 1.定义数组
var movies = ["海王", "上海堡垒", "唐人街探案", "少年派"];
console.log(movies);

// 2.获取数组的长度属性: length
console.log(movies.length);

// 3.根据索引值获取数据
// 强调: 如果传入不存在的索引值, 返回的数据是undefined
var m1 = movies[1];
var m2 = movies[10]; // undefined
var m3 = movies[-1]; // undefined
console.log(m1, m2, m3);
</script>

数组的遍历

遍历:遍及所有,历经全部的意思,也被称之为迭代。

对数组的每一个元素都访问一次就叫遍历。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script>
// 1.定义了数组
var names = ["why", "lilei", "hanmeimei", "lucy"];

// 2.对数组进行遍历
// console.log(names[0]);
// console.log(names[1]);
// console.log(names[2]);
// console.log(names[3]);
// console.log(names[4]);

// 注意事项: 访问数组的最后一个元素 -> length - 1位置
for (var i = 0; i < names.length; i++) {
console.log(names[i]);
}
</script>

数组的练习

练习一

反向遍历数组

字符串的拼接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<script>
// 1.定义数组
var names = ["lilei", "hanmeimei", "tom", "poly", "lily"];


// 2.反向的遍历
// for (var i = 0; i < names.length; i++) {
// console.log(names[i]);
// }
for (var i = names.length - 1; i >= 0; i--) {
console.log(i);
console.log(names[i]);
}

// 3.将数组中所有的元素使用-进行分割
/*
1.将所有的name拼接到message中
2.在所有的名字后面+ “-”
3.将最后一个”-”去除掉
*/
// 效果: "lilei-hanmeimei-tom-poly-lily"
var message; // "undefined"
for (var i = 0; i < names.length; i++) {
// console.log(names[i]);
message += names[i];
if (i !== names.length - 1) {
message += "-";
}
}
console.log(message);

// message += names[names.length-1];
</script>

练习二

计算数组中数字的和和平均值

找出数组中的最大值和最小值

数组的反转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<script>
// 1.定义数组
var nums = [10, 8, 128, 99, 222, 66, 3];

// 2.求数组中数字的和以及平均值
// var total = 0;
// for (var i = 0; i < nums.length; i++) {
// total += nums[i];
// }
// console.log("数字的和:", total);
// var average = total / nums.length;
// console.log("数字的平均值:", average);

// 3.找出数组中的最大值
/*
1.定义一个变量, 变量保存第一个数字
2.遍历所有的数字
3.将遍历的数字和保存的数字进行比较
遍历的数字 > 保存的数字
将遍历的数字放到保存的遍历中
*/
// var max = nums[0];
// for (var i = 0; i < nums.length; i++) {
// console.log(nums[i]);
// if (nums[i] > max) {
// max = nums[i];
// }
// }
// console.log(max);

// 4.反转数组
// [10, 8, 128, 99, 222, 66, 3]
// var temp = nums[0];
// nums[0] = nums[nums.length-1];
// nums[nums.length-1] = temp;
// console.log(nums);

// var temp = nums[1];
// nums[1] = nums[nums.length-2];
// nums[nums.length-2] = temp;
// console.log(nums);

// var temp = nums[2];
// nums[2] = nums[nums.length-3];
// nums[nums.length-3] = temp;
// console.log(nums);

// var temp = nums[3];
// nums[3] = nums[nums.length-4];
// nums[nums.length-4] = temp;
// console.log(nums);

for (var i = 0; i < nums.length / 2; i++) {
var temp = nums[i];
nums[i] = nums[nums.length-1-i];
nums[nums.length-1-i] = temp;
}
console.log(nums);

</script>

数组的排序:

排序算法

冒泡排序/选择排序/插入排序

堆排序/希尔排序/快速排序

练习冒泡

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<script>
// 1.定义数组
var nums = [10, 323, 8, 10, 66, 789, 128, 99, 222, 88, 43];

// 2.对数组进行排序
// 需求一: 将最大的数字想办法放到最后(冒泡思想)
// 0 1
// 1 2
// 2 3
// for (var i = 0; i < nums.length-1; i++) {
// if (nums[i] > nums[i+1]) {
// var temp = nums[i];
// nums[i] = nums[i+1];
// nums[i+1] = temp;
// }
// }

// for (var i = 0; i < nums.length-1-1; i++) {
// if (nums[i] > nums[i+1]) {
// var temp = nums[i];
// nums[i] = nums[i+1];
// nums[i+1] = temp;
// }
// }


// for (var i = 0; i < nums.length-1-1-1; i++) {
// if (nums[i] > nums[i+1]) {
// var temp = nums[i];
// nums[i] = nums[i+1];
// nums[i+1] = temp;
// }
// }

// for (var i = 0; i < nums.length-1-1-1-1; i++) {
// if (nums[i] > nums[i+1]) {
// var temp = nums[i];
// nums[i] = nums[i+1];
// nums[i+1] = temp;
// }
// }

for (var j = nums.length-1; j > 0; j--) {
for (var i = 0; i < j; i++) {
if (nums[i] > nums[i+1]) {
var temp = nums[i];
nums[i] = nums[i+1];
nums[i+1] = temp;
}
}
}

console.log(nums);

</script>

七.JavaScript的函数基础

编程范式: 编程方式

面向过程编程: C语言

面向对象编程: Java 类 -> 对象/C++

函数式编程: lisp(天才程序员会使用语言 - 黑客与画家 - 人工智能)/scheme/JavaScript

JavaScript: 函数式编程/面向对象编程(基于对象)

ES6: 箭头函数

函数的定义和调用

定义函数使用function关键字:这种写法称之为函数的声明

function 函数名(){

​ 函数封装的代码

​ ……

}

函数名的命名规则和前面变量名的命名规则是相同的

函数定义完后里面的代码是不会执行的,函数必须调用才会执行

调用函数通过函数名()即可:比如test()

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
<script>
// 1.如何定义一个函数
/*
命名规则:
第一个字符必须是字母或_或$
其他字符串字母或_或数字$
*/
// function 函数名() {
// // 封装函数的代码
// }

function printInfo() {
console.log("why");
console.log(18);
console.log(1.88);
}

printInfo();
printInfo();
printInfo();
printInfo();

// 2.练习二: 在函数内部计算10和20的和
function sum() {
var result = 10 + 20;
console.log(result);
}

sum();

</script>

函数的参数

函数,把具有独立功能的代码块 组织为一个小模块,在需要的时候调用

数的参数,增加函数的通用性,针对相同的数据处理逻辑,能够 适应更多的数据

在函数 内部,把参数当做 变量使用,进行需要的数据处理

函数调用时,按照函数定义的参数顺序,把 希望在函数内部处理的数据,通过参数传递

形参和实参

形参:定义函数时,小括号中的参数,是用来接收参数用的,在函数内部作为变量使用

实参:调用函数时,小括号中的参数,是用来把数据传递到函数内部用的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<script>
// 函数的参数传递
// function printInfo1() {
// console.log("why");
// console.log(18);
// console.log(1.88);
// }

// function printInfo2() {
// console.log("kobe");
// console.log(40);
// console.log(1.87);
// }

// function printInfo3() {
// console.log("james");
// console.log(35);
// console.log(1.86);
// }

// printInfo1();
// printInfo2();
// printInfo3();

// 2.上面的代码进行重构
// name, age, height: 形参
function printInfo(name, age, height) {
console.log(name);
console.log(age);
console.log(height);
}

// "why", 18, 1.88: 实参
printInfo("why", 18, 1.88);
printInfo("kobe", 40, 1.87);
printInfo("james", 35, 1.86);

// 3.练习二: 定义两个数字相加
function sum(num1, num2) {
var result = num1 + num2;
console.log(result);
}

sum(10, 20);
sum(34, 66);

// 作业:
// 4.练习三: 对某个人say Hello
function sayHello(name) {
console.log("Hello " + name);
console.log("Hello", name);
}

// 5.练习四: 为某个朋友唱生日歌
function singSong(name) {
console.log("Happy Birthday To You");
console.log("Happy Birthday To You");
console.log("Happy Birthday To " + name);
console.log("Happy Birthday To You");
}

sayHello("Kobe");
singSong("James");

</script>

函数的返回值

使用return关键字来返回结果

一旦在函数中执行return操作,那么当前函数会终止

如果函数中没有使用 return语句 ,那么函数有默认的返回值:undefined

如果函数使用 return语句,但是return后面没有任何值,那么函数的返回值也是:undefined

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
<script>
// function sum(num1, num2) {
// console.log(num1 + num2);
// }

// sum(20, 30);
// var age = prompt("aaaaaa");

// 1.函数的返回值的基本使用
function sum(num1, num2) {
var result = num1 + num2;
console.log(result);
return result;
}

// 调用函数
var total = sum(20, 30);
console.log(total);

// 2.返回值的注意事项
// 注意一: 一旦函数中执行了return操作, 那么函数会立即停止, 后续的代码都不再执行
// 注意二: 如果一个函数没有写返回值, 相当于默认返回undefined
// 注意三: 如果一个函数写了return, return后面没有跟内容, 相当于也是return了一个undefined
function test() {
console.log("1");
console.log("2");
return;
console.log("3");
console.log("4");
}

var result = test();
console.log(result);


// 了解: 以后会写类似这样的函数
function dateFormat(timestamp) {
return "2018-11-11";
}

var result1 = dateFormat(132342423423);
var result2 = dateFormat(132341213213);

</script>

函数的练习一

加法计算器

计算面积: 矩形/圆形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<script>
// 1.练习一: 实现一个加法计算器
function sum(num1, num2) {
// var result = num1 + num2;
// return result;
return num1 + num2;
}

var total = sum(20, 30);
console.log(total);

// 2.练习二: 定义函数, 传入宽高计算矩形的面积
// stack overflow
// 矩形面积: 宽度 * 高度
function calcRectArea(width, height) {
return width * height;
}
var area1 = calcRectArea(10, 20);
var area2 = calcRectArea(20, 30);
console.log(area1);
console.log(area2);

// 3.练习三: 定义函数, 传入半径计算圆形的面积
// 圆形的面积: πr²
function calcCircleArea(radius) {
return Math.PI * radius * radius;
}
var area3 = calcCircleArea(10);
console.log(area3);

// 补充: 获取π的值
var pi = Math.PI;
console.log(pi);

</script>

函数的练习二

计算n数字的和

反转数组

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
<script>
// 1.练习四: 定义函数, 传入一个n, 计算1~n数字的和
function calcNSum(n) {
var total = 0;
for (var i = 1; i <= n; i++) {
total += i;
}
return total;
}
// 1 2 3 4 5: 15
var result1 = calcNSum(5);
var result2 = calcNSum(100);
console.log(result1);
console.log(result2);

// 2.练习五: 定义一个函数, 传入一个数组, 对数组进行反转
// var nums = [10, 14, 8, 5, 88];
// for (var i = 0; i < nums.length / 2; i++) {
// var temp = nums[i];
// nums[i] = nums[nums.length-1-i];
// nums[nums.length-1-i] = temp;
// }
// console.log(nums);

// var nums2 = [20, 76, 44, 67, 23];
// for (var i = 0; i < nums2.length / 2; i++) {
// var temp = nums2[i];
// nums2[i] = nums2[nums2.length-1-i];
// nums2[nums2.length-1-i] = temp;
// }
// console.log(nums2);
function reverseArray(arr) {
for (var i = 0; i < arr.length / 2; i++) {
var temp = arr[i];
arr[i] = arr[arr.length-1-i];
arr[arr.length-1-i] = temp;
}
return arr;
}

var nums1 = [10, 14, 8, 5, 88];
nums1 = reverseArray(nums1);
console.log(nums1);

var nums2 = [20, 76, 44, 67, 23];
nums2 = reverseArray(nums2);
console.log(nums2);
</script>

斐波那契数列

for循环

递归调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
<script>
// 需求: 求一个斐波那契数
// 1.方式一: for循环实现
// 1 1 2 3 5 8 13 21 34.......
// n=0
// n=1
// n=2
// n=3
// n=4
function fib(n) {
if (n === 0 || n === 1) {
return 1
}
var num1 = 1;
var num2 = 1;
var sum = 2;
for (var i = 2; i < n; i++) {
num1 = num2;
num2 = sum;
sum = num1 + num2;
}
return sum;
}
console.log(fib(0));
console.log(fib(1));
console.log(fib(2));
console.log(fib(3));
console.log(fib(4));
console.log(fib(5));
console.log(fib(6));
console.log(fib(7));

// 2.方式二: 递归调用方式
// 什么递归调用
// 2.1.一个函数中可以去调用另外一个函数
function test1() {
console.log("test1被调用");
test2();
}

function test2() {
console.log("test2被调用");
}

test1();

// 2.2.函数自己调用自己: 递归调用
/*
在开发中尽量避免使用递归:
1.递归如果没有写好结束条件, 意味着会无限调用
2.递归调用非常占据栈空间内存(空间复杂度)/效率比较低(时间复杂度)
*/
// function test() {
// console.log("test被调用");
// test();
// }

// test();

// 2.3.使用递归调用实现斐波那契数列
// fib2(2): 2
// fib2(1): 1
function fib2(n) {
if (n === 0 || n === 1) {
return 1;
}
return fib2(n-1) + fib2(n-2);
}

console.log(fib2(8));

fib2(50);

// 0: 1
// 1: 1
// 2: 2
// 3: 3
// 5:

</script>

arguments参数

默认情况下,arguments对象是所有(非箭头)函数中都可用的局部变量。

该对象中存放着所有的调用者传入的参数,从0位置开始,依次存放。

arguments变量的类型是一个object类型,不是一个数组,但是和数组的用法看起来很相似。

如果调用者传入的参数多余函数接收的参数,可以通过arguments去获取所有的参数。

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
<script>

// 1.对arguments的认识
// arguments对象: 在函数当中
function sum(num1, num2) {

console.log(arguments);
console.log(arguments[2]);

return num1 + num2;
}
// var result = sum(20, 30);
// console.log(result);
var result = sum(20, 30, 40, 50, 100);
// console.log(result);


// 2.新需求: 定义一个函数, 可以计算1/2/3/4/5...
function newSum() {
var total = 0;
for (var i = 0; i < arguments.length; i++) {
// console.log(arguments[i]);
total += arguments[i];
}
return total;
}
console.log(newSum(10, 20));
console.log(newSum(5, 10, 66));

</script>

函数的调用栈

函数的调用过程是一个压栈的过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<script>
function test1() {
console.log("test1函数被调用");
test2();
}

function test2() {
console.log("test2函数被调用");
test3();
}

function test3() {
console.log("test3函数被调用");
}

test1();

</script>

变量的作用域

在JavaScript(ES5之前)中没有块级作用域的概念,但是函数可以定义自己的作用域。

什么是全局变量和局部变量?
定义在函数内部的变量,被称之为局部变量。
定义在script标签中的变量,被称之为全局变量。

在函数中,访问变量的顺序是什么呢?

变量访问: 优先局部变量, 全部变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<script>
// 变量作用域: 变量在哪一个范围内可以被使用, 这个范围就是变量的作用域.
var name = "why";
// 块级作用域: 在JavaScript(ES5)里面没有块级作用域
// 函数作用域: 函数内部的代码是有自己的作用域的

// 1.块是没有自己的作用域
// {
// var age = 18;
// }
// console.log(age);


// 2.函数的作用域
function test() {
// 局部变量
var age = 20;
var height = 1.88;
var name = "kobe";

console.log(age);
console.log(height);
console.log(name);
}

// 全局变量
var name = "why";

// 结论一: 在全局默认是不能访问局部的变量的
// console.log(age);
// 结论二: 在函数中, 访问一个变量时, 会优先去查找自己的局部变量, 如果没有找到, 会去查找全局变量.
test();

</script>

函数的表达式写法

之前定义的函数被称之为函数的声明,除了声明之外,还有其他函数形式:

函数表达式:匿名函数表达式和命名函数表达式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 2.函数定义方式二: 函数表达式
// 2.1.命名函数表达式
// name属性的值 函数的名字
var abc = function test1() {
console.log("test1函数被调用");
}
abc();

// 2.2.匿名函数表达式
// name属性的值 赋值的变量名字
var cba = function() {
console.log("cba函数被调用");
}
cba();

函数的name属性:所有的函数都有一个name属性用于获取函数的名称

1
2
3
4
5
6
7
8
9
10
11
12
13
<script>
// 1.函数定义方式一: 函数的声明写法
// name属性的值 函数的名字
function test() {
}
test();

// 3.函数都是有属性 name
console.log(test.name);
console.log(abc.name);
console.log(cba.name);

</script>

立即执行函数表达式

表达的含义是一个函数定义完后被立即执行

1
2
3
4
// 1.3.改进二: 将函数和执行的()一起外层加一个()
(function() {
console.log("test函数被调用");
}())

第一部分是定义了一个匿名函数,这个函数有自己独立的执行上下文环境。

第二部分是后面的(),表示这个函数被执行了

立即执行函数必须是一个表达式,不能是函数声明:

下面的这种写法会报错,因为是一个函数声明,不是一个函数表达式

当圆括号出现在匿名函数的末尾想要调用函数时,它会默认将函数当成是函数声明。

1
2
3
4
5
// 1.JavaScript不允许直接在一个函数的声明后面跟()执行这个函数
// 1.1.下面代码不能立即执行
function test() {
console.log("test函数被调用")
}()

当圆括号包裹函数时,它会默认将函数作为表达式去解析,而不是函数声明。

1
2
3
4
5
6
// 1.2.改进一: 对函数加上()
// 特点: 立即执行函数执行完后会立即销毁, 那么test名称就没有意义, test就可以省略掉
(function() {
console.log("test函数被调用")
})()

下面是一个函数表达式,所以可以执行

1
2
3
4
5
6
7
8
9
10
11
 		// 1.3.改进二: 将函数和执行的()一起外层加一个()
(function() {
console.log("test函数被调用");
}())

// 2.匿名函数表达式
var demo = function() {
console.log("demo函数被调用")
}()
console.log(demo);

参数值传递和引用传递

基本数据类型保存在栈内存中

引用数据类型保存在对内存中

  • 创建的数组存放在堆空间
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script>
// 1.值传递
// function test(name) {
// name = "kobe";
// }

// var temp = "why";
// test(temp);
// console.log(temp);

// 2.引用传递
function test(arr) {
arr[0] = "abc";
}

var temp = [10, 20, 30];
test(temp);
console.log(temp);

</script>

反转数组和排序算法

反转数组的代码优化

排序算法 - 选择排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<script>

// 1.反转数组
// function reverseArray(arr) {
// for (var i = 0; i < arr.length / 2; i++) {
// var temp = arr[i];
// arr[i] = arr[arr.length-1-i];
// arr[arr.length-1-i] = temp;
// }
// }

// var nums1 = [10, 14, 8, 5, 88];
// reverseArray(nums1);
// console.log(nums1);

// 2.排序
function sortArray(arr) {
for (var j = 0; j < arr.length; j++) {
for (var i = j+1; i < arr.length; i++) {
if (arr[j] > arr[i]) {
var temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
}

}
}

var nums1 = [10, 14, 8, 5, 88];
sortArray(nums1);
console.log(nums1);

</script>

后续知识点

预编译的过程

函数作用域[[scope]]

作用域链

闭包