前端JS 基础

124 阅读28分钟

JS 的组成【面试题】

* ES: 定义了 我们的 JS 的语法规范, 描述了语言的基本语法和数据类型

* DOM: 文档对象模型, 是由 HTML 提供的, 每一个标签就是一个 DOM

* BOM: 浏览器对象模型, 是由 浏览器 提供的, 能力: 跳转页面, 刷新页面

JS 的书写方式

  1. 行内(内嵌): 了解就行, 后续不要这样去写
  2. 内部: 直接在 body 标签末尾 书写一个标签 script 在这个标签内部, 就能书写 JS 代码学习阶段, 这个方式会常用
  3. 外联: 跟 内部的 方式类似, 只不过需要写一个外部的 .js 文件, 然后通过 script 的 src 属性, 引入进来,工作时常用

JS 的变量

定义: 数据存储的地方。

后续要是用这个数据,就直接通过这个变量就 OK 了。 如何创建/定义一个变量

语法:var 变量名

定义变量后, 变量内部的值, 默认为 undefined(未定义)
* 赋值
    var = 变量值
    JS中“=”为赋值号

变量的命名规范【面试题】

命名规范:

1. 命名要求 见名知意
2. 采用驼峰命名(多个单词拼接时,第二个单词开始的首字母大写。)

命名规则:

1. 由字母 数字 下划线 $ 组成,不能以数字开头。
2. 字母区分大小写。
3. 不能是关键字或保留字。
  • JS 内部报错会阻断程序运行。

JS 的基本数据类型【面试题】

  1. number 类型 不区分整数,浮点数,特殊值 NaN (如果一个值是 Number 类型,但是不能用常规数字来表达,那么就会用 NaN 来代倍)

  2. String 类型 在 Js 中,只要是引号包裹起来的内容,就是 String

  3. undefined 类型 未定义

  4. Boolean 类型 只代表两个意思,真/假 正确/错误 true 真 false 假

  5. null 类型 空对象

JS 的数据类型检测

语法:typeof 要检测的变量名 typeof(要检测的变量名) 缺点:只能用来检测基本数据类型,并且在检测 null 时,返回的不是 null 而是 object。

其他数据类型转换为 数字类型

  1. Number(数据) Number 会将传入的 数据 处理为 number 类型后 返回。

    • 字符串:纯数字字符串转为对应数字,空字符串和空白字符串转为 0,非空非纯数字字符串转为 NaN
    • 布尔值:true 转为 1,false 转为 0
    • undefined:转为 NaN
    • null:转为 0
  2. parseInt() 字符串转整数的方法

    • 对浮点数进行取整操作
      • 对数字取整直接舍弃小数部分,只保留整数
    • 将字符串转为整数数字
      • 将字符串转为整数数字,也包含取整功能
    • 字符串中,必须是纯数字字符串或者数字字符开头的字符串,才能转换为正常数字,且只取整数部分
    • 如果不是数字打头的字符串,会转换为 NaN
  3. parseFloat()方法:字符串转浮点数方法

    • 将字符串转为浮点数数字
    • 满足浮点数数字字符必须在字符串开始,如果不在开始返回值都是 NaN
  4. console.log(原本的数据 - 0)

    • 字符串整数转换为对应数字,纯数字转换为其本身,数字开头的字符串,字母开头的字符串或纯字母字符串转换为 NaN。
    • boolean 类型 true 1/false 0;
    • null - 0 undefined - NaN

其他类型转 字符串类型

  1. 变量.toString()`方法
  2. String(变量)方法,有些值没有 toString(),这个时候可以使用 String()。比如 undefined 和 null
  3. 要转换为字符串的数据/变量名 + ''(空字符串)

转布尔类型(boolean)

Boolean(要转换的数据/变量名)

  1. 转为 false:NaN、0、“”空字符串、null、undefined
  2. 转为 true:非 0 非 NaN 数字、非空字符串
  3. console.log(!!要转换的数据/变量名)

JS 的算数运算符

+ - * / %

+具有特殊的地方 符号两边如果都是 数字类型,那么会求和然后参与周围程序 如果符号两边 任意一个位置出现了字符串,那么会运行拼接

符号的运算顺序:
先乘除取余,后加减;若有小括号,先计算括号内的。

JS 的赋值运算符

  • =
  • += / -= / *= / /= / %=(相当于 num = num - 1)

比较运算符 (返回布尔值 true/false)

> / < / >= / <= / ==(等于 不会比较数值类型) / === (全等 会比较数值类型)/ != / !==

逻辑运算符

&& 逻辑与

  运行逻辑:
            1.检测符号左边的运算符布尔值是否为 true,那么运行符号右边的或者返回符号右边的
            2.如果符号左边的布尔值为 false,那么直接返回左边的(不是返回左边的布尔值)

|| 逻辑或

    运行逻辑:
            1.检测符号左边的布尔值是否为 true,如果为 true,直接返回左侧的值(注意!不是布尔值)
            2. 检测符号左边的布尔值是否为 true,如果不是,直接返回右侧的值(注意!不是布尔值)

! 逻辑非(取反)

      1. 将数据原本的布尔值,做一个取反操作
      2. 数据原本为true,那么返回的是false数钩原本为faLse,那么返回的是true

自增自减运算符 【面试题】

++ , --

  • 跟在变量前:先将当前变量的值自增或自减 1,然后参与周围程序。
  • 跟在变量后:先参与周围程序,后续在自增或自减 1。

if 分支语句

语法:if (条件) {如果条件为真,那么需要执行的代码}

    条件:最后一定会成为一个布尔值,不管你写的是 变量还是表达式。
     if 语句的 else...if 的写法
          如果 第一个if 执行,那么会跳过后续的 else if
          如果第一个 if 不执行,那么会执行后面的else ifif 的语句 最后可以再加一个else 分支
          else 分支一定要书写在 if 分支的最后。

switch 语句

  • 语法: switch (要判断的变量) { case 情况 1: console.log('符合情况 1 要执行的代码') break; case 情况 2: console.log('符合情况 2 要执行的代码') break; } default: console.log('我类似于 if 分支的 else, 当前边的所有 case 都不满足的时候, 我会执行') switch 的穿刺(穿透) 现象 *如果在 case 后的代码执行完毕没有书写 break,在执行的时候, 会找到符合条件的 case 开始执行代码, 执行完毕后, 发现没有 break, 那么会继续向下执行,不管 下一个 case 是否满足条件, 一直到找到 break 或者 代码执行结束.

三元表达式

  • 语法:条件 ? 条件为真时执行的代码(只能有一行) : 条件为假时执行的的代码(只能有一行) 意义:对 if 的优化 常用场景:
    1. 对 if 的优化
    2. 利用 三目 给变量赋值。
  • 利用逻辑与, 进行对 if 的优化 num === 0 && console.log('失败')

循环语句

  • while 循环 语法:while (条件) {满足条件时执行的代码} 一个完整循环的必要内容:
    1. 初始化
    2. 条件判断
    3. 要执行的代码
    4. 自身的改变(其实就是初始化的改变)
  • do...while 循环 语法: do {要执行的代码} while (条件) while 循环在执行的时候,会先判断条件是否成立,然后再决定是否执行代码 do. . .while 循环在执行的时候,首次会直接执行代码,不管条件是否成立 如果条件失败,后续不再执行 如果条件成功,那么继续执行循环。
  • for 循环 语法:for (1.初始化;2.条件;3.改变自身) {条件满足时要循环执行的代码}
for (var i = 0; i < 5; i++) {
  console.log("for");
}

流程控制语句

  • 两个关键字
    1. break 在循环中没有进行完毕的时候,因为我设置的某一个条件满足了然后执行 break 关键字,循环直接提前终止。
for (var i = 1; i <= 5; i++) {
  console.log("我吃了一个包子");
  if (i === 3) {
    console.log("吃了三个包子,饱了,不吃了");
    break;
  }
}
  1. continue 在循环执行过程中,设置的某一个条件触发了,执行 continue 关键字,跳过本轮循环。
for (var i = 1; i <= 5; i++) {
  if (i === 4) {
    console.log("第四个包子,掉了,不吃了");
    continue;
  }
  console.log("我吃了一个包子");
}

循环嵌套

    简单来说, 就是循环内 再写一个循环
  • 注意: 循环嵌套的时候, 初始化的变量不要相同

函数:

  在JS中,函数可以理解为一段 在程序中多次出现的一段代码。
  我们可以江浙一段代码放在一个盒子中,这个盒子就是 函数。
  后续方便我们多次使用。

函数的参数

如果一个函数没有参数,那么函数的功能十分固定。

参数分为两个:

  1. 形参: function 后的小括号内书写。书写时,直接写一个变量名,然后在这个函数内部,可以使用
  2. 实参: 函数调用时的小括号内书写的,作用是传递给函数的形参,给形参赋值。 注意:形参和实参,都可以传递多个!但是数量要一致。实参的数量 > 形参的数量; 传递的时候 实参会按照顺序依次传递给对应的形参,多余的实参,无法在当前函数以形参的方式取使用。 多余的形参,没有值,是 undefined.
  3. 参数的默认值 就在需要书写 形参的后边利用 赋值号 给这个形参一个默认值 在你没有传递对应的交参的时候,形参会利用默认值

注意:如果形参有对应的实参,那么默认值不会生效

注意:需要默认值的形参,一般会放在函数的最后

函数的返回值

    每一个函数内部都有一个 return ,他能决定当前函数的返回值是什么。
    如果没有书写,默认返回一个 undefined

    return 具有中断函数的作用,所以必须放在函数内代码最后。
    函数内创建的变量,无法在函数外使用。

预解析【面试题】

  1. 变量 变量提升其实就是在变量定义前去使用这个变量 使用 var 声明的变量,具有变量提升的能力,换句话说,再定义变量前使用变量不会报错,但是值变成了 undefined

  2. 函数(声明式函数) 浏览器在解析代码时,会将函数提升到当前作用域的最顶端。

  3. 声明式与赋值式的区别

    1. 写法不同
    2. 赋值式不能在函数定义前去调用, 而声明式可以

    原因: 赋值式是利用 变量提升 声明式是利用 函数提升

作用域【面试题】

简单来说就是变量可以使用的范围
因为变量不是在任何地方都可以使用,而这个能够使用的范围。我们称之为作用域

全局
    是JS 中最大的一个作用域
    在全局作用域中,创建的变量,可以在任意的地方使用
    直接写在 script标签内的变量,我们称之为全局变量,这个作用域也叫做
    全局作用域我们的全局作用域中有一个浏览器帮我们生成的对象(一种数据类型)
    叫做window
    我们在全局作用域声明的变量会自动添加到window对象中

局部(函数作用域)
    在Js 中,只有函数能够创建局部作用域
    在局部作用域内创建的变量,只能在当前作用域内使用,
    超过这个作用域则不能使用


尽可能的多写局部变量,不写全局变量

作用域链【面试题】

作用域链 是一个 纯概念性的东西 当我们在某一个作用域内获取一个变量的时候

  1. 首先在自己(当前)的作用域内查找, 找到就使用, 如果没有找到, 会去自己(当前)作用域的上层作用域(父级作用域)
  2. 如果在 上层作用域 找到, 直接使用, 并停止查找, 如果没有找到, 那么继续向上层查找
  3. 如果上层作用域也没有找到, 那么会继续去上层作用域找, 直到找到全局作用域, 如果还没有找到, 此时报错

上述的也叫做 访问规则; 重点, 变量在访问的时候, 会顺着作用域 逐层向上查找, 不会逐层向下查找

赋值规则:

  1. 如果再给一个变量赋值的时候, 首先会在当前作用域内查找这个变量
  2. 如果没有找到, 那么回去上层作用域查找, 如果还没有, 继续向上
  3. 直到找到了全局作用域也没有找到, 在全局创建一个变量, 并赋值

递归函数

 在一个函数内, 调用了 自身, 就算是一个递归函数, 只不过这个函数需要再设置一个结束条件

简单了解对象

    是JS中的一种数据类型;
    对象属于 引用数据类型(复杂数据类型);
    算是一种数据的集合,内部可以存储任意的数据类型。
  • 创建对象

    • 字面量方式创建对象
            var obj = {
                <!-- 大括号内书写的不是代码,书写数据 -->
            }
    
    • 内置构造函数创建
    var obj1 = new Object();
    
    • 对象内对于 键(key) 的要求
      1. 推荐书写 属性名时,参考变量的命名规范
      2. 可以使用 纯数字 当属性名
      3. 可以使用 特殊符号(# @)但是需要使用 引号包裹
  • 对象数据类型的操作(增删改查)两种语法

    • 点语法 增 -> 对象.新属性名 = 对应的属性值 删 -> delete 对象.要删除的属性名 改 -> 对象.要修改的属性名 = 新的属性值 查 -> 对象.要查询的属性名

    • 中括号语法(数组语法) 增 -> 对象['新属性名'] = 对应的属性值 删 -> delete 对象['要删除的属性名'] 改 -> 对象['要修改的属性名'] = 新的属性值 查 -> 对象['要查询的属性名']

    • 两者的差异

      • 如果对象的属性名 是符合变量的命名规范的话,那么这两种语法没有任何差异。
      • 如果对象的属性名 不符合变量的命名规范的话,使用中括号语法
      • 如果用的是变量,也需要使用中括号语法。
    • for in 循环遍历对象

//语法:for...in
var obj = {
  name: "qwer",
  age: 18,
  str: "asdf",
};
for (var a in obj) {
  // console.log(a)
  console.log(a, obj[a]);
}

数组数据类型

数组: 一个存放一组数据的集合 简单来说, 我们将一组数据, 存放到一个盒子中, 这个盒子就是一个数组 数组的创建

  1. 字面量的方式 (常用)
 // 1. 字面量的方式
         var arr = [] 创建一个空数组
         var arr = [1, 2, 'qwe', 'rty', true, false, undefined, { name: 'QF001' }]
         console.log(arr)
  1. 内置构造函数
   // 2. 内置构造函数
         var arr = new Array()    空数组
         var arr = new Array(5)  创建一个 长度 为 5 的空数组
         var arr = new Array(1, 2, 3, 4, 5)  // 创建一个 内容为 1 2 3 4 5 的数组
         console.log(arr)

数组的 length 其实就是数组的长度, 由数组内部多少个 成员(数据) 来决定的 跟数组每个成员的值, 没有任何关系

// length
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var arr1 = [100, 200, 300, 400, 500];
console.log(arr1);
console.log(arr1.length);

数组的 索引(下标) 下标表示的是 数组当前位置 从 0 开始!!! 到 数组.length - 1 结束

冒泡排序

var arr = [9, 8, 7, 6, 5, 4, 3, 2, 1];
console.log("原数组", arr);
for (var k = 0; k < arr.length - 1; k++) {
  // 决定内部的 冒泡排序执行多少次
  // 内循环: 冒泡排序的核心代码
  for (var i = 0; i < arr.length - 1 - k; i++) {
    console.log("当前对比的是: ", arr[i], arr[i + 1]);
    if (arr[i] > arr[i + 1]) {
      var tem = arr[i];
      arr[i] = arr[i + 1];
      arr[i + 1] = tem;
    }
  }
}
console.log(arr);

选择排序

var arr = [9, 3, 6, 2, 4, 1, 8, 5, 7];
for (var k = 0; k < arr.length; k++) {
  // 1. 创建一个变量, 存储当前假设的 最小值的下标
  var minIndex = k;
  // 2. 遍历数组, 寻找真实最小值的下标
  for (var i = k + 1; i < arr.length; i++) {
    if (arr[minIndex] > arr[i]) {
      minIndex = i;
    }
  }
  // 3. 经过上述循环遍历之后, minIndex 一定是 真实最小值的下标, 所以此时交换两个下标的值
  var tem = arr[k];
  arr[k] = arr[minIndex];
  arr[minIndex] = tem;
}
console.log("选择排序后: ", arr);

数据类型之间的区别

数据类型之间的区别

  1. 基本数据类型
  2. 复杂数据类型

存储的区别

  1. 基本数据类型 (string, numbe, undefined, null, boolean) 直接将数据类型存储到 栈内存中
  2. 复杂数据类型 (object, array, function) 将数据本体, 存放在堆内存中, 然后将指向堆内存的地址, 存储在 变量名中, 最后变量名存储在 栈内存中

赋值的区别

  1. 基本数据类型 直接将数据赋值给另一个变量; 赋值完成之后, 两个变量没有任何关系 类似于, 我有一张考试卷子, 我复制出来一份给你, 然后你对你的卷子有任何修改, 都不会影响我这一张卷子
  2. 复杂数据类型 因为 复杂数据类型的变量名中 存储的是指向一个堆内存的地址, 所以在做赋值的时候, 是把这个地址赋值给另一个变量了 所以修改另外一个变量的时候, 会影响自身 类似于: 我有一个房间的钥匙, 然后我将钥匙复制一份, 给你一个, 你后续能够进入这个房间了, 后续如果你对这个房间做了任何修改 在我进入房间的时候, 我都能看到

比较的区别

  1. 基本数据类型 直接将数据进行对比
  2. 复杂数据类型 因为变量内部存储的是 一个地址, 所以对比时, 对比的是地址, 而不是真正的值

传参的区别

  1. 基本数据类型 将数据拷贝一份传递给形参, 在函数内对形参的修改并不会影响外界
  2. 复杂数据类型 将变量内部存储的地址, 赋值给形参, 也就是说, 函数内部的形参, 和外部的变量, 共同享用同一个地址 所以在函数内对形参的修改会影响外界

数组的常用方法

数组的常用方法

  1. push
    • 语法: 数组.push(数据)
      
    • 作用: 将这个 "数据", 追加到数组的末尾, 向数组末尾, 添加新数据
      
    • 返回值: 追加新数据后, 数组的最新的长度 length
      
  2. pop
    • 语法: 数组.pop()
      
    • 作用: 删除数组的最后一项
      
    • 返回值: 删除的哪一项对应的值
      
  3. unshift
    • 语法: 数组.unshift(数据)
      
    • 作用: 将这个 "数据", 添加到数组的开头
      
    • 返回值: 追加新数据后, 数组的最新长度 length
      
  4. shift
    • 语法: 数组.shift()
      
    • 作用: 删除数组的第一项
      
    • 返回值: 删除的哪一项对应的值
      
  5. reverse()
    • 语法: 数组.reverse()
      
    • 作用: 反转数组
      
    • 返回值: 反转后的数组
      
  6. sort()
    • 语法:数组.sort()
      
      传参数:数组.sort(function (a,b) {return a-b}) 数组.sort(function (a,b) {return b-a})
    • 作用:对数组进行排序
      
    _ =>不穿参数: _ 将数组内部的数据,全部转换为 字符串,然后一位一位的对比。 _ =>传参数: _ a-b 按照从小到大的排列方式 _ b-a 按照从大到小
    • 返回值:不穿参数:将排序后的数组返回
      
    _
  7. splice()
    • 语法:数组.splice(开始索引,多少个);数组.splice(开始索引,多少个,要插入的数据 1,要插入的数据 2,...)
      
    • 作用:截取数组 类似于剪切;
      
    • 返回值:截取到的数据(以数组的形式) 
          数组方法中,只有以上 7 种可以改变原数组。
      
  8. slice()
    • 语法:数组.slice(开始索引,结束索引)
      
    参数的特点: 1.包头不包尾;包含开始索引,不包含结束索引 2.参数接受负数(相当于 数组.length + 负数) 3.参数可以不传递。 =>结束下标不传,相当于 从开始下标复制到数组的尾部 =>两个参数都不传递,相当于从[0] 复制到数组的末尾。
    • 作用: 类似与复制
      
    • 返回值:复制到的的数据(以数组的形式)
      
  9. concat()
    • 语法:数组.concat(数据1,数据1,数据3,...)
      
    • 作用:  将小括号内的数据,合并当 当前数组中
      
    • 返回值:返回合并后的数组
      
  10. join()
    • 语法:数组.join('连接符')
      
    • 作用:通过连接符,将数组的每一项合并起来,如果不传递连接符,默认逗号连接。
      
    • 返回值:连接好的数据(字符串类型的)
      
  11. indexOf(默认从[0] 找到数组的末尾)
    • 语法:数组.indexOf(数据); 数组.indexOf(数据 ,从哪里开始)
      
    • 作用:在数组内寻找 你传入的 数据
      
    • 返回值: 如果找到了,返回数据第一次出现的下标
          如果没找到,返回 -1
      
  12. lastIndexOf(默认从数组的末尾, 找到 [0])
    • 语法:数组.lastIndexOf(数据); 数组.lastIndexOf(数据 ,从哪里开始)
      
    • 作用:在数组内寻找 你传入的 数据
      
    • 返回值:如果找到了,返回数据第一次出现的下标
          如果没找到,返回 -1
      
  13. forEach
    • 语法:数组.forEach(function (item;index;origin) {遍历数组需要执行的代码})
      
      item: 遍历数组的当前项 index:item对应的下标 origin:对应的原数组
    • 作用:遍历数组
      
    • 返回值:没有返回值,永远是undefined
      
  14. map
    • 语法:数组.forEach(function (item;index;origin) {遍历数组需要执行的代码})
      
    • 作用:映射数组,映射出来一个数组长度与原数组一模一样的数组,但新数组的值,取决于return
      
    • 返回值:映射出来的数组
      
  15. filter
    • 语法:数组.filter(function (item;index;origin) {遍历数组需要执行的代码})
      
    • 作用:过滤数组
      
    • 返回值:过滤后的新数组,过滤条件取决于 函数内的return
      
  16. find
    • 语法:数组.find(function (item;index;origin) {遍历数组需要执行的代码})
      
    • 作用:查找数据
      
    • 返回值:在数组内找到的第一个符合条件的数据(不是数组)  如果找不到 返回 undefined
      
  17. findIndex
    • 语法:数组.findIndex(function (item;index;origin) {遍历数组需要执行的代码})
      
    • 作用:查找数据 第一次出现的 下标
      
    • 返回值:在数组内找到的第一个符合条件的数据 的下标  如果找不到 返回 -1
      
  18. every
    • 语法:数组.every(function (item;index;origin) {遍历数组需要执行的代码})
      
    • 作用:判断数组的每一项是否都符合条件
      
    • 返回值:true  都符合条件
       false   至少有一个不符合条件
      
  19. some
    • 语法:数组.some(function (item;index;origin) {遍历数组需要执行的代码})
      
    • 作用:判断数组是否 有一项 符合条件
      
    • 返回值:true  最少有一项符合条件
       false   都不符合条件
      
  20. reduce
    • 语法:数组.reduce(function (prev, item, index, origin) {}, init)
       prev: 表示初始值(需要传递init)  
             或者表示数组[0]的值(需要不传递init)
       item: 如果传递了 init, item 的值为 数组[0]      
             如果没有传递 init, item 的值为 数组[1]
       index/origin:    与forEach 相同
      
注意:
    init 为可选项
    如果书写了 init, 那么 prev 的第一次的值, 就是由 init 传递的, 然后 item 的值是从 [0] 开始的
    如果没有书写 init, 那么 prev 的第一次的值, 是数组 [0] 的值, 然后 item 的值使用[1]
 *     作用: 累加(叠加)
 *     返回值: 循环运行后的值

字符串的常用方法

  1. charAt
    • 语法:字符串.charAt(索引)
      
    • 作用:找到字符串中这个索引对应的文本
      
    • 返回值:查询到的值   如果没有找到,返回一个空字符串
      
  2. charCodeAt
    • 语法:字符串.charCodeAt(索引)
      
    • 作用:找到字符串中这个索引对应的文本 的十进制编码
      
    • 返回值:查询到的值对应的编码   如果没有找到,返回NaN
      
  3. toLowerCase
    • 语法:字符串.toLowerCase()
      
    • 作用:将字符串全部转换为 小写
      
    • 返回值:转换后的字符串
      
  4. toUpperCase
    • 语法:字符串.toUpperCase()
      
    • 作用:将字符串全部转换为 大写
      
    • 返回值:转换后的字符串
      
  5. substr 了解即可
    •  语法:字符串.substr(开始索引,多少个)
      
    •  作用:截取指定范围的字符串
      
    •   返回值:截取到的字符串。
      
  6. substring
    •   语法:字符串.substring(开始索引,结束索引)
      
    •   作用:截取指定字符串
      
    •   返回值:截取到的字符串。
      
  7. slice
    • 语法:字符串.slice(开始索引,结束索引)
      
    • 参数的特点: 1.包头不包尾;包含开始索引,不包含结束索引 2.参数接受负数(相当于 数组.length + 负数) 3.参数可以不传递。 =>结束下标不传,相当于 从开始下标复制到数组的尾部 =>两个参数都不传递,相当于从[0] 复制到数组的末尾。
    • 作用:截取指定字符串
      
    • 返回值:截取到的字符串。
      
  8. concat
    • 语法:字符串.concat(数据1,数据2,...)
    • 作用:将数据合并到字符串中
    • 返回值:合并后的字符串。
  9. split
    • 语法:字符串.split(分隔符)
      
    • 作用:在当前字符串中找到指定的分隔符,然后根据分隔符将当前字符串拆分开,以数组的形式保存。
      
    • 返回值:拆分后的数组。
      
      注意:
        1. 字符串中, 有对应的分隔符: 将字符串根据分隔符分隔开
        1. 字符串中, 没有对应的分隔符: 将字符串当成一个整体, 放在数组中
        1. 如果传递的是 空字符串: 将字符串每一个字符串全都分隔开, 放在数组中
  10. indexOf
    • 语法:字符串.indexOf(数据,开始下标)
      
    • 作用:查找数据在字符串中的位置
      
    • 返回值:找到时返回数据在字符串中的下标
      
    •          找不到返回-1
      
  11. lastindexOf
    • 语法:字符串.lastindexOf(从最后开始查找)
      
    • 作用:查找数据在字符串中的位置
      
    • 返回值:找到时返回数据在字符串中的下标
      
    •          找不到返回-1
      
  12. trim (纯木)
    • 语法:字符串.trim()
      
    • 作用:去除字符串左右两边所有的空格
      
    • 返回值:去掉空格后的字符串
      
  13. trimStart(trimLeft)
    •  语法:字符串.trimStart()
      
    •  作用:去除字符串左边所有的空格
      
    •  返回值:去掉空格后的字符串
      
  14. trimEnd(trimRight)
    •  语法:字符串.trimEnd()
      
    •  作用:去除字符串右边所有的空格
      
    •  返回值:去掉空格后的字符串
      
  15. includes
    •  语法:字符串.includes(字符串片段)
      
    •  作用:判断 当前字符串中 是否拥有这个字符串片段
      
    •  返回值:布尔值   true  拥有
      
    •                  false  没有
      
  16. startsWith
    •  语法:字符串.startsWith(字符串片段)
      
    •  作用:判断 当前字符串开头中 是否拥有这个字符串片段
      
    •  返回值:布尔值   true  拥有
      
    •                  false  没有
      
  17. endsWith
    •  语法:字符串.endsWith(字符串片段)
      
    •  作用:判断 当前字符串结尾中 是否拥有这个字符串片段
      
    •  返回值:布尔值   true  拥有
      
    •                  false  没有
      
  18. replace
    •  语法:字符串.replace('要被替换的字符串''新的字符' )
      
    •  作用:在字符串中 先找到 要被替换的字符串,找到后将 新的字符串 替换过去
      
    •  返回值:替换后的字符串
      
    •          找不到返回原字符串。
      

严格模式

 严格模式:
     *其实就是因为 JS 初期的不严谨, 后续特意推出了一个严谨的版本, 我们叫做严格模式
     *在 JS 中默认是关闭的, 如果要打开, 需要在 JS 开始的位置, 书写一个字符串 'use strict'
     *  在严格模式中, 变量 必须定义
     *  函数的形参名不能重复

进制转换与保留小数

  1. 进制转换 (了解) => 十进制转换成其他进制 十进制的数字.toString(你要转换的进制数) => 其他进制转换成十进制 parseInt(数字, 将数字视为x进制的数字然后转换成10进制)
  2. 保留小数 (掌握) => 要保留小数的数字.toFixed(要保留几位小数) 采用四舍五入的方式, 并且返回的是一个 字符串

定时器与倒计时器

  1. 定时器
      setInterval(function () {
           // 定时器每次执行的时候, 要执行的代码
             console.log('当前定时器, 每 1 秒, 执行一次')
         }, 500)    // 时间单位是毫秒
  1. 倒计时器
        setTimeout(function () {
             console.log('当前倒计时器, 会在 3 秒后执行一次')
         }, 3000)

返回值: 含义: 表明当前页面有多少个定时器或者倒计时器 作用: 停止当前定时器或者倒计时器 关闭定时器的注意事项: 关闭的时候, 有两个方法 clearTimeout/clearInterval; 可以混用

      但是不推荐混用

数学方法

  1. random
    • 返回一个 0~1 之间的随机数, 不包含1.
  2. round 将一个小数 进行四舍五入取整
    • console.log(Math.round(1.4))
  3. ceil 将一个小数 进行 向上 取整
    • console.log(Math.ceil(1.4))
  4. floor 将一个小数 进行 向下 取整
    • console.log(Math.floor(1.4))
  5. abs 绝对值
    • console.log(Math.abs(1.4))
  6. sqrt 求平方根
    • var num = Math.sqrt(9)
    • console.log(num)
  7. pow
    • var num = Math.pow(3,4) //求数字3的4次幂
    • console.log(num)
  8. max
    • var num = Math.max(3,4)
    • console.log(num)
  9. min
    • var num = Math.min(3,4)
    • console.log(num)

时间对象

时间对象

 不传参数,直接获取当前时间
  var timer = new Date();
  console.log(timer)

  传递参数,传递字符串
  var timer = new Date('2000-5-3 12:13:14');
  console.log(timer)

  传递数字,最少传递两个
  var timer = new Date(2002,5,3,12,12,12);//JS中,月份的表示是从0~11.
  console.log(timer)

时间对象的获取类方法

  1. getFullYear 获取年份
  2. getMonth 获取月份
  3. getDay 获取周几
  4. getDate 获取一个月中的哪天
  5. getHours 获取哪一小时
  6. getMinutes 获取分钟
  7. getSeconds 获取秒
  8. getTime 获取毫秒数

时间对象的设置类方法

  1. setFullYear 设置年份
  2. setMonth 设置月份
  3. setDate 设置一个月中的哪天
  4. setHours 设置哪一小时
  5. setMinutes 设置分钟
  6. setSeconds 设置秒
  7. setTime 设置毫秒数
  8. setDay 不管用

BOM

  1. 获取浏览器窗口的尺寸
    • 宽度:window.innerWidth
    • 高度:window.innerHeight
  2. 浏览器弹出框
    • window.prompt() 输入框
    • window.alert() 弹出框
    • window.confirm() 询问框
  3. 浏览器的地址信息
    • 在 window 中,有一个对象location,他是专门用来 存储浏览器的地址信息
    • location这个对象中有一个属性是href 我们可以给他重新赋值一个地址,实现页面的跳转还有一个方法,reload,我们调用之后,可以刷新当前页面
  4. 通过 BOM 获取到 浏览器的版本信息 (了解) navigator
  5. 浏览器的 onload 事件
    • 会将 内部的代码 等到页面所有内容加载完毕后执行
  6. 浏览器的滚动事件 onscroll 事件在元素滚动条在滚动时触发。
    • window.onscroll = function () {}

3.1 浏览器的滚动距离

  • 思考: 浏览器滚动了吗?
  • 回答: 没有滚动, 其实是浏览器内的页面在滚动 语法1: document.body.scrollTop 语法2: document.documentElement.scrollTop 区别:
    1. IE 浏览器 (了解) 没有 DOCTYPE, 那么使用两个中任意一个都可以 有 DOCTYPE, 那么只能使用 documentElement
    2. Chrome 和 火狐浏览器 没有 DOCTYPE, 用 body 有 DOCTYPE, 使用 documentElement
    3. Safari 这两个都不能使用, 使用 window.pageYOffset

3.2 浏览器的横向滚动距离

         语法1: document.body.scrollLeft
         语法2: document.documentElement.scrollLeft
  区别参考上边的
// 1. 获取浏览器窗口的尺寸 (通过 window 可以操作 BOM)
var aaa = 100
console.log(window)
console.log(aaa)
console.log(window.aaa)

console.log('高度', window.innerHeight)
console.log('宽度', window.innerWidth)
console.log('高度', innerHeight)
console.log('宽度', innerWidth)

// 2. 浏览器的弹窗框
var str = window.prompt('请您输入一个内容') // 输入框
alert('一个弹出框') // 弹出框
var boo = confirm('您确定跳转页面吗?')   // 询问框
console.log(boo)
// 3. 浏览器的地址信息
console.log(window.location)

BOM 本地存储

  1. storage (四套润此)
    • localStorage
               浏览器本地存储,持久存储,一旦存储永久存在
               只能存储基本数据类型(一般是字符串)
               能够跨页面通讯
                    我在A页面存储,但是在B页面能够获取到,那么就是跨页面通讯
      
// localStorage
// 1. 新增一个本地存储
/window.localStorage.setItem(key, value)  // key 相当于变量名, value 你真正要存储的值
window.localStorage.setItem('WX', 'QF001')
window.localStorage.setItem('QQ', 'QF888')
// 2. 删除一个本地存储
window.localStorage.removeItem(key)  // 你要删除哪一个本地存储, 就把这个 key 写成哪一个
window.localStorage.removeItem('WX')
// 3. 清空本地存储
window.localStorage.clear()
//4. 查询一个本地存储的值
     //返回值:
     //查询到 -> 把这个 key 对应的 value 返回出来
     //没有查询到 -> 返回一个 null
var res = window.localStorage.getItem('WX1234567890')
console.log(res)
//5. 存储引用数据类型(数组---对象)
// 错误存储数组
var arr = [1, 2, 3, 4, 5]
window.localStorage.setItem('arr', arr)
var res = window.localStorage.getItem('arr')
console.log(res)
// 错误存储对象
var obj = {
     name: 'QF001',
     age: 18
     }
window.localStorage.setItem('obj', obj)
var res = window.localStorage.getItem('obj')
console.log(res)
/**
*  在 JS 中 有一个对象叫做 JSON, 她提供了两个方法
*          1. JSON.stringify(传入要转换的数据)     能够将其它类型的数据, 转换为 JSON 格式的字符串
*          2. JSON.parse(传入要转换的数据)         能够将 JSON 格式的字符串, 转换为 原本的数据类型
*/
        var obj = {
            name: 'QF001',
            age: 18
        }
        var newObj = JSON.stringify(obj)

        var arr = [1, 2, 3, 4, 5]
        var newArr = JSON.stringify(arr)

        // console.log(obj)
        // console.log(newObj)
        // console.log(arr)
        // console.log(newArr)

        window.localStorage.setItem('arr', newArr)
        window.localStorage.setItem('obj', newObj)

        var arr1 = JSON.parse(window.localStorage.getItem('arr'))
        var obj1 = JSON.parse(window.localStorage.getItem('obj'))

        console.log(arr1)
        console.log(obj1)
 *     sessionStorage
           浏览器本地存储,临时存储,关闭浏览器后,存储内容自动消失
           如果想要跨页面通讯,必须是从本次页面跳转的才可以打开
           增; 删; 清除; 获取;  和localStorage一样
  1. cookie (kuki)
    •  只能存储字符串,且有固定格式( key=value)
      
    •  存储大小有限制
      
    •  操作cookie 必须依赖服务器(本地启动文件不能运行 cookie)
      
    •  跟随前后端交互,自动携带
          将来前端向后端发送请求时,如果 cookie 内有数据,那么会自动携带
      
    •  前后端操作
          前端:JS   
          后端:任何一个后端语言都可以操作 cookie
      
    •  存储依赖域名
           哪一个域名存储, 哪一个域名能够使用, 不能跨页面通讯
      

cookie 和 storage 的区别【面试题】

  1. 出现时间: cookie 是有JS的时候就存在了 storage H5出现后才出现
  2. 存储大小 cookie 4kb storage 20MB/5MB
  3. 前后端交互 cookie 请求时自动携带 storage 请求时不会自动携带,可以手动携带
  4. 前后端操作 cookie 前后端都可以操作 storage 只有前端 JS 能操作
  5. 过期时间 cookie 默认会话级别,但是可以手动设置过期时间 storage 不能手动设置过期时间
  6. 两个 storage (localStorage;sessionStorage) 有什么区别?
    1. 过期时间
    2. 跨页面通讯
  • 共同点:
    1. 只能存储字符串,不能存储复杂数据类型
    2. 直接存储其他数据类型,获取回来的也是字符串类型
  1. 在 JS 中 有一个对象叫做 JSON, 她提供了两个方法
    1. JSON.stringify(传入要转换的数据) 能够将其它类型的数据, 转换为 JSON 格式的字符串
    2. JSON.parse(传入要转换的数据) 能够将 JSON 格式的字符串, 转换为 原本的数据类型

DOM

文档对象模型;操作 HTML 标签的能力

    获取一个元素(标签、节点、DOM节点)
    移除一个元素
    创建一个元素
    向页面中添加一个元素
    给页面绑定事件(单击、双击、键盘按下...)
    获取元素的一些属性
    获取元素的css样式
    给一个元素添加css样式
  • DOM 的核心是 document 对象
  • document 对象是浏览器内置的一个对象,里面存储着专门用来操作元素的各种方法

获取页面的常规元素

  1. 通过元素的id名获取标签
var id_ele = document.getElementById("id_box");
console.log(id_ele)
  1. 通过元素的 class 名 注意:
    • getElementsByClassName Element(爱了门特)
    • 获取到的元素, 放在了一个长得很像数组的数据结构内
    • 我们可以通过下标去获取到准确的 DOM节点, 也可以通过 length 知道获取了多少个元素
    • 但是数组的一些方法不能使用, 比如 forEach, map....
    • 我们给这个数组起了个名字叫做 伪数组
var cla_box = document.getElementsByClassName("class_box");
console.log(cla_box)
  1. 通过元素的标签
var div_box = document.getElementsByTagName("div");
console.log(div_box)
  1. 类似 css 选择器的方式 document.querySelector (快润设莱克特) 获取到的是页面中第一个符合的标签
var new_div_box = document.querySelector('div')
var new_div_box = document.querySelector(".class_box");
console.log(new_div_box);
  1. 获取到页面中所有符合要求的 标签 也是一个伪数组的形式, 但是能使用 forEach 个人建议, 使用伪数组的时候, 不要使用数组的方法 最好的方式将这个伪书组转换成真实数组 var arr = [...伪数组]
var new_div_box = document.querySelectorAll('div')
var new_div_box = [...document.querySelectorAll("div")];
console.log(new_div_box);

操作元素的属性

获取到DOM 节点的属性,并直接渲染到页面

  • 获取标签
var boxO = document.querySelector('#box_o')
var boxT = document.getElementById('box_t')
  1. innerHTML 获取标签内部的结构
console.log(boxO.innerHTML)
// 设置的时候能够解析字符串中的 html 标签
boxT.innerHTML = '<span>hello<span>'
  1. innerText 获取元素内部的文本 (获取不到html 标签)
console.log(boxO.innerText)
// 设置的时候会将字符串的所有内容添加到标签的文本区, 字符串中哪怕是写了标签, 他也不认识
boxT.innerText = '<span>hello</span>'
  1. 获取元素的某个属性 (包括自定义属性)
console.log(boxT.getAttribute('a'))    // getAttribute(鹅腿比u特) 获取到当前标签的这个属性对应的值
console.log(boxT.getAttribute('id'))    // getAttribute 获取到当前标签的这个属性对应的值
  1. 设置元素的某个属性
boxT.setAttribute('my_box', 'QF001')    // 新加一个属性
boxT.setAttribute('a', 'QF666')         // 修改原有的属性
  1. 删除元素的某一个属性
boxT.removeAttribute('a')   // 将这个标签的属性a, 删除
  1. H5自定义属性
    • 属性名: data- 后的内容 如果一个 H5 自定义属性写为: data-id="QF001" 属性名: id 属性值: 'QF001' data- 的作用仅仅表示这是一个 H5的自定义属性
// 增加
boxEle.dataset.name = 'wang'
// 删除
delete boxEle.dataset.id
// 获取
console.log(boxEle.dataset.xbox)
  1. style 专门用来给某个元素添加 css 样式 添加的样式是行内样式
boxEle.style.width = '100px'
boxEle.style.height = '100px'
boxEle.style.backgroundColor = 'pink'
  1. className 专门用于操作元素类名; 设置类名的时候, 不管之前有多少个, 直接全部覆盖
boxEle.className = 'new_box'
console.log(boxEle.className)
  • classList 也是用于操作元素类名的, 具有一些方法, 如下所示
// 新增一个类名
boxEle.classList.add('new_box')    
// 删除一个
boxEle.classList.remove('new_box')
console.log(boxEle.classList)