JS基础

96 阅读5分钟

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。