JS基础部分总结

在这里插入图片描述

第一部分

1. JavaScript 介绍

  • JavaScript 又简称为 JS ,是一门脚本语言,可以让网页具备“思考”能力
  • JavaScript作者: 布兰登·艾奇
  • JavaScript 组成
    • ECMAScript:
      • 简称ES、ES5、ES6
      • JavaScript的语法规范
    • DOM:
      • 文档对象模型
      • 操作页面内容
    • BOM
      • 浏览器对象模型
      • 操作浏览器功能

2. JavaScript 基础写法

2.1 JavaScript 的三种书写方式

  • 内联:

    • script标签
    • JS代码写在这个标签理念
    • 小规范:script标签写在body结束的位置
  • 外联(链)

    • js独立出来的文件是以 .js 后缀结尾
    • script 配合 src 属性导入
    • src里写js文件的路径
    • 注意:如果写了外联,那么在 script 标签里,就不要写其他JS代码,因为写了也没用
  • 行内(了解)

      <button onclick="alert('Vinson')">点我,告诉你最帅的男人</button>
    

2.2 JavaScript 的注释

  • // :
    • 单行注释,也就是//后面的一行内容会被浏览器忽略不执行,可以嵌套
    • 快捷键:ctrl + /
  • /* */: 多行注释,不能嵌套(会报错)
    • 快捷键:shift + alt + a

2.3 JavaScript 输入和输出语句

  • alert(‘想提示的内容’)
    • 弹出一个提示框
  • prompt(‘提示用户输入什么’)
    • 弹出一个输入框,可以进行输入
  • confirm(‘提示用户的内容’)
    • 用的极少
    • 弹出的是一个确认框,只能点确定或取消

2.4 JavaScript 结束符说明

  • 结束符的符号是: ;
    • 英文分号
  • 可以写也可以不写
  • 除非你需要把它们都写在同一行,那么就要加 分号 , 也可以 逗号 ,空格不可以,要报错
  • 建议如果你要写,就每句都写,如果你不写,就每句都不写,这样可以保证你的编码风格是统一的
  • 我这里是:不写分号,因为后面vue的标准语法规范不推荐加分号

3. 变量声明、赋值、使用

  • 什么是变量?

    • 可以理解为一个容器
    • 装数据的容器
  • 变量的声明

    let 变量名
    // 例
    let name  // 创建了一个叫name的变量(盒子)
    
  • 变量的赋值

    变量名 = 数据
    // 例
    name = 'Vinson'
    
  • 变量的使用(取值)

    // 直接写变量名
    name  
    alert(name)  // 取出name的值再提示出来
    alert('name') // 就是提示name
    
    • 注意:写变量的时候不要打引号,打引号就不是取出变量的值了,就只是提示这个东西
  • 注意:

    • 声明变量时我们用 let,也可以用 var
    • 目前而言没区别,区别在JS高级的时候会讲
    • let是ES6出来的(更推荐使用的),var是ES5就有的(不推荐了)
  • 变量的初始化:

    • 在声明变量时就赋值

      let name = 'Vinson'
      // 或者也可以让用户输入
      let name = prompt('请输入姓名')
      
  • 变量的本质:就是在内存中开辟一个空间,在空间里放数据

4. 变量的细节补充

  • 同时声明多个变量并赋值

    • 用逗号隔开
    let name = 'jack',age = 16
    
  • 如果变量只声明不赋值,那么值是undefined

    	let name
        alert(name) // undefined	
    
    	let name, age = 16 // 相当于写的是 let name   let age = 16
        alert(name) // undefined
        alert(age) // 16
    
  • 变量的值也可以重新赋值

        let name = '刘德华'
        alert(name) // 刘德华
    
        name = '周星驰'
        alert(name) // 周星驰
    
  • 如果一个变量不声明也不赋值,不能用,会报错

    // 变量没声明没赋值不能用,会报错
    alert(age)
    
  • 如果一个变量不声明,但是直接复制了,可以用,但是不推荐

    // 变量没声明,但是直接赋值,可以用,不推荐这样写
        age = 30
        alert(age) 
    

5. 变量案例: 交换两个变量的值

  • 使用一个第三方变量来保存

    let name1 = '枸杞'
    let name2 = '水蜜桃'
    
    let temp = name1
    name1 = name2 
    name2 = temp
    

6. 变量命名规则与规范

  • 规则:

    • 必须要遵守,不遵守就会报错,导致程序无法往下执行
    • 相当于是现实中的法律,不遵守就没自由无法正常生活
  • 规范:

    • 建议遵守的行为,不遵守也不会报错,会显得不专业
  • 规则:

    1. 不能用关键字
      • 关键字:在js中又特殊含义的字符,例如:let、var
      • 关键字不用特意去记,写着写着就知道有哪些了
    2. 变量名只能是由字母、数字、下划线、美元符号($) 组成,而且数字不能开头
  • 规范:

    1. 起名要有意义,变量的名字跟保存的数据有关
      • 例:要保存名字,建议变量名叫name 要保存年龄,建议变量名叫 age,要保存金额用money等
      • 而且尽量是英文单词,不会的单词查词典
      • 不好的例子:mmd、bbd,尽量不要用拼音缩写
    2. 要用驼峰命名法
      • 如果一个变量名由多个单词组成吗,那么第一个单词首字母小写,后面每个单词首字母大写
      • 例:userName、 userLoginName

7. 数据类型

对数据进行分类

7.1 数据类型介绍

  • Number:

    • 数值型(数字型),参与数学运算做数字的标识
    • 写法:直接写数字,例如:10,11,12, 10.32, 11.2, -0.3
  • String:

    • 字符串型,用来表示文字的

    • 写法:

      • 用单引号或双引号或反引号包起来的都是字符串

      • 建议用单引号(1.敲出来轻松 2.可以跟html做区分 3.因为标准语法规范建议用单引号)

      • 例:

        'hello'"hello"`hello`1左边的那个键)
        
  • Boolean:

    • 布尔类型,用来表示两种对立的状态:真与假、对与错、开与关
    • 这种类型只有两个数据: true 与 false
    • 如果是直接写 true 、false都是布尔类型
  • undefined:

    • 代表未定义
    • 只有一个值就叫undefined
  • 如果写了一段字符,不符合任意数据类型的写法, 他就找变量,如果找到取出变量的值,找不到就报错

  • JS是弱类型的语言:变量的类型没有限制死,可以随时改成别的类型

  • 是根据赋值时,右边的值是什么就确定是什么类型

  • 所以如果一个变量只声明没赋值是undefined,因为没法确定是什么类型,所以就未定义

7.2 console.log 以及不同数据类型输出特征

  • 它主要是给程序员自己调试数据用的

  • 在浏览器的f12 -> Console 来显示

    console.log(直接写数据) 或者 console.log(变量名)
    
  • 在控制台中,如果数据是字符串,则颜色为黑色

7.3 typeof 检测数据类型

  • 作用:检测数据类型是什么

  • 用法:

    typeof 数据
    typeof 变量名
    

8. 算术运算符

  • +:
    • 一般情况下都是把两个数字相加
    • 如果+两边有一个是字符串,那么都是拼接产生一个新的字符串
    • 相减
    • 相乘
  • /
    • 相除
  • %
    • 取余数
  • 优先级:先乘除后加减,有括号的先算括号里面的,同级就从左往右依次运算

9. 拼接字符串

  • 用 + 号可以对两边有任意一个是字符串的数据进行拼接得到新字符串
  • 如果要拼接的内容很多,可以先写一个字符串,发现有些内容不能写死,则删掉这个内容,打’’ 再++,再++中间写变量名
  • 口诀:引引++

10. document.write

  • 给 body 内增加内容

  • 如果内容带标签,会解析成html元素

    document.write('<h3>哈哈哈,我出现了</h3>')
    

11. 转义符

  • 符号:\ 可以把右边的符号转换原来的意义
  • 有:
    • \n: 换行
    • \': 输出单引号
    • \": 输出双引号
    • \\ : 输出\

12. 模板字符串

  • 符号:`` (反引号)
  • 好处:
    • 内容怎么写的,它就是怎么展示的
    • 如果想输出变量的值,不用再拼接字符串,写${变量名} 自动填充在里面

第二部分

1. 类型转换

把一种数据类型转换为另外一种数据类型

1.2 隐式转换

  • 不用额外写代码、程序自己根据一定的规则来转换成某种类型
  • + 两边如果有一个是字符串,会把另外一个非字符串的也自动转换成字符串
  • 除了+以外的所有算术运算符(-、*、/、%) 都会把别的类型转换成数字类型,如果无法得到数字的,会得到NaN
  • NaN:Not a Number 代表非数字,它也是number类型(数字类型)
    • 它做任意数学运算得到的结果也一定是NaN
  • 只要是数学运算都是转换成数字,但是如果是拼接就是转换成字符串
  • 缺点:需要记住这些规则,不太明显,增加了代码阅读难度

1.2 显式转换

  • 自己写代码强制告诉数据转成什么类型

  • 转换成字符串:

    • String(数据)
    • 数据.toString()
      • toString最好用在变量,否则可能会报错
  • 转换成数字类型

    • Number(数据)

      • 只要有一个是非数字,得到的都是NaN,两边有空格无所谓,中间有就不行
      • 整数小数都能转换
    • parseInt(数据)

      • 转换成整数,只会得到整数部分
      • 从左往右依次转换,遇到非数字就立刻停止,有几个数字就转换几个,一个没有得到NaN
    • parseFloat(数据)

      • 转换成整数或小数(数字是什么就得到什么)
      • 原理效果跟parseInt一样的,也是从左往右依次转换
    • 快速转:

      • 直接在数据前面写+
    • 利用隐式转换快速砖

      • 数据 - 0 或 数据 * 1 或者 数据 / 1
    • 补充:

      • 0不能作为除数,就是 / 右边的数,其他语言里会报错,JS里得到Infinity
      • Infinity代表无穷大,-Infinity代表无穷小

2. 自增和自减

  • 自增:

    • 符号:++
    • 就是让自己 +1
  • 自减:

    • 符号:–
    • 就是让自己-1
  • 如果不参与运算,++(–)写在前或者写在后都一样

  • 如果参与运算前缀和后缀就有区别:

    • 前缀:先自增(自减),再用自增(自减)后的值参与运算
    • 后缀:先用原值参与运算,再自增(自减)

3. 比较运算符

>:判断左边是否大于右边

<:判断左边是否小于右边

>=:判断左边是否大于或等于右边

<=:判断左边是否小于或等于右边

==:判断左右两边是否相等,只判断值相等,不判断类型

===:判断左右两边是否全等,既要值相等,也要类型相等

!=:判断左右两边是否不等

  • 得到的结果是布尔类型,也就是得到true或false
  • 一定要区分:赋值就是一个 = 不要写成 == ,除非你要判断值是否相等才写成 ==

4. 逻辑运算符

  • &&:逻辑与
    • 左右两边都是true,结果才是true,有一个是false结果就是false
    • 口诀:一假则假
  • ||:逻辑或
    • 左右两边有一个是true结果就是true,两个是false结果才是false
    • 口诀:一真则真
  • !:逻辑非
    • true变false,false变true
    • 真变假,假变真
    • 它还有把别的数据类型转成布尔类型的特点
  • 转换成布尔类型
    • Boolean(数据)
    • 只有0、空字符串、NaN、undefined、null转成false,其他都是true
  • 逻辑运算符中的短路:
    • 指的不执行右边的式子
    • 只存在于 && 和 || 中有短路
    • 当左边能确定整个式子结果,就没必要看右边了,所以发生了短路的现象(不执行右边的式子)
    • &&什么时候短路:在左边式子为false时短路
    • || 什么时候短路: 在左边式子为true的时候短路
  • 逻辑运算式的运算结果
    • 如果有短路,则运算结果就是左边式子的结果
    • 如果无短路,则运算结果就是右边式子的结果

5. 赋值运算符

  • 符号:
    • =
      • 代表把右边的值赋值给左边变量
      • 他不是判断相等,判断相等是 ==
    • +=
      • 在自己值的基础上再+一个值
    • -=
      • 在自己值的基础上再-一个值
    • *=
      • 在自己值的基础上再*一个值
    • /=
      • 在自己值的基础上再/一个值
    • %=
      • 在自己值的基础上再%一个值

6. 运算符优先级

在这里插入图片描述

let a = 3 > 5 && 2 < 7 && 3 == 4
console.log(a)
let b = 3 <= 4 || 3 > 1 || 3 != 2
console.log(b)
let c = 2 === "2";
console.log(c)
let d = !c || b && a ;
console.log(d)

7. 程序的三种结构

  • 顺序结构:
    • 程序从上往下依次执行
    • 程序默认就是顺序结构
  • 分支结构
  • 循环结构:

8. 分支语句之if

  • 语法

    if (条件) {
        
      	代码
    }
    
    • 当 if 小括号里的 条件 为 true 时,则执行大括号里的代码,如果为false就不执行大括号里的代码
    if (true) {
        alert('我被执行了')
    }
    
  •     // 模拟进网吧
        alert('我要去网吧了~咿呀咿呀哟')
        // 网管要问你多大了
        let age = prompt('你今年多大了?')
    
        // 判断是否大于或等于18
        if (age >= 18) {
          // 如果 年龄 大于或等于 18
          // 就上网
          alert('我要去浪漫的网吧偷耳机')
        }
    
        alert('回家了')
    

9.分支语句之if-else

  • 语法

    if (条件) {
        
        代码1
    } else {
        
        代码2
    }
    
    • 如果条件满足,执行代码1,不满足就执行代码2
    • 所以也就是说代码1和代码2,只会选择一个来执行
  • 这也可以称之为双分支语句

10. 三元表达式

  • 由三元运算符组成的式子叫三元表达式

  • 三元运算符符号:?:

  • 语法:

    条件 ? 代码1 : 代码2
    
    • 条件为true执行代码1,拿到代码1的结果
    • 条件为false执行代码2,拿到代码2的结果

11. 分支语句之if - else if - else

  • 语法

    if (条件1) {
        代码1
    }else if (条件2) {
        代码2
    }else if (条件3) {
        代码3
    }
    			....... (可以写n多个else ifelse {
        代码n
    }
    
    • 先判断条件1,如果为true则执行代码1,如果为false则继续往下判断条件2,为true则执行代码2,为false则继续往下判断条件3,为true执行代码3,以此类推,如果上面条件都不满足就只执行else里的代码n
        /*
          花花有多少钱
            如果是1万以上,全体去大保健
            如果是5000 - 1万,那么去洗个脚
            如果是2000 - 5000,那么就请大家去吃个饭
            如果是1000 - 2000,那么就一人一杯奶茶
            如果是1000以下,那么就暴打花花一顿,然后叫他回去再拿钱
        */
        let money = 800
    
        if (money >= 10000) {
    
          alert('花花说:学习累了,大伙去按个摩我请客')
    
        }else if (money >= 5000) {
    
          alert('花花说:读万卷书,行万里路,所以我们先去洗个脚,我请客')
    
        }else if (money >= 2000) {
    
          alert('花花说:肚子饿了,大家去吃个饭,我请客')
    
        }else if (money >= 1000) {
    
          alert('花花说:我给大家点了奶茶,大家来拿一下')
    
        }else {
    
          alert('大伙说:你大爷的!!(噼里啪啦一顿打),快回去拿钱!')
        }
    

12. 分支语句之switch

  • switch也是多分支语句

  • 语法

    switch (数据) {
            
        case1:
            代码1
         break;
        case2:
            代码2
         break;
        case3:
            代码3
         break;
        case4:
            代码4
        break;
        default:
            代码n
            break;
    }
    
    • 看某个case的值是否有跟小括号里的数据全等的,如果有,就执行这个全等的case里的代码,如果没有全等的,就执行default里面的代码n

多分支 if 和 switch的比较

  • 能用if做的switch也能做,能用switch做的if也能做
  • 如果以后是范围判断,那么就用if会好一些
  • 如果是一些少量具体的值,就用switch会好一些

13. 相等的一些细节

  • undefined == null 得到true
  • undefined === null 得到false
  • NaN 不等于任何数据,包括它自己
    • NaN == NaN 永远都是false
  • 那么如何判断是否为NaN?
    • isNaN(数据)
      • 如果是NaN得到true
      • 否则得到false

第三部分

1.循环结构

重复执行某段代码

  • 因为有的时候一段代码需要重复执行,而用复制会比较傻也不利于维护,所以用循环结构会方便很多

2.while循环

  • 语法:

    while (循环条件) {
        循环体
    }
    
    • 循环体:就是要重复执行的代码

    • 语义: 判断循环条件是否为true,如果为true则执行循环体,否则跳出while循环

      • 如果为true时执行完循环体,会又回到while的循环条件的位置,继续判断是否为true,以此类推
    • 一般情况下,我们需要一个变量来控制循环的次数,这个变量叫循环增量,所以我们一般会这样写

      let i = 0
      while (i < 次数) {
          循环体
          i++
      }
      
      • 想执行几次,就在次数那写几
      • 切记:一定要写i++,因为如果不写会导致无限循环,这种我们称之为死循环

3.do-while 循环

    do {
      循环体
    }while(循环条件)
  • 先执行循环体,然后再判断循环条件,如果条件为true,回来继续执行循环体,那么如果为false,就跳出循环
  • do-while循环的循环体至少会执行1次
  • 如果某个循环体,至少要执行1次的,那么就用do-while

4.for 循环

  • 实际开发用的最多的循环

  • 之前用while循环也能做限制次数的循环,但是容易忘记写i++,而且我们的循环增量跟循环有点割裂

  • for可以解决上面的问题

  • 语法

    for (声明循环变量;循环条件;变量++ ) {
        循环体
    }
    后面的代码
    
    • 执行过程:
      • 先执行声明循环变量,再判断循环条件是否为true,为true就执行循环体,为false就直接跳出循环
      • 为true执行完循环体,会回到变量++的位置来做变量自增,自增完了再来判断循环条件,依次类推

5.break和continue

  • break:
    • 结束所在的switch语句
    • 结束所在的循环
  • continue:
    • 只能用在循环
    • 结束当次循环,继续下次循环

6.循环嵌套

  • 循环里面再写一个循环就叫循环的嵌套

7.循环嵌套案例 - 九九乘法表

<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>

  <style>
    table {
      margin:60px auto;
      /* 合并单元格缝隙  */
      border-collapse: collapse;
    }
	/* 边框,宽高、居中  */
    td{
      border: 1px solid #000;
      width:100px;
      height:35px;
      text-align: center;
    }
  </style>
</head>

<body>
  <script>
    document.write('<table>')
    // 里面的tr和td,没必要一个一个自己写,而是可以循环生成
    for (let i = 1; i <= 9; i++) {

      document.write('<tr>')

      // 内层循环
      for (let j = 1; j <= i; j++) {

        document.write('<td>')

        // document.write('列 X 行 = 它们相乘的结果')
        document.write(`${j} x ${i} = ${j * i}`)

        document.write('</td>')
      }

      document.write('</tr>')
    }
    document.write('</table>')
  </script>
</body>

</html>

第四部分

1.数组介绍

  • 数组作用:保存多个数据
  • 它在内存中的本质相当于是开了一个大空间里面分成了n多个小空间来保存每个数据
  • 数据可以保存任意类型的数据

2.数组的语法

  • 数组的初始化

    let 数组名 = [ 数据列表 ]
    
    • 数组名可以随便写,但是要符合变量的命名规则和规范
    • 数据列表可以写任意个数据,如果多个数据用逗号隔开
  • 名词:

    • 元素:数组里保存的每个数据都叫数组元素
    • 下标/索引:每个数据的编号,从0开始
    • 长度:数组中数据的个数
  • 单独取出某个数组里的元素,该怎么取?

    • 用下标取

    • 语法是:

      数组名[下标]
      // 例
      nums[0] // 取出下标为0的元素,其实就是第一个元素
      
  • 数组元素的重新赋值

    • 也是通过下标重新赋值

    • 语法是:

      数组名[下标] = 数据
      nums[0] = 999  // 把下标为0的元素,修改为999
      
  • 数组的最大下标 = 长度 - 1

3.获取数组长度

数组名.length 可以得到长度
nums.length // 获取nums的长度

4.遍历数组

  • 把数组中每个元素给取出来

  • 语法

    for (let i = 0; i < 数组.length; i++){
        
        数组[i]
    }
    
    // 例
    let nums = [10, 20, 30, 40, 50]
    for (let i = 0; i < nums.length; i++) {
        
        console.log(nums[i])
    }
    

5.数组长度

- 数组的长度可以改
- 数组长度++,则是在最后多一个元素,用undefined补齐
- 数组长度--,则相当于删除数组最后一个元素
- 数组长度直接赋值,如果赋的值比原来的长度要大,相当于增加,增加部分用undefined补齐
- 数组长度直接复制,如果赋的值比原来的长度要小,相当于删除,减少几个就删除后面几个

6.数组动态添加元素

  • 可以对数组原本不存在的下标进行赋值,那么它就会在这个下标位置增加数据
  • 如果这个下标跟原本存数据的下标存在一段距离,那么这段距离会用undefined补齐
  • 例:一个数组为let nums = [10,20, 30] 下标只到2, 但是如果我 nums[8] = 999 ,那么在下标8会多一个999,然后在下标3到下标7用undefined补齐

7.那如何保证我们是按顺序添加元素

  • 按顺序添加数组语法
数组名[数组名.length] = 数据
例:
nums[nums.length] = 60
  • 案例:让用户输入5个成绩依次存到数组,并得到最高分、最低分、总分、平均分
    • 参考代码
    // 请用户输入一共有多少人
   let cont = +prompt('请输入班级人数')
        let arry = []
        let sum = 0
        let max = 0
        let mix = 100
        for (let i = 0; i < cont; i++) {
            arry[i] = +prompt(`请输入第${i + 1}个数`)
            sum += arry[i]
            if (arry[i] > max) {
                max = arry[i]
            }
            if (arry[i] < mix) {
                mix = arry[i]
            }
        }
        alert(`班级总分:${sum},平均分:${sum / arry.length},最高分:${max},最低分:${mix}`)

8.数组综合案例

  • 数组去重
    • 参考代码
    /*
      数组去重:去除数组里的重复项
      假设有一个数组: [ 10, 15, 29, 10, 29, 30 ]
      去重后变 [10, 15, 29, 30]
    */
    let arr = [10, 15, 29, 10, 29, 30]
    let newArr = [] 
    // 第一个元素绝对不可能重复,所以直接扔到新数组
    newArr[0] = arr[0]
    for (let i = 1; i < arr.length; i++) {
      // arr[i] 旧数组的当前元素
      // 遍历新数组
      // 我立一个flag,我假设这个元素可以添加到新数组
      // 所以我这个值先立为true
      let flag = true
      for (let j = 0; j < newArr.length; j++) {
        // 判断 旧数组的当前元素  是否跟 新数组的每个元素是否相等
        // newArr[j] 新数组的每个元素
        if (arr[i] == newArr[j]) {
          flag = false
          // 相等没必要往后判断,直接break
          break
        }
      }
      // 新数组遍历完才能决定扔不扔到新数组里
      if (flag) { 
        // 只有小括号里为true才会执行下面代码。为false不执行下面代码就不会加
        // 只有当新数组有相同数据的时候才会为false,只要新数组没相同的flag还是为true
        // 为true就执行代码往后面加
        // 加到新数组
        newArr[newArr.length] = arr[i]
      }
    }
    console.log(newArr)
    
  • 斐波那契数列
    • 参考代码
    /*
       1 1 2 3 5 8 13 21 34 55 89 ...........
       特点:前两列是1,从第三列开始,每一列的值都是它前两列的和
       求出第n列的斐波那契数列上的值是几
       如果,我写5,那么就要得到第五列,就是5
       如果我写8,就得到第八列,就得到21
       首先斐波那契确定的值只有前面两列为1, 从第三列开始都是要计算出来
       所以我们可以准备一个数组,先只装1,1
       假设我要求第3列,那么就是求下标2的位置
       下标2位置的值 = 下标2-1 + 下标2-2
       下标3位置的值 = 下标3-1 + 下标3-2
        。。。。。。
       下标n位置的值 = 下标n-1 + 下标n-2
       例如:我要算下标5位置的值, 就用 下标5-1 + 下标5-2 就能得到结果
       问题是,我在算下标5之前,要不要先把下标2,下标3,下标4算出来?要
       所以,这里就有一个循环
       例如:要算下标5
       那么就从下标2开始循环,依次计算出下标2、下标3、下标4、直到下标5的值
    */
    let fib = [1, 1]
    // 我就要算下标5
    // fib[2] = fib[2 - 1] + fib[2 - 2]
    // fib[3] = fib[3 - 1] + fib[3 - 2]
    // fib[4] = fib[4 - 1] + fib[4 - 2]
    // fib[5] = fib[5 - 1] + fib[5 - 2]
    // 请输入要查询第几列
    let col = prompt('请输入要查询第几列')
    // 从第三列(也就是下标2开始)一直算到要查询的列
    for (let i = 2; i < col; i++) {
      // 当前这列等于前两列之和
      fib[i] = fib[i - 1] + fib[i - 2]
    }
    // 输出最后一列的结果
    alert(fib[fib.length - 1])
    

第五部分

1.函数介绍

  • 函数:就是一种把代码封装起来的语法
  • 作用:提高代码复用,便于维护与解决代码冗余

2.函数的基本使用

  • 声明语法

    function 函数名 () {
        函数体
    }
    
  • 调用语法

    函数名()
    
  • 注:函数只声明不调用,里面代码不会被执行

3.有参数的函数

  • 有的时候函数完成某个功能需要外界传入数据,这时候就需要有参数的函数

  • 语法

    function 函数名 (参数列表) {
        函数体
    }
    
  • 参数列表,就是定义需要几个数据,多个之间用逗号隔开

4.形参和实参

  • 形参:
    • 声明函数时写在小括号里的叫形参
  • 实参:
    • 调用函数时写在小括号里的叫实参

5.有返回值的函数

  • 为什么需要?

    • 因为调用函数时会得到一个结果,而这个结果是调用者想要得到的,所以应该把这个结果返回给调用者
  • 语法

    function 函数名 (参数列表) {
        
        函数体
        return 数据 // 代表把数据返回出去
    }
    
  • 例:

    function f1 () {
        
        return 'hello' // 返回hello
    }
    
    let res = f1()  // 把f1返回的hello赋值给res
    
  • 可以返回变量值,也可以直接返回数据

6.return 关键字

  • return后面可以直接写数据,也可以写变量(代表取出变量的值返回),也可以写表达式(算出表达式的结果再返回)
  • return有立即结束函数的作用,所以return后面的代码不会被执行
  • return后面也可以不加任何数据,也有返回值,只不过返回值是undefined
  • 函数内也可以不写return,只不过这个时候函数的返回值就是undefined

7.注意

  • 函数要想被调用,必须加小括号:函数名()
  • 换句话说,只要加了小括号,都代表调用了这个函数
  • 如果只是写函数名,不加小括号,不是调用,它只是代表找到这个函数里保存的代码

8.函数的另一声明

  • 表达式声明

    let 变量 = function () {
        
        函数体
    }
    
  • 如果用这种方式声明的函数,不能再它声明之前调用

  • 但是用function 声明的函数,可以在声明之前调用

第六部分

1.对象

如何保存一个人的姓名、年龄、性别等特征以及吃饭的行为?

    let p = {
      name: 'jack',
      sex: '男',
      age: 16,
      eat: function () {
        console.log('吃啊吃,我肚子大大大')
      }
    }

    console.log(p)
    console.log(p.name)
    console.log(p.age)
    console.log(p.sex)
    p.eat()
  • 对象也可以保存多个数据,并且取值时能很清晰的知道取的是什么
  • 对象跟顺序无关,所以我们一般称对象是无序存储,而数组叫有序存储

2.对象的初始化

let 对象名 = {
    属性名: 属性值,
} 
  • 例:

    let p = {
          name: 'jack',
          sex: '男',
          age: 16,
          eat: function () {
            console.log('吃啊吃,我肚子大大大')
          }
        }
    

3.跟对象有关的名词

  • 对象这种数据类型一般是用来用代码描述现实中的某个具体事物

  • 属性:对象拥有的特征

  • 方法:对象

  • 例:要用代码去表示一只猫

    • 特征:昵称、年龄、品种…
    • 行为:抓沙发

4.方法的说明

  • 方法就是对象的行为
  • 在代码中其本质是函数
  • 所以函数可以有参数和返回值,方法也有,写法跟函数一样

5.内置对象

  • JS已经提供好的对象

  • Math对象:

    • 这个对象表示的是一个数学高手

    • 它可以做一些数学运算

    • Math.pow(): 幂运算(基本不用,了解)

    • Math.abs():取绝对值

    • 取整的方法:

      • Math.round(): 四舍五入取整,本质是找离自己最近的整数,.5会取更大的整数
      • Math.floor(): 向下取整,得到的整数一定比原来的值要小
      • Math.ceil():向上取整,得到的整数一定比原来的值要大
      • parseInt() : 直接取整
    • 生成随机数:

      • Math.random() : 生成 0 - 1之间的随机数,包括0,不包括1

      • 如果要生成任意整数之间的随机数,公式:

        Math.floor(Math.random() * (-+ 1)) +

6.对象赋值的细节

  • 对象如果对一个已经存在的属性赋值,就是修改
  • 如果对一个不存在的属性进行赋值,就是增加

7.对象取值的另外一种方法

  • 对象如果访问一个不存在的属性,得到undefined

  • 对象.属性名 这种形式叫点语法

    • 永远不会找变量,就是找这个对象里的这个属性
  • 对象[字符串]

    • 也是代表找字符串对应的整个属性
  • 对象[变量名]

    • 代表先取出变量的值,变量值是什么就找什么属性

    • let p = {name:'jack',age:16}
      let attr = 'name'
      p['attr'] // 就代表找attr属性
      p[attr] // 代表取出attr的值,也就是'name',所以相当于找的就是name属性
      
      
    • 一定要注意,加引号就不是找变量而是就找这个属性,不加引号才是找变量取出变量的值

8.遍历对象

  • 遍历对象:就是把对象中每个数据取出来

  • 语法

    for (let key in 对象名) {
        // 不一定要叫key,也可以叫别的,但是建议叫key或者k
        // key就是属性名,所以可以通过属性名访问属性值
        对象名[key]
    }
    // 例:
    for (let key in p) {
        
        p[key]
    }
    

9.构造函数

  • 工厂模式:

    • 本质就是封装代码
    • 封装创建对象的代码,因为我们发现每次创建同一种类型的对象代码都一样,所以可以封装成函数
    • 那么这种函数就叫工厂函数
    • 特点:函数内自己创建对象,自己返回对象,调用时不用写new
        function factory(name, age, sex) {
    
          // 现在我要创建2个对象,都有name、age、sex属性,和吃饭的行为
          let p = {}
    
          // 左边是属性名,右边是变量名,到时候会取出变量名的值作为属性值
          p.name = name
          p.age = age
          p.sex = sex
          p.eat = function () {
            console.log('吃啊吃啊,我骄傲放纵')
          }
    
          return p
        }
    
  • 构造函数:

    • 实际上构造函数就是对工厂函数的升级
    • 升级在:不用我们自己创建对象,也不用我们自己返回对象,利用this关键字访问到构造函数帮我们创建的对
    • 注意:构造函数的函数名首字母大写,尽量用名词
    function Person(name, age, sex) {
    
          // 现在这个对象是构造函数帮我们创建的,所以不叫p了
          // 访问创建的对象用this
          this.name = name
          this.age = age
          this.sex = sex
          this.eat = function () {
            console.log('吃啊吃啊,我骄傲放纵')
          }
    }
    
    let p1 = new Person('jack',16,'男')
    
  • new关键字做的三件事:

    1. 创建了一个新的空对象
    2. 把函数内的this指向到这个新的空对象
    3. 在函数结束的时候返回这个新的对象

10.new调用函数内return的细节

  • 数据类型也分为两大类
    • 基本数据类型
      • string、number、boolean、undefined、null
    • 复杂数据类型
      • 数组、函数、对象
  • 如果使用new关键字调用的函数内部写return不跟值,还是new帮我们创建的对象
  • 如果写return,后面接基本数据类型,还是new帮我们创建的对象
  • 如果写return,后面接复杂数据类型,那么就是返回这个复杂数据类型

11.使用构造函数创建数组和对象

let arr = new Array()
let obj = new Object()
let f1 = new Function() //函数

12.字面量概念

  • 就是通过字面意思就能知道是什么数据类型
  • {}字面就是对象,[]字面就是数组

13.数组内置的方法

  • 数组本质也是一种对象
  • 所有它也有属性和方法
  • 属性:
    • 数组.length
  • 方法:
    • reverse() : 反转数组
    • push():
      • 在数组末尾添加元素
      • 也可以一次性添加多个,用逗号隔开
      • 返回值是新长度
    • pop()
      • 删除数组末尾的元素(一次只能删一个)
      • 返回值就是被删除的元素
    • unshift()
      • 在数组第一个位置添加元素
      • 也可以一次性添加多个,用逗号隔开
      • 返回值是新长度
    • shift()
      • 删除数组的第一个元素
      • 返回值是被删除的元素
    • join()
      • 把数组中每个元素用一个符号连接起来
      • 如果什么都不传,默认是逗号隔开
      • 如果传空字符串,那么每月任何隔开符,如果传空格字符串,用空格隔开
      • 返回一个字符串

14.数组的排序方法

  • sort()

    • 默认是先比较第一位,再比较第二位,依次类推
    • 如果比较字符,它会先把字符根据ASCII码转整数,小的前面,大的后面
    • ascii就是计算机中把英文字母(英文符号)都有对应的整数值,A是65 小a是97
  • 如果我希望就是按数字大小从小到大排列就传入函数

    数组.sort( function (a,b) {
        
        return a - b
    } )
    
  • 如果我希望就是按数字大小从大到小排列就传入函数

    数组.sort( function (a,b) {
        
        return b - a
    } )
    

15.数组splice

  • 删除
    • splice(从哪个下标开始,删除几个)
      • splice(2,3) 代表下标2开始删,删除3个
  • 替换
    • splice(从哪个下标开始,找几个,替换成什么)
      • splice(2,3,300) 下标2开始一共找3个,都只替换成一个300
      • 替换多个,也是逗号隔开
  • 新增
    • splice(新增到哪个下标,0, 新增的内容)
      • splice(1,0, 999) 下标1的位置新增999
      • 如果要新增多个,则逗号隔开

16.数组indexOf和lastIndexOf

  • indexOf(数据)
    • 从前往后找匹配的数据,返回找到的第一个的下标
    • 如果不存在得到-1
  • laseIndexOf(数据)
    • 从后往前找匹配的数据
    • 不存在也得到-1
  • 主要作用:判断数据在不在数组里面,如果不在得到-1,在就不等于-1

17.字符串内置的方法

  • indexOf和lastIndexOf

    • 跟数组一样的效果
    • 但是如果传入空字符串,则永远得到0
  • 字符串不可改!

    • 所谓的不可改是它的内容不可改,不是说变量不能重新赋值

      let str = 'hello'
      str = '你好' // 这个可以,因为不算改字符串的内容,只是相当于指向一个新的字符串
      
      str[0] = 'z' // 无效,因为字符串内容不可改
      
  • split

    • 把字符串按照某个符号切割为数组

          let str = '刘德华|张学友|郭富城|黎明'
          // 我需要把字符串转成数组
          let arr = str.split('|') // 按竖线分割字符串变成数组
          console.log(arr)
      
    • 如果传入不存在的字符,或者没传任何参数,那么会把字符串当做一个整体元素

    • 如果传入空字符串,会把字符串的每个内容都当做一个元素

  • replace

    • 替换字符串
    • 参数1:被替换的内容
    • 参数2:替换的新内容
    • 只会得到新的结果,不会直接改变原来的值
  • toUpperCase()

    • 转大写
  • toLowerCase()

    • 转小写
  • trim()

    • 取出两边空格

18.日期对象

  • 表示日期的对象
  • 方法:
    • getFullYear()
      • 获得年
    • getMonth()
      • 获得月,但是月从0开始,所以要+1才能转成现实生活中的月份
    • getDate()
      • 获得日期的日
    • getDay()
      • 获得星期几,星期天获得0,其他都是获得对应的数字
    • getHours()
      • 获得时
    • getMinutes()
      • 获得分
    • getSeconds()
      • 获得秒

第七部分

1.this 关键字

  • 普通函数里的this,一般是window对象
  • 构造函数里的this,一般是new关键字刚刚出来的新对象
  • 方法里的this,谁调用这个方法,方法里的this就是谁

2.日期对象创建时指定时间

  • 默认 new Date()什么都不传就获取当前时间

  • new Date() 如果依次传入年、月、日、时、分、秒,就是得到对应的时间,但是要注意传入0得到1月,传入1得到2月

    	let time1 = new Date(1990, 0, 1, 12, 32, 45)
        console.log(time1.getFullYear(), time1.getMonth(), time1.getDate())
        console.log(time1)
    
  • new Date() 如果传入一个字符串时间,就是得到字符串内容的时间,更加精确

    	let time2 = new Date('1990-2-1 12:32:45')
        console.log(time2)
    

3.时间戳

  • 时间戳获取的是自 1970年1月1日0点0分0秒 到现在过了多少毫秒
  • 怎么获取?
    • 构造函数获取
      • Date.now()
    • 使用实例化的日期对象来获取
      • 对象.getTime()
      • 把 对象 转成 number 类型就能获取
  • 通过时间戳可以得到指定日期

4.利用时间戳计算倒计时

公式总结如下:

天 = parseInt (总毫秒 / (1000 * 60 * 60 * 24))

总毫秒 = 总毫秒 % (1000 * 60 * 60 * 24) // 得到剩余毫秒

时 = parseInt ( 总毫秒 / (1000 * 60 * 60) )

总毫秒 = 总毫秒 % (1000 * 60 * 60 ) // 得到剩余毫秒

分 = parseInt ( 总毫秒 / (1000 * 60) )

总毫秒 = 总毫秒 % (1000 * 60 * 60 ) // 得到剩余毫秒

秒 = parseInt ( 总毫秒 / 1000 )
  • 代码如下:

        // 获取当前时间
        let now = new Date()
        // 再获取目标时间
        let distTime = new Date('2020-11-11 0:0:0')
        // 把两个日期转成时间戳再相减,就能得到两段时间间隔多少毫秒
        // 再把毫秒转成天、时、分、秒就行了
        let milSec = distTime - now
        let day = parseInt(milSec / (1000 * 60 * 60 * 24))
        // 得到算了天后剩余的毫秒
        milSec = milSec % (1000 * 60 * 60 * 24)
        // 算出时
        let hour = parseInt(milSec / (1000 * 60 * 60))
    
        milSec = milSec % (1000 * 60 * 60)
        // 算出分
        let min = parseInt(milSec / (1000 * 60))
        // 算出剩余毫秒
        milSec = milSec % (1000 * 60)
        let sec = parseInt(milSec / 1000)
    
        document.write(`
          <h3>双11距离现在还有:</h3>
          <div>${day}${hour}${min}${sec}秒</div>
        `)
    

5.全局作用域、局部作用域、块级作用域

  • 全局作用域
    • script 开头到 script 结尾的区域
  • 局部作用域
    • 只有函数会开辟局部作用域,函数内的就叫局部作用域
  • 块作用域
    • 任何 {} 都叫 块作用域,但是只有 let 声明的变量才区分块作用域,var只有全局和局部
  • 全局变量
    • 在全局作用域里声明的变量叫全局变量
    • 任意范围可以访问
  • 局部变量
    • 在函数内声明的变量叫局部变量
    • 只有这个函数内可以访问
  • 块变量
    • {}里用let声明的变量叫块变量,只能在这个大括号里访问
    • var不存在块作用域,只有let存在
{
    var a = 10
    console.log(a) // 10
}
console.log(a) // 10 因为var不存在块作用域,所以还能访问

{
    let b = 10
    console.log(b) // 10
}
console.log(b) // 报错,因为b是块变量,只能在大括号里访问

6.作用域链

  • 只有函数可以开辟作用域
  • 默认也有作用域叫 全局作用域 ,我们也称之为0级作用域
  • 如果在0级作用域里声明一个函数,那么这个函数开辟的作用域就叫1级作用域
  • 如果在1级作用域里又声明一个函数,那么这个函数开辟的作用域就叫2级作用域

在这里插入图片描述

  • 练习

    <script>
    
        var num = 10;
        if(num > 0){
            var sum = 20;
        }
        console.log ( sum );  // 20
    
    
        for(var i = 0;i<5;i++){
    
        }
        console.log ( i ); // 5
    
    
        var name = '张三';
        function fn (  ) {
            name = '李四';
        }
        fn();
        console.log ( name ); // 李四
    </script>
    

7.预解析以及声明的提升

    console.log ( num ); // undefined
    var num = 10;
    console.log ( num ); // 10


    fn();
    function fn (  ) {
        console.log ( num ); // undefined
        console.log ( "哈哈哈" );
        var num = 10;
        console.log ( num ); // 10

    }

   console.log ( a ) ;   
    var a = "我是变量";
    function a(){
        console.log ( "我是函数" );
    };
    console.log ( a );
</script>

8.let 与 var 的异同总结

  • 相同点:都是声明变量
  • 不同点:
    • let只认块,也就是 {} ,在哪个大括号里声明,就只能在这个大括号里使用
    • var认作用域,所以var里会分0级、1级、2级,还要注意,只有function才可以开辟作用域
    • var参与预解析时的变量提升,而let不参与
    • let在同一个块里不能声明同名变量,var无所谓

9.回调函数、自执行函数

  • 回调函数:

    • 函数A当做参数传递给另外一个函数B,那么函数A就叫回调函数
  • 自执行函数

    • 写法

      ;( function () {
          
          
      }) ()  // 常用的
      
      
      ;( function () {
          
          
      }())   // 不太常用的
      
      • 记住:自执行函数前面记得加分号,不加可能报错
    • 作用:开辟新的作用域,避免变量冲突

10.arguments

  • arguments是一个伪数组,它里面保存了调用函数时传递过来的所有实参
  • arguments只能用在函数里
  • arguments作用:就是可以让函数的扩展性更强,因为可以让它传入任意个参数,我们都可以拿到并处理

11.instanceof

  • 可以判断一个数据是复杂数据类型的哪种

  • 它用来判断复杂数据类型,基本数据类型用typeof

  • 用法:

    数据 instanceof 构造函数
    
    数据 instanceof Array  // 判断是否为数组
    数据 instanceof Function // 判断是否为函数
    数据 instanceof Date // 判断是否为日期对象
    数据 instanceof Object // 判断是否为对象(所有复杂数据类型本质都是对象)
    
  • 如果是这个类型得到true,不是得到false

12.案例:统计一个字符串中每个字符出现的次数

 // 我们准备一个字符串
    let str = 'abasfggghjjkkgfddsssss3444343'
    // 统计每个字符出现的次数
    let obj = {} // 准备一个空对象
    for (let i = 0; i < str.length; i++) {
      let ch = str[i]
      // 判断这个ch字符在不在对象的属性里
      if (obj[ch]) {
        // 代表在里面,已经有了
        obj[ch]++
      } else {
        // 不在里面,还没有
        obj[ch] = 1
      }
    }
    let max = 0
    let maxCh = ''
    // 全部打印出来
    for (let key in obj) {
      if (obj[key] > max) {
        max = obj[key] // 次数
        maxCh = key  // 字符
      }
    }
    console.log(`${maxCh}出现的次数最多,它的次数是${max}`)
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值