js(JavaScript) 介绍
介绍
- Javascript 是一个单线程的语言,通过
EventLoop(事件循环)
感知和调度任务- 函数调度通过宿主(网页中指的是浏览器,Node中指的是Node引擎)提供实现,并在操作完成时将结果(异步的,会有延迟)放入Javascript引擎的task队列,由 Javascript 引擎处理
- EventLoop 本质是 Javascript 引擎中的一个循环,它是一个不停地从
任务队列(task queue)
中取出任务执行的过程 microtask queue(微任务队列)
ES6 标准中称为 Job Queue
,是 Promise 的回调函数是存放的队列microtask
的优先级是比 task
高的,会优先执行
- Javascript 运行时会生成一个新的调用结构压入 CallStack
调用栈(Call Stack)
也被称为 执行栈(Execution Stack)
- LIFO
执行上下文(Execution Context)
是执行 Javascript 代码的环境,执行上下文有两种类型:全局执行上下文(Global Execution Context)
程序开始时创建,有且只有一个- Javascript 引擎在执行代码时会创建一个
全局对象(global object)
- 在浏览器中全局对象为 window 对象
- 在 Node 环境中为 global 对象
- 在函数外层定义的
变量
都会保存在 全局对象
中 - 在函数内,未使用
var
,let
或 const
修饰的变量定义也会存储在 全局对象
中var
定义的变量初始值为 undefined
let
定义的变量初始值为 UnInitialized
,它定义的变量在定义之前引用会抛出异常
局部执行上下文(Local Execution Context)
调用函数时创建- 又称为
函数执行上下文(Function Execution Context)
- 执行上下文的创建分为两个阶段:参考
创建阶段(Creation Phase)
,动作包括- 绑定
this
到全局对象 - 创建一个
全局环境对象(Global Environment)
执行阶段(Execution Phase)
# 全局执行上下文
GlobalExecutionContext = {
Phase: Creation, // 创建阶段
this: GlobalObject,
GlobalEnvironment: {
name: undefined,
email: undefined,
greeting: fn,
}
}
# 局部执行上下文
Greeting ExecutionContext = {
Phase: Creation, // 创建阶段
this: GlobalObject,
LocalEnvironment: {
// 没有变量或函数定义
outer: <GlobalEnvironment>
},
}
- 闭包:指函数中能访问在函数外层定义的变量
- 在函数调用中,
arguments
对象中包含传入的所有参数、参数的长度以及其他一些信息
function f(a, b, c) {
console.log(arguments);
}
f(1, 2); // Arguments(2) [1, 2, callee: ƒ, Symbol(Symbol.iterator): ƒ]
- this 绑定
- 上述调试工具
javascript-visualizer
模块
- 模块是为了软件封装,复用
- 模块的规范主要有3种
- CommonJS 模块
- CommonJS 是通用的 Javascript 语言规范,Node 中的模块遵循 CommonJS 规范
require
方法用来加载模块
var fs = require('fs');
fs.readFile('file1.txt', 'utf8', function (err, data) {
if (err) {
console.error(err);
} else {
console.log(data);
}
});
# 加载自定义模块,默认后缀为 .js,可省略
var myModule = require('./myModule');
myModule.func1();
# 导出模块
function addTwoNumber(a, b) {
return a + b;
}
// 方式一
exports.addTwoNumber = addTwoNumber;
// 方式二
module.exports.addTwoNumber = addTwoNumber;
// 方式三
module.exports = {
addTwoNumber: addTwoNumber
};
- AMD 模块
- ES6 模块
- ES6 在标准层面为 Javascript 引入了一套简单的模块系统
- ES6 模块完全可以取代 CommonJS 和 AMD 规范
- React 和 Vue 等遵守 ES6 规范
- 静态加载:指
编译
时就已经确定模块导出,高效率,便于做静态代码分析- 静态加载限制了只能在文件中所有语句之前加载模块,并且导入语法中不能含有动态的语法结构
- 使用
export
导出接口,import from
导入需要使用的接口
// myMath.js
export var pi = 3.14;
export function addTwoNumber(a, b) {
return a + b;
}
// 或
var pi = 3.14;
function addTwoNumber(a, b) {
return a + b;
}
export { pi, addTwoNumber };
// main.js
import { addTwoNumber } from './myMath';
console.log(addTwoNumber(10, 20));
// myModule.js
var funcA = function () {
}
var funcB = function () {
}
export {
funcA as func1,
funcB as func2,
funcB as myFunc,
}
// main.js
import { func1, func2, myFunc } from './myModule';
// main.js
import { func1 as func } from './myModule';
- default导出方式可以看做是导出了一个别名为default的接口
# default导出
// myModule.js
export default function () {
console.log('hi');
}
// or
var f = function () {
console.log('hi');
}
export { f as default };
// main.js 导入时,没有 {}
import func from './myModule';
func();
- default 和普通 export 同时存在的场景
function foo() {
console.log('foo');
}
export default foo;
function bar() {
console.log('bar');
}
export { bar };
// main.js
import foo, { bar } from './myModule';
// myModule.js
export function funcA() {
console.log('funcA');
}
export function funcB() {
console.log('funcB');
}
// main.js
import * as m from './myModule';
m.funcA();
m.funcB();
语法
- 普通函数:
function(){}
- 箭头函数:
() => {}
UMD
UMD(Universal Module Definition)
是一种 javascript 通用模块定义规范,让模块能在 javascript 所有运行环境中发挥作用
Promise
- Promise 是一门新的ES6规范,是 JS 中进行异步编程的新解决方案
- 旧方案使用单纯的回调函数,会陷入
回调地狱(callback hell)
- Promise 是一个构造函数,Promise 对象用来封装一个异步操作并可以获取其成功/失败的结果值
Promise
对象一共有3中状态pending
任务仍在进行中,初始时状态resolved(fullfilled)
任务已完成,状态由 pending
转换为 resolved
reject
任务出错,状态由 pending
转换为 rejected
- 函数原型
let p = new Promise(executor(resolve, reject));
# then() 方法指定成功或失败的回调处理
p.then(succ_handler, fail_handler)
# catch() 方法用来捕获错误,等同于 then(null, handler)
p.catch(handler)
ES6 还提供了两个简单易用的创建 Promise 对象的方式
Promise.resolve
Promise.reject
Promise.all
等待多个异步操作完成后再进行一些处理
Promise.race
接受一个可迭代对象作为参数,返回一个新的 Promise 对象,只要参数中有一个 Promise 对象状态发生变化,新对象的状态就会变化
示例
debug
// 启动计时器
console.time('testForEach');
// (写一些测试用代码)
// 停止计时,输出时间
console.timeEnd('testForEach');
console.time
执行后开始计时,console.timeEnd
执行后停止计时,并输出脚本执行的时间
在 js 中输入 debugger
,F12 会进入 debugger 模式