JavaScript 基础 && 高级

JavaScript 基础 && 高级

  • [Web APIs](#Web APIs)
    • DOM
      • [1、 DOM 简介](#1、 DOM 简介)
        • [1.1 什么是 DOM](#1.1 什么是 DOM)
        • [1.2 DOM 树](#1.2 DOM 树)
      • 2、获取元素
        • [2.1 如何获取页面元素](#2.1 如何获取页面元素)
        • [2.2 根据 ID 获取](#2.2 根据 ID 获取)
        • [2.3 根据标签名获取](#2.3 根据标签名获取)
        • [2.4 通过 HTML5 新增的方法获取](#2.4 通过 HTML5 新增的方法获取)
        • [2.5 获取特殊元素(body,html)](#2.5 获取特殊元素(body,html))
      • [3、 事件基础](#3、 事件基础)
        • [3.1 事件概述](#3.1 事件概述)
        • [3.2 事件三要素](#3.2 事件三要素)
        • [3.3 执行事件的步骤](#3.3 执行事件的步骤)
        • [3.4 常见的鼠标事件](#3.4 常见的鼠标事件)
      • [4、 操作元素](#4、 操作元素)
        • [4.1 改变元素内容](#4.1 改变元素内容)
        • [4.2 常用元素的属性操作](#4.2 常用元素的属性操作)
        • [4.3 表单元素的属性操作](#4.3 表单元素的属性操作)
        • [4.4 样式属性操作](#4.4 样式属性操作)
        • [4.5 排他思想](#4.5 排他思想)
        • [4.6 自定义属性的操作](#4.6 自定义属性的操作)
        • [4.7 H5自定义属性](#4.7 H5自定义属性)
      • [5、 节点操作](#5、 节点操作)
        • [5.1 为什么学节点操作](#5.1 为什么学节点操作)
        • [5.2 节点概述](#5.2 节点概述)
        • [5.3 节点层级](#5.3 节点层级)
        • [5.4 创建节点](#5.4 创建节点)
        • [5.5 添加节点](#5.5 添加节点)
        • [5.6 删除节点](#5.6 删除节点)
        • [5.7 复制节点(克隆节点)](#5.7 复制节点(克隆节点))
        • [5.8 三种动态创建元素区别](#5.8 三种动态创建元素区别)
      • [6、 DOM 重点核心](#6、 DOM 重点核心)
        • [6.1 创建](#6.1 创建)
        • [6.2 增](#6.2 增)
        • [6.3 删](#6.3 删)
        • [6.4 改](#6.4 改)
        • [6.5 查](#6.5 查)
        • [6.6 属性操作](#6.6 属性操作)
        • [6.7 事件操作](#6.7 事件操作)
    • 事件高级
      • [1、 注册事件(绑定事件)](#1、 注册事件(绑定事件))
        • [1.1 注册事件概述](#1.1 注册事件概述)
        • [1.2 addEventListener 事件监听方式](#1.2 addEventListener 事件监听方式)
        • [1.3 attachEvent 事件监听方式](#1.3 attachEvent 事件监听方式)
        • [1.4 注册事件兼容性解决方案](#1.4 注册事件兼容性解决方案)
      • [2、 删除事件(解绑事件)](#2、 删除事件(解绑事件))
        • [2.1 删除事件的方式](#2.1 删除事件的方式)
        • [2.2 删除事件兼容性解决方案](#2.2 删除事件兼容性解决方案)
      • [3、 DOM 事件流](#3、 DOM 事件流)
      • [4、 事件对象](#4、 事件对象)
        • [4.1 什么是事件对象](#4.1 什么是事件对象)
        • [4.2 事件对象的使用语法](#4.2 事件对象的使用语法)
        • [4.3 事件对象的兼容性方案](#4.3 事件对象的兼容性方案)
        • [4.4 事件对象的常见属性和方法](#4.4 事件对象的常见属性和方法)
      • [5、 阻止事件冒泡](#5、 阻止事件冒泡)
        • [5.1 阻止事件冒泡的两种方式](#5.1 阻止事件冒泡的两种方式)
        • [5.2 阻止事件冒泡的兼容性解决方案](#5.2 阻止事件冒泡的兼容性解决方案)
      • [6、 事件委托(代理、委派)](#6、 事件委托(代理、委派))
      • [7、 常用的鼠标事件](#7、 常用的鼠标事件)
        • [7.1 常用的鼠标事件](#7.1 常用的鼠标事件)
        • [7.2 鼠标事件对象](#7.2 鼠标事件对象)
      • [8、 常用的键盘事件](#8、 常用的键盘事件)
        • [8.1 常用键盘事件](#8.1 常用键盘事件)
        • [8.2 键盘事件对象](#8.2 键盘事件对象)
    • [PC 端网页特效](#PC 端网页特效)
      • [1、 元素偏移量 offset 系列](#1、 元素偏移量 offset 系列)
        • [1.1 offset 概述](#1.1 offset 概述)
        • [1.2 offset 与 style 区别](#1.2 offset 与 style 区别)
      • [2、元素可视区 client 系列](#2、元素可视区 client 系列)
      • [3、 元素滚动 scroll 系列](#3、 元素滚动 scroll 系列)
        • [3.1 元素 scroll 系列属性](#3.1 元素 scroll 系列属性)
        • [3.2 页面被卷去的头部](#3.2 页面被卷去的头部)
        • [3.3 页面被卷去的头部兼容性解决方案](#3.3 页面被卷去的头部兼容性解决方案)
      • 4、三大系列总结
      • [5、mouseenter 和mouseover的区别](#5、mouseenter 和mouseover的区别)
        • [5.1 mouseenter 鼠标事件](#5.1 mouseenter 鼠标事件)
      • [6、 动画函数封装](#6、 动画函数封装)
        • [6.1 动画实现原理](#6.1 动画实现原理)
        • [6.2 动画函数简单封装](#6.2 动画函数简单封装)
        • [6.3 动画函数给不同元素记录不同定时器](#6.3 动画函数给不同元素记录不同定时器)
        • [6.4 缓动效果原理](#6.4 缓动效果原理)
        • [6.5 动画函数多个目标值之间移动](#6.5 动画函数多个目标值之间移动)
        • [6.6 动画函数添加回调函数](#6.6 动画函数添加回调函数)
      • 7、常见网页特效案例
        • [7.1 节流阀](#7.1 节流阀)
    • 移动端网页特效
      • [1、 触屏事件](#1、 触屏事件)
        • [1.1 触屏事件概述](#1.1 触屏事件概述)
        • [1.2 触摸事件对象(TouchEvent)](#1.2 触摸事件对象(TouchEvent))
        • [1.3 移动端拖动元素](#1.3 移动端拖动元素)
      • [2、 移动端常见特效](#2、 移动端常见特效)
        • [2.1 classList 属性](#2.1 classList 属性)
        • [2.2 click 延时解决方案](#2.2 click 延时解决方案)
    • [BOM 浏览器对象模型](#BOM 浏览器对象模型)
      • [1、 BOM 概述](#1、 BOM 概述)
        • [1.1 什么是 BOM](#1.1 什么是 BOM)
        • [1.2 BOM 的构成](#1.2 BOM 的构成)
      • [2、window 对象的常见事件](#2、window 对象的常见事件)
        • [2.1 窗口加载事件](#2.1 窗口加载事件)
        • [2.2 调整窗口大小事件](#2.2 调整窗口大小事件)
      • [3、 定时器](#3、 定时器)
        • [3.1 两种定时器](#3.1 两种定时器)
        • [3.2 setTimeout() 定时器](#3.2 setTimeout() 定时器)
        • [3.3 停止 setTimeout() 定时器](#3.3 停止 setTimeout() 定时器)
        • [3.4 setInterval() 定时器](#3.4 setInterval() 定时器)
        • [3.5 停止 setInterval() 定时器](#3.5 停止 setInterval() 定时器)
        • [3.6 this](#3.6 this)
      • [4、 JS 执行机制](#4、 JS 执行机制)
        • [4.1 JS 是单线程](#4.1 JS 是单线程)
        • [4.2 同步和异步](#4.2 同步和异步)
        • [4.4 JS 执行机制](#4.4 JS 执行机制)
      • [5、 location 对象](#5、 location 对象)
        • [5.1 什么是 location 对象](#5.1 什么是 location 对象)
        • [5.2 URL](#5.2 URL)
        • [5.3 location 对象的属性](#5.3 location 对象的属性)
        • [5.4 location 对象的方法](#5.4 location 对象的方法)
      • [6、 navigator 对象](#6、 navigator 对象)
      • [7、 history 对象](#7、 history 对象)
    • 本地存储
      • 1、本地存储
        • [2. window.sessionStorage](#2. window.sessionStorage)
        • [3. window.localStorage](#3. window.localStorage)
  • JavaScript基础
    • 计算机编程基础
      • [1、 编程语言](#1、 编程语言)
        • [1.1 编程](#1.1 编程)
        • [1.2 计算机语言](#1.2 计算机语言)
        • [1.3 编程语言](#1.3 编程语言)
        • [1.4 翻译器](#1.4 翻译器)
        • [1.5 编程语言和标记语言区别](#1.5 编程语言和标记语言区别)
      • 2、计算机基础
        • [2.1 计算机组成](#2.1 计算机组成)
        • [2.2 数据存储](#2.2 数据存储)
        • [2.3 数据存储单位](#2.3 数据存储单位)
    • 初识JavaScript
      • [1、 初识 JavaScript](#1、 初识 JavaScript)
        • [1.1 JavaScript 是什么](#1.1 JavaScript 是什么)
        • [1.2 JavaScript 的作用](#1.2 JavaScript 的作用)
        • [1.3 HTML/CSS/JS 的关系](#1.3 HTML/CSS/JS 的关系)
        • [1.4 浏览器执行 JS 简介](#1.4 浏览器执行 JS 简介)
        • [1.5 JS 的组成](#1.5 JS 的组成)
        • [1.6 JS 初体验](#1.6 JS 初体验)
      • [2、 JavaScript注释](#2、 JavaScript注释)
        • [2.1 单行注释](#2.1 单行注释)
        • [2.2 多行注释](#2.2 多行注释)
      • [3. JavaScript 输入输出语句](#3. JavaScript 输入输出语句)
    • 变量
      • [1、 变量概述](#1、 变量概述)
        • [1.1 什么是变量](#1.1 什么是变量)
        • [1.2 变量在内存中的存储](#1.2 变量在内存中的存储)
      • [2、 变量的使用](#2、 变量的使用)
      • 3、变量语法扩展
        • [3.1 更新变量](#3.1 更新变量)
        • [3.2 同时声明多个变量](#3.2 同时声明多个变量)
        • [3. 3声明变量特殊情况](#3. 3声明变量特殊情况)
      • 4、变量命名规范
    • 数据类型
      • 1、数据类型简介
        • [1.1 为什么需要数据类型](#1.1 为什么需要数据类型)
        • [1.2 变量的数据类型](#1.2 变量的数据类型)
        • [1.3 数据类型的分类](#1.3 数据类型的分类)
      • [2、 简单数据类型](#2、 简单数据类型)
        • [2.1 简单数据类型(基本数据类型)](#2.1 简单数据类型(基本数据类型))
        • [2.2 数字型 Number](#2.2 数字型 Number)
        • [2.3 字符串型 String](#2.3 字符串型 String)
        • [2.4 布尔型 Boolean](#2.4 布尔型 Boolean)
        • [2.5 Undefined 和 Null](#2.5 Undefined 和 Null)
      • 3、获取变量数据类型
        • [3.1 获取检测变量的数据类型](#3.1 获取检测变量的数据类型)
        • [3.2 字面量](#3.2 字面量)
      • [4、 数据类型转换](#4、 数据类型转换)
        • [4.1 什么是数据类型转换](#4.1 什么是数据类型转换)
        • [4.2 转换为字符串](#4.2 转换为字符串)
        • [4.3 转换为数字型](#4.3 转换为数字型)
        • [4.4 转换为布尔型](#4.4 转换为布尔型)
      • 5、标识符、关键字、保留字
        • [5.1 标识符](#5.1 标识符)
        • [5.2 关键字](#5.2 关键字)
        • [5.3 保留字](#5.3 保留字)
    • [JavaScript 运算符](#JavaScript 运算符)
      • 1、运算符
      • 2、算数运算符
        • [2.1 算术运算符概述](#2.1 算术运算符概述)
        • [2.2 浮点数的精度问题](#2.2 浮点数的精度问题)
        • [2.3 表达式和返回值](#2.3 表达式和返回值)
      • 3、递增和递减运算符
        • [3.1 递增和递减运算符概述](#3.1 递增和递减运算符概述)
        • [3.2 递增运算符](#3.2 递增运算符)
        • [3.3 前置递增和后置递增小结](#3.3 前置递增和后置递增小结)
      • [4、 比较运算符](#4、 比较运算符)
        • [4.1 比较运算符概述](#4.1 比较运算符概述)
        • [4.2 =小结](#4.2 =小结)
      • 5、逻辑运算符
        • [5.1 逻辑运算符概述](#5.1 逻辑运算符概述)
        • [5.2 逻辑与&&](#5.2 逻辑与&&)
        • [5.3 逻辑或 ||](#5.3 逻辑或 ||)
        • [5.4 逻辑非 !](#5.4 逻辑非 !)
        • [5.5 短路运算(逻辑中断)](#5.5 短路运算(逻辑中断))
      • 6、赋值运算符
      • [7、 运算符优先级](#7、 运算符优先级)
    • [JavaScript 流程控制-分支](#JavaScript 流程控制-分支)
      • 1、流程控制
      • 2、顺序流程控制
      • [3、分支流程控制 if 语句](#3、分支流程控制 if 语句)
        • [3.1 分支结构](#3.1 分支结构)
        • [3.2 if 语句](#3.2 if 语句)
        • [3.3 if else语句(双分支语句)](#3.3 if else语句(双分支语句))
        • [3.4 if else if 语句(多分支语句)](#3.4 if else if 语句(多分支语句))
      • [4、 三元表达式](#4、 三元表达式)
      • [5、 分支流程控制 switch 语句](#5、 分支流程控制 switch 语句)
        • [5.1 语法结构](#5.1 语法结构)
        • [5.2 switch 语句和 if else if 语句的区别](#5.2 switch 语句和 if else if 语句的区别)
    • [JavaScript 流程控制-循环](#JavaScript 流程控制-循环)
      • [1、 循环](#1、 循环)
      • [2、 for 循环](#2、 for 循环)
        • [2.1 语法结构](#2.1 语法结构)
        • [2.2 for 循环重复相同的代码](#2.2 for 循环重复相同的代码)
        • [2.3 for 循环重复不相同的代码](#2.3 for 循环重复不相同的代码)
        • [2.4 for 循环重复某些相同操作](#2.4 for 循环重复某些相同操作)
      • [3、 双重 for 循环](#3、 双重 for 循环)
        • [3.1 双重 for 循环概述](#3.1 双重 for 循环概述)
        • [3.2 双重 for 循环语法](#3.2 双重 for 循环语法)
        • [3.3 打印五行五列星星](#3.3 打印五行五列星星)
      • [4、 while 循环](#4、 while 循环)
      • [5、do while 循环](#5、do while 循环)
      • [6、continue break](#6、continue break)
        • [6.1 continue 关键字](#6.1 continue 关键字)
        • [6.2 break 关键字](#6.2 break 关键字)
    • [JavaScript 数组(Array)](#JavaScript 数组(Array))
    • [JavaScript 函数](#JavaScript 函数)
      • 1、函数的概念
      • [2、 函数的使用](#2、 函数的使用)
        • [2.1 声明函数](#2.1 声明函数)
        • [2.2 调用函数](#2.2 调用函数)
        • [2.3 函数的封装](#2.3 函数的封装)
      • 3、函数的参数
        • [3.1 形参和实参](#3.1 形参和实参)
        • [3.2 函数参数的传递过程](#3.2 函数参数的传递过程)
        • [3.3 函数形参和实参个数不匹配问题](#3.3 函数形参和实参个数不匹配问题)
        • [3.4 小结](#3.4 小结)
      • [4、 函数的返回值](#4、 函数的返回值)
        • [4.1 return 语句](#4.1 return 语句)
        • [4.2 return 终止函数](#4.2 return 终止函数)
        • [4.3 return 的返回值](#4.3 return 的返回值)
        • [4.4 函数没有 return 返回 undefined](#4.4 函数没有 return 返回 undefined)
        • [4.5 break ,continue ,return 的区别](#4.5 break ,continue ,return 的区别)
      • [5、 arguments的使用](#5、 arguments的使用)
      • 6、函数的两种声明方式
    • [JavaScript 作用域](#JavaScript 作用域)
    • [JavaScript 预解析](#JavaScript 预解析)
    • [JavaScript 对象](#JavaScript 对象)
      • [1、 对象](#1、 对象)
        • [1.1 什么是对象?](#1.1 什么是对象?)
        • [1.2 为什么需要对象](#1.2 为什么需要对象)
      • [2、 创建对象的三种方式](#2、 创建对象的三种方式)
        • [2.1 利用字面量创建对象](#2.1 利用字面量创建对象)
        • [2.2 利用new Object创建对象](#2.2 利用new Object创建对象)
        • [2.3 利用构造函数创建对象](#2.3 利用构造函数创建对象)
        • [2.4 构造函数和对象](#2.4 构造函数和对象)
      • [3、 new关键字](#3、 new关键字)
      • 4、遍历对象属性
    • [JavaScript 内置对象](#JavaScript 内置对象)
      • [1、 内置对象](#1、 内置对象)
      • 2、查文档
        • [2.1 MDN](#2.1 MDN)
      • [3、 Math 对象](#3、 Math 对象)
        • [3.1 Math 概述](#3.1 Math 概述)
        • [3.2 随机数方法 random()](#3.2 随机数方法 random())
      • [4、 日期对象](#4、 日期对象)
        • [4.1 Date 概述](#4.1 Date 概述)
        • [4.2 Date()方法的使用](#4.2 Date()方法的使用)
        • [4.3 日期格式化](#4.3 日期格式化)
        • [4.4 获取日期的总的毫秒形式](#4.4 获取日期的总的毫秒形式)
      • [5、 数组对象](#5、 数组对象)
        • [5.1 数组对象的创建](#5.1 数组对象的创建)
        • [5.2 检测是否为数组](#5.2 检测是否为数组)
        • [5.3 添加删除数组元素的方法](#5.3 添加删除数组元素的方法)
        • [5.4 数组排序](#5.4 数组排序)
        • [5.5 数组索引方法](#5.5 数组索引方法)
        • [5.6 数组转换为字符串](#5.6 数组转换为字符串)
        • 5.7其他
      • [6、 字符串对象](#6、 字符串对象)
        • [6.1 基本包装类型](#6.1 基本包装类型)
        • [6.2 字符串的不可变](#6.2 字符串的不可变)
        • [6.3 根据字符返回位置](#6.3 根据字符返回位置)
        • [6.4 根据位置返回字符](#6.4 根据位置返回字符)
        • [6.5 字符串操作方法](#6.5 字符串操作方法)
        • [6.6 replace()方法](#6.6 replace()方法)
        • [6.7 split()方法](#6.7 split()方法)
        • [6.8 大小写](#6.8 大小写)
    • [JavaScript 简单类型与复杂类型](#JavaScript 简单类型与复杂类型)
      • [1、 简单类型与复杂类型](#1、 简单类型与复杂类型)
      • [2、 堆和栈](#2、 堆和栈)
      • 3、简单类型的内存分配
      • [4、 复杂类型的内存分配](#4、 复杂类型的内存分配)
      • [5、 简单类型传参](#5、 简单类型传参)
      • [6、 复杂类型传参](#6、 复杂类型传参)
  • JavaScript高级
    • [**JavaScript** 面向对象](#JavaScript 面向对象)
      • [1、 **面向对象编程介绍**](#1、 面向对象编程介绍)
        • [**1.1** 两大编程思想](#1.1 两大编程思想)
        • [**1.2** 面向过程编程 POP(Process-oriented programming)](#1.2 面向过程编程 POP(Process-oriented programming))
        • [**1.3** **面向对象编程** **OOP** (Object Oriented Programming)](#1.3 面向对象编程 OOP (Object Oriented Programming))
        • [**1.4** 面向过程和面向对象的对比](#1.4 面向过程和面向对象的对比)
      • 2、ES6中的类和对象
        • [**2.1** 对象](#2.1 对象)
        • [2.2类 class](#2.2类 class)
        • [**2.3** 创建类](#2.3 创建类)
        • [**2.4** **类** **constructor** 构造函数](#2.4 constructor 构造函数)
        • [**2.5** 类添加方法](#2.5 类添加方法)
      • [3、 **类的继承**](#3、 类的继承)
        • [**3.1** **继承**](#3.1 继承)
        • [**3.2** **super** **关键字**](#3.2 super 关键字)
    • 构造函数和原型
      • **1、构造函数和原型**
        • [**1.1** **概述**](#1.1 概述)
        • [**1.2** 构造函数](#1.2 构造函数)
        • [**1.3** 构造函数的问题](#1.3 构造函数的问题)
        • [**1.4** **构造函数原型** prototype](#1.4 构造函数原型 prototype)
        • [**1.5** 对象原型\\proto\\](#1.5 对象原型__proto__)
        • [**1.6** **constructor** 构造函数](#1.6 constructor 构造函数)
        • [**1.7** 构造函数、实例、原型对象三者之间的关系](#1.7 构造函数、实例、原型对象三者之间的关系)
        • [**1.8** 原型链](#1.8 原型链)
        • [1.9 **JavaScript** 的成员查找机制(规则)](#1.9 JavaScript 的成员查找机制(规则))
        • [**1.10** 原型对象this指向](#1.10 原型对象this指向)
        • [**1.11** 扩展内置对象](#1.11 扩展内置对象)
      • [**2、** 继承](#2、 继承)
        • [2.1 call()](#2.1 call())
        • [**2.2** 借用构造函数继承父类型属性](#2.2 借用构造函数继承父类型属性)
        • [**2.3** 借用原型对象继承父类型方法](#2.3 借用原型对象继承父类型方法)
      • [**3、** **类的本质**](#3、 类的本质)
      • [**4、ES5** **中的新增方法**](#4、ES5 中的新增方法)
        • [**4.1 ES5** **新增方法概述**](#4.1 ES5 新增方法概述)
        • [**4.2** **数组方法**](#4.2 数组方法)
        • [**4.3** **字符串方法**](#4.3 字符串方法)
        • [**4.4** **对象****方法**](#4.4 对象****方法)
    • **函数进阶**
      • [**1、** **函数的定义和调用**](#1、 函数的定义和调用)
        • [**1.1** **函数的定义方式**](#1.1 函数的定义方式)
        • [**1.2** 函数的调用方式](#1.2 函数的调用方式)
      • [**2、 this**](#2、 this)
        • [**2.1** 函数内 **this** 的指向](#2.1 函数内 this 的指向)
        • [**2.2 call apply bind** **总结**](#2.2 call apply bind 总结)
      • [**3、** **严格模式**](#3、 严格模式)
        • [**3.1** **什么是严格模式**](#3.1 什么是严格模式)
        • [**3.2** **开启**严格模式](#3.2 开启严格模式)
        • [**3.3** **严格模式中的变化**](#3.3 严格模式中的变化)
      • [**4、** **高阶函数**](#4、 高阶函数)
      • [**5、** **闭包**](#5、 闭包)
        • [**5.1** **变量作用域**](#5.1 变量作用域)
        • [**5.2** **什么是闭包**](#5.2 什么是闭包)
        • [**5.3** **闭包的作用**](#5.3 闭包的作用)
      • [**6、** **递归**](#6、 递归)
        • [**6.1** **什么是递归?**](#6.1 什么是递归?)
    • **正则表达式**
      • [**1、** **正则表达式概述**](#1、 正则表达式概述)
        • [**1.1** 什么是正则表达式](#1.1 什么是正则表达式)
        • [**1.2** 正则表达式的特点](#1.2 正则表达式的特点)
      • [**2、** 正则表达式在 **JavaScript** **中的使用**](#2、 正则表达式在 JavaScript 中的使用)
        • [**2.1** **创建正则表达式**](#2.1 创建正则表达式)
        • [**2.2** 测试正则表达式 **test**](#2.2 测试正则表达式 test)
      • 3、正则表达式中的特殊字符
        • [**3.1** 正则表达式的组成](#3.1 正则表达式的组成)
        • [3.2 边界符](#3.2 边界符)
        • [**3.3** **字符类**](#3.3 字符类)
        • [**3.4** **量词符**](#3.4 量词符)
        • [**3.5** **括号总结**](#3.5 括号总结)
        • [**3.6** **预定义类**](#3.6 预定义类)
      • [**4、** **正则表达式中的替换**](#4、 正则表达式中的替换)
        • [**4.1 replace** **替换**](#4.1 replace 替换)
        • [**4.2** **正则表达式**参数](#4.2 正则表达式参数)

Web APIs

DOM

1、 DOM 简介

1.1 什么是 DOM
  • 文档对象模型(Document Object Model,简称 DOM),是 W3C 组织推荐的处理可扩展标记语言(HTML
    或者XML)的标准编程接口。
  • W3C 已经定义了一系列的 DOM 接口,通过这些 DOM 接口可以改变网页的内容、结构和样式。
1.2 DOM 树
  • 文档:一个页面就是一个文档,DOM 中使用 document 表示
  • 元素:页面中的所有标签都是元素,DOM 中使用 element 表示
  • 节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM 中使用 node 表示
  • DOM 把以上内容都看做是对象

2、获取元素

2.1 如何获取页面元素
  • DOM在我们实际开发中主要用来操作元素。
  • 获取页面中的元素可以使用以下几种方式:
    • 根据 ID 获取
    • 根据标签名获取
    • 通过 HTML5 新增的方法获取
    • 特殊元素获取
2.2 根据 ID 获取
  • 使用 getElementById() 方法可以获取带有 ID 的元素对象
js 复制代码
document.getElementById('id');
  • 使用 console.dir() 可以打印我们获取的元素对象,更好的查看对象里面的属性和方法。
2.3 根据标签名获取
  • 使用 getElementsByTagName() 方法可以返回带有指定标签名的对象的集合。
js 复制代码
document.getElementsByTagName('标签名');
  • 注意:
    1. 因为得到的是一个对象的集合,所以我们想要操作里面的元素就需要遍历。
    2. 得到元素对象是动态的
2.4 通过 HTML5 新增的方法获取
js 复制代码
 document.getElementsByClassName('类名');// 根据类名返回元素对象集合
 document.querySelector('选择器'); // 根据指定选择器返回第一个元素对象
 document.querySelectorAll('选择器'); // 根据指定选择器返回
  • 注意:
    querySelector 和 querySelectorAll里面的选择器需要加符号,比如:document.querySelector('#nav');
2.5 获取特殊元素(body,html)
  • 获取body元素
js 复制代码
doucumnet.body // 返回body元素对象
  • 获取html元素
js 复制代码
document.documentElement // 返回html元素对象

3、 事件基础

3.1 事件概述
  • JavaScript 使我们有能力创建动态页面,而事件是可以被 JavaScript 侦测到的行为。
  • 简单理解: 触发--- 响应机制。
  • 网页中的每个元素都可以产生某些可以触发 JavaScript 的事件,例如,我们可以在用户点击某按钮时产生一个
    事件,然后去执行某些操作。
3.2 事件三要素
  1. 事件源 (谁)
  2. 事件类型 (什么事件)
  3. 事件处理程序 (做啥)
3.3 执行事件的步骤
  1. 获取事件源
  2. 注册事件(绑定事件)
  3. 添加事件处理程序(采取函数赋值形式)
3.4 常见的鼠标事件

4、 操作元素

  • JavaScript 的 DOM 操作可以改变网页内容、结构和样式,我们可以利用 DOM 操作元素来改变元素里面的内
    容 、属性等。注意以下都是属性
4.1 改变元素内容
javascript 复制代码
element.innerText
  • 从起始位置到终止位置的内容, 但它去除 html 标签, 同时空格和换行也会去掉
javascript 复制代码
element.innerHTML
  • 起始位置到终止位置的全部内容,包括 html 标签,同时保留空格和换行
4.2 常用元素的属性操作
javascript 复制代码
innerText、innerHTML 改变元素内容
src、href
id、alt、title
4.3 表单元素的属性操作
  • 利用 DOM 可以操作如下表单元素的属性:
javascript 复制代码
type、value、checked、selected、disabled
4.4 样式属性操作
  • 我们可以通过 JS 修改元素的大小、颜色、位置等样式。
javascript 复制代码
element.style 行内样式操作
element.className 类名样式操作
  • 注意:

    1.JS 里面的样式采取驼峰命名法 比如 fontSize、 backgroundColor

    2.JS 修改 style 样式操作,产生的是行内样式,CSS 权重比较高

    3.如果样式修改较多,可以采取操作类名方式更改元素样式。

    4.class因为是个保留字,因此使用className来操作元素类名属性

    5.className 会直接更改元素的类名,会覆盖原先的类名。

4.5 排他思想
  • 如果有同一组元素,我们想要某一个元素实现某种样式, 需要用到循环的排他思想算法:
  1. 所有元素全部清除样式(干掉其他人)
  2. 给当前元素设置样式 (留下我自己)
  3. 注意顺序不能颠倒,首先干掉其他人,再设置自己
4.6 自定义属性的操作
  1. 获取属性值
  • element.属性 获取属性值。

  • element.getAttribute('属性');

  • 区别:

    • element.属性 获取内置属性值(元素本身自带的属性)
    • element.getAttribute('属性'); 主要获得自定义的属性 (标准) 我们程序员自定义的属性
  1. 设置属性值
  • element.属性 = '值' 设置内置属性值。

  • element.setAttribute('属性', '值');

  • 区别:

    • element.属性 设置内置属性值
    • element.setAttribute('属性'); 主要设置自定义的属性 (标准)
  1. 移除属性
  • element.removeAttribute('属性');
4.7 H5自定义属性
  • 自定义属性目的:是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。
  • 自定义属性获取是通过getAttribute('属性') 获取。
  • 但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性。
  1. 设置H5自定义属性
  • H5规定自定义属性data-开头做为属性名并且赋值。

  • 比如

    或者使用 JS 设置
    element.setAttribute('data-index', 2)

  1. 获取H5自定义属性
  • 兼容性获取 element.getAttribute('data-index');

  • H5新增 element.dataset.index 或者 element.dataset['index'] ie 11才开始支持

5、 节点操作

5.1 为什么学节点操作
  • 获取元素通常使用两种方式:
  1. 利用 DOM 提供的方法获取元素
  • document.getElementById()
  • document.getElementsByTagName()
  • document.querySelector 等
  • 逻辑性不强、繁琐
  1. 利用节点层级关系获取元素
  • 利用父子兄节点关系获取元素

  • 逻辑性强, 但是兼容性稍差

  • 这两种方式都可以获取元素节点,我们后面都会使用,但是节点操作更简单

5.2 节点概述
  • 网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM 中,节点使用 node 来表示。

  • HTML DOM 树中的所有节点均可通过 JavaScript 进行访问,所有 HTML 元素(节点)均可被修改,也可以

    创建或删除。

  • 一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个

    基本属性。

  • 元素节点 nodeType 为 1

  • 属性节点 nodeType 为 2

  • 文本节点 nodeType 为 3 (文本节点包含文字、空格、换行等)

  • 我们在实际开发中,节点操作主要操作的是元素节点

5.3 节点层级
  • 利用 DOM 树可以把节点划分为不同的层级关系,常见的是父子兄层级关系。
  1. 父级节点
javascript 复制代码
node.parentNode
  • parentNode 属性可返回某节点的父节点,注意是最近的一个父节点
  • 如果指定的节点没有父节点则返回 null
  1. 子节点
javascript 复制代码
parentNode.childNodes(标准)
  • parentNode.childNodes 返回包含指定节点的子节点的集合,该集合为即时更新的集合。
  • 注意:返回值里面包含了所有的子节点,包括元素节点,文本节点等。
    如果只想要获得里面的元素节点,则需要专门处理。 所以我们一般不提倡使用childNodes
javascript 复制代码
var ul = document. querySelector('ul');
for(var i = 0; i < ul.childNodes.length;i++) {
	if (ul.childNodes[i].nodeType == 1) {
		// ul.childNodes[i] 是元素节点
		console.log(ul.childNodes[i]);
	}
}
javascript 复制代码
parentNode.children(非标准)
  • parentNode.children 是一个只读属性,返回所有的子元素节点。它只返回子元素节点,其余节点不返
    回 (这个是我们重点掌握的)。
  • 虽然children 是一个非标准,但是得到了各个浏览器的支持,因此我们可以放心使用
javascript 复制代码
parentNode.firstChild
  • firstChild 返回第一个子节点,找不到则返回null。同样,也是包含所有的节点
javascript 复制代码
parentNode.lastChild
  • lastChild 返回最后一个子节点,找不到则返回null。同样,也是包含所有的节点。
javascript 复制代码
parentNode.firstElementChild
  • firstElementChild 返回第一个子元素节点,找不到则返回null。
javascript 复制代码
parentNode.lastElementChild
  • lastElementChild 返回最后一个子元素节点,找不到则返回null。

  • 注意:这两个方法有兼容性问题,IE9 以上才支持。

  • 实际开发中,firstChild 和 lastChild 包含其他节点,操作不方便,而 firstElementChild 和

    lastElementChild 又有兼容性问题,那么我们如何获取第一个子元素节点或最后一个子元素节点呢?

  • 解决方案:

    • 如果想要第一个子元素节点,可以使用 parentNode.chilren[0]
    • 如果想要最后一个子元素节点,可以使用 parentNode.chilren[parentNode.chilren.length - 1]
  1. 兄弟节点
javascript 复制代码
node.nextSibling
  • nextSibling 返回当前元素的下一个兄弟元素节点,找不到则返回null。同样,也是包含所有的节点。
javascript 复制代码
node.previousSibling
  • previousSibling 返回当前元素上一个兄弟元素节点,找不到则返回null。同样,也是包含所有的节点。
javascript 复制代码
node.nextElementSibling
  • nextElementSibling 返回当前元素下一个兄弟元素节点,找不到则返回null。
javascript 复制代码
node.previousElementSibling
  • previousElementSibling 返回当前元素上一个兄弟节点,找不到则返回null。

  • 注意:这两个方法有兼容性问题, IE9 以上才支持。

  • 如何解决兼容性问题 ?

javascript 复制代码
function getNextElementSibling(element) {
	var el = element;
	while (el = el.nextSibling) {
		if (el.nodeType === 1) {
			return el;
		}
	}
	return null;
}
5.4 创建节点
javascript 复制代码
document.createElement('tagName')
  • document.createElement() 方法创建由 tagName 指定的 HTML 元素。因为这些元素原先不存在,
    是根据我们的需求动态生成的,所以我们也称为动态创建元素节点。
5.5 添加节点
javascript 复制代码
node.appendChild(child)
  • node.appendChild() 方法将一个节点添加到指定父节点的子节点列表末尾。类似于 CSS 里面的
    after 伪元素。
javascript 复制代码
node.insertBefore(child, 指定元素)
  • node.insertBefore() 方法将一个节点添加到父节点的指定子节点前面。类似于 CSS 里面的 before
    伪元素。
5.6 删除节点
javascript 复制代码
node.removeChild(child)
  • node.removeChild() 方法从 DOM 中删除一个子节点,返回删除的节点。
5.7 复制节点(克隆节点)
javascript 复制代码
node.cloneNode()
  • node.cloneNode() 方法返回调用该方法的节点的一个副本。 也称为克隆节点/拷贝节点

  • 注意:

    1. 如果括号参数为空或者为 false ,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点。
    2. 如果括号参数为 true ,则是深度拷贝,会复制节点本身以及里面所有的子节点。
5.8 三种动态创建元素区别
  • document.write()

  • element.innerHTML

  • document.createElement()

  • 区别

  1. document.write 是直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘
  2. innerHTML 是将内容写入某个 DOM 节点,不会导致页面全部重绘
  3. innerHTML 创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂
  4. createElement() 创建多个元素效率稍低一点点,但是结构更清晰
  5. 总结:不同浏览器下,innerHTML 效率要比 creatElement 高

6、 DOM 重点核心

  1. 对于JavaScript,为了能够使JavaScript操作HTML,JavaScript就有了一套自己的dom编程接口。
  2. 对于HTML,dom使得html形成一棵dom树. 包含 文档、元素、节点
  3. 我们获取过来的DOM元素是一个对象(object),所以称为 文档对象模型
  • 关于dom操作,我们主要针对于元素的操作。主要有创建、增、删、改、查、属性操作、事件操作。
6.1 创建
  1. document.write
  2. innerHTML
  3. createElement
6.2 增
  1. appendChild
  2. insertBefore
6.3 删
  1. removeChild
6.4 改
  • 主要修改dom的元素属性,dom元素的内容、属性, 表单的值等
  1. 修改元素属性: src、href、title等
  2. 修改普通元素内容: innerHTML 、innerText
  3. 修改表单元素: value、type、disabled等
  4. 修改元素样式: style、className
6.5 查
  • 主要获取查询dom的元素
  1. DOM提供的API 方法: getElementById、getElementsByTagName 古老用法 不太推荐
  2. H5提供的新方法: querySelector、querySelectorAll 提倡
  3. 利用节点操作获取元素: 父(parentNode)、子(children)、兄(previousElementSibling、
    nextElementSibling) 提倡
6.6 属性操作
  • 主要针对于自定义属性。
  1. setAttribute:设置dom的属性值
  2. getAttribute:得到dom的属性值
  3. removeAttribute移除属性
6.7 事件操作
  • 给元素注册事件, 采取 事件源.事件类型 = 事件处理程序

事件高级

1、 注册事件(绑定事件)

1.1 注册事件概述
  • 给元素添加事件,称为注册事件或者绑定事件。
  • 注册事件有两种方式:传统方式和方法监听注册方式
  1. 传统注册方式
  • 利用 on 开头的事件 onclick
  • <button οnclick="alert('hi~')">
  • btn.onclick = function() {}
  • 特点: 注册事件的唯一性
  • 同一个元素同一个事件只能设置一个处理函数,最
    后注册的处理函数将会覆盖前面注册的处理函数
  1. 方法监听注册方式
  • w3c 标准 推荐方式
  • addEventListener() 它是一个方法
  • IE9 之前的 IE 不支持此方法,可使用 attachEvent() 代替
  • 特点:同一个元素同一个事件可以注册多个监听器
  • 按注册顺序依次执行
1.2 addEventListener 事件监听方式
javascript 复制代码
eventTarget.addEventListener(type, listener[, useCapture])
  • eventTarget.addEventListener()方法将指定的监听器注册到 eventTarget(目标对象)上,当该对

    象触发指定的事件时,就会执行事件处理函数。

  • 该方法接收三个参数:

    • type:事件类型字符串,比如 click 、mouseover ,注意这里不要带 on
    • listener:事件处理函数,事件发生时,会调用该监听函数
    • useCapture:可选参数,是一个布尔值,默认是 false。学完 DOM 事件流后,我们再进一步学习
1.3 attachEvent 事件监听方式
javascript 复制代码
eventTarget.attachEvent(eventNameWithOn, callback)
  • eventTarget.attachEvent()方法将指定的监听器注册到 eventTarget(目标对象) 上,当该对象触

    发指定的事件时,指定的回调函数就会被执行。

  • 该方法接收两个参数:

    • eventNameWithOn:事件类型字符串,比如 onclick 、onmouseover ,这里要带 on
    • callback: 事件处理函数,当目标触发事件时回调函数被调用
    • 注意:IE8 及早期版本支持
1.4 注册事件兼容性解决方案
javascript 复制代码
function addEventListener(element, eventName, fn) {
	// 判断当前浏览器是否支持 addEventListener 方法
	if (element.addEventListener) {
		element.addEventListener(eventName, fn); // 第三个参数 默认是false
	} else if (element.attachEvent) {
		element.attachEvent('on' + eventName, fn);
	} else {
		// 相当于 element.onclick = fn;
		element['on' + eventName] = fn;
    }
}
  • 兼容性处理的原则: 首先照顾大多数浏览器,再处理特殊浏览器

2、 删除事件(解绑事件)

2.1 删除事件的方式
  1. 传统注册方式
javascript 复制代码
eventTarget.onclick = null;
  1. 方法监听注册方式
javascript 复制代码
eventTarget.removeEventListener(type, listener[, useCapture]);
eventTarget.detachEvent(eventNameWithOn, callback);
2.2 删除事件兼容性解决方案
javascript 复制代码
function removeEventListener(element, eventName, fn) {
	// 判断当前浏览器是否支持 removeEventListener 方法
	if (element.removeEventListener) {
		element.removeEventListener(eventName, fn); // 第三个参数 默认是false
	} else if (element.detachEvent) {
		element.detachEvent('on' + eventName, fn);
	} else {
		element['on' + eventName] = null;
    }
}

3、 DOM 事件流

  • 事件流描述的是从页面中接收事件的顺序。

  • 事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即 DOM 事件流。

  • DOM 事件流分为3个阶段:

    1. 捕获阶段
    2. 当前目标阶段
    3. 冒泡阶段
  • 事件冒泡: IE 最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到到 DOM 最顶层节点的过程。

  • 事件捕获: 网景最早提出,由 DOM 最顶层节点开始,然后逐级向下传播到到最具体的元素接收的过程。

  • 我们向水里面扔一块石头,首先它会有一个下降的过程,这个过程就可以理解为从最顶层向事件发生的最具

    体元素(目标点)的捕获过程;之后会产生泡泡,会在最低点( 最具体元素)之后漂浮到水面上,这个过程相当于事件冒泡。

  • 注意

  1. JS 代码中只能执行捕获或者冒泡其中的一个阶段。
  2. onclick 和 attachEvent 只能得到冒泡阶段。
  3. addEventListener(type, listener[, useCapture])第三个参数如果是 true,表示在事件捕获阶段调用事件处理程序;如果是 false(不写默认就是false),表示在事件冒泡阶段调用事件处理程序。
  4. 实际开发中我们很少使用事件捕获,我们更关注事件冒泡。
  5. 有些事件是没有冒泡的,比如 onblur、onfocus、onmouseenter、onmouseleave
  6. 事件冒泡有时候会带来麻烦,有时候又会帮助很巧妙的做某些事件,我们后面讲解。

4、 事件对象

4.1 什么是事件对象
javascript 复制代码
eventTarget.onclick = function(event) {}
eventTarget.addEventListener('click', function(event) {})
// 这个 event 就是事件对象,我们还喜欢的写成 e 或者 evt
  • 官方解释:event 对象代表事件的状态,比如键盘按键的状态、鼠标的位置、鼠标按钮的状态。

  • 简单理解:事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象

    event,它有很多属性和方法。

  • 比如:

  1. 谁绑定了这个事件。
  2. 鼠标触发事件的话,会得到鼠标的相关信息,如鼠标位置。
  3. 键盘触发事件的话,会得到键盘的相关信息,如按了哪个键。
4.2 事件对象的使用语法
javascript 复制代码
eventTarget.onclick = function(event) {
// 这个 event 就是事件对象,我们还喜欢的写成 e 或者 evt
}
eventTarget.addEventListener('click', function(event) {
// 这个 event 就是事件对象,我们还喜欢的写成 e 或者 evt
})
  • 这个 event 是个形参,系统帮我们设定为事件对象,不需要传递实参过去。
  • 当我们注册事件时, event 对象就会被系统自动创建,并依次传递给事件监听器(事件处理函数)。
4.3 事件对象的兼容性方案
  • 事件对象本身的获取存在兼容问题:
  1. 标准浏览器中是浏览器给方法传递的参数,只需要定义形参 e 就可以获取到。
  2. 在 IE6~8 中,浏览器不会给方法传递参数,如果需要的话,需要到 window.event 中获取查找。
  • 解决:
    e = e || window.event;
4.4 事件对象的常见属性和方法
  • e.target 和 this 的区别:
    • this 是事件绑定的元素, 这个函数的调用者(绑定这个事件的元素)
    • e.target 是事件触发的元素。

5、 阻止事件冒泡

5.1 阻止事件冒泡的两种方式
  • 事件冒泡:开始时由最具体的元素接收,然后逐级向上传播到到 DOM 最顶层节点。
  • 事件冒泡本身的特性,会带来的坏处,也会带来的好处,需要我们灵活掌握。
  1. 阻止事件冒泡
  • 标准写法:利用事件对象里面的 stopPropagation()方法
javascript 复制代码
e.stopPropagation()
  • 非标准写法:IE 6-8 利用事件对象 cancelBubble 属性
javascript 复制代码
e.cancelBubble = true;
5.2 阻止事件冒泡的兼容性解决方案
javascript 复制代码
if(e && e.stopPropagation){
	e.stopPropagation();
}else{
	window.event.cancelBubble = true;
}

6、 事件委托(代理、委派)

html 复制代码
<ul>
	<li>知否知否,应该有弹框在手</li>
	<li>知否知否,应该有弹框在手</li>
	<li>知否知否,应该有弹框在手</li>
	<li>知否知否,应该有弹框在手</li>
	<li>知否知否,应该有弹框在手</li>
</ul>
  • 点击每个 li 都会弹出对话框,以前需要给每个 li 注册事件,是非常辛苦的,而且访问 DOM 的次数越多,这就

    会延长整个页面的交互就绪时间。

  • 以上案例:给 ul 注册点击事件,然后利用事件对象的 target 来找到当前点击的 li,因为点击 li,事件会冒泡到 ul 上,ul 有注册事件,就会触发事件监听器。

  • 事件委托

    事件委托也称为事件代理, 在 jQuery 里面称为事件委派。

  • 事件委托的原理

    不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点。

  • 事件委托的作用

    我们只操作了一次 DOM ,提高了程序的性能。

7、 常用的鼠标事件

7.1 常用的鼠标事件

1.禁止鼠标右键菜单

contextmenu主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单

javascript 复制代码
document.addEventListener('contextmenu', function(e) {
	e.preventDefault();
})

2.禁止鼠标选中(selectstart 开始选中)

javascript 复制代码
document.addEventListener('selectstart', function(e) {
	e.preventDefault();
})
7.2 鼠标事件对象
  • event对象代表事件的状态,跟事件相关的一系列信息的集合。现阶段我们主要是用鼠标事件对象
    MouseEvent 和键盘事件对象 KeyboardEvent。

8、 常用的键盘事件

8.1 常用键盘事件
  • 事件除了使用鼠标触发,还可以使用键盘触发。
  • 注意:
  1. 如果使用addEventListener 不需要加 on
  2. onkeypress 和前面2个的区别是,它不识别功能键,比如左右箭头,shift 等。
  3. 三个事件的执行顺序是: keydown -- keypress --- keyup
8.2 键盘事件对象
  • 注意: onkeydown 和 onkeyup 不区分字母大小写,onkeypress 区分字母大小写。
    在我们实际开发中,我们更多的使用keydown和keyup, 它能识别所有的键(包括功能键)
    Keypress 不识别功能键,但是keyCode属性能区分大小写,返回不同的ASCII值

PC 端网页特效

1、 元素偏移量 offset 系列

1.1 offset 概述
  • offset 翻译过来就是偏移量, 我们使用 offset 系列相关属性可以动态的得到该元素的位置(偏移)、大小等。

  • 获得元素距离带有定位父元素的位置

  • 获得元素自身的大小(宽度高度)

  • 注意: 返回的数值都不带单位

  • offset 系列常用属性:

1.2 offset 与 style 区别
  1. offset
  • offset 可以得到任意样式表中的样式值
  • offset 系列获得的数值是没有单位的
  • offsetWidth 包含padding+border+width
  • offsetWidth 等属性是只读属性,只能获取不能赋值
  • 所以,我们想要获取元素大小位置,用offset更合适
  1. style
  • style 只能得到行内样式表中的样式值
  • style.width 获得的是带有单位的字符串
  • style.width 获得不包含padding和border 的值
  • style.width 是可读写属性,可以获取也可以赋值
  • 所以,我们想要给元素更改值,则需要用style改变

2、元素可视区 client 系列

  • client 翻译过来就是客户端,我们使用 client 系列的相关属性来获取元素可视区的相关信息。通过 client 系列的相关属性可以动态的得到该元素的边框大小、元素大小等。

3、 元素滚动 scroll 系列

3.1 元素 scroll 系列属性
  • scroll 翻译过来就是滚动的,我们使用 scroll 系列的相关属性可以动态的得到该元素的大小、滚动距离等。

3.2 页面被卷去的头部
  • 如果浏览器的高(或宽)度不足以显示整个页面时,会自动出现滚动条。当滚动条向下滚动时,页面上面被隐藏
    掉的高度,我们就称为页面被卷去的头部。滚动条在滚动时会触发 onscroll 事件。
3.3 页面被卷去的头部兼容性解决方案
  • 需要注意的是,页面被卷去的头部,有兼容性问题,因此被卷去的头部通常有如下几种写法:
  1. 声明了 DTD,使用 document.documentElement.scrollTop
  2. 未声明 DTD,使用 document.body.scrollTop
  3. 新方法 window.pageYOffset 和 window.pageXOffset,IE9 开始支持
javascript 复制代码
function getScroll() {
	return {
		left: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft||0,
		top: window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0
	};
}
//使用的时候 getScroll().left

4、三大系列总结

  1. offset系列 经常用于获得元素位置 offsetLeft offsetTop
  2. client 经常用于获取元素大小 clientWidth clientHeight
  3. scroll 经常用于获取滚动距离 scrollTop scrollLeft
  4. 注意页面滚动的距离通过 window.pageXOffset 获得

5、mouseenter 和mouseover的区别

5.1 mouseenter 鼠标事件
  • 当鼠标移动到元素上时就会触发 mouseenter 事件
  • 类似 mouseover,它们两者之间的差别是
  • mouseover 鼠标经过自身盒子会触发,经过子盒子还会触发。 mouseenter 只会经过自身盒子触发
  • 之所以这样,就是因为mouseenter不会冒泡
  • 跟mouseenter搭配 鼠标离开 mouseleave 同样不会冒泡

6、 动画函数封装

6.1 动画实现原理
  • 核心原理:通过定时器 setInterval() 不断移动盒子位置。

  • 实现步骤:

  1. 获得盒子当前位置
  2. 让盒子在当前位置加上1个移动距离
  3. 利用定时器不断重复这个操作
  4. 加一个结束定时器的条件
  5. 注意此元素需要添加定位,才能使用element.style.left
6.2 动画函数简单封装
  • 注意函数需要传递2个参数,动画对象和移动到的距离。
6.3 动画函数给不同元素记录不同定时器
  • 如果多个元素都使用这个动画函数,每次都要var 声明定时器。我们可以给不同的元素使用不同的定时器(自
    己专门用自己的定时器)。
  • 核心原理:利用 JS 是一门动态语言,可以很方便的给当前对象添加属性。
6.4 缓动效果原理
  • 缓动动画就是让元素运动速度有所变化,最常见的是让速度慢慢停下来

  • 思路:

  1. 让盒子每次移动的距离慢慢变小,速度就会慢慢落下来。
  2. 核心算法: (目标值 - 现在的位置 ) / 10 做为每次移动的距离 步长
  3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器
  4. 注意步长值需要取整
6.5 动画函数多个目标值之间移动
  • 可以让动画函数从 800 移动到 500。
  • 当我们点击按钮时候,判断步长是正值还是负值
  1. 如果是正值,则步长 往大了取整
  2. 如果是负值,则步长 向小了取整
6.6 动画函数添加回调函数
  • 回调函数原理:函数可以作为一个参数。将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,
    再执行传进去的这个函数,这个过程就叫做回调。
  • 回调函数写的位置:定时器结束的位置。

7、常见网页特效案例

7.1 节流阀
  • 防止轮播图按钮连续点击造成播放过快。
  • 节流阀目的:当上一个函数动画内容执行完毕,再去执行下一个函数动画,让事件无法连续触发。
  • 核心实现思路:
    • 利用回调函数,添加一个变量来控制,锁住函数和解锁函数。
    • 开始设置一个变量 var flag = true;
    • If(flag) {flag = false; do something} 关闭水龙头
    • 利用回调函数 动画执行完毕, flag = true 打开水龙头

移动端网页特效

1、 触屏事件

1.1 触屏事件概述
  • 移动端浏览器兼容性较好,我们不需要考虑以前 JS 的兼容性问题,可以放心的使用原生 JS 书写效果,但是移动
    端也有自己独特的地方。比如触屏事件 touch(也称触摸事件),Android 和 IOS 都有。
  • touch 对象代表一个触摸点。触摸点可能是一根手指,也可能是一根触摸笔。触屏事件可响应用户手指(或触控
    笔)对屏幕或者触控板操作。
  • 常见的触屏事件如下:
1.2 触摸事件对象(TouchEvent)
  • TouchEvent 是一类描述手指在触摸平面(触摸屏、触摸板等)的状态变化的事件。这类事件用于描述一个或多
    个触点,使开发者可以检测触点的移动,触点的增加和减少,等等
  • touchstart、touchmove、touchend 三个事件都会各自有事件对象。
  • 触摸事件对象重点我们看三个常见对象列表:
  • 因为平时我们都是给元素注册触摸事件,所以重点记住 targetTocuhes
1.3 移动端拖动元素
  1. touchstart、touchmove、touchend 可以实现拖动元素
  2. 但是拖动元素需要当前手指的坐标值 我们可以使用 targetTouches[0] 里面的pageX 和 pageY
  3. 移动端拖动的原理: 手指移动中,计算出手指移动的距离。然后用盒子原来的位置 + 手指移动的距离
  4. 手指移动的距离: 手指滑动中的位置 减去 手指刚开始触摸的位置
  • 拖动元素三步曲:
    (1) 触摸元素 touchstart: 获取手指初始坐标,同时获得盒子原来的位置
    (2) 移动手指 touchmove: 计算手指的滑动距离,并且移动盒子
    (3) 离开手指 touchend:
  • 注意: 手指移动也会触发滚动屏幕所以这里要阻止默认的屏幕滚动 e.preventDefault();

2、 移动端常见特效

2.1 classList 属性
  • classList属性是HTML5新增的一个属性,返回元素的类名。但是ie10以上版本支持。

  • 该属性用于在元素中添加,移除及切换 CSS 类。有以下方法

  • 添加类:

    javascript 复制代码
    element.classList.add('类名');
    focus.classList.remove('current');
  • 移除类:

    javascript 复制代码
    element.classList.remove('类名');
    focus.classList.remove('current');
  • 切换类:

    JavaScript 复制代码
    element.classList.toggle('类名');
    focus.classList.toggle('current');
  • 注意以上方法里面,所有类名都不带点

2.2 click 延时解决方案
  • 移动端 click 事件会有 300ms 的延时,原因是移动端屏幕双击会缩放(double tap to zoom) 页面。

  • 解决方案:

  1. 禁用缩放。 浏览器禁用默认的双击缩放行为并且去掉 300ms 的点击延迟
html 复制代码
<meta name="viewport" content="user-scalable=no">
  1. 利用touch事件自己封装这个事件解决 300ms 延迟。
  • 原理就是:
    • 当我们手指触摸屏幕,记录当前触摸时间
    • 当我们手指离开屏幕, 用离开的时间减去触摸的时间
    • 如果时间小于150ms,并且没有滑动过屏幕, 那么我们就定义为点击
javascript 复制代码
//封装tap,解决click 300ms 延时
function tap (obj, callback) {
	var isMove = false;
	var startTime = 0; // 记录触摸时候的时间变量
	obj.addEventListener('touchstart', function (e) {
		startTime = Date.now(); // 记录触摸时间
	});
	obj.addEventListener('touchmove', function (e) {
		isMove = true; // 看看是否有滑动,有滑动算拖拽,不算点击
	});
	obj.addEventListener('touchend', function (e) {
		if (!isMove && (Date.now() - startTime) < 150) { // 如果手指触摸和离开时间小于150ms 算点击
		callback && callback(); // 执行回调函数
	}
	isMove = false; // 取反 重置
	startTime = 0;
	});
} //调用
tap(div, function(){ /* 执行代码*/ });
  1. 使用插件。 fastclick 插件解决 300ms 延迟。

BOM 浏览器对象模型

1、 BOM 概述

1.1 什么是 BOM
  • BOM(Browser Object Model)即浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是 window。

  • BOM 由一系列相关的对象构成,并且每个对象都提供了很多方法与属性。

  • BOM 缺乏标准,JavaScript 语法的标准化组织是 ECMA,DOM 的标准化组织是 W3C,BOM 最初是Netscape 浏

    览器标准的一部分。

  1. DOM
  • 文档对象模型
  • DOM 就是把「文档」当做一个「对象」来看待
  • DOM 的顶级对象是 document
  • DOM 主要学习的是操作页面元素
  • DOM 是 W3C 标准规范
  1. BOM
  • 浏览器对象模型
  • 把「浏览器」当做一个「对象」来看待
  • BOM 的顶级对象是 window
  • BOM 学习的是浏览器窗口交互的一些对象
  • BOM 是浏览器厂商在各自浏览器上定义的,兼容性较差
1.2 BOM 的构成
  • BOM 比 DOM 更大,它包含 DOM。
  • window 对象是浏览器的顶级对象,它具有双重角色。
  1. 它是 JS 访问浏览器窗口的一个接口。
  2. 它是一个全局对象。定义在全局作用域中的变量、函数都会变成 window 对象的属性和方法。
  3. 在调用的时候可以省略 window,前面学习的对话框都属于 window 对象方法,如 alert()、prompt() 等。
  4. 注意:window下的一个特殊属性 window.name

2、window 对象的常见事件

2.1 窗口加载事件
javascript 复制代码
window.onload = function(){}
或者
window.addEventListener("load",function(){});
  • window.onload 是窗口 (页面)加载事件,当文档内容完全加载完成会触发该事件(包括图像、脚本文件、CSS

    文件等), 就调用的处理函数。

  • 注意:

  1. 有了 window.onload 就可以把 JS 代码写到页面元素的上方,因为 onload 是等页面内容全部加载完毕,
    再去执行处理函数。
  2. window.onload 传统注册事件方式 只能写一次,如果有多个,会以最后一个 window.onload 为准。
  3. 如果使用 addEventListener 则没有限制
javascript 复制代码
document.addEventListener('DOMContentLoaded',function(){})
  • DOMContentLoaded 事件触发时,仅当DOM加载完成,不包括样式表,图片,flash等等。
  • Ie9以上才支持
  • 如果页面的图片很多的话, 从用户访问到onload触发可能需要较长的时间, 交互效果就不能实现,必然影响用
    户的体验,此时用 DOMContentLoaded 事件比较合适。
2.2 调整窗口大小事件
javascript 复制代码
window.onresize = function(){}
window.addEventListener("resize",function(){});
  • window.onresize 是调整窗口大小加载事件, 当触发时就调用的处理函数。

  • 注意:

  1. 只要窗口大小发生像素变化,就会触发这个事件。
  2. 我们经常利用这个事件完成响应式布局。 window.innerWidth 当前屏幕的宽度

3、 定时器

3.1 两种定时器
  • window 对象给我们提供了 2 个非常好用的方法-定时器。
    • setTimeout()
    • setInterval()
3.2 setTimeout() 定时器
javascript 复制代码
window.setTimeout(调用函数, [延迟的毫秒数]);
  • setTimeout() 方法用于设置一个定时器,该定时器在定时器到期后执行调用函数。

  • 注意:

  1. window 可以省略。
  2. 这个调用函数可以直接写函数,或者写函数名或者采取字符串'函数名()'三种形式。第三种不推荐
  3. 延迟的毫秒数省略默认是 0,如果写,必须是毫秒。
  4. 因为定时器可能有很多,所以我们经常给定时器赋值一个标识符。
  • setTimeout() 这个调用函数我们也称为回调函数 callback
  • 普通函数是按照代码顺序直接调用。
    而这个函数,需要等待时间,时间到了才去调用这个函数,因此称为回调函数。
  • 简单理解: 回调,就是回头调用的意思。上一件事干完,再回头再调用这个函数。
  • 以前我们讲的 element.onclick = function(){} 或者 element.addEventListener("click", fn); 里面的 函数也是回调
    函数。
3.3 停止 setTimeout() 定时器
javascript 复制代码
window.clearTimeout(timeoutID)
  • clearTimeout()方法取消了先前通过调用 setTimeout() 建立的定时器。

  • 注意:

  1. window 可以省略。
  2. 里面的参数就是定时器的标识符 。
3.4 setInterval() 定时器
javascript 复制代码
window.setInterval(回调函数, [间隔的毫秒数]);
  • setInterval() 方法重复调用一个函数,每隔这个时间,就去调用一次回调函数。

  • 注意:

  1. window 可以省略。
  2. 这个调用函数可以直接写函数,或者写函数名或者采取字符串 '函数名()' 三种形式。
  3. 间隔的毫秒数省略默认是 0,如果写,必须是毫秒,表示每隔多少毫秒就自动调用这个函数。
  4. 因为定时器可能有很多,所以我们经常给定时器赋值一个标识符。
  5. 第一次执行也是间隔毫秒数之后执行,之后每隔毫秒数就执行一次。
3.5 停止 setInterval() 定时器
javascript 复制代码
window.clearInterval(intervalID);
  • clearInterval()方法取消了先前通过调用 setInterval()建立的定时器。

  • 注意:

  1. window 可以省略。
  2. 里面的参数就是定时器的标识符 。
3.6 this
  • this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,一般情况下this
    的最终指向的是那个调用它的对象
  • 现阶段,我们先了解一下几个this指向
  1. 全局作用域或者普通函数中this指向全局对象window(注意定时器里面的this指向window)
  2. 方法调用中谁调用this指向谁
  3. 构造函数中this指向构造函数的实例

4、 JS 执行机制

4.1 JS 是单线程
  • JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。这是因为 Javascript 这门脚

    本语言诞生的使命所致------JavaScript 是为处理页面中用户的交互,以及操作 DOM 而诞生的。比如我们对

    某个 DOM 元素进行添加和删除操作,不能同时进行。 应该先进行添加,之后再删除。

  • 单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。这样所导致的问题是: 如果

    JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。

4.2 同步和异步
  • 为了解决这个问题,利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创

    建多个线程。于是,JS 中出现了同步和异步。

  • 同步

    前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。比如做饭的同步做

    法:我们要烧水煮饭,等水开了(10分钟之后),再去切菜,炒菜。

  • 异步

    你在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事情。比如做

    饭的异步做法,我们在烧水的同时,利用这10分钟,去切菜,炒菜。

  • 他们的本质区别: 这条流水线上各个流程的执行顺序不同。

  • 同步任务

    同步任务都在主线程上执行,形成一个执行栈。

  • 异步任务

    JS 的异步是通过回调函数实现的。

  • 一般而言,异步任务有以下三种类型:

    1、普通事件,如 click、resize 等

    2、资源加载,如 load、error 等

    3、定时器,包括 setInterval、setTimeout 等

  • 异步任务相关回调函数添加到任务队列中(任务队列也称为消息队列)。

4.4 JS 执行机制
  1. 先执行执行栈中的同步任务。
  2. 异步任务(回调函数)放入任务队列中。
  3. 一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任
    务结束等待状态,进入执行栈,开始执行。

  • 由于主线程不断的重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为事件循环( event loop)。

5、 location 对象

5.1 什么是 location 对象
  • window 对象给我们提供了一个 location 属性用于获取或设置窗体的 URL,并且可以用于解析 URL 。 因为
    这个属性返回的是一个对象,所以我们将这个属性也称为 location 对象。
5.2 URL
  • 统一资源定位符 (Uniform Resource Locator, URL) 是互联网上标准资源的地址。互联网上的每个文件都有

    一个唯一的 URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。

  • URL 的一般语法格式为:

javascript 复制代码
protocol://host[:port]/path/[?query]#fragment
http://www.itcast.cn/index.html?name=andy&age=18#link
5.3 location 对象的属性
  • 重点记住: href 和 search
5.4 location 对象的方法
  • navigator 对象包含有关浏览器的信息,它有很多属性,我们最常用的是 userAgent,该属性可以返回由客

    户机发送服务器的 user-agent 头部的值。

  • 下面前端代码可以判断用户那个终端打开页面,实现跳转

javascript 复制代码
if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|
	Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS
	|Symbian|Windows Phone)/i))) {
	window.location.href = ""; //手机
	} else {
	window.location.href = ""; //电脑
}

7、 history 对象

  • window 对象给我们提供了一个 history 对象,与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中) 访问过的 URL。

本地存储

1、本地存储

  • 随着互联网的快速发展,基于网页的应用越来越普遍,同时也变的越来越复杂,为了满足各种各样的需求,会经

    常性在本地存储大量的数据,HTML5规范提出了相关解决方案。

  • 本地存储特性

    1、数据存储在用户浏览器中

    2、设置、读取方便、甚至页面刷新不丢失数据

    3、容量较大,sessionStorage约5M、localStorage约20M

    4、只能存储字符串,可以将对象JSON.stringify() 编码后存储

2. window.sessionStorage

​ 1、生命周期为关闭浏览器窗口

​ 2、在同一个窗口(页面)下数据可以共享

​ 3、以键值对的形式存储使用

  • 存储数据:
javascript 复制代码
sessionStorage.setItem(key, value)
  • 获取数据:
javascript 复制代码
sessionStorage.getItem(key)
  • 删除数据:
javascript 复制代码
sessionStorage.removeItem(key)
  • 删除所有数据:
javascript 复制代码
sessionStorage.clear()
3. window.localStorage

​ 1、声明周期永久生效,除非手动删除 否则关闭页面也会存在

​ 2、可以多窗口(页面)共享(同一浏览器可以共享)

​ 3、以键值对的形式存储使用

  • 存储数据:
javascript 复制代码
localStorage.setItem(key, value)
  • 获取数据:
javascript 复制代码
localStorage.getItem(key)
  • 删除数据:
javascript 复制代码
localStorage.removeItem(key)
  • 删除所有数据:
javascript 复制代码
localStorage.clear()

JavaScript基础

计算机编程基础

1、 编程语言

1.1 编程
  • 编程:就是让计算机为解决某个问题而使用某种程序设计语言编写程序代码,并最终得到结果的过程。
  • 计算机程序:就是计算机所执行的一系列的指令集合,而程序全部都是用我们所掌握的语言来编写的,所以
    人们要控制计算机一定要通过计算机语言向计算机发出命令。
  • 从事编程的人员,就是程序员。 但是一般程序员都比较幽默,为了形容自己的辛苦工作,也成为"码农",
    或者 "程序猿"/ "程序媛"
  • 注意:上面所定义的计算机指的是任何能够执行代码的设备,可能是智能手机、ATM机、黑莓PI、服务器
    等等。
1.2 计算机语言
  • 计算机语言指用于人与计算机之间通讯的语言,它是人与计算机之间传递信息的媒介。
  • 计算机语言的种类非常的多,总的来说可以分成机器语言,汇编语言和高级语言三大类。
  • 实际上计算机最终所执行的都是 机器语言,它是由"0"和"1"组成的二进制数,二进制是计算机语言的基
    础。
1.3 编程语言
  • 可以通过类似于人类语言的 "语言"来控制计算机,让计算机为我们做事情,这样的语言就叫做编程语言(ProgrammingLanguage)。
  • 编程语言是用来控制计算机的一系列指令,它有固定的格式和词汇(不同编程语言的格式和词汇不一样),必须遵守。
  • 如今通用的编程语言有两种形式:汇编语言和高级语言。
    • 汇编语言和机器语言实质是相同的,都是直接对硬件操作,只不过指令采用了英文缩写的标识符,容易识别和记忆。
    • 高级语言主要是相对于低级语言而言,它并不是特指某一种具体的语言,而是包括了很多编程语言,常用的有C语言、C++、Java、C#、Python、PHP、JavaScript、Go语言、Objective-C、Swift等。
1.4 翻译器
  • 高级语言所编制的程序不能直接被计算机识别,必须经过转换才能被执行,为此,我们需要一个翻译器。
    翻译器可以将我们所编写的源代码转换为机器语言,这也被称为二进制化。 记住1和 0。
  • 翻译器翻译的方式有两种:一个是编译,另外一个是解释。两种方式之间的区别在于翻译的时间点不同
  • 编译器是在代码执行之前进行编译,生成中间代码文件
  • 解释器是在运行时进行及时解释,并立即执行(当编译器以解释方式运行的时候,也称之为解释器)
  • 执行过程
  • 类似于请客吃饭:
    • 编译语言:首先把所有菜做好,才能上 桌吃饭
    • 解释语言:好比吃火锅,边吃边涮,同时进行
1.5 编程语言和标记语言区别
  • 编程语言有很强的逻辑和行为能力。在编程语言里, 你会看到很多 if else 、for 、while等具有逻辑性和行为能力的指令,这是主动的。
  • 标记语言(html)不用于向计算机发出指令,常用于格式化和链接。标记语言的存在是用来被读取的, 他是被动的。

2、计算机基础

2.1 计算机组成
2.2 数据存储
  1. 计算机内部使用二进制 0 和 1来表示数据。
  2. 所有数据,包括文件、图片等最终都是以二进制数据(0 和 1)的形式存放在硬盘中的。
  3. 所有程序,包括操作系统,本质都是各种数据,也以二进制数据的形式存放在硬盘中。平时我们所说的安
    装软件,其实就是把程序文件复制到硬盘中。
  4. 硬盘、内存都是保存的二进制数据。
2.3 数据存储单位
  • bit < byte < kb < GB < TB<...
  • 位(bit): 1bit 可以保存一个 0 或者 1 (最小的存储单位)
  • 字节(Byte):1B = 8b
  • 千字节(KB):1KB = 1024B
  • 兆字节(MB):1MB = 1024KB
  • 吉字节(GB): 1GB = 1024MB
  • 太字节(TB): 1TB = 1024GB
  • ...

初识JavaScript

1、 初识 JavaScript

1.1 JavaScript 是什么
  • JavaScript 是世界上最流行的语言之一,是一种运行在客户端的脚本语言 (Script 是脚本的意思)
  • 脚本语言:不需要编译,运行过程中由 js 解释器( js 引擎)逐行来进行解释并执行
  • 现在也可以基于 Node.js 技术进行服务器端编程
1.2 JavaScript 的作用
  • 表单动态校验(密码强度检测) ( JS 产生最初的目的 )
  • 网页特效
  • 服务端开发(Node.js)
  • 桌面程序(Electron)
  • App(Cordova)
  • 控制硬件-物联网(Ruff)
  • 游戏开发(cocos2d-js)
1.3 HTML/CSS/JS 的关系
  • HTML/CSS 标记语言--描述类语言

    • HTML 决定网页结构和内容( 决定看到什么 ),相当
      于人的身体
    • CSS 决定网页呈现给用户的模样( 决定好不好看 ),
      相当于给人穿衣服、化妆
  • JS 脚本语言--编程类语言

    • 实现业务逻辑和页面控制( 决定功能 ),相当
      于人的各种动作
1.4 浏览器执行 JS 简介
  • 浏览器分成两部分:渲染引擎和 JS 引擎

    • 渲染引擎:用来解析HTML与CSS,俗称内核,比如 chrome 浏览器的 blink ,老版本的 webkit
    • JS 引擎:也称为 JS 解释器。 用来读取网页中的JavaScript代码,对其处理后运行,比如 chrome 浏览器的 V8
  • 浏览器本身并不会执行JS代码,而是通过内置 JavaScript 引擎(解释器) 来执行 JS 代码 。JS 引擎执行代码时逐行解释每一句源码(转换为机器语言),然后由计算机去执行,所以 JavaScript 语言归为脚本语言,会逐行解释执行

1.5 JS 的组成
  1. ECMAScript
  • ECMAScript 是由ECMA 国际( 原欧洲计算机制造商协会)进行标准化的一门编程语言,这种语言在万维网上应用广泛,它往往被称为 JavaScript 或 JScript,但实际上后两者是 ECMAScript 语言的实现和扩展。
  • ECMAScript:ECMAScript 规定了JS的编程语法和基础核心知识,是所有浏览器厂商共同遵守的一套JS语法工业标准。
  • 更多参看MDN: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/JavaScript_technologies_overview
  1. DOM ------文档对象模型
  • 文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标记语言的标准编程接口。通过 DOM 提供的接口可以对页面上的各种元素进行操作(大小、位置、颜色等)。
  1. BOM ------浏览器对象模型
  • BOM (Browser Object Model,简称BOM) 是指浏览器对象模型,它提供了独立于内容的、可以与浏览器窗口进行互动的对象结构。通过BOM可以操作浏览器窗口,比如弹出框、控制浏览器跳转、获取分辨率等。
1.6 JS 初体验
  • JS 有3种书写位置,分别为行内、内嵌和外部。
  1. 行内式 JS
html 复制代码
<input type="button" value="点我试试" onclick="alert('Hello World')" />
  • 可以将单行或少量 JS 代码写在HTML标签的事件属性中(以 on 开头的属性),如:onclick
  • 注意单双引号的使用:在HTML中我们推荐使用双引号, JS 中我们推荐使用单引号
  • 可读性差, 在html中编写JS大量代码时,不方便阅读;
  • 引号易错,引号多层嵌套匹配时,非常容易弄混;
  • 特殊情况下使用
  1. 内嵌 JS
html 复制代码
<script>
	alert('Hello World~!');
</script>
  • 可以将多行JS代码写到
  1. 外部 JS文件
html 复制代码
<script src="my.js"></script>
  • 利于HTML页面代码结构化,把大段 JS代码独立到 HTML 页面之外,既美观,也方便文件级别的复用
  • 引用外部 JS文件的 script 标签中间不可以写代码
  • 适合于JS 代码量比较大的情况

2、 JavaScript注释

2.1 单行注释
  • 为了提高代码的可读性,JS与CSS一样,也提供了注释功能。JS中的注释主要有两种,分别是单行注释和多行注释。
  • 单行注释的注释方式如下
javascript 复制代码
// 我是一行文字,不想被 JS引擎 执行,所以 注释起来
2.2 多行注释
  • 多行注释的注释方式如下:
javascript 复制代码
/*
获取用户年龄和姓名
并通过提示框显示出来
*/

3. JavaScript 输入输出语句

  • 为了方便信息的输入输出,JS中提供了一些输入输出语句,其常用的语句如下:
  • 注意:alert() 主要用来显示消息给用户,console.log() 用来给程序员自己看运行时的消息。

变量

1、 变量概述

1.1 什么是变量
  • 白话:变量就是一个装东西的盒子。
  • 通俗:变量是用于存放数据的容器。 我们通过 变量名 获取数据,甚至数据可以修改。
1.2 变量在内存中的存储
  • 本质:变量是程序在内存中申请的一块用来存放数据的空间。
  • 类似我们酒店的房间,一个房间就可以看做是一个变量。

2、 变量的使用

  • 变量在使用时分为两步: 1. 声明变量 2. 赋值
  1. 声明变量
javascript 复制代码
// 声明变量
var age; // 声明一个 名称为age 的变量
  • var 是一个 JS关键字,用来声明变量( variable 变量的意思 )。使用该关键字声明变量后,计算机会自动为变量分配内存空间,不需要程序员管
  • age 是程序员定义的变量名,我们要通过变量名来访问内存中分配的空间
  1. 赋值
javascript 复制代码
age = 10; // 给 age 这个变量赋值为 10
  • = 用来把右边的值赋给左边的变量空间中 此处代表赋值的意思
  • 变量值是程序员保存到变量空间里的值
  1. 变量的初始化
javascript 复制代码
var age = 18; // 声明变量同时赋值为 18
  • 声明一个变量并赋值, 我们称之为变量的初始化

3、变量语法扩展

3.1 更新变量
  • 一个变量被重新复赋值后,它原有的值就会被覆盖,变量值将以最后一次赋的值为准。
javascript 复制代码
var age = 18;
age = 81; // 最后的结果就是81因为18 被覆盖掉了
3.2 同时声明多个变量
  • 同时声明多个变量时,只需要写一个 var, 多个变量名之间使用英文逗号隔开。
javascript 复制代码
var age = 10, name = 'zs', sex = 2;
3. 3声明变量特殊情况

4、变量命名规范

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

数据类型

1、数据类型简介

1.1 为什么需要数据类型
  • 在计算机中,不同的数据所需占用的存储空间是不同的,为了便于把数据分成所需内存大小不同的数据,充分利
    用存储空间,于是定义了不同的数据类型。
  • 简单来说,数据类型就是数据的类别型号。比如姓名"张三",年龄18,这些数据的类型是不一样的。
1.2 变量的数据类型
  • 变量是用来存储值的所在处,它们有名字和数据类型。变量的数据类型决定了如何将代表这些值的位存储到计算机的内存中。
  • JavaScript 是一种弱类型或者说动态语言。这意味着不用提前声明变量的类型,在程序运行过程中,类型会被自动确定。
javascript 复制代码
var age = 10; // 这是一个数字型
var areYouOk = '是的'; // 这是一个字符串
  • 在代码运行时,变量的数据类型是由 JS引擎 根据 = 右边变量值的数据类型来判断 的,运行完毕之后, 变量就确定了数据类型。
  • JavaScript 拥有动态类型,同时也意味着相同的变量可用作不同的类型:
javascript 复制代码
var x = 6; // x 为数字
var x = "Bill"; // x 为字符串
1.3 数据类型的分类
  • JS 把数据类型分为两类:
    • 简单数据类型 (Number,String,Boolean,Undefined,Null)
    • 复杂数据类型 (object)

2、 简单数据类型

2.1 简单数据类型(基本数据类型)
  • JavaScript 中的简单数据类型及其说明如下:
2.2 数字型 Number
  • JavaScript 数字类型既可以用来保存整数值,也可以保存小数(浮点数)。
javascript 复制代码
var age = 21; // 整数
var Age = 21.3747; // 小数
  1. 数字型进制
    • 最常见的进制有二进制、八进制、十进制、十六进制。
javascript 复制代码
// 1.八进制数字序列范围:0~7
var num1 = 07; // 对应十进制的7
var num2 = 019; // 对应十进制的19
var num3 = 08; // 对应十进制的8
// 2.十六进制数字序列范围:0~9以及A~F
var num = 0xA;
  1. 数字型范围
  • JavaScript中数值的最大和最小值
javascript 复制代码
alert(Number.MAX_VALUE); // 1.7976931348623157e+308
alert(Number.MIN_VALUE); // 5e-324
  • 最大值:Number.MAX_VALUE,这个值为: 1.7976931348623157e+308
  • 最小值:Number.MIN_VALUE,这个值为:5e-32
  1. 数字型三个特殊值
javascript 复制代码
alert(Infinity); // Infinity
alert(-Infinity); // -Infinity
alert(NaN); // NaN
  • Infinity ,代表无穷大,大于任何数值
  • -Infinity ,代表无穷小,小于任何数值
  • NaN ,Not a number,代表一个非数值
  1. isNaN()
  • 用来判断一个变量是否为非数字的类型,返回 true 或者 false
javascript 复制代码
var usrAge = 21;
var isOk = isNaN(userAge);
console.log(isNum); // false ,21 不是一个非数字
var usrName = "andy";
console.log(isNaN(userName)); // true ,"andy"是一个非数字
2.3 字符串型 String
  • 字符串型可以是引号中的任意文本,其语法为 双引号 "" 和 单引号''
javascript 复制代码
var strMsg = "我爱北京天安门~"; // 使用双引号表示字符串
var strMsg2 = '我爱吃猪蹄~'; // 使用单引号表示字符串
// 常见错误
var strMsg3 = 我爱大肘子; // 报错,没使用引号,会被认为是js代码,但js没有这些语法
  • 因为 HTML 标签里面的属性使用的是双引号,JS 这里我们更推荐使用单引号。
  1. 字符串引号嵌套
  • JS 可以用单引号嵌套双引号 ,或者用双引号嵌套单引号 (外双内单,外单内双)
javascript 复制代码
var strMsg = '我是"高帅富"程序猿'; // 可以用''包含""
var strMsg2 = "我是'高帅富'程序猿"; // 也可以用"" 包含''
// 常见错误
var badQuotes = 'What on earth?"; // 报错,不能 单双引号搭配
  1. 字符串转义符
  • 类似HTML里面的特殊字符,字符串中也有特殊字符,我们称之为转义符。
  • 转义符都是 \ 开头的,常用的转义符及其说明如下:
  1. 字符串长度
  • 字符串是由若干字符组成的,这些字符的数量就是字符串的长度。通过字符串的 length 属性可以获取整个字符
    串的长度
javascript 复制代码
var strMsg = "我是帅气多金的程序猿!";
alert(strMsg.length); // 显示 11
  1. 字符串拼接
  • 多个字符串之间可以使用 + 进行拼接,其拼接方式为 字符串 + 任何类型 = 拼接之后的新字符串
  • 拼接前会把与字符串相加的任何类型转成字符串,再拼接成一个新的字符串
javascript 复制代码
//1.1 字符串 "相加"
alert('hello' + ' ' + 'world'); // hello world
//1.2 数值字符串 "相加"
alert('100' + '100'); // 100100
//1.3 数值字符串 + 数值
alert('11' + 12); // 1112
  • +号总结口诀:数值相加 ,字符相连
  1. 字符串拼接加强
javascript 复制代码
console.log('zhangsan' + 18); // 只要有字符就会相连
var age = 18;
// console.log('zhangsanage岁啦'); // 这样不行
console.log('zhangsan' + age); // zhangsan18
console.log('zhangsan' + age + '岁啦'); // zhangsan18岁啦
  • 我们经常会将字符串和变量来拼接,因为变量可以很方便地修改里面的值
  • 变量是不能添加引号的,因为加引号的变量会变成字符串
  • 如果变量两侧都有字符串拼接,口诀"引引加加 ",删掉数字,变量写加中间
2.4 布尔型 Boolean
  • 布尔类型有两个值:true 和 false ,其中 true 表示真(对),而 false 表示假(错)。
  • 布尔型和数字型相加的时候, true 的值为 1 ,false 的值为 0。
javascript 复制代码
console.log(true + 1); // 2
console.log(false + 1); // 1
2.5 Undefined 和 Null
  • 一个声明后没有被赋值的变量会有一个默认值 undefined ( 如果进行相连或者相加时,注意结果)
javascript 复制代码
var variable;
console.log(variable); // undefined
console.log('你好' + variable); // 你好undefined
console.log(11 + variable); // NaN
console.log(true + variable); // NaN
  • 一个声明变量给 null 值,里面存的值为空(学习对象时,我们继续研究null)
javascript 复制代码
var vari = null;
console.log('你好' + vari); // 你好null
console.log(11 + vari); // 11
console.log(true + vari); // 1

3、获取变量数据类型

3.1 获取检测变量的数据类型
  • typeof 可用来获取检测变量的数据类型
javascript 复制代码
var num = 18;
console.log(typeof num) // 结果 number
  • 不同类型的返回值
3.2 字面量
  • 字面量是在源代码中一个固定值的表示法,通俗来说,就是字面量表示如何表达这个值。
    • 数字字面量:8, 9, 10
    • 字符串字面量:"大前端"
    • 布尔字面量:true,false

4、 数据类型转换

4.1 什么是数据类型转换
  • 使用表单、prompt 获取过来的数据默认是字符串类型的,此时就不能直接简单的进行加法运算,而需要转换变
    量的数据类型。通俗来说,就是把一种数据类型的变量转换成另外一种数据类型。
4.2 转换为字符串
  • toString() 和 String() 使用方式不一样。
  • 三种转换方式,我们更喜欢用第三种加号拼接字符串转换方式, 这一种方式也称之为隐式转换。
4.3 转换为数字型
  • 注意 parseInt 和 parseFloat 单词的大小写,这2个是重点
  • 隐式转换是我们在进行算数运算的时候,JS 自动转换了数据类型
4.4 转换为布尔型
  • 代表空、否定的值会被转换为 false ,如 ''、0、NaN、null、undefined
  • 其余值都会被转换为 true
javascript 复制代码
console.log(Boolean('')); // false
console.log(Boolean(0)); // false
console.log(Boolean(NaN)); // false
console.log(Boolean(null)); // false
console.log(Boolean(undefined)); // false
console.log(Boolean('小白')); // true
console.log(Boolean(12)); // true

5、标识符、关键字、保留字

5.1 标识符
  • 标识(zhi)符:就是指开发人员为变量、属性、函数、参数取的名字。
  • 标识符不能是关键字或保留字。
5.2 关键字
  • 关键字:是指 JS本身已经使用了的字,不能再用它们充当变量名、方法名。
  • 包括:break、case、catch、continue、default、delete、do、else、finally、for、function、if、in、
    instanceof、new、return、switch、this、throw、try、typeof、var、void、while、with 等。
5.3 保留字
  • 保留字:实际上就是预留的"关键字",意思是现在虽然还不是关键字,但是未来可能会成为关键字,同样不能
    使用它们当变量名或方法名。
  • 包括:boolean、byte、char、class、const、debugger、double、enum、export、extends、
    fimal、float、goto、implements、import、int、interface、long、mative、package、
    private、protected、public、short、static、super、synchronized、throws、transient、
    volatile 等。
  • 注意:如果将保留字用作变量名或函数名,那么除非将来的浏览器实现了该保留字,否则很可能收不到任何错
    误消息。当浏览器将其实现后,该单词将被看做关键字,如此将出现关键字错误。

JavaScript 运算符

1、运算符

  • 运算符(operator)也被称为操作符,是用于实现赋值、比较和执行算数运算等功能的符号。
  • JavaScript中常用的运算符有:
    • 算数运算符
    • 递增和递减运算符
    • 比较运算符
    • 逻辑运算符
    • 赋值运算符

2、算数运算符

2.1 算术运算符概述
  • 概念:算术运算使用的符号,用于执行两个变量或值的算术运算。
2.2 浮点数的精度问题
  • 浮点数值的最高精度是 17 位小数,但在进行算术计算时其精确度远远不如整数。
JavaScript 复制代码
var result = 0.1 + 0.2; // 结果不是 0.3,而是:0.30000000000000004
console.log(0.07 * 100); // 结果不是 7, 而是:7.000000000000001
  • 所以:不要直接判断两个浮点数是否相等 !
2.3 表达式和返回值
  • 表达式:是由数字、运算符、变量等以能求得数值的有意义排列方法所得的组合

  • 简单理解:是由数字、运算符、变量等组成的式子

  • 表达式最终都会有一个结果,返回给我们,我们成为返回值

3、递增和递减运算符

3.1 递增和递减运算符概述
  • 如果需要反复给数字变量添加或减去1,可以使用递增(++)和递减( -- )运算符来完成。
  • 在 JavaScript 中,递增(++)和递减( -- )既可以放在变量前面,也可以放在变量后面。放在变量前面时,
    我们可以称为前置递增(递减)运算符,放在变量后面时,我们可以称为后置递增(递减)运算符。
  • 注意:递增和递减运算符必须和变量配合使用。
3.2 递增运算符
  1. 前置递增运算符
  • ++num 前置递增,就是自加1,类似于 num = num + 1,但是 ++num 写起来更简单。
  • 使用口诀:先自加,后返回值
javascript 复制代码
var num = 10;
alert(++num + 10); // 21
  1. 后置递增运算符
  • num++ 后置递增,就是自加1,类似于 num = num + 1 ,但是 num++ 写起来更简单。
  • 使用口诀:先返回原值,后自加
javascript 复制代码
var num = 10;
alert(10 + num++); // 20
3.3 前置递增和后置递增小结
  • 前置递增和后置递增运算符可以简化代码的编写,让变量的值 + 1 比以前写法更简单
  • 单独使用时,运行结果相同
  • 与其他代码联用时,执行结果会不同
  • 后置:先原值运算,后自加(先人后己)
  • 前置:先自加,后运算(先已后人)
  • 开发时,大多使用后置递增/减,并且代码独占一行,例如:num++; 或者 num--;

4、 比较运算符

4.1 比较运算符概述
  • 概念:比较运算符(关系运算符)是两个数据进行比较时所使用的运算符,比较运算后,会返回一个布尔值(true / false)作为比较运算的结果。
4.2 =小结
javascript 复制代码
console.log(18 == '18');//true
console.log(18 === '18');//false

5、逻辑运算符

5.1 逻辑运算符概述
  • 概念:逻辑运算符是用来进行布尔值运算的运算符,其返回值也是布尔值。后面开发中经常用于多个条件的判断
5.2 逻辑与&&
  • 两边都是 true才返回 true,否则返回 false
5.3 逻辑或 ||
  • 两边都为 false 才返回 false,否则都为true
5.4 逻辑非 !
  • 逻辑非(!)也叫作取反符,用来取一个布尔值相反的值,如 true 的相反值是 false
javascript 复制代码
var isOk = !true;
console.log(isOk); // false
5.5 短路运算(逻辑中断)
  • 短路运算的原理:当有多个表达式(值)时,左边的表达式值可以确定结果时,就不再继续运算右边的表达式的值;
  1. 逻辑与
  • 语法: 表达式1 && 表达式2
  • 如果第一个表达式的值为真,则返回表达式2
  • 如果第一个表达式的值为假,则返回表达式1
javascript 复制代码
console.log( 123 && 456 ); // 456
console.log( 0 && 456 ); // 0
console.log( 123 && 456&& 789 ); // 789
  1. 逻辑或

    • 语法: 表达式1 || 表达式2
    • 如果第一个表达式的值为真,则返回表达式1
    • 如果第一个表达式的值为假,则返回表达式2
    javascript 复制代码
    console.log( 123 || 456 ); // 123
    console.log( 0 || 456 ); // 456
    console.log( 123 || 456 || 789 ); // 123

6、赋值运算符

  • 概念:用来把数据赋值给变量的运算符。
javascript 复制代码
var age = 10;
age += 5; // 相当于 age = age + 5;
age -= 5; // 相当于 age = age - 5;
age *= 10; // 相当于 age = age * 10;

7、 运算符优先级

  • 一元运算符里面的逻辑非优先级很高
  • 逻辑与比逻辑或优先级高

JavaScript 流程控制-分支

1、流程控制

  • 在一个程序执行的过程中,各条代码的执行顺序对程序的结果是有直接影响的。很多时候我们要通过控制代码
    的执行顺序来实现我们要完成的功能。
  • 简单理解: 流程控制就是来控制我们的代码按照什么结构顺序来执行
  • 流程控制主要有三种结构,分别是顺序结构、分支结构和循环结构,这三种结构代表三种代码执行的顺序。

2、顺序流程控制

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

3、分支流程控制 if 语句

3.1 分支结构
  • 由上到下执行代码的过程中,根据不同的条件,执行不同的路径代码(执行代码多选一的过程),从而得到不同的结果
  • JS 语言提供了两种分支结构语句
    • if 语句
    • switch 语句
3.2 if 语句
  1. 语法结构
javascript 复制代码
// 条件成立执行代码,否则什么也不做
if (条件表达式) {
// 条件成立执行的代码语句
}
  • 语句可以理解为一个行为,循环语句和分支语句就是典型的语句。一个程序由很多个语句组成,一般情况下,会分割成一个一个的语句。
  1. 执行流程
3.3 if else语句(双分支语句)
  1. 语法结构
javascript 复制代码
// 条件成立 执行 if 里面代码,否则执行else 里面的代码
if (条件表达式) {
// [如果] 条件成立执行的代码
} else {
// [否则] 执行的代码
}
  1. 执行流程
3.4 if else if 语句(多分支语句)
  1. 语法结构
javascript 复制代码
// 适合于检查多重条件。
if (条件表达式1) {
语句1;
} else if (条件表达式2) {
语句2;
} else if (条件表达式3) {
语句3;
....
} else {
// 上述条件都不成立执行此处代码
}
  1. 执行流程

4、 三元表达式

  • 三元表达式也能做一些简单的条件选择。 有三元运算符组成的式子称为三元表达式
  1. 语法结构
javascript 复制代码
表达式1 ? 表达式2 : 表达式3;
  1. 执行思路
  • 如果表达式1为 true ,则返回表达式2的值,如果表达式1为 false,则返回表达式3的值
  • 简单理解: 就类似于 if else (双分支) 的简写

5、 分支流程控制 switch 语句

5.1 语法结构
  • switch 语句也是多分支语句,它用于基于不同的条件来执行不同的代码。当要针对变量设置一系列的特定值
    的选项时,就可以使用 switch。
javascript 复制代码
switch( 表达式 ){
 case value1:
	// 表达式 等于 value1 时要执行的代码
	break;
 case value2:
	// 表达式 等于 value2 时要执行的代码
	break;
 default:
	// 表达式 不等于任何一个 value 时要执行的代码
}
  • switch :开关 转换 , case :小例子 选项

  • 关键字 switch 后面括号内可以是表达式或值, 通常是一个变量

  • 关键字 case , 后跟一个选项的表达式或值,后面跟一个冒号

  • switch 表达式的值会与结构中的 case 的值做比较

  • 如果存在匹配全等(===) ,则与该 case 关联的代码块会被执行,并在遇到 break 时停止,整个 switch 语句代码

    执行结束

  • 如果所有的 case 的值都和表达式的值不匹配,则执行 default 里的代码

  • 注意: 执行case 里面的语句时,如果没有break,则继续执行下一个case里面的语句。

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

JavaScript 流程控制-循环

1、 循环

  • 循环目的

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

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

    • for 循环
    • while 循环
    • do...while 循环

2、 for 循环

  • 在程序中,一组被重复执行的语句被称之为循环体,能否继续重复执行,取决于循环的终止条件。由循环体
    及循环的终止条件组成的语句,被称之为循环语句
2.1 语法结构
  • for 循环主要用于把某些代码循环若干次,通常跟计数有关系。其语法结构如下:
javascript 复制代码
for(初始化变量; 条件表达式; 操作表达式 ){
	//循环体
}
  • 初始化变量:通常被用于初始化一个计数器,该表达式可以使用 var 关键字声明新的变量,这个变量帮我们来记录次数。

  • 条件表达式:用于确定每一次循环是否能被执行。如果结果是 true 就继续循环,否则退出循环。

  • 操作表达式:每次循环的最后都要执行的表达式。通常被用于更新或者递增计数器变量。当然,递减变量也是可以的。

  • 执行过程:

  1. 初始化变量,初始化操作在整个 for 循环只会执行一次。
  2. 执行条件表达式,如果为true,则执行循环体语句,否则退出循环,循环结束。
  3. 执行操作表达式,此时第一轮结束。
  4. 第二轮开始,直接去执行条件表达式(不再初始化变量),如果为 true ,则去执行循环体语句,否则退出循环。
  5. 继续执行操作表达式,第二轮结束。
  6. 后续跟第二轮一致,直至条件表达式为假,结束整个 for 循环。
2.2 for 循环重复相同的代码
  • for循环可以重复相同的代码 ,比如我们要输出10句"媳妇我错了"
javascript 复制代码
// 基本写法
for(var i = 1; i <= 10; i++){
	console.log('媳妇我错了~');
}
// 用户输入次数
var num = prompt('请输入次数:');
for ( var i = 1 ; i <= num; i++) {
	console.log('媳妇我错了~');
}
2.3 for 循环重复不相同的代码
  • for 循环还可以重复不同的代码,这主要是因为使用了计数器 ,计数器在每次循环过程中都会有变化。

  • 例如,求输出一个人1到100岁:

javascript 复制代码
// 基本写法
for (var i = 1; i <= 100; i++) {
	console.log('这个人今年' + i + '岁了');
}
// for 里面是可以添加其他语句的
for (var i = 1; i <= 100; i++) {
	if (i == 1) {
		console.log('这个人今年1岁了, 它出生了');
	} else if (i == 100) {
		console.log('这个人今年100岁了,它死了');
	} else {
		console.log('这个人今年' + i + '岁了');
	}
}
2.4 for 循环重复某些相同操作
  • for 循环因为有了计数器的存在,我们还可以重复的执行某些操作,比如做一些算术运算。

3、 双重 for 循环

3.1 双重 for 循环概述
  • 很多情况下,单层 for 循环并不能满足我们的需求,比如我们要打印一个 5 行 5 列的图形、打印一个倒
    直角三角形等,此时就可以通过循环嵌套来实现。
  • 循环嵌套是指在一个循环语句中再定义一个循环语句的语法结构,例如在for循环语句中,可以再嵌套一个
    for 循环,这样的 for 循环语句我们称之为双重for循环。
3.2 双重 for 循环语法
javascript 复制代码
for (外循环的初始; 外循环的条件; 外循环的操作表达式) {
	for (内循环的初始; 内循环的条件; 内循环的操作表达式) {
		需执行的代码;
	}
}
  • 内层循环可以看做外层循环的语句
  • 内层循环执行的顺序也要遵循 for 循环的执行顺序
  • 外层循环执行一次,内层循环要执行全部次数
3.3 打印五行五列星星
  • 核心:
  1. 内层循环负责一行打印五个星星
  2. 外层循环负责打印五行
javascript 复制代码
var star = '';
for (var j = 1; j <= 3; j++) {
	for (var i = 1; i <= 3; i++) {
		star += '☆'
	}
	// 每次满 5个星星 就 加一次换行
	star += '\n'
}
console.log(star);

4、 while 循环

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

  • while语句的语法结构如下:

javascript 复制代码
while (条件表达式) {
	// 循环体代码
}
  • 执行思路:

    • ① 先执行条件表达式,如果结果为 true,则执行循环体代码;如果为 false,则退出循环,执行后面代码
    • ② 执行循环体代码
    • ③ 循环体代码执行完毕后,程序会继续判断执行条件表达式,如条件仍为true,则会继续执行循环体,直到循环条件为 false 时,整个循环过程才会结束
  • 注意:

    • ① 使用 while 循环时一定要注意,它必须要有退出条件,否则会成为死循环
    • ② while 循环和 for 循环的不同之处在于 while 循环可以做较为复杂的条件判断,比如判断用户名和密码

5、do while 循环

  • do... while 语句其实是 while 语句的一个变体。该循环会先执行一次代码块,然后对条件表达式进行判断,如
    果条件为真,就会重复执行循环体,否则退出循环。
  • do... while 语句的语法结构如下:
javascript 复制代码
do {
// 循环体代码 - 条件表达式为 true 时重复执行循环体代码
} while(条件表达式);
  • 执行思路:
    • ① 先执行一次循环体代码
    • ② 再执行条件表达式,如果结果为 true,则继续执行循环体代码,如果为 false,则退出循环,继续执行后面代码
  • 注意:先再执行循环体,再判断,我们会发现 do...while 循环语句至少会执行一次循环体代码

6、continue break

6.1 continue 关键字
  • continue 关键字用于立即跳出本次循环,继续下一次循环(本次循环体中 continue 之后的代码就会少执行
    一次)。
  • 例如,吃5个包子,第3个有虫子,就扔掉第3个,继续吃第4个第5个包子,其代码实现如下:
javascript 复制代码
for (var i = 1; i <= 5; i++) {
	if (i == 3) {
		console.log('这个包子有虫子,扔掉');
		continue; // 跳出本次循环,跳出的是第3次循环
	}
	console.log('我正在吃第' + i + '个包子呢');
}
6.2 break 关键字
  • break 关键字用于立即跳出整个循环(循环结束)。
  • 例如,吃5个包子,吃到第3个发现里面有半个虫子,其余的不吃了,其代码实现如下:
javascript 复制代码
for (var i = 1; i <= 5; i++) {
	if (i == 3) {
		break; // 直接退出整个for 循环,跳到整个for下面的语句
	}
	console.log('我正在吃第' + i + '个包子呢');
}

JavaScript 数组(Array)

1、数组的概念

  • 数组是指一组数据的集合,其中的每个数据被称作元素,在数组中可以存放任意类型的元素。数组是一种将一组数据存储在单个变量名下的优雅方式。
javascript 复制代码
//普通变量一次只能存储一个值
var num = 10;
//数组一次可以存储多个值
var arr = [1,2,3,4,5];

2、创建数组

2.1数组的创建方式
  • JS中创建数组有两种方式:
    • 利用new创建数组
    • 利用数组字面量创建数组
2.2利用new创建数组
javascript 复制代码
var 数组名= new Array() ;
var arr = new Array0 ;l/创建---个新的空数组
2.3利用数组字面量创建数组
javascript 复制代码
//1.使用数组字面量方式创建空的数组
var 数组名 =[];
//2.使用数组字面量方式创建带初始值的数组
var 数组名 =[ 小白',小黑,'大黄,'瑞奇'];
  • 数组的字面量是方括号[]
  • 声明数组并赋值称为数组的初始化
2.4数组元素的类型
  • 数组中可以存放任意类型的数据,例收字符串,数字,布尔值等。
javascript 复制代码
var arrStuS =['小白',12,true,28.9] ;

3、获取数组元素

3.1数组的索引
  • 索引(下标)∶用来访问数组元素的序号(数组下标从0开始)。
  • 数组可以通过索引来访问、设置、修改对应的数组元素,我们可以通过"数组名[索引]"的形式来获取数组中的元素。
  • 这里的访问就是获取得到的意思
javascript 复制代码
//定义数组
var arrStuS =[1,2,3];
//获取数组中的第2个元素
alert (arrStus[1]);

4、遍历数组

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

5、数组中新增元素

  • 可以通过修改length长度以及索引号增加数组元素
5.1通过修改length长度新增数组元素
  • 可以通过修改length长度来实现数组扩容的目的
  • length属性是可读写的
javascript 复制代码
var arr =[ 'red' , 'green' , 'blue','pink' ];
arr.length = 7;
console.log(arr);
console.log(arr[4]);
console.log(arr[5]);
console.log(arr[6]);
  • 其中索引号是4,5,6的空间没有给值,就是声明变量未给值,默认值就是undefined.
5.2通过修改数组索引新增数组元素
  • 可以通过修改数组索引的方式追加数组元素

  • 不能直接给数组名赋值,否则会覆盖掉以前的数据

    javascript 复制代码
    var arr = [ 'red' , 'green' , 'blue', 'pink' ];
    arr[4] = 'hotpink' ;
    console.log (arr);
  • 这种方式也是我们最常用的一种方式。

JavaScript 函数

1、函数的概念

  • 在 JS 里面,可能会定义非常多的相同代码或者功能相似的代码,这些代码可能需要大量重复使用。
  • 虽然 for循环语句也能实现一些简单的重复操作,但是比较具有局限性,此时我们就可以使用 JS 中的函数。
  • 函数:就是封装了一段可被重复调用执行的代码块。通过此代码块可以实现大量代码的重复使用。

2、 函数的使用

  • 函数在使用时分为两步:声明函数和调用函数。
2.1 声明函数
javascript 复制代码
// 声明函数
function 函数名() {
	//函数体代码
}
  • function 是声明函数的关键字,必须小写
  • 由于函数一般是为了实现某个功能才定义的, 所以通常我们将函数名命名为动词,比如 getSum
2.2 调用函数
javascript 复制代码
// 调用函数
函数名(); // 通过调用函数名来执行函数体代码
  • 调用的时候千万不要忘记添加小括号

  • 口诀:函数不调用,自己不执行。

  • 注意:声明函数本身并不会执行代码,只有调用函数时才会执行函数体代码。

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

3、函数的参数

3.1 形参和实参
  • 在声明函数时,可以在函数名称后面的小括号中添加一些参数,这些参数被称为形参,而在调用该函数时,同样也需要传递相应的参数,这些参数被称为实参。
  • 参数的作用 : 在函数内部某些值不能固定,我们可以通过参数在调用函数时传递不同的值进去。
javascript 复制代码
// 带参数的函数声明
function 函数名(形参1, 形参2 , 形参3...) { // 可以定义任意多的参数,用逗号分隔
// 函数体
}
// 带参数的函数调用
函数名(实参1, 实参2, 实参3...);
3.2 函数参数的传递过程
javascript 复制代码
// 声明函数
function getSum(num1, num2) {
console.log(num1 + num2);
}
// 调用函数
getSum(1, 3); // 4
getSum(6, 5); // 11
  1. 调用的时候实参值是传递给形参的
  2. 形参简单理解为:不用声明的变量
  3. 实参和形参的多个参数之间用逗号(,)分隔
3.3 函数形参和实参个数不匹配问题
javascript 复制代码
function sum(num1, num2) {
	console.log(num1 + num2);
}
sum(100, 200); // 形参和实参个数相等,输出正确结果
sum(100, 400, 500, 700); // 实参个数多于形参,只取到形参的个数
sum(200); // 实参个数少于形参,多的形参定义为undefined,结果为NaN
  • 注意:在JavaScript中,形参的默认值是undefined。
3.4 小结
  • 函数可以带参数也可以不带参数
  • 声明函数的时候,函数名括号里面的是形参,形参的默认值为 undefined
  • 调用函数的时候,函数名括号里面的是实参
  • 多个参数中间用逗号分隔
  • 形参的个数可以和实参个数不匹配,但是结果不可预计,我们尽量要匹配

4、 函数的返回值

4.1 return 语句
  • 有的时候,我们会希望函数将值返回给调用者,此时通过使用 return 语句就可以实现。
  • return 语句的语法格式如下:
javascript 复制代码
// 声明函数
function 函数名(){
...
return 需要返回的值;
}
// 调用函数
函数名(); // 此时调用函数就可以得到函数体内return 后面的值
  • 在使用 return 语句时,函数会停止执行,并返回指定的值

  • 如果函数没有 return ,返回的值是 undefined

  • 例如,声明了一个sum()函数,该函数的返回值为666,其代码如下:

javascript 复制代码
// 声明函数
function sum(){
...
return 666;
}
// 调用函数
sum(); // 此时 sum 的值就等于666,因为 return 语句会把自身后面的值返回给调用者
4.2 return 终止函数
  • return 语句之后的代码不被执行。
javascript 复制代码
function add(num1,num2){
	//函数体
	return num1 + num2; // 注意:return 后的代码不执行
	alert('我不会被执行,因为前面有 return');
}
var resNum = add(21,6); // 调用函数,传入两个实参,并通过 resNum 接收函数返回值
alert(resNum); // 27
4.3 return 的返回值
  • return 只能返回一个值。如果用逗号隔开多个值,以最后一个为准。
javascript 复制代码
function add(num1,num2){
//函数体
return num1,num2;
}
var resNum = add(21,6); // 调用函数,传入两个实参,并通过 resNum 接收函数返回值
alert(resNum); // 6
4.4 函数没有 return 返回 undefined
  • 函数都是有返回值的
    • 如果有return 则返回 return 后面的值
    • 如果没有return 则返回 undefined
4.5 break ,continue ,return 的区别
  • break :结束当前的循环体(如 for、while)
  • continue :跳出本次循环,继续执行下次循环(如 for、while)
  • return :不仅可以退出循环,还能够返回 return 语句中的值,同时还可以结束当前的函数体内的代码

5、 arguments的使用

  • 当我们不确定有多少个参数传递的时候,可以用 arguments 来获取。在 JavaScript 中,arguments 实际上

    它是当前函数的一个内置对象。所有函数都内置了一个 arguments 对象,arguments 对象中存储了传递的

    所有实参。

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

    • 具有 length 属性
    • 按索引方式储存数据
    • 不具有数组的 push , pop 等方法
javascript 复制代码
function maxValue() {
	var max = arguments[0];
	for (var i = 0; i < arguments.length; i++) {
		if (max < arguments[i]) {
			max = arguments[i];
		}
	}
	return max;
}
console.log(maxValue(2, 4, 5, 9));
console.log(maxValue(12, 4, 9));

6、函数的两种声明方式

  1. 自定义函数方式(命名函数)
  • 利用函数关键字 function 自定义函数方式。
javascript 复制代码
// 声明定义方式
function fn() {...}
// 调用
fn();
  • 因为有名字,所以也被称为命名函数
  • 调用函数的代码既可以放到声明函数的前面,也可以放在声明函数的后面
  1. 函数表达式方式(匿名函数)
  • 利用函数表达式方式的写法如下:
javascript 复制代码
// 这是函数表达式写法,匿名函数后面跟分号结束
var fn = function(){...};
// 调用的方式,函数调用必须写到函数体下面
fn();
  • 因为函数没有名字,所以也被称为匿名函数
  • 这个fn 里面存储的是一个函数
  • 函数表达式方式原理跟声明变量方式是一致的
  • 函数调用的代码必须写到函数体后面

JavaScript 作用域

1、作用域

1.1作用域概述
  • 通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。作用域的使用提高宁程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。
  • JS没有块级作用域

2、变量的作用域

2.1变量作用域的分类
  • 在JavaScript中,根据作用域的不同,变呈可以分为两种:全局变量、局部变量
2.2全局变量
  • 在全局作用域下声明的变量叫做全局变量(在函数外部定义的变量)。
  • 全局变量在代码的任何位置都可以使用
  • 在全局作用域下var声明的变量是全局变量
  • 特殊情况下,在函数内不使用var声明的变量也是全局变量(不建议使用)
2.3局部变量
  • 在局部作用域下声明的变量叫做局部变量(在函数内部定义的变量)
  • 局部变量只能在该函数内部使用
  • 在函数内部var声明的变量是局部变量
  • 函数的形参实际上就是局部变量
2.4 全局变量和局部变量的区别
  • 全局变量∶在任何一个地方都可以使用,只有在浏览器关闭时才会被销毁,因此比较占内存
  • 局部变呈∶只在函数内部使用,当其所在的代码块被执行时,会被初始化;当代码块运行结束后,就会被销毁,因此更节省内存空间

3、作用域链

  • 只要是代码,就至少有一个作用域
  • 写在函数内部的局部作用域
  • 如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
  • 根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作作用域链

JavaScript 预解析

1、预解析

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

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

  • 变量提升就是把所有的变量声明提升到当前的作用域最前面﹐不提升赋值操作

  • 函数提升就是把所有的函数声明提升到当前作用域的最前面不调用函数

JavaScript 对象

1、 对象

1.1 什么是对象?
  • 现实生活中:万物皆对象,对象是一个具体的事物,看得见摸得着的实物。例如,一本书、一辆汽车、一个人

    可以是"对象",一个数据库、一张网页、一个与远程服务器的连接也可以是"对象"。

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

    函数等。

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

    • 属性:事物的特征,在对象中用属性来表示(常用名词)
    • 方法:事物的行为,在对象中用方法来表示(常用动词)
1.2 为什么需要对象
  • 保存一个值时,可以使用变量,保存多个值(一组值)时,可以使用数组。如果要保存一个人的完整信息呢?
  • 例如,将"张三疯"的个人的信息保存在数组中的方式为:
javascript 复制代码
var arr = ['张三疯', '男', 128,154];
  • JS 中的对象表达结构更清晰,更强大。张三疯的个人信息在对象中的表达结构如下:
javascript 复制代码
张三疯.姓名 = '张三疯';
张三疯.性别 = '男';
张三疯.年龄 = 128;
张三疯.身高 = 154;

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

2、 创建对象的三种方式

  • 在 JavaScript 中,现阶段我们可以采用三种方式创建对象(object):
    • 利用字面量创建对象
    • 利用 new Object 创建对象
    • 利用构造函数创建对象
2.1 利用字面量创建对象
  • 对象字面量:就是花括号 { } 里面包含了表达这个具体事物(对象)的属性和方法。
  • { } 里面采取键值对的形式表示
  • 键:相当于属性名
  • 值:相当于属性值,可以是任意类型的值(数字类型、字符串类型、布尔类型,函数类型等)
javascript 复制代码
var star = {
	name : 'pink',
	age : 18,
	sex : '男',
	sayHi : function(){
		alert('大家好啊~');
	}
};
  • 对象的调用
    • 对象里面的属性调用 : 对象.属性名 ,这个小点 . 就理解为" 的 "
    • 对象里面属性的另一种调用方式 : 对象['属性名'],注意方括号里面的属性必须加引号,我们后面会用
    • 对象里面的方法调用:对象.方法名() ,注意这个方法名字后面一定加括号
javascript 复制代码
console.log(star.name) // 调用名字属性
console.log(star['name']) // 调用名字属性
star.sayHi(); // 调用 sayHi 方法,注意,一定不要忘记带后面的括号
  • 变量、属性、函数、方法总结
    • 变量:单独声明赋值,单独存在
    • 属性:对象里面的变量称为属性,不需要声明,用来描述该对象的特征
    • 函数:单独存在的,通过"函数名()"的方式就可以调用
    • 方法:对象里面的函数称为方法,方法不需要声明,使用"对象.方法名()"的方式就可以调用,方法用来描述该对象的行为和功能。
2.2 利用new Object创建对象
javascript 复制代码
var andy = new Obect();
andy.name = 'pink';
andy.age = 18;
andy.sex = '男';
andy.sayHi = function(){
	alert('大家好啊~');
}
  • Object() :第一个字母大写
  • new Object() :需要 new 关键字
  • 使用的格式:对象.属性 = 值;
2.3 利用构造函数创建对象
  • 构造函数 :是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与 new 运算符一起
    使用。我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面。
  • 在 js 中,使用构造函数要时要注意以下两点:
    • 构造函数用于创建某一类对象,其首字母要大写
    • 构造函数要和 new 一起使用才有意义
javascript 复制代码
function Person(name, age, sex) {
	this.name = name;
	this.age = age;
	this.sex = sex;
	this.sayHi = function() {
		alert('我的名字叫:' + this.name + ',年龄:' + this.age + ',性别:' + this.sex);
	}
}
var bigbai = new Person('大白', 100, '男');
var smallbai = new Person('小白', 21, '男');
console.log(bigbai.name);
console.log(smallbai.name);
  • 注意:
  1. 构造函数约定首字母大写。
  2. 函数内的属性和方法前面需要添加 this ,表示当前对象的属性和方法。
  3. 构造函数中不需要 return 返回结果。
  4. 当我们创建对象的时候,必须用 new 来调用构造函数。
2.4 构造函数和对象
  • 构造函数,如 Stars(),抽象了对象的公共部分,封装到了函数里面,它泛指某一大类(class)
  • 创建对象,如 new Stars(),特指某一个,通过 new 关键字创建对象的过程我们也称为对象实例化

3、 new关键字

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

4、遍历对象属性

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

JavaScript 内置对象

1、 内置对象

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

2、查文档

2.1 MDN
  • 学习一个内置对象的使用,只要学会其常用成员的使用即可,我们可以通过查文档学习,可以通过MDN/W3C
    来查询。
  • Mozilla 开发者网络(MDN)提供了有关开放网络技术(Open Web)的信息,包括 HTML、CSS 和万维网及
    HTML5 应用的 API。
  • MDN: https://developer.mozilla.org/zh-CN/

3、 Math 对象

3.1 Math 概述
  • Math 对象不是构造函数,它具有数学常数和函数的属性和方法。跟数学相关的运算(求绝对值,取整、最大值
    等)可以使用 Math 中的成员。
javascript 复制代码
Math.PI // 圆周率
Math.floor() // 向下取整
Math.ceil() // 向上取整
Math.round() // 四舍五入版 就近取整 注意 -3.5 结果是 -3
Math.abs() // 绝对值
Math.max()/Math.min() // 求最大和最小值
  • 注意:上面的方法必须带括号
3.2 随机数方法 random()
  • random() 方法可以随机返回一个小数,其取值范围是 [0,1),左闭右开 0 <= x < 1

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

javascript 复制代码
function getRandom(min, max) {
	return Math.floor(Math.random() * (max - min + 1)) + min;
}

4、 日期对象

4.1 Date 概述
  • Date 对象和 Math 对象不一样,他是一个构造函数,所以我们需要实例化后才能使用
  • Date 实例用来处理日期和时间
4.2 Date()方法的使用
  1. 获取当前时间必须实例化
javascript 复制代码
var now = new Date();
console.log(now);
  1. Date() 构造函数的参数
  • 如果括号里面有时间,就返回参数里面的时间。例如日期格式字符串为'2019-5-1',可以写成new Date('2019-5-1') 或者 new Date('2019/5/1')
  • 如果Date()不写参数,就返回当前时间
  • 如果Date()里面写参数,就返回括号里面输入的时间
4.3 日期格式化
  • 我们想要 2019-8-8 8:8:8 格式的日期,要怎么办?
  • 需要获取日期指定的部分,所以我们要手动的得到这种格式。
4.4 获取日期的总的毫秒形式
  • Date 对象是基于1970年1月1日(世界标准时间)起的毫秒数

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

javascript 复制代码
// 实例化Date对象
var now = new Date();
// 1. 用于获取对象的原始值
console.log(date.valueOf())
console.log(date.getTime())
// 2. 简单写可以这么做
var now = + new Date();
// 3. HTML5中提供的方法,有兼容性问题
var now = Date.now();
  • d = parseInt(总秒数/ 60/60 /24); // 计算天数
  • h = parseInt(总秒数/ 60/60 %24) // 计算小时
  • m = parseInt(总秒数 /60 %60 ); // 计算分数
  • s = parseInt(总秒数%60); // 计算当前秒数

5、 数组对象

5.1 数组对象的创建
  • 创建数组对象的两种方式
    • 字面量方式
    • new Array()
5.2 检测是否为数组
  • instanceof 运算符,可以判断一个对象是否属于某种类型
  • Array.isArray()用于判断一个对象是否为数组,isArray() 是 HTML5 中提供的方法
javascript 复制代码
var arr = [1, 23];
var obj = {};
console.log(arr instanceof Array); // true
console.log(obj instanceof Array); // false
console.log(Array.isArray(arr)); // true
console.log(Array.isArray(obj)); // false
5.3 添加删除数组元素的方法
  • 有一个包含工资的数组[1500, 1200, 2000, 2100, 1800],要求把数组中工资超过2000的删除,剩余的放到新数组里面
javascript 复制代码
var arr = [1500, 1200, 2000, 2100, 1800];
var newArr = [];
for (var i = 0; i < arr.length; i++) {
	if (arr[i] < 2000) {
		newArr.push(arr[i]);
	}
}
console.log(newArr);
5.4 数组排序

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/cac93ca219874bd99add77360b9eaf3f.png

javascript 复制代码
var arr = [1, 64, 9, 6];
arr.sort(function(a, b) {
	return b - a; // 降序
	// return a - b; // 升序
});
console.log(arr);
5.5 数组索引方法
5.6 数组转换为字符串
5.7其他
  • splice 删除/插入/替换
    • 删除:第二个参数传入删除几个元素(不传的话则在开始后面的元素全部删除)
    • 替换:第二个参数传入删除几个元素,后面传入对应的元素用以替换
    • 插入:第二个参数为零,后面输入需要插入的元素(在开始元素后面插入)

6、 字符串对象

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

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

javascript 复制代码
// 下面代码有什么问题?
var str = 'andy';
console.log(str.length);
  • 按道理基本数据类型是没有属性和方法的,而对象才有属性和方法,但上面代码却可以执行,这是因为 js 会把
    基本数据类型包装为复杂数据类型,其执行过程如下 :
javascript 复制代码
// 1. 生成临时变量,把简单类型包装为复杂数据类型
var temp = new String('andy');
// 2. 赋值给我们声明的字符变量
str = temp;
// 3. 销毁临时变量
temp = null;
6.2 字符串的不可变
  • 指的是里面的值不可变,虽然看上去可以改变内容,但其实是地址变了,内存中新开辟了一个内存空间。
javascript 复制代码
var str = 'abc';
str = 'hello';
// 当重新给 str 赋值的时候,常量'abc'不会被修改,依然在内存中
// 重新给字符串赋值,会重新在内存中开辟空间,这个特点就是字符串的不可变
// 由于字符串的不可变,在大量拼接字符串的时候会有效率问题
var str = '';
for (var i = 0; i < 100000; i++) {
	str += i;
}
console.log(str); // 这个结果需要花费大量时间来显示,因为需要不断的开辟新的空间
6.3 根据字符返回位置
  • 字符串所有的方法,都不会修改字符串本身(字符串是不可变的),操作完成会返回一个新的字符串。
6.4 根据位置返回字符


6.5 字符串操作方法
6.6 replace()方法
  • replace() 方法用于在字符串中用一些字符替换另一些字符。
javascript 复制代码
replace(被替换的字符串, 要替换为的字符串);
6.7 split()方法
  • split()方法用于切分字符串,它可以将字符串切分为数组。在切分完毕之后,返回的是一个新数组。
javascript 复制代码
var str = 'a,b,c,d';
console.log(str.split(',')); // 返回的是一个数组 [a, b, c, d]
6.8 大小写
  • toUpperCase() //转换大写
  • toLowerCase() //转换小写

JavaScript 简单类型与复杂类型

1、 简单类型与复杂类型

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

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

      string ,number,boolean,undefined,null

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

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

2、 堆和栈

  • 堆栈空间分配区别:
    1、栈(操作系统):由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈;
      2、堆(操作系统):存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。
  • 简单数据类型存放到栈里面
  • 复杂数据类型存放到堆里面
  • 注意:JavaScript中没有堆栈的概念,通过堆栈的方式,可以让大家更容易理解代码的一些执行方式,便于将来学习其他语言。

3、简单类型的内存分配

  • 值类型(简单数据类型): string ,number,boolean,undefined,null
  • 值类型变量的数据直接存放在变量(栈空间)中

4、 复杂类型的内存分配

  • 引用类型(复杂数据类型):通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等
  • 引用类型变量(栈空间)里存放的是地址,真正的对象实例存放在堆空间中

5、 简单类型传参

  • 函数的形参也可以看做是一个变量,当我们把一个值类型变量作为参数传给函数的形参时,其实是把变量在栈
    空间里的值复制了一份给形参,那么在方法内部对形参做任何修改,都不会影响到的外部变量。
JavaScript 复制代码
function fn(a) {
	a++;
	console.log(a);
}
var x = 10;
fn(x);
console.log(x);

6、 复杂类型传参

  • 函数的形参也可以看做是一个变量,当我们把引用类型变量传给形参时,其实是把变量在栈空间里保存的堆地
    址复制给了形参,形参和实参其实保存的是同一个堆地址,所以操作的是同一个对象。
javascript 复制代码
function Person(name) {
	this.name = name;
}
function f1(x) { // x = p
	console.log(x.name); // 2. 这个输出刘德华 
	x.name = "张学友";
	console.log(x.name); // 3. 这个输出张学友 
}
var p = new Person("刘德华");
console.log(p.name); // 1. 这个输出刘德华 
f1(p);
console.log(p.name); // 4. 这个输出张学友

JavaScript高级

JavaScript 面向对象

1、 面向对象编程介绍

1.1 两大编程思想
  • 面向过程

  • 面向对象

1.2 面向过程编程 POP(Process-oriented programming)
  • 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候再一个一个的依次调用就可以了。
  • 举个栗子:将大象装进冰箱,面向过程做法。
  • 面向过程,就是按照我们分析好了的步骤,按照步骤解决问题。
1.3 面向对象编程 OOP (Object Oriented Programming)
  • 面向对象是把事务分解成为一个个对象,然后由对象之间分工与合作。

  • 举个栗子:将大象装进冰箱,面向对象做法。

  • 先找出对象,并写出这些对象的功能

  1. 大象对象

    进去

  2. 冰箱对象

    打开

    关闭

  3. 使用大象和冰箱的功能

  • 面向对象是以对象功能来划分问题,而不是步骤。

  • 在面向对象程序开发思想中,每一个对象都是功能中心,具有明确分工。

  • 面向对象编程具有灵活、代码可复用、容易维护和开发的优点,更适合多人合作的大型软件项目。

  • 面向对象的特性:

    封装性

    继承性

    多态性

1.4 面向过程和面向对象的对比
  • 面向过程

    优点:性能比面向对象高,适合跟硬件联系很紧密的东西,例如单片机就采用的面向过程编程。

    缺点:没有面向对象易维护、易复用、易扩展

  • 面向对象

    优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系 统 更加灵活、更加易于维护

    缺点:性能比面向过程低

  • 用面向过程的方法写出来的程序是一份蛋炒饭,而用面向对象写出来的程序是一份盖浇饭。

2、ES6中的类和对象

  • 面向对象

    • 面向对象更贴近我们的实际生活, 可以使用面向对象描述现实世界事物. 但是事物分为具体的事物和抽象的事物
  • 面向对象的思维特点:

    • 抽取(抽象)对象共用的属性和行为组织(封装)成一个类(模板)

    • 对类进行实例化, 获取类的对象

  • 面向对象编程我们考虑的是有哪些对象,按照面向对象的思维特点,不断的创建对象,使用对象,指挥对象做事情.

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

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

  • 对象是由属性和方法组成的:

    • 属性:事物的特征,在对象中用属性来表示(常用名词)
    • 方法:事物的行为,在对象中用方法来表示(常用动词)
2.2类 class
  • 在 ES6 中新增加了类的概念,可以使用 class 关键字声明一个类,之后以这个类来实例化对象。

  • 类抽象了对象的公共部分,它泛指某一大类(class)

  • 对象特指某一个,通过类实例化一个具体的对象

2.3 创建类
javascript 复制代码
class name {
  // class body
}       
  • 创建实例:
javascript 复制代码
var xx = new name();     
  • 注意: 类必须使用 new 实例化对象
2.4 constructor 构造函数
  • constructor() 方法是类的构造函数(默认方法),用于传递参数,返回实例对象,通过 new 命令生成对象实例时,自动调用该方法。如果没有显示定义, 类内部会自动给我们创建一个constructor()
javascript 复制代码
class Person {
  constructor(name,age) {   // constructor 构造方法或者构造函数
      this.name = name;
      this.age = age;
    }
}   
  • 创建实例:
javascript 复制代码
var ldh = new Person('刘德华', 18); 
console.log(ldh.name)    
2.5 类添加方法
javascript 复制代码
class Person {
  constructor(name,age) {   // constructor 构造器或者构造函数
      this.name = name;
      this.age = age;
    }
   say() {
      console.log(this.name + '你好');
   }
}     
  • 创建实例:
javascript 复制代码
var ldh = new Person('刘德华', 18); 
ldh.say()   
  • 注意: 方法之间不能加逗号分隔,同时方法不需要添加 function 关键字。

3、 类的继承

3.1 继承
  • 现实中的继承:子承父业,比如我们都继承了父亲的姓。

  • 程序中的继承:子类可以继承父类的一些属性和方法。

javascript 复制代码
class Father{   // 父类
} 
class  Son extends Father {  // 子类继承父类
}       
  • 实例:
javascript 复制代码
class Father {
      constructor(surname) {
        this.surname= surname;
      }
      say() {
        console.log('你的姓是' + this.surname);

       }
}
class Son extends Father{  // 这样子类就继承了父类的属性和方法

}
var damao= new Son('刘');
damao.say();      
3.2 super 关键字
  • super 关键字用于访问和调用对象父类上的函数。可以调用父类的构造函数,也可以调用父类的普通函数
javascript 复制代码
class Person {   // 父类
      constructor(surname){
         this.surname = surname;
     }
} 
class  Student extends Person {       // 子类继承父类
     constructor(surname,firstname){
          super(surname);             // 调用父类的constructor(surname)
	this.firstname = firstname; // 定义子类独有的属性
     }
}       
javascript 复制代码
class Father {
     say() {
         return '我是爸爸';

     }
}
class Son extends Father { // 这样子类就继承了父类的属性和方法
     say() {
          // super.say()  super 调用父类的方法
          return super.say() + '的儿子';
     }
}
var damao = new Son();
console.log(damao.say());  
  • 注意: 子类在构造函数中使用super, 必须放到 this 前面 (必须先调用父类的构造方法,在使用子类构造方法)
javascript 复制代码
 class Father {
    constructor(surname) {
        this.surname = surname;
     }
    saySurname() {
      console.log('我的姓是' + this.surname);
    }
}
class Son extends Father { // 这样子类就继承了父类的属性和方法
    constructor(surname, fristname) {
         super(surname);   // 调用父类的constructor(surname)
         this.fristname = fristname;
     }
    sayFristname() {
         console.log("我的名字是:" + this.fristname);

    }
}
var damao = new Son('刘', "德华");
damao.saySurname();
damao.sayFristname();      
  • 注意点:

    1.在 ES6 中类没有变量提升,所以必须先定义类,才能通过类实例化对象.

    2.类里面的共有属性和方法一定要加this使用.

    3.类里面的this指向问题.

    4.constructor 里面的this指向实例对象, 方法里面的this 指向这个方法的调用者

构造函数和原型

1、构造函数和原型

1.1 概述
  • 在典型的 OOP 的语言中(如 Java),都存在类的概念,类就是对象的模板,对象就是类的实例,但在 ES6之前, JS 中并没用引入类的概念。

  • ES6, 全称 ECMAScript 6.0 ,2015.06 发版。但是目前浏览器的 JavaScript 是 ES5 版本,大多数高版本的浏览器也支持 ES6,不过只实现了 ES6 的部分特性和功能。

  • 在 ES6之前 ,对象不是基于类创建的,而是用一种称为构建函数的特殊函数来定义对象和它们的特征。

  • 创建对象可以通过以下三种方式:

    1. 对象字面量

    2. new Object()

    3. 自定义构造函数

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

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

    1.构造函数用于创建某一类对象,其首字母要大写

    2.构造函数要和 new 一起使用才有意义

  • new在执行时会做四件事情:

    ①在内存中创建一个新的空对象。

    ②让 this 指向这个新的对象。

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

    ④返回这个新对象(所以构造函数里面不需要 return )。

  • JavaScript 的构造函数中可以添加一些成员,可以在构造函数本身上添加,也可以在构造函数内部的 this 上添加。通过这两种方式添加的成员,就分别称为静态成员和实例成员。

    • 静态成员:在构造函数本上添加的成员称为静态成员,只能由构造函数本身来访问

    • 实例成员:在构造函数内部创建的对象成员称为实例成员,只能由实例化的对象来访问

1.3 构造函数的问题
  • 构造函数方法很好用,但是存在浪费内存的问题。
javascript 复制代码
function Star(uname, age) {
    this.uname = uname;
    this.age = age;
    this.sing = function() {
        console.log('我会唱歌');
    }
}
var ldh = new Star('刘德华', 18);
var zxy = new Star('张学友', 19);
  • 我们希望所有的对象使用同一个函数,这样就比较节省内存,那么我们要怎样做呢?
1.4 构造函数原型 prototype
  • 构造函数通过原型分配的函数是所有对象所共享的

  • JavaScript 规定,每一个构造函数都有一个 prototype 属性,指向另一个对象。注意这个 prototype 就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有。

  • 我们可以把那些不变的方法,直接定义在 prototype 对象上,这样所有对象的实例就可以共享这些方法。

  1. 原型是什么 ?

    一个对象,我们也称为 prototype 为原型对象。

  2. 原型的作用是什么 ?

    共享方法。

1.5 对象原型__proto__
  • 对象都会有一个属性 proto 指向构造函数的 prototype 原型对象,之所以我们对象可以使用构造函数 prototype 原型对象的属性和方法,就是因为对象有 proto 原型的存在。

  • __proto__对象原型和原型对象 prototype 是等价的

  • __proto__对象原型的意义就在于为对象的查找机制提供一个方向,或者说一条路线,但是它是一个非标准属性,因此实际开发中,不可以使用这个属性,它只是内部指向原型对象 prototype

1.6 constructor 构造函数
  • 对象原型(proto)和构造函数(prototype)原型对象里面都有一个属性 constructor 属性 ,constructor 我们称为构造函数,因为它指回构造函数本身。

  • constructor 主要用于记录该对象引用于哪个构造函数,它可以让原型对象重新指向原来的构造函数。

  • 一般情况下,对象的方法都在构造函数的原型对象中设置。如果有多个对象的方法,我们可以给原型对象采取对象形式赋值,但是这样就会覆盖构造函数原型对象原来的内容,这样修改后的原型对象 constructor 就不再指向当前构造函数了。此时,我们可以在修改后的原型对象中,添加一个 constructor 指向原来的构造函数。

1.7 构造函数、实例、原型对象三者之间的关系
1.8 原型链
1.9 JavaScript 的成员查找机制(规则)
  • ①当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性。

  • ②如果没有就查找它的原型(也就是 __proto__指向的 prototype 原型对象)。

  • ③如果还没有就查找原型对象的原型(Object的原型对象)。

  • ④依此类推一直找到 Object 为止(null)。

  • ⑤__proto__对象原型的意义就在于为对象成员查找机制提供一个方向,或者说一条路线。

1.10 原型对象this指向
  • 构造函数中的this 指向我们实例对象.

  • 原型对象里面放的是方法, 这个方法里面的this 指向的是 这个方法的调用者, 也就是这个实例对象.

1.11 扩展内置对象
  • 可以通过原型对象,对原来的内置对象进行扩展自定义的方法。比如给数组增加自定义求偶数和的功能。
  • 注意:数组和字符串内置对象不能给原型对象覆盖操作 Array.prototype = {} ,只能是 Array.prototype.xxx = function(){} 的方式。

2、 继承

  • ES6之前并没有给我们提供 extends 继承。我们可以通过构造函数+原型对象模拟实现继承,被称为组合继承。
2.1 call()
  • 调用这个函数, 并且修改函数运行时的 this 指向
javascript 复制代码
fun.call(thisArg, arg1, arg2, ...) 
  • thisArg :当前调用函数 this 的指向对象

  • arg1,arg2:传递的其他参数

2.2 借用构造函数继承父类型属性
  • 核心原理: 通过 call() 把父类型的 this 指向子类型的 this ,这样就可以实现子类型继承父类型的属性。
javascript 复制代码
    // 父类
    function Person(name, age, sex) {
      this.name = name;
      this.age = age;
      this.sex = sex;
    }
    // 子类
    function Student(name, age, sex, score) {
      Person.call(this, name, age, sex);  // 此时父类的 this 指向子类的 this,同时调用这个函数
      this.score = score;
    }
    var s1 = new Student('zs', 18, '男', 100);
    console.dir(s1); 
2.3 借用原型对象继承父类型方法
  • 一般情况下,对象的方法都在构造函数的原型对象中设置,通过构造函数无法继承父类方法。

  • 核心原理:

    ①将子类所共享的方法提取出来,让子类的 prototype 原型对象 = new 父类()

    ②本质:子类原型对象等于是实例化父类,因为父类实例化之后另外开辟空间,就不会影响原来父类原型对象

    ③将子类的 constructor 从新指向子类的构造函数

3、 类的本质

  1. class本质还是function.

  2. 类的所有方法都定义在类的prototype属性上

  3. 类创建的实例,里面也有_proto_ 指向类的prototype原型对象

  4. 所以ES6的类它的绝大部分功能,ES5都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。

  5. 所以ES6的类其实就是语法糖.

  6. 语法糖:语法糖就是一种便捷写法. 简单理解, 有两种方法可以实现同样的功能, 但是一种写法更加清晰、方便,那么这个方法就是语法糖

4、ES5 中的新增方法

4.1 ES5 新增方法概述
  • ES5 中给我们新增了一些方法,可以很方便的操作数组或者字符串,这些方法主要包括:

    ​ 数组方法

    ​ 字符串方法

    ​ 对象方法

4.2 数组方法
  • 迭代(遍历)方法:forEach()、map()、filter()、some()、every();
javascript 复制代码
array.forEach(function(currentValue, index, arr))
  • currentValue:数组当前项的值
  • index:数组当前项的索引
  • arr:数组对象本身
javascript 复制代码
array.filter(function(currentValue, index, arr))
  • filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素,主要用于筛选数组

  • 注意它直接返回一个新数组

  • currentValue: 数组当前项的值

  • index:数组当前项的索引

  • arr:数组对象本身

javascript 复制代码
array.some(function(currentValue, index, arr))
  • some() 方法用于检测数组中的元素是否满足指定条件. 通俗点 查找数组中是否有满足条件的元素

  • 注意它返回值是布尔值, 如果查找到这个元素, 就返回true , 如果查找不到就返回false.

  • 如果找到第一个满足条件的元素,则终止循环. 不在继续查找.

  • currentValue: 数组当前项的值

  • index:数组当前项的索引

  • arr:数组对象本身

4.3 字符串方法
  • trim() 方法会从一个字符串的两端删除空白字符。
javascript 复制代码
str.trim()
  • trim() 方法并不影响原字符串本身,它返回的是一个新的字符串。
4.4 对象****方法
  • 1.Object.keys() 用于获取对象自身所有的属性
javascript 复制代码
Object.keys(obj)
  • 效果类似 for...in

  • 返回一个由属性名组成的数组

  • 2.Object.defineProperty() 定义新属性或修改原有的属性。

javascript 复制代码
Object.defineProperty(obj, prop, descriptor)
  • Object.defineProperty() 第三个参数 descriptor 说明: 以对象形式 { } 书写

  • value: 设置属性的值 默认为undefined

  • writable: 值是否可以重写。true | false 默认为false

  • enumerable: 目标属性是否可以被枚举。true | false 默认为 false

  • configurable: 目标属性是否可以被删除或是否可以再次修改特性 true | false 默认为false

函数进阶

1、 函数的定义和调用

1.1 函数的定义方式
  1. 函数声明方式 function 关键字 (命名函数)

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

  3. new Function()

javascript 复制代码
var fn = new Function('参数1','参数2'..., '函数体')
  • Function 里面参数都必须是字符串格式

  • 第三种方式执行效率低,也不方便书写,因此较少使用

  • 所有函数都是 Function 的实例(对象)

  • 函数也属于对象

1.2 函数的调用方式
  1. 普通函数

  2. 对象的方法

  3. 构造函数

  4. 绑定事件函数

  5. 定时器函数

  6. 立即执行函数

2、 this

2.1 函数内 this 的指向
  • 这些 this 的指向,是当我们调用函数的时候确定的。 调用方式的不同决定了this 的指向不同

  • 一般指向我们的调用者.

  • JavaScript 为我们专门提供了一些函数方法来帮我们更优雅的处理函数内部 this 的指向问题,常用的有 bind()、call()、apply() 三种方法。

  1. call 方法
  • call() 方法调用一个对象。简单理解为调用函数的方式,但是它可以改变函数的 this 指向。
javascript 复制代码
fun.call(thisArg, arg1, arg2, ...) 
  • thisArg:在 fun 函数运行时指定的 this 值

  • arg1,arg2:传递的其他参数

  • 返回值就是函数的返回值,因为它就是调用函数

  • 因此当我们想改变 this 指向,同时想调用这个函数的时候,可以使用 call,比如继承

  1. apply方法
  • apply() 方法调用一个函数。简单理解为调用函数的方式,但是它可以改变函数的 this 指向。
javascript 复制代码
fun.apply(thisArg, [argsArray])
  • thisArg:在fun函数运行时指定的 this 值

  • argsArray:传递的值,必须包含在数组里面

  • 返回值就是函数的返回值,因为它就是调用函数

  • 因此 apply 主要跟数组有关系,比如使用 Math.max() 求数组的最大值

  1. bind方法
  • bind() 方法不会调用函数。但是能改变函数内部this 指向
javascript 复制代码
fun.bind(thisArg, arg1, arg2, ...) 
  • thisArg:在 fun 函数运行时指定的 this 值

  • arg1,arg2:传递的其他参数

  • 返回由指定的 this 值和初始化参数改造的原函数拷贝

  • 因此当我们只是想改变 this 指向,并且不想调用这个函数的时候,可以使用 bind

2.2 call apply bind 总结
  • 相同点:

    都可以改变函数内部的this指向.

  • 区别点:

    1.call 和 apply 会调用函数, 并且改变函数内部this指向.

    2.call 和 apply 传递的参数不一样, call 传递参数 aru1, aru2...形式 apply 必须数组形式[arg]

    3.bind 不会调用函数, 可以改变函数内部this指向.

  • 主要应用场景:

    1.call 经常做继承.

    2.apply 经常跟数组有关系. 比如借助于数学对象实现数组最大值最小值

    3.bind 不调用函数,但是还想改变this指向. 比如改变定时器内部的this指向.

3、 严格模式

3.1 什么是严格模式
  • JavaScript 除了提供正常模式外,还提供了严格模式(strict mode)。ES5 的严格模式是采用具有限制性 JavaScript 变体的一种方式,即在严格的条件下运行 JS 代码。

  • 严格模式在 IE10 以上版本的浏览器中才会被支持,旧版本浏览器中会被忽略。

  • 严格模式对正常的 JavaScript 语义做了一些更改:

    ​ 1.消除了 Javascript 语法的一些不合理、不严谨之处,减少了一些怪异行为。

    ​ 2.消除代码运行的一些不安全之处,保证代码运行的安全。

    ​ 3.提高编译器效率,增加运行速度。

    ​ 4.禁用了在 ECMAScript 的未来版本中可能会定义的一些语法,为未来新版本的 Javascript 做好铺垫。比如一 些保留字如:class, enum, export, extends, import, super 不能做变量名

3.2 开启严格模式
  • 严格模式可以应用到整个脚本或个别函数中。因此在使用时,我们可以将严格模式分为为脚本开启严格模式和为函数开启严格模式两种情况。
  1. 为脚本开启严格模式
  • 为整个脚本文件开启严格模式,需要在所有语句之前放一个特定语句"use strict";(或'use strict';)。
javascript 复制代码
<script>
  "use strict";
  console.log("这是严格模式。");
</script>
  • 因为"use strict"加了引号,所以老版本的浏览器会把它当作一行普通字符串而忽略。

  • 有的 script 脚本是严格模式,有的 script 脚本是正常模式,这样不利于文件合并,所以可以将整个脚本文件放在一个立即执行的匿名函数之中。这样独立创建一个作用域而不影响其他 script 脚本文件。

javascript 复制代码
<script>
  (function (){
    "use strict";
       var num = 10;
    function fn() {}
   })();
</script>
  1. 为函数开启严格模式
  • 要给某个函数开启严格模式,需要把"use strict"; (或 'use strict'; ) 声明放在函数体所有语句之前。
javascript 复制代码
function fn(){
  "use strict";
  return "这是严格模式。";
}
  • 将 "use strict" 放在函数体的第一行,则整个函数以 "严格模式" 运行。
3.3 严格模式中的变化
  • 严格模式对 Javascript 的语法和行为,都做了一些改变。
  1. 变量规定
  • ①在正常模式中,如果一个变量没有声明就赋值,默认是全局变量。严格模式禁止这种用法,变量都必须先用var 命令声明,然后再使用。

  • ②严禁删除已经声明变量。例如,delete x; 语法是错误的。

  1. 严格模式下 this 指向问题
  • ①以前在全局作用域函数中的 this 指向 window 对象。

  • ②严格模式下全局作用域中函数中的 this 是 undefined。

  • ③以前构造函数时不加 new也可以 调用,当普通函数,this 指向全局对象

  • ④严格模式下,如果 构造函数不加new调用, this 指向的是undefined 如果给他赋值则 会报错

  • ⑤new 实例化的构造函数指向创建的对象实例。

  • ⑥定时器 this 还是指向 window 。

  • ⑦事件、对象还是指向调用者。

  1. 函数变化

4、 高阶函数

  • 高阶函数是对其他函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出。
javascript 复制代码
<script>
function fn(callback){
  callback && callback();
}
fn(function(){alert('hi')}
</script>
html 复制代码
<script>
function fn(){
    return function() {}
}
 fn();
</script>
  • 此时fn 就是一个高阶函数

  • 函数也是一种数据类型,同样可以作为参数,传递给另外一个参数使用。 最典型的就是作为回调函数。

  • 同理函数也可以作为返回值传递回来

5、 闭包

5.1 变量作用域
  • 变量根据作用域的不同分为两种:全局变量和局部变量。
  1. 函数内部可以使用全局变量。

  2. 函数外部不可以使用局部变量。

  3. 当函数执行完毕,本作用域内的局部变量会销毁。

5.2 什么是闭包
  • 闭包(closure)指有权访问另一个函数作用域中变量的函数。 ----- JavaScript 高级程序设计

  • 简单理解就是 ,一个作用域可以访问另外一个函数内部的局部变量。

html 复制代码
<script>
 function fn1(){    // fn1 就是闭包函数
    var num = 10;
    function fn2(){
      console.log(num); // 10
    }
       fn2()
 }
  fn1();
</script>
5.3 闭包的作用
  • 提问:我们怎么能在 fn()函数外面访问 fn( )中的局部变量num呢?
html 复制代码
<script>
 function fn() {    
    var num = 10;    
    return function {      
         console.log(num); // 10             
     }
  }
  var f = fn();
  f()
</script>
  • 闭包作用:延伸变量的作用范围。

6、 递归

6.1 什么是递归?
  • 如果一个函数在内部可以调用其本身,那么这个函数就是递归函数。

  • 简单理解:函数内部自己调用自己, 这个函数就是递归函数

  • 递归函数的作用和循环效果一样

  • 由于递归很容易发生"栈溢出"错误(stack overflow),所以必须要加退出条件 return。

正则表达式

1、 正则表达式概述

1.1 什么是正则表达式
  • 正则表达式( Regular Expression **)**是用于匹配字符串中字符组合的模式。在 JavaScript中,正则表达式也是对象。

  • 正则表通常被用来检索、替换那些符合某个模式(规则)的文本,例如验证表单:用户名表单只能输入英文字母、数字或者下划线, 昵称输入框中可以输入中文(匹配)。此外,正则表达式还常用于过滤掉页面内容中的一些敏感词(替换),或从字符串中获取我们想要的特定部分(提取)等 。

  • 其他语言也会使用正则表达式,本阶段我们主要是利用 JavaScript 正则表达式完成表单验证。

1.2 正则表达式的特点
  1. 灵活性、逻辑性和功能性非常的强。

  2. 可以迅速地用极简单的方式达到字符串的复杂控制。

  3. 对于刚接触的人来说,比较晦涩难懂。比如: ^\w+([-+.]\w+)*@\w+([-.]\w+)*.\w+([-.]\w+)*$

  4. 实际开发,一般都是直接复制写好的正则表达式. 但是要求会使用正则表达式并且根据实际情况修改正则表达式. 比如用户名: /^[a-z0-9_-]{3,16}$/

2、 正则表达式在 JavaScript 中的使用

2.1 创建正则表达式
  • 在 JavaScript 中,可以通过两种方式创建一个正则表达式。
  1. 通过调用RegExp对象的构造函数创建
javascript 复制代码
var 变量名 = new RegExp(/表达式/); 
  1. 通过字面量创建
javascript 复制代码
var 变量名 = /表达式/; 
  • // 注释中间放表达式就是正则字面量
2.2 测试正则表达式 test
  • test() 正则对象方法,用于检测字符串是否符合该规则,该对象会返回 true 或 false,其参数是测试字符串。
javascript 复制代码
regexObj.test(str) 
  1. regexObj 是写的正则表达式

  2. str 我们要测试的文本

  3. 就是检测str文本是否符合我们写的正则表达式规范.

3、正则表达式中的特殊字符

3.1 正则表达式的组成
3.2 边界符
  • 正则表达式中的边界符(位置符)用来提示字符所处的位置,主要有两个字符。
  • 如果 ^ 和 $ 在一起,表示必须是精确匹配。
3.3 字符类
  • 字符类表示有一系列字符可供选择,只要匹配其中一个就可以了。所有可供选择的字符都放在方括号内。

1.\ [ ] 方括号

javascript 复制代码
   /[abc]/.test('andy')     // true 
  • 后面的字符串只要包含 abc 中任意一个字符,都返回 true 。
  1. [-] 方括号内部 范围符-
javascript 复制代码
   /^[a-z]$/.test('c')     // true
  • 方括号内部加上 - 表示范围,这里表示 a 到 z 26个英文字母都可以。
  1. [^] 方括号内部 取反符^
javascript 复制代码
   /[^abc]/.test('andy')     // false
  • 方括号内部加上 ^ 表示取反,只要包含方括号内的字符,都返回 false 。

  • 注意和边界符 ^ 区别,边界符写到方括号外面。

  1. 字符组合
javascript 复制代码
   /[a-z1-9]/.test('andy')     // true
  • 方括号内部可以使用字符组合,这里表示包含 a 到 z 的26个英文字母和 1 到 9 的数字都可以。
3.4 量词符
  • 量词符用来设定某个模式出现的次数。
3.5 括号总结
  1. 大括号 量词符. 里面表示重复次数

  2. 中括号 字符集合。匹配方括号中的任意字符.

  3. 小括号 表示优先级

3.6 预定义类
  • 预定义类指的是某些常见模式的简写方式。

4、 正则表达式中的替换

4.1 replace 替换
  • replace() 方法可以实现替换字符串操作,用来替换的参数可以是一个字符串或是一个正则表达式。
javascript 复制代码
   stringObject.replace(regexp/substr,replacement)
  1. 第一个参数: 被替换的字符串 或者 正则表达式

  2. 第二个参数: 替换为的字符串

  3. 返回值是一个替换完毕的新字符串

4.2 正则表达式参数
javascript 复制代码
   /表达式/[switch]
  • switch(也称为修饰符) 按照什么样的模式来匹配. 有三种值:

    g:全局匹配

    i:忽略大小写

    gi:全局匹配 + 忽略大小写

相关推荐
烟雨国度1 小时前
双向数据绑定原理图
前端·javascript·vue.js
GISer_Jing1 小时前
React速成
前端·javascript·react.js
李元中1 小时前
2024下半年软考中级软件设计师,这100题,必做!
java·开发语言·javascript·人工智能·算法·ecmascript
敏编程3 小时前
网页前端开发之Javascript入门篇(9/9):对象
开发语言·javascript
太阳花ˉ4 小时前
html+css+js实现Collapse 折叠面板
javascript·css·html
曹天骄4 小时前
React 组件命名规范
前端·javascript
陆仟4 小时前
正则表达式【JavaScript】
javascript·正则表达式
谢尔登5 小时前
【React】类组件和函数组件
javascript·react.js·ecmascript
Jiaberrr5 小时前
微信小程序实战教程:如何使用map组件实现地图功能
前端·javascript·微信小程序·小程序·map