关键字:JS执行原理,this,call、apply、bind,AMD和CommonJS,原型和原型链,new,闭包、作用域链,异步(Promise),ES6新特性
一、JS执行原理
(一)JS任务分类
- 同步任务:主线程任务,按照顺序由上至下依次执行,形成一个执行栈;
- 异步任务:不进入主线程,进入任务队列,执行完毕后会产生回调函数通知主线程,主线程任务执行完后,会调取最早通知自己的回调函数。
- 异步任务又分宏任务(事件、网络请求、定时器、读取文件等)和微任务(Promise.then()、async/await)
(二) 事件循环(Event Loop)
- 进入到script标签就进入第一次事件循环;
- 遇到同步代码,立即执行;
- 遇到宏任务和微任务,放入宏任务队列和微任务队列;
- 执行完所有同步代码
- 执行微任务队列中的任务
- 微任务代码执行完毕,本次队列清空
- 寻找下一个宏任务重复步骤1。如此反复直到清空所有宏任务,就叫事件循环。
一、this
this是执行上下文中的一个属性,它指向最后一次调用这个方法的对象。
- (1)全局上下文 非严格模式下this指向window,严格模式下this的值为undefined。 函数调用模式
- (2)普通函数调用 当函数不是对象的属性,作为函数直接调用时,this指向全局对象
- (3)方法调用 函数作为一个对象的属性方法来调用时,this指向这个对象。
- (4)call、apply、bind调用模式 三个方法可以显示的指定调用函数的this指向。apply接收两个参数:一个是this的绑定对象,一个时参数数组;call方法接受第一个参数时this的绑定对象,后面的都是传入函数执行的参数;bind传入一个对象,返回一个this绑定了传入对象的新函数。
二、箭头函数
- 箭头函数不会创建自己的this,会继承所处外层执行环境的this;
- apply、call、bind无法改变箭头函数种this的指向;
- 箭头函数不能作为构造函数使用;
- 箭头函数没有自己的arguments(类数组对象,存储实际传给函数的参数)
- 箭头函数没有原型prototype
三、call、apply、bind
call、apply和bind的核心理念就是借用方法,借助已实现的方法,改变this指向(改变执行上下文),减少重复代码,节约内存。常用于借用已有方法,以及对象继承。call和apply都返回fun的执行结果,bind返回fun的拷贝并指定了this
fun.call(thisArg, param1, param2, ...)// 第2~n个参数都是传给fun
fun.apply(thisArg, [param1,param2,...])//第二个参数必须是数组传给fun
fun.bind(thisArg, param1, param2, ...)
实现call
Function.prototype.myCall = function(target, ...args){
target = target || window
const symbolKey = Symbol()
target[symbolKey] = this
const res = target[symbolKey](...args)
delete target[symbolKey]
return res
}
四、CommonJS、AMD、CMD和ES6
- (1)CommonJS:module、exports、require、global,用同步的方式加载模块,但在浏览器端限于网络原因,更推荐用异步方式加载。
- (2)AMD(require.js)异步方式加载模块,依赖此模块的语句会定义在回调函数。依赖前置。
- (3)CMD(sea.js)类似AMD,区别是依赖就近、延迟执行。
- (4)export和import实现模块功能,CommonJS是对模块的浅拷贝,ES6是对模块的引用;CommonJS是运行时加载,ES6是编译时输出接口(静态代码解析阶段)。
五、原型和原型链
- (1)原型对象:函数类数据的prototype属性,指向一个对象,存放公共属性和方法,原型对象的constructor指向它的构造函数
- (2)显示原型:函数类数据利用prototype查找原型;
- (3)隐式原型:利用_proto_属性查找原型,该属性指向当前对象的构造函数的原型对象。
- (4)原型链:顺着_proto_属性一步步网上查找,直到Object.prototype,再往上没有更上一层了返回undefined,这个链式结构叫做原型链。
6、new
- 创建新的空对象;
- 设置原型,将对象的原型设置为构造函数的的prototype对象。
- 让函数的this指向新的对象(call),执行构造函数(为新对象添加属性);
- 判断函数返回值类型,如果是值类型则返回对象,如果是引用型,就返回这个引用类型的对象。
7、闭包、作用域链
8、异步(Promise)
Promise是异步编程的一种解决方案,其本身是同步立即执行的构造函数,用来生成Promise实例。
- pending->fulfilled:已成功,执行resolve
- pending->rejected:已失败,执行reject
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
- Promise实例具有then方法,then方法返回一个新的Promise实例,因此可以采用链式写法。
- Promise.all()可将多个Promise实例包装成一个新的Promise对象,所有子状态都为fulfilled,封装实例才会为fulfilled状态,有一个被reject,则会返回最先reject的实例。成功时返回结果数组,失败时返回最先被reject的状态。
- Promise.race()捕获返回最快的的结果,不管是成功还是失败。
9、ES6新特性
- 箭头函数
- 模板字符串
- Promise
- symbol:表示独一无二的值,不能与其他数据类型进行运算。
- 新增声明方式:let和const
- 新增模块化:import和export或export default
- Map和Set