【JavaScript面试题】面试题整理一

1.说说你对对TS的理解

TS就是JS的基础上对数据进行强制的类型检查,生成JS代码的时候进行编译,弱类型的静态语言

  • TypeScript更适合编写应用程序
  • TypeScript跨平台、开源
  • 开始于JS,,结束于JS
  • 重用JS,直接引入JS流行的库
  • 类、接口、模块
  • 在Vue、Node、React中都可以使用TypeScript
  • 强类型限制(JavaScript是弱类型)
2.说说nextTick()及应用场景

nextTick():会在dom更新完成之后再去执行其中的操作

nextTick(()=>{
    // 这里面的代码会在dom更新完成之后再执行
    ...
})
  • 当一个元素通过v-if控制显示隐藏,当修改完元素的状态,立马就需要通过ref去操作此元素,这个时候就会报错。原因是这个时候,该元素还未渲染完成。
  • 使用nextTick()就可以很好的解决这个问题
3.Node中间件用过吗
  • 一个中间件是一个用于处理客户端用户请求的函数
  • 处于操作系统软件和用户应用软件中间
  • 中间件是一个函数,他可以访问请求对象,响应对象和web应用中处于请求-相应循环流程中的中间件,一般被命名为next的变量
// 中间件(就是一个函数) —— 案例一:auth
// 形似函数抽离
const auth = async function(req, res, next) =>{
    const raw = String(req.headers.authorization)
    const { id } = jwt.verify(raw, SECRET)
    if(!id){
        return res.status(402).send({
            message: 'token无效!'
        })
    }
    req.user = await User.findById(id)
    // 继续执行后续操作
    next()
}
// token获取个人信息 : 先执行auth中间件
app.get('/api/profile',  auth , async function(req, res){
    return res.send(req.user)
})
4.说一下webpack热更新的原理

Webpack的热更新又称热更替(Hot Module Replacement)。这个机制可以做到不需要刷新浏览器而将变更的模块替换掉旧的模块

HMR的核心就是客户端从服务端拉取更新后的文件,准确的来说是chunk diff(chunk需要更新的部分),实际上WDS与浏览器之间维护了一个websocket,当本地资源的发生变化时,WDS会向浏览器推送更新,并带上构建时的hash,让客户端与上一次资源进行对比。客户端对比出现差异后会向WDS发起Ajax请求,来获取更改内容(文件列表,hash),这样客户端就可以再借助这些信息继续向WDS发起jsonp请求获取chunk的增量更新

5.数组去重的方法
  • 利用Set数据结构:[...new Set( Arr )]
  • 利用双重for循环+splice的方法去重
  • 利用IndexOf去重
  • 利用sortincludes去重
  • 利用hasOwnProperty
  • 利用递归去重
6.什么是promise?
  • promise是一个容器,里面存储着未来才会结束的事件的结果,通常是一个异步操作
  • 从语法上讲,promise是一个对象,用来处理异步操作
  • 从字面上理解,promise是承诺、许诺的意思,意思是使用promise后不管成功还是失败都会有返回值
  • promise的三个状态: pending:进行中resolved: 完成rejected: 失败
  • promise.then的回调函数中,可以返回一个新的promise
let promise = new Promise(function(resolve, reject) {
    console.log('Promise');
    resolve();});

    promise.then(function() {
        console.log('resolved.');
    });
}

console.log('Hi!');
// Promise    // Hi!     // resolved

promise新建后就会立即执行,所以输出如代码所示结果

*Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。

7.浏览器缓存及区别

浏览器缓存:Cookie、LocalStorage、SessionStorage

对比

8._ proto和prototype有什么区别?
  • _ proto是每个实例都有的,prototype是构造函数才有的
  • _ proto可以访问prototype上的属性
  • 实例的_ proto和构造函数的prototype是一个对象
9.什么是arguments?

传递给函数的参数类型对象,可以返回实例对象,也可以返回指定的函数

10.js的内置对象

Object是JS中所有对象的父对象
数据封装类对象:Object、Array、Boolean、Number、String
其他对象:Function、Math、Date、Argument、RegExp、Error

11.JS异常捕获方式
try {
    // 执行代码
} catch(err){
    // 错误处理
}
12.创建对象的几种方式
// 1.直接定义
var person = {
    name: 'Joseph',
    age: ' 24 '
}

// 2.对象实例化
function Person(){  }
 
 // 实例化
 var person = new Person()
person.name = 'xxx'
person.age = 25
...
13.js继承
  • 构造函数
  • 原型链继承
  • 实例继承
  • 拷贝继承
// 原型链prototype机制/call和apply方法比较简单。建议使用构造函数、原型混合
function Parent(){
    this.name = ' Joseph ';
}

function Child(){
    this.age = 24;
}

Child.prototype = new Parent()// 通过原型,继承了Parent
var child = new Child();
console.log( child.age );
console.log( child.name );  // 得到被继承的属性
14.Window和Document的区别
  • Window是窗体,Document是指页面。Document是Window的一个子对象
  • 用户不能该改变document.location ( 因为这是当前文档显示位置 ),window.location是对象,document.location不是
15.闭包

嵌套的函数,当内部函数引用外部函数的变量时就产生了闭包。

注:闭包不会造成内存泄漏,内泄是指访问不到的变量,占用内存。:IE中有bug,IE 中使用闭包后,闭包里面引用的变量不会被垃圾回收机制回收。使用不当会造成内存泄漏。

16.事件委托

利用事件冒泡,只指定一个事件处理程序,就可以管理某一类的所有事件

事件代理( Event Delegation ),又称之为事件委托。是 JavaScript 中常用的绑定事件的常用技巧。顾名思义,“事件代理”即是把原本需要绑定的事件委托给父元素,让父元素担当事件监听的职务。事件代理的原理是DOM元素的事件冒泡。使用事件代理的好处是可以提高性能

  • 可以大量节省内存占用,减少事件注册,比如在 table 上代理所有 td 的 click 事件就非常棒
  • 可以实现当新增子对象时无需再次对其绑定
17.push、pop、shift、unshift功能

push: 将元素添加到数组中,返回新的数组长度
pop: 将数组最后一位元素从数组移除,返回移除的元素
shift:将数组的首个元素移除,返回移除的元素
unshift:将元素添加到数组的第一位置,返回新的数组

18.var、let、const的区别
  • var定义的变量,没有块的概念,可以跨块访问,不能跨函数访问。let、const有的概念
  • var会挂载到window上(使用window.xxx访问),有变量提升,同作用域下可声明同样的变量
  • const声明时必须赋值,不能用null占位,如果是复合数据类型,可以修改其属性
19.防抖、节流(性能优化)

防抖:触发后会在一定时间后执行,再次触发则重新计时(多次触发只执行一次)

  • 调整浏览器窗口大小
  • 文本编辑器实时保存
  • 搜索框的输入查询

在这里插入图片描述

节流规定时间内多次触发只执行一次

  • 鼠标连续点击
  • 监听滚动事件
  • 搜索框实时查询事件

在这里插入图片描述

区别

  • 1、防抖就是触发事件后n秒后才执行事件处理函数,如果在n秒内又触发了事件,就会重新计时。
  • 2、节流就是连续触发事件,在指定时间间隔内只会执行一次函数,节流会减少函数的执行频率。
20.深拷贝的实现方法
  • JSON.parse( JSON.stringify( obj ) )
  • 使用循环、递归实现
  • 使用Object.create()实现

注:Object.assign(),当属性只有两层的时候为深拷贝,更多则为浅拷贝

21.判断是不是一个数组
let arr = [1,2,3]
console.log( arr instanceof Array ); // true
console.log( Array.isArray(arr) ); // true
console.log( Object.prototype.toString.call(a) === '[Object Array]' ); // true
console.log( arr.constructor == Array ); // true
22.Js数据类型

基本数据类型

  • String
  • Number
  • Boolean
  • Null
  • Undefined
  • Symbol :Es6新增

引用数据类型

  • Object
  • BigInt:Es7新增
23.从输入URL到页面加载发生了什么
  1. DNS解析
  2. TCP连接
  3. 发送HTTP请求
  4. 服务器处理请求并返回HTTP报文
  5. 浏览器解析渲染页面
  6. 连接结束
24.call,apply,bind对比
  • 作用相同

都可以动态修改this的指向,不会修改原先函数的this指向

  • 执行方式不同
  • call和apply是改变后页面加载之后就立即执行,是同步函数
  • bind是异步函数,改变后不会立即执行,而是返回一个新的函数
  • 传参方式不同
  • call:第二个参数和后面的参数可以传任意类型的数据
  • apply:可以使用数组的方式传入,只要是数组方式就可以使用剩余参数的方式传入
  • call和apply都是第一个参数是this的指向 ,只是传参的方式不同。bind() 就是将某个函数绑定到某个对象上
  • 修改this的性质不同

call、apply只是临时修改一次,再次调用函数的时候,他的指向还是原来的指向。而bind则是永久修改函数的this指向,但是它修改的不是原来的函数,而是返回一个修改过后新的函数,此函数的this永远被改变。

function fn(a, b){
    console.log(this, a + b);
}
const obj = { name: 'Joseph'}

fn(1,2)
fn.call(obj, 3, 4)
fn.call(obj, [3, 4]) // call不能使用剩余参数的方式传参
fn.apply(obj, [3, 4])

// bind会永久性的修改fn中的this指向,实则为返回一个修改后的新函数(newFun)
var newFun = fn.bind(obj)
newFun(5, 6)
fn(5, 6)

在这里插入图片描述

25.this的指向
  • 普通函数调用,此时this指向window
  • 构造函数调用,此时this指向实例对象(new会改变this的指向)
  • 对象方法调用,此时指向该方法所属的对象
  • 通过事件绑定的方法,此时指向绑定事件的对象
  • 定时器函数,此时指向window
26.Object.assign()

用于将所有可枚举属性的值从一个或多个对象复制到目标对象,浅拷贝当对象层级不超过两级的时候,为伪深拷贝

  • 复制对象
  • 合并对象:具有相同属性的对象,同名属性,后面的会覆盖前面的

实用技巧
由于Object.assign()有上述特性,所以我们在Vue中可以这样使用:
Vue组件可能会有这样的需求:在某种情况下,需要重置Vue组件的data数据。此时,我们可以通过this.$data获取当前状态下的data,通过this.$options.data()获取该组件初始状态下的data。然后只要使用Object.assign(this.$data, this.$options.data())就可以将当前状态的data重置为初始状态,非常方便!

27.什么是diff算法

笼统的理解就是:新旧虚拟节点对比,并返回一个patch对象,用来存储两个节点不同的地方,最后根据patch记录的消息去局部更新Dom

  • diff算法就是在虚拟Dom树从上至下进行同级比较,如果上层已经不一致,下面的Dom就全部重新渲染。这样的好处是算法简单,减少对比的次数,加快算法完成速度。
  • 特点1:只在同级比较,不会跨级
  • 特点2:在diff比较的过程中,循环从两边向中间比较

diff算法步骤: 用JavaScript对象结构表示Dom树的结构;然后用这个树构建一个真正的Dom树,插入到文档中,当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行对比(diff),记录两棵树的差异,把第二棵树所记录的差异应用到第一棵所构建的真正Dom树上(patch),视图就更新了

28.vue计算属性computed和事件methods、Watch区别有什么区别
  • Computed在初始化时执行,属性的结果会被缓存,除非依赖的响应式属性发生变化才会重新计算,主要当作属性来使用,专注于结果
  • Watch是一个对象,键是需要观察的表达式,值是对应回调的函数,主要是监听某些特定数据的变化,专注于过程
  • Methods只有调用的时候才会及执行,不会自动同步数据
29.前端性能优化

在这里插入图片描述

参考

30.JavaScript设计模式

设计模式:假如有一个空房间,我们要日复一日的往里面放东西,最简单的办法就是往里面直接丢,但是时间久了,就会发现很难从里面找到想要的东西,要调整物品的位置也不容易。所以在房间里面做一些柜子,虽然柜子会增加我们的成本,但它可以在后期的维护阶段带来好处。使用这些柜子存放东西的规则,或许就是一种模式。

  • 单例模式
  • 策略模式
  • 代理模式等
31.JavaScript中typeof能得到哪些类型
  • String
  • Number
  • Boolean
  • undefined
  • Object
  • Function
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Joseph365

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值