JS 简介

JavaScript 简称 JS,可运行于浏览器 或 node 环境。

JS 的特点

  • 单线程——同一时间只能执行一个任务,多个任务时会排队,后续任务必须等到前一个任务结束才能开始执行。
  • 为什么JavaScript不能有多个线程?
    因为作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,会带来很复杂的同步问题。所以,为了避免复杂性,JavaScript只能是单线程,将来也不会改变。(为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质。)
  • 遵循ECMAScript标准
  • ECMAScript是一种由Ecma国际(前身为欧洲计算机制造商协会,英文名称是European Computer Manufacturers Association)制定和发布的脚本语言规范。
  • 解释型语言:不需要事先被翻译为机器码(编译成计算机能够执行的指令),而是边翻译边执行(翻译一行,执行一行)
  • 开发方便、运行较慢
  • 以事件驱动为核心 —— JavaScript 与 HTML 之间的交互是通过事件实现
  • 弱类型 —— 对使用的数据类型没有严格的要求,可以将一个变量初始化为任意类型,也可以随时改变这个变量的类型。
  • 跨平台 —— JavaScript 可以在任意系统上运行,只需要系统上的浏览器支持 JavaScript 即可。

运行流程

  1. 语法分析
  2. 预编译
    此阶段会完成变量和函数的声明(只是完成变量的声明,不会执行变量的赋值),所以即便函数调用在函数声明之前,也能正常执行。
b();//b可以运行

// 定义式函数——预编译时进行预处理
function b() { console.log('b') }
a();//a未定义报错;

// 变量赋值式函数——预编译时不进行预处理,待调用时才进行处理
let a = function () { console.log('a') }
  1. 解释执行
  • 函数覆盖
fn();
function fn() {
    console.log(1);
}
function fn() {
    console.log(2);
}
// 控制台打印:“2”
  • 变量提升
console.log(a);//存在a变量,但a为undefined;
console.log(b);//存在b变量,但b为undefined;
var a = 1;
var b = function () { };

浏览器对每个scrip

运行机制【重要】

  • 异步机制、同步任务、异步任务、宏任务、微任务、Event Loop 等
  • event loop(事件循环/事件轮询)
  • 代码的执行顺序

注释

单行注释 ctrl+/

// 单行注释

多行注释 ( 输入 /** 快捷触发)

/**
 * 函数 validateString
 * @param 参数 str
 * @returns 返回值 true/false
 */

HTML中引入 JS

无论是哪种方式引入的 js ,同一个html文件中的 js 共享同一个作用域,不同 js 定义的变量是共用的。

  • 内嵌 js
    通常建议写在 body 标签的尾部,也有例外,如下例:
<body>
    <script>
      if (/Mobile|iP(hone|od|ad)|Android|BlackBerry|IEMobile/.test(navigator.userAgent)) {
        // 若浏览器移动设备上的浏览器代码
        // location.href = '移动端代码的首页地址'
      }
    </script>
    <div id="app"></div>
  </body>
  • 外链 js
<body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>

若是 url 地址的 js 文件,用 // 开头,以便自动加载当前协议(避免 https网站引用http路径的 js 失效)

异步加载外链 js
允许浏览器异步下载并执行JS文件,适用于不依赖于文档其他部分的脚本。

<script src="example.js" async></script>

延迟加载外链 js
允许浏览器异步下载JS文件,但要等HTML文档完全解析完毕才开始执行。

<script src="example.js" defer></script>

动态加载外链 js

// 动态加载js文件
function load_script(url) {
  let script = document.createElement("script");
  script.type = "text/javascript";
  script.src = url;
  document.getElementsByTagName("head")[0].appendChild(script);
}

专业术语

  • 标识符
    所有可以由我们自主命名的都可以称之为标识符。 例如:变量名、函数名、属性名都属于标识符。 标识符的命名规则和变量的命令规则是一样的。 不能使用脚本语言中保留的关键字及保留字。

JS 基础

数据类型

对象【重要】

数组【重要】

数据类型转换

JS 的内置对象

除了与数据类型对应的 Number 数值对象,String 字符串对象,Boolean 布尔对象 和 Object 外,还有:

Map

ES6 新增语法

Set

ES6 新增语法

时间日期 Date

数学运算 Math

正则表达式 RegExp

Error

当程序中出现错误时,就会抛出一个Error 对象。

// 创建一个错误对象
let e = new Error("变量名不符合规范");

// Error 对象的 name 属性 --- 报错的名称
console.log(e.name); // Error

// Error 对象的 message 属性 --- 报错的详情
console.log(e.message); // 变量名不符合规范

派生出的其他报错对象有:

  • EvalError 执行错误
  • RangeError 范围错误
  • ReferenceError 引用错误
  • SyntaxError 语法错误
  • TypeError 类型错误
  • URIError URL错误

抛出错误 throw

  • 一般性的错误
throw new Error('Division by zero!');
  • 指定明确的错误类型
throw new RangeError('Division by zero!')
  • 抛出一个一般对象
throw {
  name: "MyError",
  message: "OMG! Something terrible has happened"
}

使用自定义的错误名解决浏览器之间由于抛出错误不相同所导致的问题。

JSON

JSON是 JavaScript 对象标记法(JavaScriptObjectNotation)的简称,是一个轻量级的数据交换格式,不是构造器(无法 new)

let obj = { a: 1 };
// JSON.stringify 用于将对象转为JSON 格式的字符串
let obj_str = JSON.stringify(obj); // 得到字符串 '{"a":1}'

// JSON.parse 用于将JSON 格式的字符串转为对象
let obj2 = JSON.parse(obj_str); // 得到对象 { a: 1 }
// 此时 obj2 是对 obj 的一次深拷贝(此种方式仅适用于简易对象的深拷贝)

console

声明常量和变量 const let var

运算符

【实战】精确计算

解决 js 四则运算精度缺失问题

表达式

由运算符构成,会计算出一个值的语法结构。

// 【字面量】直接表示数据的值的一种语法,如 1, true,null,{} 等。

// 字面量表达式
1; // 结果为 1

let num = 1;

// 正则表达式
/\d/;

// 变量表达式
num; // 结果为 1

// 关键字表达式
this; // 在浏览器中,结果为 Window 对象

// 算术表达式
1 + 1; // 结果为 2

// 关系表达式
1 === 1; // 结果为 true
2 > 1; // 结果为 true

// 逻辑表达式
2 || 0; // 结果为 2
0 && 3; // 结果为 0

// 三元表达式
2 > 1 ? "正确" : "错误"; // 结果为 '正确'

// 函数定义表达式 ——  结果为 函数 sum
function sum(a, b) {
  return a + b;
}

// 函数调用表达式
sum(1, 1); // 结果为 2

let obj = {
  name: "朝阳",
};

let list = [1, 2, 3];

// 属性访问表达式
obj.name; // 结果为 "朝阳"
list[0]; // 结果为 1

// 对象创建表达式
new Object(); // 结果为 一个空对象

// 等等(能计算得到一个值的短语都是!)

语句

声明语句,赋值语句,条件判断语句,循环语句,中断语句 break,继续语句 continue,返回语句 return 等

作用域

函数 function

类 class

模块 module

含 ES6 模块规范 vs CommonJS 模块规范

文档对象模型 DOM

浏览器对象模型 BOM

【实战】获取并解析 url 中参数

本地存储【重要】

Cookie、sessionStorage、localStorage 的区别和用法,详见

错误处理 try catch

try {
  // 可能存在报错的代码
} catch (e){  // 此处的 e 即错误对象 Error
  console.log(e) // 可以是修复错误的代码,或打印错误内容
} finally {
  alert('Finally!'); // 无论是否报错,都会执行finally中的代码
}

JS 进阶

异步【重要】

  • js 【详解】异步-CSDN博客
  • js【详解】Promise-CSDN博客
  • js【详解】async await-CSDN博客

闭包【重要】

设计模式

JS 原理

原型 vs 原型链

浅拷贝 VS 深拷贝

  • 深拷贝的缺陷,5种手写深拷贝
  • 声明变量和变量赋值的原理(含浅拷贝详解)

JS 实战

等待接口访问成功后执行指定代码

文件相关的处理

CSS 样式相关的处理

手机号脱敏

// 手机号码脱敏处理:方法1
var phone="13812345678";
var str=phone.substring(0,3)+"****"+phone.substring(7);
// 手机号码脱敏处理:方法2
var phone="13812345678";
var str=phone.substr(0,3)+"****"+phone.substring(7);
// 区别是:
// substring第一个参数是开始下标,第二个是结束下标
// substr第一个参数是开始下标,第二个是截取几位
// 手机号码脱敏处理:方法3
var phone="13812345678"
var pho=/(\d{3})\d*(\d{4})/
var str=phone.replace(pho,'$1****$2');
console.log(str)

代码调试 vs 优化

debugger 语句

开发者工具

打开浏览器,鼠标右键,选择审核元素,在打开的开发者工具中,切换到控制台页签。(快捷键 Ctrl+Shift+i )

  • Control 控制台页签 —— 可即时执行 JS 代码,查询当前页面的信息(Shift + Enter 可实现换行)
  • Element 元素页签 —— 查看并检查当前页面的DOM以及样式。
  • Network 网络页签 —— 各类网络请求相关的调试,例如实时监控某个资源在网络上的下载情况。
  • Sources 源代码/来源页签【最重要】—— 对JavaScript代码进行调试
  • 点击行号,添加断点
  • 刷新页面,代码会在断点处停止运行
  • 通过调试面板控制代码单步执行
  • Call Stack 中查看调用栈
  • Scope 中查看变量值

统计代码执行的时间

参数的值相同时,就会计时

console.time('obj find')
// 执行的代码
console.timeEnd('obj find')