1. 数据类型转化

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

我们通常会实现3种方式的转换:

1.1 转换为字符串类型

  1. // 1. 把数字型转换为字符串型 变量.toString()
  2. var num = 10;
  3. var str = num.toString();
  4. console.log(str);
  5. console.log(typeof str);
  6. // 2. 我们利用 String(变量)
  7. console.log(String(num));
  8. // 3. 利用 + 拼接字符串的方法实现转换效果 隐式转换
  9. console.log(num + '');

1.2 转换为数字型

  1. // var age = prompt('请输入您的年龄');
  2. // 1. parseInt(变量) 可以把 字符型的转换为数字型 得到是整数
  3. // console.log(parseInt(age));
  4. console.log(parseInt('3.14')); // 3 取整
  5. console.log(parseInt('3.94')); // 3 取整
  6. console.log(parseInt('120px')); // 120 会去到这个px单位
  7. console.log(parseInt('rem120px')); // NaN
  8. // 2. parseFloat(变量) 可以把 字符型的转换为数字型 得到是小数 浮点数
  9. console.log(parseFloat('3.14')); // 3.14
  10. console.log(parseFloat('120px')); // 120 会去掉这个px单位
  11. console.log(parseFloat('rem120px')); // NaN
  12. // 3. 利用 Number(变量)
  13. var str = '123';
  14. console.log(Number(str));
  15. console.log(Number('12'));
  16. // 4. 利用了算数运算 - * / 隐式转换
  17. console.log('12' - 0); // 12
  18. console.log('123' - '120');
  19. console.log('123' * 1);

1.3 转换为布尔型

代表空、否定的值会被转换为 false ,如 ‘’、0、NaN、null、undefined

  1. console.log(Boolean('')); // false
  2. console.log(Boolean(0)); // false
  3. console.log(Boolean(NaN)); // false
  4. console.log(Boolean(null)); // false
  5. console.log(Boolean(undefined)); // false
  6. console.log(Boolean('小白')); // true
  7. console.log(Boolean(12)); // true

2. 递增运算符练习

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

3. 短路运算(逻辑中断)

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

3.1 逻辑与

语法: 表达式1 && 表达式2
如果第一个表达式的值为真,则返回表达式2
如果第一个表达式的值为假,则返回表达式1

3.2 逻辑或

语法: 表达式1 || 表达式2
如果第一个表达式的值为真,则返回表达式1
如果第一个表达式的值为假,则返回表达式2

实例:

  1. var num = 0;
  2. console.log(123 || num++); // 123
  3. console.log(num); // 0

4. 数组

案例1:筛选数组

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

案例分析:

1.声明一个新的数组用于存放新数据。
2.遍历原来的数组,找出大于等于 10 的元素。
3.依次追加给新数组 newArr。

实现代码1:

  1. var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7];
  2. var newArr = [];
  3. // 定义一个变量 用来计算 新数组的索引号
  4. var j = 0;
  5. for (var i = 0; i < arr.length; i++) {
  6. if (arr[i] >= 10) {
  7. // 给新数组
  8. newArr[j] = arr[i];
  9. // 索引号 不断自加
  10. j++;
  11. }
  12. }
  13. console.log(newArr);

实现代码2:

  1. var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7];
  2. var newArr = [];
  3. for (var i = 0; i < arr.length; i++) {
  4. if (arr[i] >= 10) {
  5. // 给新数组
  6. newArr[newArr.length] = arr[i];
  7. }
  8. }
  9. console.log(newArr);

案例2:删除指定数组元素

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

实现代码:

  1. var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7];
  2. var newArr = []; // 空数组的默认的长度为 0
  3. // 定义一个变量 i 用来计算新数组的索引号
  4. for (var i = 0; i < arr.length; i++) {
  5. // 找出大于 10 的数
  6. if (arr[i] != 0) {
  7. // 给新数组
  8. // 每次存入一个值,newArr长度都会 +1
  9. newArr[newArr.length] = arr[i];
  10. }
  11. }
  12. console.log(newArr);

案例3:翻转数组

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

实现代码1:

  1. var arr = ['red', 'green', 'blue', 'pink', 'purple'];
  2. var newArr = [];
  3. for (var i = 0; i < arr.length; i++) {
  4. // newArr 是接收方,arr 是输送方
  5. newArr[i] = arr[arr.length - i - 1];
  6. }
  7. console.log(newArr);

实现代码2:

  1. var arr = ['red', 'green', 'blue', 'pink', 'purple'];
  2. var newArr = [];
  3. for (var i = arr.length - 1; i >= 0; i--) {
  4. newArr[newArr.length] = arr[i];
  5. }
  6. console.log(newArr);

案例4:冒泡排序

冒泡排序:是一种算法,把一系列的数据按照一定的顺序进行排列显示(从小到大或从大到小)。
例如,我们可以将数组 [5, 4, 3, 2, 1]中的元素按照从小到大的顺序排序,输出: 1,2,3,4,5

  1. var arr = [5, 4, 3, 2, 1];
  2. for (var i = 0; i < arr.length - 1; i++) {
  3. // 5个数据一共需要走四趟,长度就是数组长度减一
  4. for (var j = 0; j < arr.length - i - 1; j++) {
  5. // 第一趟交换四次,第二趟交换三次。。。长度就是数组长度减去次数再减一
  6. if (arr[j] > arr[j + 1]) {
  7. var temp = arr[j];
  8. arr[j] = arr[j + 1];
  9. arr[j + 1] = temp;
  10. }
  11. }
  12. }
  13. console.log(arr);

5. 函数

5.1 arguments的使用

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

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

  • 具有 length 属性
  • 按索引方式储存数据
  • 不具有数组的 push , pop 等方法

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

    1. function maxValue() {
    2. var max = arguments[0];
    3. for (var i = 0; i < arguments.length; i++) {
    4. if (max < arguments[i]) {
    5. max = arguments[i];
    6. }
    7. }
    8. return max;
    9. }
    10. console.log(maxValue(2, 4, 5, 9));
    11. console.log(maxValue(12, 4, 9));

    5.2 函数的两种声明方式

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

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

    1. // 声明定义方式
    2. function fn() {...}
    3. // 调用
    4. fn();
  • 因为有名字,所以也被称为命名函数

  • 调用函数的代码既可以放到声明函数的前面,也可以放在声明函数的后面

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

    利用函数表达式方式的写法如下:

    1. // 这是函数表达式写法,匿名函数后面跟分号结束
    2. var fn = function(){...};
    3. // 调用的方式,函数调用必须写到函数体下面
    4. fn();
  • 因为函数没有名字,所以也被称为匿名函数

  • 这个 fn 里面存储的是一个函数
  • 函数表达式方式原理跟声明变量方式是一致的
  • 函数调用的代码必须写到函数体后面

    6. 作用域

    6.1 作用域概述

    通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。
    JavaScript(es6前)中的作用域有两种:

  • 全局作用域

作用于所有代码执行的环境(整个 script 标签内部)或者一个独立的 js 文件。

  • 局部作用域(函数作用域)

作用于函数内的代码环境,就是局部作用域。 因为跟函数有关系,所以也称为函数作用域。

6.2 变量的作用域

6.2.1 变量作用域的分类

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

  • 全局变量
  • 局部变量 (函数作用域,块作用域)

    6.2.2 全局变量

    在全局作用域下声明的变量叫做全局变量(在函数外部定义的变量)。

  • 全局变量在代码的任何位置都可以使用

  • 在全局作用域下 var 声明的变量是全局变量
  • 特殊情况下,在函数内不使用 var 声明的变量也是全局变量(不建议使用)

    6.2.3 局部变量

    在局部作用域下声明的变量叫做局部变量(在函数内部定义的变量)

  • 局部变量只能在该函数内部使用

  • 在函数内部 var 声明的变量是局部变量
  • 函数的形参实际上就是局部变量

    6.2.4 全局变量和局部变量的区别

  • 全局变量:在任何一个地方都可以使用,只有在浏览器关闭时才会被销毁,因此比较占内存

  • 局部变量:只在函数内部使用,当其所在的代码块被执行时,会被初始化;当代码块运行结束后,就会被销毁,因此更节省内存空间

    6.3 作用域链

  • 只要是代码,就至少有一个作用域

  • 写在函数内部的局部作用域
  • 如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
  • 根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作作用域链
  • 作用域链:采取就近原则的方式来查找变量最终的值。

    7. 预解析(变量提升)

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

  • 预解析:在当前作用域下, JS 代码执行之前,浏览器会默认把带有 var 和 function 声明的变量在内存中进行提前声明或者定义。

  • 代码执行: 从上到下执行JS语句。

预解析只会发生在通过 var 定义的变量和 function 上。学习预解析能够让我们知道为什么在变量声明之前访问变量的值是 undefined,为什么在函数声明之前就可以调用函数

案例1:

  1. var a = 25;
  2. function abc() {
  3. console.log(a);
  4. var a = 10;
  5. }
  6. abc(); // undefined

案例2:

  1. console.log(a)
  2. function a() {
  3. console.log("aa");
  4. }
  5. var a = 1;
  6. console.log(a);
  7. // 以下输出
  8. ƒ a() {
  9. console.log("aa");
  10. }
  11. 1

案例3:

  1. var a = 18;
  2. f1();
  3. function f1 () {
  4. var b = 9;
  5. console.log(a);
  6. console.log(b);
  7. var a = 123;
  8. }
  9. // undefined
  10. // 9

案例4:

  1. f1();
  2. console.log(c);
  3. console.log(b);
  4. console.log(a);
  5. function f1() {
  6. var a = b = c = 9;
  7. console.log(a);
  8. console.log(b);
  9. console.log(c);
  10. }

QQ截图20210327222105.png
相当于执行一下代码

  1. function f1() {
  2. var a;
  3. a = b = c = 9;
  4. // 相当于 var a = 9; b = 9; c = 9; b 和 c 直接赋值 没有var 声明 当 全局变量看
  5. // 集体声明 var a = 9, b = 9, c = 9;
  6. console.log(a);
  7. console.log(b);
  8. console.log(c);
  9. }
  10. f1();
  11. console.log(c);
  12. console.log(b);
  13. console.log(a);

8. 对象

8.1 创建对象的三种方式

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

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

    8.1.1 利用字面量创建对象

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

  • 键:相当于属性名

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

    1. var star = {
    2. name : 'pink',
    3. age : 18,
    4. sex : '男',
    5. sayHi : function(){
    6. alert('大家好啊~');
    7. }
    8. };

    对象的调用

  • 对象里面的属性调用 : 对象.属性名 ,这个小点 . 就理解为“ 的 ”

  • 对象里面属性的另一种调用方式 : 对象[‘属性名’],注意方括号里面的属性必须加引号,我们后面会用
  • 对象里面的方法调用:对象.方法名() ,注意这个方法名字后面一定加括号

    1. console.log(star.name) // 调用名字属性
    2. console.log(star['name']) // 调用名字属性
    3. star.sayHi(); // 调用 sayHi 方法,注意,一定不要忘记带后面的括号

    8.1.2 利用new Object创建对象

    跟我们前面学的 new Array() 原理一致

    1. var andy = new Object();
    2. andy.name = 'pink';
    3. andy.age = 18;
    4. andy.sex = '男';
    5. andy.sayHi = function(){
    6. alert('大家好啊~');
    7. }
  • Object() :第一个字母大写

  • new Object() :需要 new 关键字
  • 使用的格式:对象.属性 = 值;

    8.1.3 利用构造函数创建对象

    构造函数 :是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与 new 运算符一起使用。我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面。

在 js 中,使用构造函数要时要注意以下两点:

  • 构造函数用于创建某一类对象,其首字母要大写
  • 构造函数要和 new 一起使用才有意义

    1. function Person(name, age, sex) {
    2. this.name = name;
    3. this.age = age;
    4. this.sex = sex;
    5. this.sayHi = function() {
    6. alert('我的名字叫:' + this.name + ',年龄:' + this.age + ',性别:' + this.sex);
    7. }
    8. }
    9. var bigbai = new Person('大白', 100, '男');
    10. var smallbai = new Person('小白', 21, '男');
    11. console.log(bigbai.name);
    12. console.log(smallbai.name);

    注意
    1. 构造函数约定首字母大写。
    2. 函数内的属性和方法前面需要添加 this ,表示当前对象的属性和方法。
    3. 构造函数中不需要 return 返回结果。
    4. 当我们创建对象的时候,必须用 new 来调用构造函数。

    8.1.4 构造函数和对象

  • 构造函数,如 Stars(),抽象了对象的公共部分,封装到了函数里面,它泛指某一大类(class)

  • 创建对象,如 new Stars(),特指某一个,通过 new 关键字创建对象的过程我们也称为对象实例化

    8.2 new关键字(重点)

    new 在执行时会做四件事情:
    1. 在内存中创建一个新的空对象。
    2. 让 this 指向这个新的对象。
    3. 执行构造函数里面的代码,给这个新对象添加属性和方法。
    4. 返回这个新对象(所以构造函数里面不需要return)

    8.3 遍历对象属性

    for…in 语句用于对数组或者对象的属性进行循环操作。
    其语法如下:
    1. for (变量 in 对象名字) {
    2. // 在此执行代码
    3. }
    语法中的变量是自定义的,它需要符合命名规范,通常我们会将这个变量写为 k 或者 key。
    1. for (var k in obj) {
    2. console.log(k); // 这里的 k 是属性名
    3. console.log(obj[k]); // 这里的 obj[k] 是属性值
    4. }

    8.4 小结

  1. 对象可以让代码结构更清晰
    2. 对象复杂数据类型object。
    3. 本质:对象就是一组无序的相关属性和方法的集合。
    4. 构造函数泛指某一大类,比如苹果,不管是红色苹果还是绿色苹果,都统称为苹果。
    5. 对象实例特指一个事物,比如这个苹果、正在给你们讲课的pink老师等。
    6. for…in 语句用于对对象的属性进行循环操作。

    9. 内置对象

    9.1 内置对象

  • JavaScript 中的对象分为3种:自定义对象 、内置对象、 浏览器对象
  • 前面两种对象是JS 基础 内容,属于 ECMAScript; 第三个浏览器对象属于我们JS 独有的, 我们JS API 讲解
  • 内置对象就是指 JS 语言自带的一些对象,这些对象供开发者使用,并提供了一些常用的或是最基本而必要的功能(属性和方法)
  • 内置对象最大的优点就是帮助我们快速开发
  • JavaScript 提供了多个内置对象:Math、 Date 、Array、String等

    9.2 Math对象

    Math 对象不是构造函数,它具有数学常数和函数的属性和方法。跟数学相关的运算(求绝对值,取整、最大值等)可以使用 Math 中的成员。
    1. Math.PI // 圆周率
    2. Math.floor() // 向下取整
    3. Math.ceil() // 向上取整
    4. Math.round() // 四舍五入版 就近取整 注意 -3.5 结果是 -3
    5. Math.abs() // 绝对值
    6. Math.max()/Math.min() // 求最大和最小值
    注意:上面的方法必须带括号

案例:封装自己的数学对象
利用对象封装自己的数学对象 里面有 PI 最大值和最小值

  1. // 利用对象封装自己的数学对象 里面有 PI 最大值和最小值
  2. var myMath = {
  3. PI: 3.141592653,
  4. max: function() {
  5. var max = arguments[0];
  6. for (var i = 1; i < arguments.length; i++) {
  7. if (arguments[i] > max) {
  8. max = arguments[i];
  9. }
  10. }
  11. return max;
  12. },
  13. min: function() {
  14. var min = arguments[0];
  15. for (var i = 1; i < arguments.length; i++) {
  16. if (arguments[i] < min) {
  17. min = arguments[i];
  18. }
  19. }
  20. return min;
  21. }
  22. }
  23. console.log(myMath.PI);
  24. console.log(myMath.max(1, 5, 9));
  25. console.log(myMath.min(1, 5, 9));

9.3 日期对象

9.3.1 Date 概述

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

    9.3.2 Date()方法的使用

    1. 获取当前时间必须实例化

    1. var now = new Date();
    2. console.log(now); // Fri Jun 24 2022 20:41:30 GMT+0800 (中国标准时间)

    2. 时间对象的方法

    如果括号里面有时间,就返回参数里面的时间。例如日期格式字符串为‘2019-5-1’,可以写成new Date(‘2019-5-1’) 或者 new Date(‘2019/5/1’)

  • 如果Date()不写参数,就返回当前时间

  • 如果Date()里面写参数,就返回括号里面输入的时间

image.png
案例: 格式化日期年月日

  1. // 格式化日期 年月日
  2. var date = new Date();
  3. console.log(date.getFullYear()); // 返回当前日期的年 2019
  4. console.log(date.getMonth() + 1); // 月份 返回的月份小1个月 记得月份+1 呦
  5. console.log(date.getDate()); // 返回的是 几号
  6. console.log(date.getDay()); // 3 周一返回的是 1 周六返回的是 6 但是 周日返回的是 0
  7. // 我们写一个 2019年 5月 1日 星期三
  8. var year = date.getFullYear();
  9. var month = date.getMonth() + 1;
  10. var dates = date.getDate();
  11. var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
  12. var day = date.getDay();
  13. console.log('今天是:' + year + '年' + month + '月' + dates + '日 ' + arr[day]);

案例: 格式化日期时分秒

  1. // 格式化日期 时分秒
  2. var date = new Date();
  3. console.log(date.getHours()); // 时
  4. console.log(date.getMinutes()); // 分
  5. console.log(date.getSeconds()); // 秒
  6. // 要求封装一个函数返回当前的时分秒 格式 08:08:08
  7. function getTimer() {
  8. var time = new Date();
  9. var h = time.getHours();
  10. h = h < 10 ? '0' + h : h;
  11. var m = time.getMinutes();
  12. m = m < 10 ? '0' + m : m;
  13. var s = time.getSeconds();
  14. s = s < 10 ? '0' + s : s;
  15. return h + ':' + m + ':' + s;
  16. }

新案例:页面显示事件

需求:将当前时间以:YYYY-MM-DD HH:mm 形式显示在页面
分析:
①:调用时间对象方法进行转换
②:字符串拼接后,通过 innerText 给 标签
image.png

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <style>
  9. div {
  10. width: 400px;
  11. height: 50px;
  12. background-color: pink;
  13. text-align: center;
  14. line-height: 50px;
  15. }
  16. </style>
  17. </head>
  18. <body>
  19. <div></div>
  20. <script>
  21. let arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
  22. let div = document.querySelector('div')
  23. // 先调用,就省去了1秒的空白期
  24. getTime()
  25. setInterval(getTime, 1000)
  26. function getTime() {
  27. // 1. 实例化时间对象 一定写到定时器里面才可以
  28. let date = new Date()
  29. let year = date.getFullYear()
  30. let month = date.getMonth() + 1
  31. let date1 = date.getDate()
  32. let hour = date.getHours()
  33. let min = date.getMinutes()
  34. let sec = date.getSeconds()
  35. let day = date.getDay()
  36. div.innerHTML = `今天是: ${year}年${month}月${date1}日 ${hour < 10 ? '0' + hour : hour}:${min < 10 ? '0' + min : min}:${sec < 10 ? '0' + sec : sec} ${arr[day]}`
  37. }
  38. </script>
  39. </body>
  40. </html>

3.时间戳

  • 什么是时间戳
    • 是指1970年01月01日00时00分00秒起至现在的毫秒数,它是一种特殊的计量时间的方式
  • 三种方式获取时间戳
    1. 使用 getTime() 和 valueOf() 方法
    2. 简写 +new Date()
    3. Date.now()

注意:
Date.now()无需实例化,但是只能得到当前的时间戳, 而前面两种可以返回指定时间的时间戳,比如 console.log(+new Date(‘2021-8-30 12:00:00’))
如果使用getTime() 和 valueOf() 方法获取指定时间的时间戳,那么具体时间放在Date()构造函数里面,不能放在方法的参数中

案例: 获得Date总的毫秒数(时间戳)

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

案例:倒计时效果

  1. // 倒计时效果
  2. // 1.核心算法:输入的时间减去现在的时间就是剩余的时间,即倒计时 ,但是不能拿着时分秒相减,比如 05 分减去25分,结果会是负数的。
  3. // 2.用时间戳来做。用户输入时间总的毫秒数减去现在时间的总的毫秒数,得到的就是剩余时间的毫秒数。
  4. // 3.把剩余时间总的毫秒数转换为天、时、分、秒 (时间戳转换为时分秒)
  5. // 转换公式如下:
  6. // d = parseInt(总秒数/ 60/60 /24); // 计算天数
  7. // h = parseInt(总秒数/ 60/60 %24) // 计算小时
  8. // m = parseInt(总秒数 /60 %60 ); // 计算分数
  9. // s = parseInt(总秒数%60); // 计算当前秒数
  10. function countDown(time) {
  11. var nowTime = +new Date(); // 返回的是当前时间总的毫秒数
  12. var inputTime = +new Date(time); // 返回的是用户输入时间总的毫秒数
  13. var times = (inputTime - nowTime) / 1000; // times是剩余时间总的秒数
  14. var d = parseInt(times / 60 / 60 / 24); // 天
  15. d = d < 10 ? '0' + d : d;
  16. var h = parseInt(times / 60 / 60 % 24); //时
  17. h = h < 10 ? '0' + h : h;
  18. var m = parseInt(times / 60 % 60); // 分
  19. m = m < 10 ? '0' + m : m;
  20. var s = parseInt(times % 60); // 当前的秒
  21. s = s < 10 ? '0' + s : s;
  22. return d + '天' + h + '时' + m + '分' + s + '秒';
  23. }
  24. console.log(countDown('2019-5-1 18:00:00'));
  25. var date = new Date();
  26. console.log(date);

新案例:下课倒计时效果

分析:
①用将来时间减去现在时间就是剩余的时间
②核心: 使用将来的时间戳减去现在的时间戳
③最后把剩余的时间转换为 天 时 分 秒

注意:
1. 通过时间戳得到是毫秒,需要转换为 秒 再计算
2. 转换公式:
d = parseInt(总秒数/ 60/60 /24); // 计算天数
h = parseInt(总秒数/ 60/60 %24) // 计算小时
m = parseInt(总秒数 /60 %60 ); // 计算分数
s = parseInt(总秒数%60); // 计算当前秒数

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  7. <title>Document</title>
  8. <style>
  9. .countdown {
  10. width: 240px;
  11. height: 305px;
  12. text-align: center;
  13. line-height: 1;
  14. color: #fff;
  15. background-color: brown;
  16. /* background-size: 240px; */
  17. /* float: left; */
  18. overflow: hidden;
  19. }
  20. .countdown .next {
  21. font-size: 16px;
  22. margin: 25px 0 14px;
  23. }
  24. .countdown .title {
  25. font-size: 33px;
  26. }
  27. .countdown .tips {
  28. margin-top: 80px;
  29. font-size: 23px;
  30. }
  31. .countdown small {
  32. font-size: 17px;
  33. }
  34. .countdown .clock {
  35. width: 142px;
  36. margin: 18px auto 0;
  37. overflow: hidden;
  38. }
  39. .countdown .clock span,
  40. .countdown .clock i {
  41. display: block;
  42. text-align: center;
  43. line-height: 34px;
  44. font-size: 23px;
  45. float: left;
  46. }
  47. .countdown .clock span {
  48. width: 34px;
  49. height: 34px;
  50. border-radius: 2px;
  51. background-color: #303430;
  52. }
  53. .countdown .clock i {
  54. width: 20px;
  55. font-style: normal;
  56. }
  57. </style>
  58. </head>
  59. <body>
  60. <div class="countdown">
  61. <p class="next">今天是2021年8月28日</p>
  62. <p class="title">下班倒计时</p>
  63. <p class="clock">
  64. <span id="hour">00</span>
  65. <i>:</i>
  66. <span id="minutes">25</span>
  67. <i>:</i>
  68. <span id="scond">20</span>
  69. </p>
  70. <p class="tips">
  71. 现在是18:30:00
  72. </p>
  73. </div>
  74. <script>
  75. let hour = document.querySelector('#hour')
  76. let minutes = document.querySelector('#minutes')
  77. let scond = document.querySelector('#scond')
  78. time()
  79. setInterval(time, 1000)
  80. function time() {
  81. // 1. 得到现在的时间戳
  82. let now = +new Date()
  83. // 2. 得到指定时间的时间戳
  84. let last = +new Date('2023-6-24 22:00:00')
  85. // 3. (计算剩余的毫秒数) / 1000 === 剩余的秒数
  86. let count = (last - now) / 1000
  87. // console.log(count)
  88. // 4. 转换为时分秒
  89. // h = parseInt(总秒数 / 60 / 60 % 24) // 计算小时
  90. let h = parseInt(count / 60 / 60 % 24)
  91. h = h < 10 ? '0' + h : h
  92. // m = parseInt(总秒数 / 60 % 60); // 计算分数
  93. let m = parseInt(count / 60 % 60)
  94. m = m < 10 ? '0' + m : m
  95. // s = parseInt(总秒数 % 60); // 计算当前秒数
  96. let s = parseInt(count % 60);
  97. s = s < 10 ? '0' + s : s
  98. // console.log(h, m, s)
  99. hour.innerHTML = h
  100. minutes.innerHTML = m
  101. scond.innerHTML = s
  102. }
  103. </script>
  104. </body>
  105. </html>

9.4 数组对象

9.4.1 数组对象的创建

创建数组对象的两种方式

  • 字面量方式
  • new Array() ```javascript // 创建数组的两种方式 // 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);

  1. <a name="77f4923a"></a>
  2. ### 9.4.2 检测是否为数组
  3. - instanceof 运算符,可以判断一个对象是否属于某种类型
  4. - Array.isArray()用于判断一个对象是否为数组,isArray() 是 HTML5 中提供的方法
  5. ```javascript
  6. // 翻转数组
  7. function reverse(arr) {
  8. // if (arr instanceof Array) {
  9. if (Array.isArray(arr)) {
  10. var newArr = [];
  11. for (var i = arr.length - 1; i >= 0; i--) {
  12. newArr[newArr.length] = arr[i];
  13. }
  14. return newArr;
  15. } else {
  16. return 'error 这个参数要求必须是数组格式 [1,2,3]'
  17. }
  18. }
  19. console.log(reverse([1, 2, 3]));
  20. console.log(reverse(1, 2, 3));
  21. // 检测是否为数组
  22. // (1) instanceof 运算符 它可以用来检测是否为数组
  23. var arr = [];
  24. var obj = {};
  25. console.log(arr instanceof Array);
  26. console.log(obj instanceof Array);
  27. // (2) Array.isArray(参数); H5新增的方法 ie9以上版本支持
  28. console.log(Array.isArray(arr));
  29. console.log(Array.isArray(obj));

9.4.3 添加删除数组元素的方法

image.png

  1. // 添加删除数组元素方法
  2. // 1. push() 在我们数组的末尾 添加一个或者多个数组元素 push 推
  3. var arr = [1, 2, 3];
  4. // arr.push(4, 'pink');
  5. console.log(arr.push(4, 'pink'));
  6. console.log(arr);
  7. // (1) push 是可以给数组追加新的元素
  8. // (2) push() 参数直接写 数组元素就可以了
  9. // (3) push完毕之后,返回的结果是 新数组的长度
  10. // (4) 原数组也会发生变化
  11. // 2. unshift 在我们数组的开头 添加一个或者多个数组元素
  12. console.log(arr.unshift('red', 'purple'));
  13. console.log(arr);
  14. // (1) unshift是可以给数组前面追加新的元素
  15. // (2) unshift() 参数直接写 数组元素就可以了
  16. // (3) unshift完毕之后,返回的结果是 新数组的长度
  17. // (4) 原数组也会发生变化
  18. // 3. pop() 它可以删除数组的最后一个元素
  19. console.log(arr.pop());
  20. console.log(arr);
  21. // (1) pop是可以删除数组的最后一个元素 记住一次只能删除一个元素
  22. // (2) pop() 没有参数
  23. // (3) pop完毕之后,返回的结果是 删除的那个元素
  24. // (4) 原数组也会发生变化
  25. // 4. shift() 它可以删除数组的第一个元素
  26. console.log(arr.shift());
  27. console.log(arr);
  28. // (1) shift是可以删除数组的第一个元素 记住一次只能删除一个元素
  29. // (2) shift() 没有参数
  30. // (3) shift完毕之后,返回的结果是 删除的那个元素
  31. // (4) 原数组也会发生变化

案例:筛选数组

  1. // 有一个包含工资的数组[1500, 1200, 2000, 2100, 1800],要求把数组中工资超过2000的删除,剩余的放到新数组里面
  2. var arr = [1500, 1200, 2000, 2100, 1800];
  3. var newArr = [];
  4. for (var i = 0; i < arr.length; i++) {
  5. if (arr[i] < 2000) {
  6. // newArr[newArr.length] = arr[i];
  7. newArr.push(arr[i]);
  8. }
  9. }
  10. console.log(newArr);

9.4.4 数组排序

image.png

  1. // 数组排序
  2. // 1. 翻转数组
  3. var arr = ['pink', 'red', 'blue'];
  4. arr.reverse();
  5. console.log(arr);
  6. // 2. 数组排序(冒泡排序)
  7. var arr1 = [13, 4, 77, 1, 7];
  8. arr1.sort(function(a, b) {
  9. // return a - b; 升序的顺序排列
  10. return b - a; // 降序的顺序排列
  11. });
  12. // 如果不写function那么只能进行个位数的排序,而且只能升序
  13. console.log(arr1);

9.4.5 数组索引方法

image.png

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

案例: 数组去重(重点案例)

  1. // 数组去重 ['c', 'a', 'z', 'a', 'x', 'a', 'x', 'c', 'b'] 要求去除数组中重复的元素。
  2. // 1.目标:把旧数组里面不重复的元素选取出来放到新数组中,重复的元素只保留一个,放到新数组中去重。
  3. // 2.核心算法:我们遍历旧数组,然后拿着旧数组元素去查询新数组,如果该元素在新数组里面没有出现过,我们就添加,否则不添加。
  4. // 3.我们怎么知道该元素没有存在?利用新数组.indexOf(数组元素) 如果返回时-1就说明新数组里面没有改元素
  5. // 封装一个去重的函数 unique 独一无二的
  6. function unique(arr) {
  7. var newArr = [];
  8. for (var i = 0; i < arr.length; i++) {
  9. if (newArr.indexOf(arr[i]) === -1) {
  10. newArr.push(arr[i]);
  11. }
  12. }
  13. return newArr;
  14. }
  15. // var demo = unique(['c', 'a', 'z', 'a', 'x', 'a', 'x', 'c', 'b'])
  16. var demo = unique(['blue', 'green', 'blue'])
  17. console.log(demo);

9.4.6 数组转换为字符串

image.png

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

9.4.7 其他数组对象

image.png
slice和splice的区别.gif

9.5 字符串对象

9.5.1 基本包装类型

为了方便操作基本数据类型,JavaScript 还提供了三个特殊的引用类型:String、Number和 Boolean。
基本包装类型就是把简单数据类型包装成为复杂数据类型,这样基本数据类型就有了属性和方法。

  1. // 下面代码有什么问题?
  2. var str = 'andy';
  3. console.log(str.length);

按道理基本数据类型是没有属性和方法的,而对象才有属性和方法,但上面代码却可以执行,这是因为 js 会把基本数据类型包装为复杂数据类型,其执行过程如下 :

  1. // 1. 生成临时变量,把简单类型包装为复杂数据类型
  2. var temp = new String('andy');
  3. // 2. 赋值给我们声明的字符变量
  4. str = temp;
  5. // 3. 销毁临时变量
  6. temp = null;

9.5.2 字符串的不可变

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

  1. var str = 'abc';
  2. str = 'hello';
  3. // 当重新给 str 赋值的时候,常量'abc'不会被修改,依然在内存中
  4. // 重新给字符串赋值,会重新在内存中开辟空间,这个特点就是字符串的不可变
  5. // 由于字符串的不可变,在大量拼接字符串的时候会有效率问题
  6. var str = '';
  7. for (var i = 0; i < 100000; i++) {
  8. str += i;
  9. }
  10. console.log(str); // 这个结果需要花费大量时间来显示,因为需要不断的开辟新的空间

9.5.3 根据字符返回位置

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

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

案例:返回字符位置(重点)

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

  1. // 查找字符串"abcoefoxyozzopp"中所有o出现的位置以及次数
  2. // 核心算法:先查找第一个o出现的位置
  3. // 然后 只要indexOf 返回的结果不是 -1 就继续往后查找
  4. // 因为indexOf 只能查找到第一个,所以后面的查找,一定是当前索引加1,从而继续查找
  5. var str = "oabcoefoxyozzopp";
  6. var index = str.indexOf('o');
  7. var num = 0;
  8. // console.log(index);
  9. while (index !== -1) {
  10. console.log(index);
  11. num++;
  12. index = str.indexOf('o', index + 1);
  13. }
  14. console.log('o出现的次数是: ' + num);

课后作业 [‘red’, ‘blue’, ‘red’, ‘green’, ‘pink’,’red’], 求 red 出现的位置和次数

  1. var arr = ['red', 'blue', 'red', 'green', 'pink','red'];
  2. var index = arr.indexOf('red');
  3. var num = 0;
  4. while (index !== -1) {
  5. console.log(index);
  6. num++;
  7. index = arr.indexOf('red', index + 1)
  8. }
  9. console.log('red出现的次数是: ' + num);

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

image.png

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

image.png

案例:判断出现次数最多的字符(重点)

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

  1. // 有一个对象 来判断是否有该属性 对象['属性名']
  2. var o = {
  3. age: 18
  4. }
  5. if (o['sex']) {
  6. console.log('里面有该属性');
  7. } else {
  8. console.log('没有该属性');
  9. }
  10. // 判断一个字符串 'abcoefoxyozzopp' 中出现次数最多的字符,并统计其次数。
  11. // o.a = 1
  12. // o.b = 1
  13. // o.c = 1
  14. // o.o = 4
  15. // 核心算法:利用 charAt() 遍历这个字符串
  16. // 把每个字符都存储给对象, 如果对象没有该属性,就为1,如果存在了就 +1
  17. // 遍历对象,得到最大值和该字符
  18. var str = 'abcoefoxyozzopp';
  19. var o = {};
  20. for (var i = 0; i < str.length; i++) {
  21. var chars = str.charAt(i); // chars 是 字符串的每一个字符
  22. if (o[chars]) { // o[chars] 得到的是属性值
  23. o[chars]++;
  24. } else {
  25. o[chars] = 1;
  26. }
  27. }
  28. console.log(o);
  29. // 2. 遍历对象
  30. var max = 0;
  31. var ch = '';
  32. for (var k in o) {
  33. // k 得到是 属性名
  34. // o[k] 得到的是属性值
  35. if (o[k] > max) {
  36. max = o[k];
  37. ch = k;
  38. }
  39. }
  40. console.log(max);
  41. console.log('最多的字符是' + ch);

9.5.5 字符串操作方法(重点)

image.png

  1. // 字符串操作方法
  2. // 1. concat('字符串1','字符串2'....)
  3. var str = 'andy';
  4. console.log(str.concat('red'));
  5. // 2. substr('截取的起始位置', '截取几个字符');
  6. var str1 = '改革春风吹满地';
  7. console.log(str1.substr(2, 2)); // 第一个2 是索引号的2 从第几个开始 第二个2 是取几个字符

9.5.6 其他方法

  • replace()方法
  • split()方法
  • toUpperCase() //转换大写
  • toLowerCase() //转换小写 ```javascript // 1. 替换字符 replace(‘被替换的字符’, ‘替换为的字符’) 它只会替换第一个字符 var str = ‘andyandy’; console.log(str.replace(‘a’, ‘b’)); // 有一个字符串 ‘abcoefoxyozzopp’ 要求把里面所有的 o 替换为 var str1 = ‘abcoefoxyozzopp’; while (str1.indexOf(‘o’) !== -1) { str1 = str1.replace(‘o’, ‘‘); } console.log(str1);

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

  1. <a name="khxkL"></a>
  2. # 10. 简单类型与复杂类型(理解)
  3. <a name="kWKFl"></a>
  4. ## 10.1 简单类型与复杂类型
  5. 简单类型又叫做基本数据类型或者值类型,复杂类型又叫做引用类型。
  6. - 值类型:简单数据类型/基本数据类型,在存储时变量中存储的是值本身,因此叫做值类型 string ,number,boolean,undefined,null
  7. - 引用类型:复杂数据类型,在存储时变量中存储的仅仅是地址(引用),因此叫做引用数据类型 通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等
  8. <a name="G624R"></a>
  9. ## 10.2 堆和栈
  10. 堆栈空间分配区别:  <br />1、栈(操作系统):由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈; 简单数据类型存放到栈里面  <br />2、堆(操作系统):存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。 复杂数据类型存放到堆里面 <br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2158347/1609948089084-eca358b3-7ab1-4ce9-8fa1-4b6e1f125f31.png#crop=0&crop=0&crop=1&crop=1&height=163&id=Pjf1B&margin=%5Bobject%20Object%5D&name=image.png&originHeight=217&originWidth=377&originalType=binary&ratio=1&rotation=0&showTitle=false&size=7535&status=done&style=none&title=&width=283)<br />注意:JavaScript中没有堆栈的概念,通过堆栈的方式,可以让大家更容易理解代码的一些执行方式,便于将来学习其他语言。
  11. <a name="jdtLu"></a>
  12. ## 10.3 简单类型的内存分配
  13. - 值类型(简单数据类型): string ,number,boolean,undefined,null
  14. - 值类型变量的数据直接存放在变量(栈空间)中
  15. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/2158347/1609948167554-d64f22f7-d045-4317-8414-b4e2c6e583ed.png#crop=0&crop=0&crop=1&crop=1&height=128&id=VcjiB&margin=%5Bobject%20Object%5D&name=image.png&originHeight=170&originWidth=684&originalType=binary&ratio=1&rotation=0&showTitle=false&size=11712&status=done&style=none&title=&width=513)
  16. <a name="jNvSH"></a>
  17. ## 10.4 复杂类型的内存分配
  18. - 引用类型(复杂数据类型):通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等
  19. - 引用类型变量(栈空间)里存放的是地址,真正的对象实例存放在堆空间中
  20. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/2158347/1609948226529-72119780-cf61-45fd-8834-a7e04e4ddca0.png#crop=0&crop=0&crop=1&crop=1&height=176&id=MPMQy&margin=%5Bobject%20Object%5D&name=image.png&originHeight=235&originWidth=531&originalType=binary&ratio=1&rotation=0&showTitle=false&size=11346&status=done&style=none&title=&width=398)
  21. <a name="gi7Fw"></a>
  22. ## 10.5 简单类型传参
  23. 函数的形参也可以看做是一个变量,当我们把一个值类型变量作为参数传给函数的形参时,其实是把变量在栈空间里的值复制了一份给形参,那么在方法内部对形参做任何修改,都不会影响到的外部变量。
  24. ```javascript
  25. function fn(a) {
  26. a++;
  27. console.log(a);
  28. }
  29. var x = 10;
  30. fn(x);
  31. console.log(x)
  32. // 11
  33. // 10

10.6 复杂类型传参

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

  1. function Person(name) {
  2. this.name = name;
  3. }
  4. function f1(x) { // x = p
  5. console.log(x.name); // 2. 这个输出什么 ?
  6. x.name = "张学友";
  7. console.log(x.name); // 3. 这个输出什么 ?
  8. }
  9. var p = new Person("刘德华");
  10. console.log(p.name); // 1. 这个输出什么 ?
  11. f1(p);
  12. console.log(p.name); // 4. 这个输出什么 ?
  13. // 刘德华
  14. // 刘德华
  15. // 张学友
  16. // 张学友