2022年javascript面试题总结

讲一下 var、let、const 的区别?

  • var 声明的变量有变量提升的特性,而 let、const 没有
  • var 声明的变量会挂载到 windows 对象上,所以使用 var 声明的是全局变量,而 let 和 const 声明的变量是局部变量, 块级作用域外不能访问
  • 同一作用域下 let 和 const 不能重复声明同名变量,而var可以
  • const 声明的是常量,必须赋初值,一旦声明不能再次赋值修改,如果声明的是复合类型数据,可以修改其属性

js中的基础数据类型有哪几种

  • 基本数据类型(值类型):字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined),
  • 引用数据类型(对象类型):对象(Object)、数组(Array)、函数(Function)。
  • 特殊的对象:正则(RegExp)和日期(Date)
  • 特殊类型:underfined 未定义、Null 空对象、Infinate 无穷、NAN 非数字

基本数据类型的值直接在栈内存中存储,值与值之间独立存在,修改一个变量不会影响到其他变量。

对象是保存在堆内存中的,每创建一个新对象,就会在堆内存中开辟出一个新空间,而变量保存的是对象的内存地址(对象的引用),如果两个变量保存的是同一个对象引用,当其中一个通过变量修改属性时,另一个也会受到影响

js数据类型的检测方式有哪些?

  • typeof常用于判断基本数据类型,因为对象、数组和Null都返回的Object
  • instanceof用于判断引用数据类型,检测构造函数的prototype属性是否出现在某个实例对象的原型链上,有则返回true,否则返回false,就是判断对象属于什么类型
  • Object.prototype.toString.call()返回一个“[object XXX]”格式的字符串,XXX就是具体的数据类型

this指向的6种指向

  • 普通函数直接调用中的this: 普通函数中的 this 指向 window 对象, 严格模式下为 undefiend
  • 在对象里调用的this: 指向调用函数的那个对象,this: 谁调用就指向谁
  • 在构造函数以及类中的this: 构造函数和类需要配合 new 使用, 而 new 关键字会将构造函数中的 this 指向实例对 象,所以 this 指向 实例对象
  • 绑定事件函数的this: 谁调用就指向谁
  • 定时器中的this: 定时器中的 this 指向 window,因为定时器中采用回调函数作为处理函数,而回调函数的 this 指向 window
  • 箭头函数中的this: 箭头函数没有自己的 this,会继承其父作用域的 this。

call apply bind 的作用与区别?

  • 相同点:call 和 apply 和 bind 都可以改变this指向,都可以传参
  • 不同点call apply自动调用,bind需要再调一次,bind的返回的是对应函数
  • call apply 如果第一个参数指定了 null 或者 undefined 则内部 this 指向 window

闭包?

  • 闭包是指能够访问另一个函数作用域中的变量的一个函数。 在js中,只有函数内部的子函数才能访问局部变量, 所以闭包可以理解成 “定义在一个函数内部的函数”
  • 闭包的作用: 利用闭包可以突破作用链域,将函数内部的变量和方法传递到外部,让外部函数可以访问到内部函数的变量和方法
  • 闭包的优点: 正常的函数,在执行完之后,函数里面声明的变量会被垃圾回收机制处理掉。但是形成闭包的函数在执行之后,不会被回收,依旧存在内存中
  • 闭包的缺点: 因为变量不会被回收,所以内存中一直存在,耗费内存。
  • 防抖和节流、封装私有变量、for循环中的保留i的操作、函数柯里化

js执行机制

js是单线程:
JavaScript语言单线程,也就是说,同一个时间只能做一件事情。,由于JavaScript需要用户与页面交互,操作dom,所以只能是单线程的,而单线程就意味着所有任务需要排队,前一个任务结束才会执行后一个任务,这样所导致的问题是如果js执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉

同步和异步:
程序里面所有的任务,可以分成两类:同步任务(synchronous)和异步任务(asynchronous)。
为了利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程,但是子线程完全受主线程控制,且不得操作 DOM。本质是js还是单线程的
同步:前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。
异步:异步任务是那些被引擎放在一边,不进入主线程、而进入任务队列的任务。只有引擎认为某个异步任务可以执行了(比如 Ajax 操作从服务器得到了结果),该任务(采用回调函数的形式)才会进入主线程执行。排在异步任务后面的代码,不用等待异步任务结束会马上运行,也就是说,异步任务不具有“堵塞”效应.
它们的本质区别是:这条流水线上各个流程的执行顺序不同。
js执行机制:
1、先执行执行栈中的同步任务。
2、异步任务(回调函数)放入任务队列中。
3、一旦执行栈中的所有同步任务执行完毕,系统会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。

事件循环(Event Loop)

js解析执行时,会被引擎分为两类任务,同步任务(synchronous) 和 异步任务(asynchronous)。

  • 对于同步任务来说,会被推到执行栈按顺序去执行这些任务。
  • 对于异步任务来说,当其可以被执行时,会被放到一个任务队列(task queue)里等待js引擎去执行。

当执行栈中的所有同步任务完成后,js引擎才会去任务队列里查看是否有任务存在,并将任务放到执行栈中去执行,执行完了又会去任务队列里查看是否有已经可以执行的任务。这种循环检查的机制,就叫做事件循环(Event Loop)

宏任务和微任务

对于任务队列,其实是有更细的分类。其被分为 微任务(microtask)队列 == & == 宏任务(macrotask)队列

  • 微任务: Promise的then、Mutation Observer、process.nextTick()等,会被放在微任务(microtask)队列。
  • 宏任务: setTimeout、setInterval、ajax等,会被放在宏任务(macrotask)队列。

对内存泄漏的了解

  • 定义:程序中已在堆中分配的内存,因为某种原因未释放或者无法释放的问题
  • 简单理解: 无用的内存还在占用,得不到释放和归还,比较严重的时候,无用的内存还会增加,从而导致整个系统卡顿,甚至崩溃。

new 操作符具体干了什么?

  • 创建一个空对象,并且把 this 指向这个对象,同时还继承了该对象的原型
  • 属性和方法被加入到 this 引用的对象中

箭头函数与普通函数区别

  • 箭头函数没有属于自己的this,箭头函数没有自己的 this,会继承其父作用域的 this。)(严格模式this是undefined)
  • 不可以使用new命令(没有this),否则会抛出一个错误
  • 没有自己的this.不能调用call和apply,没有prototype,new关键字内部需要把新对象的_proto_指向函数的prototype
  • 不能使用arguments对象

JavaScript 原型,原型链 ? 有什么特点?

原型

  • 原型分为隐式原型(proto) 和 显式原型(prototype),每个对象都有它的隐式原型(proto),指向它对应构造函数的显式原型(prototype)
  • 无论何时,只要创建一个函数,就会为这个函数添加一个 prototype 属性,这个属性就指向原型对象,原型对象有一个 constructor 属性指回构造函数,每个构造函数生成的实例对象都有一个 proto 属性,这个属性也指向原型对象

原型链

  • 每个对象都有 proto 属性,这个属性指向原型对象,当想访问对象的一个属性时,如果这个对象本身没有这个属性就会通过 __proto__属性 查找,原型对象也是对象,每个对象又有自己的 proto 属性,所以就会一直这样查找上去,直到找到这个属性,这就是原型链的概念。
  • 原型链就是对象沿着 proto 这条链逐步向上搜索,最顶层是 Object,Object 的 proto 是 null。

事件代理(事件委托)

  • js 中常用绑定事件的常技巧。“事件代理”是把原本需要绑定的事件委托给父元素,让父元素担当事件监听的职务。事件代理的原理是 DOM 元素的事件冒泡。使用事件委托的好处是可以提高性能。
  • 可以大量节省内存占用,减少事件注册,当新增子对象时无需再次对其绑定。

什么是作用域,什么是作用域链(待修改)

作用域

  • 规定变量和函数的可使用范围称为作用域

作用域链

  • 查找变量或者函数时,需要从局部作用域到全局作用域依次查找,这些作用域的集合称作用域链。

浅拷贝 和 深拷贝的理解

浅拷贝:

  • 如果拷贝的是基本数据类型相当于直接拷贝它的值,修改值互不影响
  • 如果拷贝的是引用数据类型,拷贝的就是指向堆内存里面这个对象的内存地址,如果修改了其中一个对象的数据,那么另一个对象也会受到影响,因为内存地址指向堆里面同一块内存
  • 常用 es6 0bject.assign() 实现

深拷贝:

  • 深拷贝是将一个对象完整的独立拷贝一份出来,然后在堆内存中开辟一块新的内存块存储,所以不会互相影响
  • 常用 es6扩展运算符 递归 Array.concat() 实现

防抖和节流的作用

防抖

  • 在事件触发几秒后再去执行回调,如果在这几秒中再次触发,则重新及时 (输入框)

节流

  • 规定在一定的时间内只执行一次,如果在规定的时间内多次触发,只有一次生效 (按钮)

    两者的目的都是为了防止由于触发频率过高导致相应速度跟不上

js数组操作

js数组乱序去重

  • sort()

js数组去重的方法

  • 利用 es6 Set 去重
  • sort()
  • includes()
  • for+indexof
  • forEach+indexof

js数组排序的方法

  • sort()
  • 冒泡排序
  • 快速排序

js数组合并的方法

  • arr1.concat
  • […arr1, …arr2,······]
  • push(…arr)
  • arr1.push.apply(arr1, arr2)
  • arr1.push.call(arr1, …arr2)

js对象合并的方法

  • Object.assign() Object.assign()实行的是浅拷贝,也就是说如果源对象的属性是一个对象,那么目标对象得到的是这个对象的引

说说es6的新增特性

  • let、const: 声明变量和常量
  • 模板字符串:增强版的字符串,用反引号标识,嵌入变量只需要放在${}中
  • 箭头函数:ES6中函数定义不再使用关键字function(),而是利用了()=>来进行定义
  • 解构赋值:按照类型的不同有不同的方式提取值,赋值
  • Symbol:新增的基本数据类型,特点就是里面的值唯一
  • Set 和 Map 数据结构
  • 展开运算符(…): 可以将数组或对象里面的值展开, 还可以将 Set 数据结构转换为数组
  • for…of 循环: 可以遍历数组对象以及 Set 和 Map 数据结构
  • class 类:通过 extends 实现继承
  • promise、(async/await): 都是用来解决异步编程的方案
  • proxy:代理对象,直接监听对象的变化,然后触发相应的逻辑

Promise

  • Promise 是 es6 引入解决异步编程问题的解决方案
  • Promise 有三种状态:pending(进行中)、resolve(已完成)、reject(已失败)
  • 当 Promise 的状态由 pending 转变为 resolved 或 reject 时,会执行相应的回调, 一旦从 pending 状态变成为其他状态就不能再更改状态了
  • 可以链式调用,解决回调地狱的问题

Promise.all() 和 Promise.race()

  • Promise.all() 的作用是接收一组异步任务,然后并行执行任务,等所有任务执行完之后再执行回调
  • Promise.all() 传入一组 Promise 数组,只有当所有的 Promise 状态都成功才返回成功,只要有一个失败就返回失败的 Promise 状态
  • `Promise.all( 的作用是接收一组异步任务,然后并行执行任务,等所有任务执行完之后再执行回调
  • Promise.all() 传入一组 Promise 数组,只有当所有的 Promise 状态都成功才返回成功,只要有一个失败就返回失败的 Promise 状态

什么是什么是async/await?

  • async/await是写异步代码的新方式,以前的方法有回调函数和promise
  • async/await是基于promose实现的,他不能用于普通的函数
  • async/await与promise一样,是非阻塞的
  • async/await使得异步代码看起来像同步代码

for-in 和 for-of 的区别

  • 两者都可以用于遍历数组,只不过for-in遍历的是数组元素的索引 (index), 而for-of遍历的是数组元素的值
  • for-in 可以遍历普通对象,获取的是对象的键名。 for-of 不可以遍历普通对象
  • for-in 不可以遍历Set/Map for-of 可以遍历Set/Map

for和foreach谁更快,为什么?

  • forEach每次都要创建一个函数来调用,而for不会创建函数,
  • 函数需要独立的作用域,会有额外的开销
  • 越“低级”的代码,性能往往越好
  • 日常开发别只考虑性能,forEach代码可读性更好

什么是 DOM 和 BOM?

  • DOM:文档对象模型,就是把 文档 当做一个对象,顶级对象是document, dom主要是操作页面元素。
  • BOM: 浏览器对象模型,把 浏览器 当做一个对象,顶级对象是window, bom主要是控制浏览器窗口交互的一些对象,除了window还有history,navigator,location

如何判断一个对象是否属于某个类型?

  • Object.prototype.toString.call();

面向对象

什么是面向对象

  • 面向对象不是新的东西,它只是过程式代码的一种高度封装,目的在于提高代码的开发效率和可维护性。
  • 面向对象编程 —— Object Oriented Programming ,简称 OOP ,是一种编程开发思想。
  • 面向对象编程具有灵活、代码可复用、高度模块化等特点,容易维护和开发,比起由一系列函数或指令组成的传统的 过程式编程(procedural programming),更适合多人合作的大型软件项目。
  • 简而言之: 简而言之就是程序之中所有的操作都需要通过对象来完成

面向对象与面向过程

  • 面向过程就是亲力亲为,事无巨细,面面俱到,步步紧跟,有条不紊
  • 面向对象就是找一个对象,指挥得结果
  • 面向对象将执行者转变成指挥者
  • 面向对象不是面向过程的替代,而是面向过程的封装

面向对象的特性

封装性 继承性 [多态性 ]

js如何实现异步编程

  • 回调函数(callback)

    优点:解决了同步的问题(只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行。)
    缺点:回调地狱,每个任务只能指定一个回调函数,不能 return.

  • 事件监听

    这种思路是说异步任务的执行不取决于代码的顺序,而取决于某个事件是否发生。比如一个我们注册一个按钮的点 击事件或者注册一个自定义事件,然后通过点击或者trigger的方式触发这个事件。

  • Promise

  • Generator

  • 生成器 async/await,是ES7提供的一种解决方案。

跨域解决办法

背景:

  • 跨域是是因为浏览器的同源策略限制,是浏览器的一种安全机制,服务端之间是不存在跨域的。

  • 所谓同源指的是两个页面具有相同的协议、主机和端口,三者有任一不相同即会产生跨域

    解决办法

  • cors解决:只需要后端去配置响应头,就可以解决跨域(不安全)

    Access-Control-Allow-Origin//允许跨域的域名
    Access-Control-Allow-Headers//允许的header类型
    Access-Control-Allow-Methods//跨域允许的请求方式

  • jsop解决:借助 script 标签的 src 属性,跳过同源策略,这种解决办法具有局限性,需要前后端配合解决,只能解决get请求

  • (在vue.config.js文件中)中 配置webpack-dev-server 其实就是借助webpack配置的服务器去访问后端,这样就只存在服务器之间的访问而服务器之间的访问又用的是http协议,这样就可以解决跨域

变量提升

我们js引擎在运行js的时候,分为两步,第一步是预解析,一步是代码执行,预解析分为变量预解析(变量提升)与函数预解析(函数提升)。函数提升优先级高于变量提升

  • 变量提升就是把所有的变量声明提升到当前作用域的最前边,变量赋值不会提升。
  • 函数提升是函数的声明会被提升到当前作用域的最前上边,但是不会调用函数

模块化

什么是模块

  • 将一个复杂的程序依据一定的规则(规范)封装成几个块(文件), 并进行组合在一起
  • 块的内部数据与实现是私有的, 只是向外部暴露一些接口(方法)与外部其它模块通信

模块化的好处

  • 避免命名冲突(减少命名空间污染)
  • 更好的分离, 按需加载
  • 更高复用性
  • 高可维护性

实现模块化的方式

  • Commonjs模块
  • AMD
  • CMD
  • ES6 模块

js常见的设计模式

  • 单例模式
  • 工厂模式
  • 构造函数模式
  • 发布订阅者模式
  • 迭代器模式
  • 代理模式

响应方式有哪几种

  • 鼠标单击事件( onclick )
  • 鼠标经过事件( onmouseover )
  • 鼠标移开事件( onmouseout )
  • 光标聚焦事件( onfocus )
  • 失焦事件( onblur )
  • 内容选中事件( onselect )
  • 文本框内容改变事件( onchange )
  • 加载事件( onload )
  • 卸载事件( onunload )

数组扁平化

  • 递归

  • toString

  • es6 展开运算符

     let arr = [1, [2, [3, 4]]];
     function flattern(arr) {
            let result = [];
            for(let i = 0; i < arr.length; i++) {
                if(Array.isArray(arr[i])) {
                    flattern(arr[i])
                } else {
                    result.push(arr[i])
                }
            }
            return result;
        }  //递归
    
    function flatten(arr) {
        return arr.reduce(function(prev, next){
            return prev.concat(Array.isArray(next) ? flatten(next) : next)
        }, [])
    }//toString
    
    function flatten(arr) {
        while (arr.some(item => Array.isArray(item))) {
            arr = [].concat(...arr);
        }  //ES6新方法
        return arr;
    }
    

js的垃圾回收机制

js的垃圾回收机制是为了以防内存泄漏,内存泄漏的含义就是当已经不需要某块内存时这块内存还存在着,垃圾回收机制就是间歇的不定期的寻找到不再使用的变量,并释放掉它们所指向的内存

媒体查询

  • 媒体查询是自 CSS3开始加入的一个功能。它可以进行响应式适配展示。
  • 响应式适配 根据不同的屏幕尺寸, 显示不同的效果 (设置盒子的样式)

媒体查询由两部分组成:

  • 一个可选的媒体类型(如 screen、print 等)
  • 零个或多个媒体功能限定表达式(如 max-width: 500px、orientation: landscape 等)

对内存泄露的理解

  • 定义:程序中已在堆中分配的内存,因为某种原因未释放或者无法释放的问题
  • 简单理解: 无用的内存还在占用,得不到释放和归还,比较严重的时候,无用的内存还会增加,从而导致整个系统卡顿,甚至崩溃。

可能出现内存泄漏的原因

  • 意外的全局变量
  • DOM元素清空时,还存在引用
  • 闭包
  • 遗忘的定时器
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值