1. 原型
- 每一个构造函数都有一个原型对象prototype,原型对象都包含一个指向构造函数的指针Constructo。
- 每一个实例都包含一个指向原型对象的内部指针__proto__。
原型链
- 按照只身属性->构造函数prototype->Object的prototype。
person.__proto__ -> Person.prototype -> Person.prototype.__proto__ -> Object.prototype -> Object.prototype__proto__ -> null。
2. new一个对象的过程
- 创建一个新对象。
- this指向这个新对象。
- 执行代码,即对this赋值。
- 返回this。
3. bind、call、apply的区别
- 三个函数都会改成this的指向
- bind会产生新的函数,call和apply不会产生新的函数。
- 第一个参数都是要绑定的this,apply第二个参数是数组,call和bind的第二个参数单列出来,逗号分隔。
4. Class和es5构造函数的区别
- 类的内部所有定义的方法,都是不可枚举的,当是在ES5中的prototype的方法是可以进行枚举的。
- 类的构造函数,不使用new是没法调用的,会报错。es5构造函数不使用new也是可以调用的。
- Class不存在变量提升,这一点与ES5完全不同。
5. 闭包
- 闭包是指有权访问另外一个函数作用域中的变量的函数。
- 作用域:全局变量,局部变量。js中的函数可以读取全局变量,函数外部不能读取函数内部的局部变量。
- 子对象会一级一级向上寻找所有父对象的变量。
6. JS基础
- 原型链继承:将父类的实例作为子类的原型。
- 构造基础:复制父类的实例属性给子类(没有用到原型)。
- 实例继承:为父类实例添加新特性,作为子类实例方法。
- 拷贝继承:把一个对象中的属性或方法直接复制到另外一个对象中。
7. 事件循环
- JS是单线程,分为同步任务何异步任务。
- 先执行主线程代码->微任务->宏任务(有微则微,无微则宏)。
- 微任务:nextTick、promise(then、catch、finally)。
- 宏任务:I/O、setTimeout、setInterval。
- 同步代码一开始放入执行栈中执行,过程中遇到异步操作,就放到对应的任务队列中,等主线程空闲之后取出任务队列的东西放入执行栈中执行。然后重复上面的步骤,直至完成所有的任务,这就是事件循环。
8. this指向
- 以函数形式调用时,this永远指向window。
- 以方法的形式调用时,this是调用方法的对象。
- 以构造函数的形式调用时,this是新创建的那个对象。
- 使用call和apply调用时,this是指定的那个对象
- 使用箭头函数调用时:箭头函数的this看外层是否有函数,如果有,this指向外层函数,如果没有指向window。
9. require和import的区别
- require是commonJS规范的模块化语法,import是es5规范的模块化语法。commonJS定义的每一个文件都是一个模块,并有自己的作用域,而每个文件定义的变量、函数、类都是私有的,对其他模块不可见,模块的exports属性是对外的接口,只有通过module.exports导出的属性才能被识别。
- require是运行时加载,性能比较低。import是编译时加载,性能稍好。
- require可以在代码的任意位置,import只能写在文件的最顶端且不可在条件语句或函数作用域中使用。
- require通过module.exports导出的值就不能再变化了,import通过export导出的值可以改变(as)。
- require通过module.exports导出的是exports对象,import通过export导出是指定输出的代码,common模块输出的是一个值的拷贝,es6模块输出的是一个值的引用。
10. var、let、const的区别
- var声明的变量会挂载在window上,而let和const声明的变量不会。
- var声明变量存在变量提升,let和const不存在变量提升。
- let和const声明形成块作用域。
- 同一作用域下let和const不能声明同名变量,而var可以。
- const声明的是常量,值数据类型不能修改,引用数据类型能修改。
11. 箭头函数的新特性
- 不能作为构造函数,和new一起使用。
- 箭头函数没有原型属性。
- 没有定义this绑定,外层有函数则指向外层函数,否则指向window,严格模式下为undefined。
12. async/await和Promise的区别
- Promise是ES6,async/await是es7。
- Promise链式操作,自己的catch异常,async则要在函数内catch。
- Promise.all/Promise.race方法,aysync/await没有。
-async/await代码看起来是同步,实际上是异步,Promise是then回调,前者写法更加清晰。
13. 对Promise的理解
- Promise用来解决异步异步回调问题,由于JS是单线程,很多异步操作都是依靠回调方法实现的,这种方法在逻辑比较复杂的回调嵌套中会相当复杂;这也叫回调地狱。
- Promise用来将这种复杂的做法简化,让程序更具备可读性,可维护性:Promise内部有三中状态:pedding,fulfilled,rejected。
- pedding表示程序正在执行,当未得到结果,即异步操作没有执行完毕,fulfilled表示执行完毕,并执行成功,rejected表示执行完毕但失败。
- Promise中的then一般对应成功后的数据处理,catch一般对应失败后的数据处理。Promise状态一旦确定,就不会再次发生改变。
14. JS中的堆和栈
- 栈(stack):由操作系统系统自动分配内存空间,自动释放,存储的是基础变量以及一些对象的引用变量,占据固定大小的空间。Number、Boolean、undefined、String、Null、Symbol、BigInt。
- 堆(heap):由操作系统动态分配的内存,大小不一定也不会自动释放,一般由程序员分配释放,也可以由垃圾回收机制回收。Object、Function、Array。