记录最近前端面试题
-
vue-router 有几种模式,分别有什么区别,用到了哪些H5的api hash, history
hash模式:
-
url路径会出现“#”号字符 -
hash值不包括在Http请求中,它是交由前端路由处理,所以改变hash值时不会刷新页面,也不会向服务器发送请求 -
history模式:hash值的改变会触发hashchange事件 -
整个地址重新加载,可以保存历史记录,方便前进后退 -
利用pushState() ,replaceState() 可以对浏览器的历史记录栈进行修改,当浏览器跳转到新的状态的时候,将触发popState 事件依赖H5 API和后台配置,没有后台配置的话,页面刷新时会出现404
-
Node与Element的区别
- Node是节点,其中包含不同类型的节点,Element只是Node节点的一种。
- Element继承与Node,可以调用Node的方法。
- 给所有DOM元素添加方法,只需要污染Node或者Element的原型链就行。
-
伪数组与数组
- 对象没有数组的Array.prototype 的属性值,类型是 Object ,而数组类型是 Array
- 数组是索引,对象是键值对
- 使用对象创建伪数组,伪数组可以使用部分方法 ,例如:[].push.call(obj, 'd');
常用的伪数组有:函数内部的
arguments,new Set返回的值
-
new操作符做哪些操作
- 创建了一个新的空对象o
- 让这个o对象的
__proto__指向函数的原型prototype - this指向o对象
- 将o对象赋给a对象
o.__proto__ = Foo.prototype;
Foo.call(o);
a = o;
-
获取页面所有dom节点,并去重 document.getElementsByTagName('html'),循环获取得节点,判断节点类型是不是为1,则将节点属性为1的标签作为属性值存在对象中,再判断有没有孩子节点,有的话化递归一下
-
Set, Map, WeakSet, WeakMap的区别
-
Set
- 成员唯一、无序且不重复
- [value, value],键值与键名是一致的(或者说只有键值,没有键名)
- 可以遍历,方法有:add、delete、has
-
WeakSet
- 成员都是对象
- 成员都是弱引用,可以被垃圾回收机制回收,可以用来保存DOM节点,不容易造成内存泄漏
- 不能遍历,方法有add、delete、has
-
Map
- 本质上是键值对的集合,类似集合
- 可以遍历,方法很多可以跟各种数据格式转换
-
WeakMap
- 只接受对象作为键名(null除外),不接受其他类型的值作为键名
- 键名是弱引用,键值可以是任意的,键名所指向的对象可以被垃圾回收,此时键名是无效的
- 不能遍历,方法有get、set、has、delete
-
-
webpack中style-loader,css-loader的作用
- less-loader 是将less语法转为css
- css-loader只是帮我们解析了css文件里面的css代码转为js。
- style-loader将css-loader解析后的内容挂载到html页面
- vue父子组件传值,兄弟组件传值, 孙子组件传值
- 父子组件传值: props, parent, root, listener,ref, $refs, provide/inject
- 兄弟组件传值: eventBus, vue.prototype.eventBus = new Vue(), 子组件通过this.eventBus.on('name','所传的值')
-
...解构赋值, object.assign(), concat是浅拷贝还是深拷贝
-
手写防抖函数
function debounce (func, wait) {
let timer;
return function() {
let context = this; // 注意 this 指向
let args = arguments; // arguments中存着e
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, args)
}, wait)
}
}
- 手写深拷贝函数
function cloneDeep (obj){
// 1.判断是否为null 或undefined
if (typeof obj == null ) return obj;
// 2.判断是否为日期Date
if (obj instanceof Date) return new Date(obj);
// 3.判断是否为正则 typeof /\d+/ === 'object'
if (obj instanceof RegExp) return new RegExp(obj);
// 4.如果不是数组或对象,返回该值
if (typeof obj !== 'object') return obj;
// 接下来,要么是对象,要么是数组 可以用 new obj.constructor得到它类型的空值
let cloneObj = new obj.constructor;
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
// 递归深拷贝
cloneObj[key] = cloneDeep(obj[key]);
}
}
return cloneObj;
}
-
闭包的作用,以及实现 闭包就是能够读取其他函数内部变量的函数
-
promise中的源码实现,比如all方法是怎么实现的
Promise.prototype.all = function(promises) {
let results = [];
let promiseCount = 0;
let promisesLength = promises.length;
return new Promise(function(resolve, reject) {
for (let i; i< promisesLength; i++) {
Promise.resolve(promises[i]).then(function(res) {
promiseCount++;
// results.push(res);
results[i] = res;
// 当所有函数都正确执行了,resolve输出所有返回结果。
if (promiseCount === promisesLength) {
return resolve(results);
}
}, function(err) {
return reject(err);
});
}
});
};
-
vue模板编译过程 Vue中模版的编译是如下过程:模版--->ast(抽象树)-->render 函数->虚拟 dom->实际 dom。
-
diff算法
-
vue双向数据绑定以及监听更新
-
eventloop的运行机制
-
vue3的新特性, 静态模板
-
怎样让for of 遍历对象不报错,或者说怎么将对象转为可迭代器
-
canvas的方法 ctx = canvas.getContext("2d") canvas.toDataURL("image/jpg", 0.6) ctx.drawImage(img, 0, 0, newW, newH) ctx.getImageData(x, y, el.width, el.height); ctx.putImageData(oImgData, 0, 0);
-
原型与原型链,执行上下文 原型: 函数有prototype,是个对象,指向内存地址中这个构造函数的属性和方法 原型链: 每个对象都有一个__proto__属性,指向构造该对象的构造函数的原型
-
设计模式 单例模式,观察者模式,原型模式,工厂模式,装饰者模式
-
图片压缩以及比例缩放 利用canvas
-
webpack如何做编译,实现按需加载 webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时,它会在内部从一个或多个入口点构建一个 [依赖图(dependency graph)],然后将你项目中所需的每一个模块组合成一个或多个 bundles,它们均为静态资源,用于展示你的内容
webpack中使用require.ensure实现按需加载
- requestAnimationFrame 是怎么实现的
优势:A. 浏览器可以优化并行的动画动作, 更合理的重新排列动作序列,并把能够合并的动作放在一个渲染周期内完成,从而呈现出更流畅的动画效果 B. 一旦页面不处于浏览器的当前标签,就会自动停止刷新, 这就节省了cpu,Gpu和电力
-
纯函数 只依赖参数的函数,同样的参数得到同样的返回结果
-
vue3中setup与vue2中的created有何不同, 为什么要加一个setup函数
-
vue指令有几个勾子
bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用unbind:只调用一次,指令与元素解绑时调用。
勾子有四个参数el, binding, vnode,oldVnode
- HTML代码中<% %>、<%=%>、<%:%>各是什么意思 <%%> 中间可以写服务端代码
<%=%> 与<%:%> 表示取后台变量
-
htmlwebpackplugin 插件是干嘛的 生成新的index.html文件,并自动将webpack打包的bundle.js自动引入
-
获取页面中所有标签,去重
let allDom = document.querySelectorAll('*')
let obj = {}
for(let i in allDom){
let name = allDom[i].localName
obj[name] = allDom[i]
}
let allLabel = Object.keys(obj)
console.log('aa', allLabel)
- 浏览器重绘与重排
重排(也称回流):当DOM的变化影响了元素的几何属性(宽或高),浏览器需要重新计算元素的几何属性,浏览器会使渲染树中受到影响的部分失效,并重新构造渲染树,然后将渲染树绘制到屏幕上, 叫做重排, 重排必重绘
重绘: 将渲染树将受影响的部分渲染到屏幕上叫重绘
重排何时发生
很显然,每次重排,必然会导致重绘,那么,重排会在哪些情况下发生?
- 添加或者删除可见的DOM元素
- 元素位置改变
- 元素尺寸改变
- 元素内容改变(例如:一个文本被另一个不同尺寸的图片替代)
- 页面渲染初始化(这个无法避免)
- 浏览器窗口尺寸改
获取布局信息的操作会导致队列刷新,比如:
- offsetTop, offsetLeft, offsetWidth, offsetHeight
- scrollTop, scrollLeft, scrollWidth, scrollHeight
- clientTop, clientLeft, clientWidth, clientHeight
- getComputedStyle() (currentStyle in IE)
总结
重排和重绘是DOM编程中耗能的主要原因之一,平时涉及DOM编程时可以参考以下几点:
- 尽量不要在布局信息改变时做查询(会导致渲染队列强制刷新)
- 同一个DOM的多个属性改变可以写在一起(减少DOM访问,同时把强制渲染队列刷新的风险降为0)
- 如果要批量添加DOM,可以先让元素脱离文档流,操作完后再带入文档流,这样只会触发一次重排(fragment元素的应用)
- 将需要多次重排的元素,position属性设为absolute或fixed,这样此元素就脱离了文档流,它的变化不会影响到其他元素。例如有动画效果的元素就最好设置为绝对定位。
-
柯里化函数 柯里化是一种将使用多个参数的函数转换成使用单参数的函数链,也就是将一个n参函数转成n个一元函数。 使用场景,比如bind。 例: f(a,b,c) = f(a)(b)(c)
-
偏函数 偏函数则是固定一个函数的一个或者多个参数,也就是将一个n元函数转换成n-x元函数。 例: f(a,b,c) = f(a,b)(c)
-
compose函数, 利用reduceRight() 加载方向是从右往左
-
pipe函数 加载方向是从左往右
-
强缓存与协商缓存 www.jianshu.com/p/9c95db596…
在浏览器中输入URL并回车后都发生了什么?
-
解析URL
-
DNS解析
-
浏览器与网站建立Tcp链接
-
请求和传输数据
-
浏览器渲染页面
-
自己实现一个eventBus,或者说vue的eventBus实现原理
-
webpack打包做了什么 它会在内部从一个或多个入口点构建一个依赖图,然后将项目中所需的每一个模块组合成一个或多个bundles,它们均为静态资源,用于项目展示内容
-
loader是什么 loader让webpack能够去处理其他类型的文件,并将它们转换为有效模块,以供应用程序使用,以及被加载到依赖视图中
-
plugin是什么 插件是扩展webpack的功能,可以用于执行范围更广的任务。包括:打包优化,资源管理,注入环境变量
-
webpack配置
-
CommonJS规范,AMD规范 CommonJS规范是同步模块加载, AMD规范是异步模块加载
CommonJS 规范是为了解决 JavaScript 的作用域问题而定义的模块形式,可以使每个模块它自身的命名空间中执行。该规范的主要内容是,模块必须通过 module.exports 导出对外的变量或接口,通过 require() 来导入其他模块的输出到当前模块作用域中。
AMD规范中模块通过 define 函数定义在闭包中,格式如下:
id 是模块的名字,它是可选的参数。 dependencies 指定了所要依赖的模块列表,它是一个数组,也是可选的参数,每个依赖的模块的输出将作为参数一次传入 factory 中。如果没有指定 dependencies ,那么它的默认值是 ["require", "exports", "module"] 。 factory 是最后一个参数,它包裹了模块的具体实现,它是一个函数或者对象。如果是函数,那么它的返回值就是模块的输出接口或值。