前端面试经典八股文(一)

数据类型 (9种)

基本数据类型(栈):Number,String,Boolean,null,undefined,symbol(创建唯一值),bigint(后两个为ES6新增)
引用数据类型(堆):object,function

判断数据类型

1、typeof typeof 是一个操作符,返回该类型的字符串(全小写字母)形式表示,包括以下 7种:number、string、boolean、undefined、symbol、object、function 等。(对于 null,返回 object 类型。)

    对于基本类型,除 null 以外,均可以返回正确的结果。
    对于引用类型,除 function ,一律返回 object 类型。

2、instanceof 检测的是原型,instanceof 只能用来判断两个对象是否属于实例关系, 而不能判断一个对象实例具体属于哪种类型。
3、toString是 Object 的原型方法,调用该方法,默认返回当前对象的 [[Class]] Object.prototype.toString.call('')
4、constructor是原型prototype的一个属性,当函数被定义时候,js引擎会为函数添加原型prototype,并且这个prototype中constructor属性指向函数引用, 因此重写prototype会丢失原来的constructor。

var、let、const

let 和 const 的优点?
let 和 const 有了块级作用域,变量声明不会提升相比于 var

var、let、const的区别

    var定义的变量,没有块的概念,可以跨块访问, 不能跨函数访问。
    let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问。
    const用来定义常量,使用时必须初始化(即必须赋值),只能在块作用域里访问,而且不能修改。

普通函数、匿名函数、箭头函数

    普通函数中的this:谁调用了函数或者方法,this指向谁
    匿名函数中的this:指向是window,而不是调用该匿名函数的对象;
    箭头函数中的this
        箭头函数中的this是在函数定义的时候就确定下来的
        箭头函数中的this指向父级作用域的执行上下文;
        箭头函数无法使用apply、call和bind方法改变this指向

箭头函数与普通函数区别

    箭头函数是匿名函数不能作为构造函数不能使用new
    箭头函数不绑定arguments,需要用运算符解决…解决
    箭头函数不绑定this,会捕获其所在的this值,作为自己的this值
    箭头函数通过call()或apply()调用一个函数,只传入了一个参数,对this并没有影响.
    箭头函数没有原型属性

new操作符具体干了什么呢

    创建一个新的对象obj
    将对象与构建函数通过原型链连接起来
    将构建函数中的this绑定到新建的对象obj上
    根据构建函数返回类型作判断,如果是原始值则被忽略,如果是返回对象,需要正常处理。

 call, apply(数组), bind

作用:

    都可以改变函数内部的this指向。
    区别点:
    call 和 apply 会调用函数,并且改变函数内部this指向。
    call 和 apply 传递的参数不一样,call 传递参数arg1,arg2…形式 apply 必须数组形式[arg]
    bind 不会调用函数,可以改变函数内部this指向。

eventloop, 宏任务和微任务

    不停检查 Call Stack 中是否有任务(也叫栈帧)需要执行,如果没有,就检查 Event Queue,从中弹出一个任务,放入 Call Stack 中,如此往复循环。

    1、所有同步任务都在主线程上执行,形成一个执行栈
    2、主线程之外,还存在一个"消息队列"。只要异步操作执行完成,就到消息队列中排队
    3、一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取消息队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行
    4、主线程不断重复上面的第三步

宏任务(setTimeout, setInterval,setImmediate) Macrotask 宏任务是指Event Loop在每个阶段执行的任务
微任务 (Promises, Object.observe)Microtask 微任务是指Event Loop在每个阶段之间执行的任务
new promise 与同步一起,先微后宏

 闭包 (概念, 用途, 手写)

一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围), 这样的组合就是闭包(closure)。也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域。在 JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来。

    闭包的特点:

        让外部访问函数内部变量成为可能;
        可以避免使用全局变量,防止全局变量污染;
        可以让局部变量常驻在内存中;
        会造成内存泄漏(有一块内存空间被长期占用,而不被释放)

function makeFunc() {var name = "Mozilla";function displayName() {alert(name);}return displayName;
}var myFunc = makeFunc();
myFunc();

继承 (extends, 原型链继承, 构造函数继承, 组合继承, 寄生组合继承)

深拷贝和浅拷贝

浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象共享同一块内存。
深拷贝会创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。

实现浅拷贝方法:
(1)Object.assign方法
(2)for in方法

实现深拷贝方法:
(1)采用递归去拷贝所有层级属性
(2)使用JSON.stringify和JSON.parse实现深拷贝:JSON.stringify把对象转成字符串,再用JSON.parse把字符串转成新的对象;
(3)热门的函数库lodash,也有提供_.cloneDeep用来做深拷贝

Promise

Promise对象, 可以将异步操作以同步的流程表达出来。使用 Promise 主要有以下好处:

    可以很好地解决回调地狱的问题(避免了层层嵌套的回调函数)。
    语法非常简洁。Promise 对象提供了简洁的API,使得控制异步操作更加容易
    new Promise(function(resolve, reject) then,catch,finally捕获错误
    Promise.all(iterable) 方法返回一个 Promise 实例,此实例在 iterable 参数内所有的promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);如果参数中promise 有一个失败(rejected),此实例回调失败(reject),失败的原因是第一个失败 promise的结果。

Promse.race Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。

Ajax请求过程

创建 XMLHttpRequest 对象,也就是创建一个异步调用对象;
创建一个新的 HTTP 请求,并指定该 HTTP 请求的方法、 URL 以及验证信息;
设置响应 HTTP 请求状态变化的函数;
发送 HTTP 请求;
获取异步调用返回的数据;
使用 JavaScript 和 DOM 实现局部刷新。

AMD、CMD、CommonJs、ES6的对比

他们都是用于在模块化定义中使用的,前三个是ES5中提供的模块化编程的方案,
AMD: 是RequireJS在推广过程中对模块定义的规范化产出(依赖前置、异步定义)

通过define()函数定义,第一个参数是一个数组,里面定义一些需要依赖的包,第二个参数是一个回调函数,通过变量来引用模块里面的方法,最后通过return来输出。

CMD:是SeaJS在推广过程中对模块定义的规范化产出,(同步模块,没有前置依赖)

通过define()定义,没有依赖前置,通过require加载jQuery插件,CMD是依赖就近,在什么地方使用到插件就在什么地方require该插件,即用即返,这是一个同步的概念

CommonJs:是通过module.exports定义的,通过node.js后端使用的。
import/export:是ES6中定义新增的,对模块进行导出导入的

require,import和import()函数的区别

import命令会被 JavaScript 引擎静态分析,先于模块内的其他模块执行(叫做”连接“更合适)。
import()函数,完成动态加载。异步加载
require是运行时加载模块,只有运行时才知道,同步加载

ES6转化为ES5

https://blog.csdn.net/weixin_44135121/article/details/104161852
Parser 解析
第一步主要是将 ES6 语法解析为 AST 抽象语法树。简单地说就是将代码打散成颗粒组装的对象。这一步主要是通过 babylon 插件来完成。
Transformer 转换
第二步是将打散的 AST 语法通过配置好的 plugins(babel-traverse 对 AST 进行遍历转译)和 presets (es2015 / es2016 / es2017 / env / stage-0 / stage-4 其中 es20xx 表示转换成该年份批准的标准,env 是最新标准,stage-0 和 stage-4 是实验版)转换成新的 AST 语法。这一步主要是由 babel-transform 插件完成。plugins 和 presets 通常在 .babelrc 文件中配置。
Generator 生成
第三步是将新的 AST 语法树对象再生成浏览器都可以识别的 ES5 语法。这一步主要是由 babel-generator 插件完成

Published by

风君子

独自遨游何稽首 揭天掀地慰生平