前端面试题库
link 和 @import的区别是什么?
- link是xhtml标签,无兼容性问题,@import是css2.1提出的,低版本浏览器不支持,只有ie5以上才支持
- link能加载css javascript @import只能加载css
- link链接的内容是和html页面同步加载的,@import需要等到页面全部加载完成之后才能加载。
- link引入的样式权重大于@import引入的样式。
几种常见浏览器,及其内核分别是什么?
现在国内常见的浏览器有:IE、Firefox、QQ浏览器、Safari、Opera、GoogleChrome、百度浏览器、搜狗浏览器、猎豹浏览器、360浏览器、UC浏览器、遨游浏览器、世界之窗浏览器等。但目前最为主流浏览器有五大款,分别是IE、Firefox、GoogleChrome、Safari、Opera。
- IE浏览器内核:Trident内核,也是俗称的IE内核;
- Chrome浏览器内核:统称为Chromium内核或Chrome内核,以前是Webkit内核,现在是Blink内核;
- Firefox浏览器内核:Gecko内核,俗称Firefox内核;
- Safari浏览器内核:Webkit内核;
- Opera浏览器内核:最初是自己的Presto内核,后来是Webkit,现在是Blink内核;
- 360浏览器、猎豹浏览器内核:IE+Chrome双内核;
- 搜狗、遨游、QQ浏览器内核:Trident(兼容模式)+Webkit(高速模式);
- 2345浏览器内核:以前是IE内核,现在也是IE+Chrome双内核;
请描述一下cookies、sessionStorage和localStorage的区别?
cookie、sessionStorage、localStorage的相同点是都存储在客户端,不同点分别表现在存储大小、有效时间、数据与服务器的交互方式
1. 存储大小
- cookie数据大小不能超过4k。
- sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。
2. 有效时间
- localStorage 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据;
- sessionStorage 数据在当前浏览器窗口关闭后自动删除。
- cookie 设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭
3. 数据与服务器之间的交互方式
- cookie的数据会自动的传递到服务器,服务器端也可以写cookie到客户端
- sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。
new操作符具体干了什么呢?
function Func(){
}
let func= new Func();
1. 创建了⼀个空对象,作为要返回的实例对象
let obj = new Object();
2. 将空对象的原型 proto 指向构造函数的 prototype 属性
obj.__proto__ = Func.prototype;
把 obj 的proto 指向构造函数Func的原型对象 prototype,此时便建立了 obj 对象的原型链:
obj->Func.prototype->Object.prototype->null
3. 以指定构造函数的 this 为新创建的对象的⽅式调⽤构造函
let result = Func.call(obj);
让Func中的this指向obj,并执行Func的函数体。
4. 判断构造函数返回值类型返回对象
if (typeof(result) == "object"){
func=result;
}
else{
func=obj;
}
判断Func的返回值类型:
如果无返回值 或者 返回一个非对象值,则将 obj 作为新对象返回;否则会将 result 作为新对象返回。
js延迟加载的方式有哪些?
- 在script标签上,设置defer属性,可以达到异步加载js文件,延迟执行js脚本文件的目的
- 在script标签上,设置async属性,可以达到异步加载js文件的目的。
- 动态创建script标签,当页面的全部内容加载完毕后,在执行创建挂载
什么是闭包?使用场景有哪些?
闭包是指有权访问另一个函数作用域中的变量的函数
function fn1() {
var name = 'Fuleny'
return function() {
console.log(name)
}
}
var fn2 = fn1()
fn2()
在上述代码中,闭包指的就是 return function() { console.log(name) }
这个函数。
这个函数在fn1函数作用域内部,所以能访问到函数内部的变量name,fn1函数内部的返回值由全局作用域下的变量fn2接收,调用fn2就可以实现在全局变量下访问局部变量中的变量的值。
常见场景:
- 用闭包模拟私有方法
- 回调
- 列表循环点击
js中null 和 undefined 有什么区别?
javascript权威指南:null 和 undefined 都表示 “值的空缺”,你可以认为 undefined 是表示系统级的、出乎意料的或类似错误的值的空缺,而null是表示程序级的、正常的或在意料之中的值的空缺。
javascript高级程序设计:在使用var声明变量但未对其加以初始化时,这个变量的值就是undefined。nunll值则是表示空对象指针
undefined
undefined代表未定义,也就是不存在的意思。也可以换个角度,就是应该有值,但是还没赋值,连null值都没有赋予。
null
null则代表有值,是存在的,但是为空值。空值不是不存在,而是有一个叫做 空值
的值。在语言层面,null是object,是一种特殊的 空对象
。如果把一个变量赋予null,则该变量原先指向的对象可以被GC回收,释放内存空间。当然也可以认为null是null类型,这不影响实际的意义。
Doctype的作用是什么?严格模式与混杂模式如何区分?它们有什么意义?
作用: DOCTYPE是document type(文档类型的)的简写。用来说明你用的是XHTML获HTML是什么版本。
如何区分: 浏览器解析时到底使⽤严格模式还是混杂模式,与⽹页中的 DTD 直接相关。不声明 DOCTYPE 的话,浏览器会以 Quicks Mode(混杂模式) 渲染页面
严格模式:⼜称标准模式,是指浏览器按照 W3C 标准解析代码。
混杂模式:⼜称怪异模式或兼容模式,是指浏览器⽤⾃⼰的⽅式解析代码。
意义: 严格模式与混杂模式存在的意义与其来源密切相关,如果说只存在严格模式,那么许多旧⽹站必然受到影响,如果只存在混杂模式,那么会回到当时浏览器⼤战时的混乱,每个浏览器都有⾃⼰的解析模式。
谈谈如何优化网页运行性能?
- 减少 HTTP 请求数
- 减少 DNS 查询
- 使用 CDN
- 避免重定向
- 图片懒加载
- 减少 DOM 元素数量
- 减少 DOM 操作
- 使用外部 JavaScript 和 CSS
- 压缩 JavaScript、CSS、字体、图片等
- 优化 CSS Sprite
- 使用 iconfont
- 多域名分发划分内容到不同域名
- 尽量减少 iframe 使用
- 避免图片 src 为空
- 把样式表放在 link 中
- 把 JavaScript 放在页面底部
js数据类型有什么?
基本数据类型:
Number、String、Boolean、Null、Undefined、Symbol、bigInt
引用数据类型:
object、Array、Date、Function、RegExp
js中数组(array)有哪些方法?
- map : 遍历数组,返回回调返回值组成的新数组
- forEach : 无法 break ,可以用 try/catch 中 throw new Error 来停止filter : 过滤
- some : 有一项返回 true ,则整体为 true
- every : 有一项返回 false ,则整体为 false
- join : 通过指定连接符生成字符串
- push / pop : 末尾推入和弹出,改变原数组, 返回推入/弹出项
- unshift / shift : 头部推入和弹出,改变原数组,返回操作项
- sort(fn) / reverse : 排序与反转,改变原数组
- concat : 连接数组,不影响原数组, 浅拷贝
- slice(start, end) : 返回截断后的新数组,不改变原数组
- splice(start,number,value…): 返回删除元素组成的数组,value 为插入项,改变原数组
- indexOf / lastIndexOf(value, fromIndex) : 查找数组项,返回对应的下标
- reduce / reduceRight(fn(prev, cur) ,defaultPrev) : 两两执行,prev 为上次化简函数的return 值,cur 为当前值(从第二项开始)
什么是同源策略?
同源指的是域名、协议、端口号相同
如何解决跨域?
- jsonp跨域
- document.domain + iframe 跨域
- nodejs中间件代理跨域
- 后端在头部信息里面设置安全域名
什么是作用域链?
作用域链可以理解为一组对象列表,包含 父级和自身的变量对象,因此我们便能通过作用域链访问到父级里声明的变量或者函数
js变量和函数声明的提升
在js中变量和函数的声明会提升到最顶部执行
函数的提升高于变量的提升
函数内部如果用 var 声明了相同名称的外部变量,函数将不再向上寻找。
匿名函数不会提升。
什么是原型、原型链、继承?
所有的函数都有prototype属性(原型)
所有的对象都有proto属性
在Javascript中,每个函数都有一个原型属性prototype指向自身的原型,而由这个函数创建的对象也有一个proto属性指向这个原型,而函数的原型是一个对象,所以这个对象也会有一个proto指向自己的原型,这样逐层深入直到Object对象的原型,这样就形成了原型链。
JS垃圾回收机制是怎样的?
1.概述
js的垃圾回收机制是为了防止内存泄漏(已经不需要的某一块内存还一直存在着),垃圾回收机制就是不停歇的寻找这些不再使用的变量,并且释放掉它所指向的内存。
在JS中,JS的执行环境会负责管理代码执行过程中使用的内存。
2.变量的生命周期
当一个变量的生命周期结束之后,它所指向的内存就会被释放。js有两种变量,局部变量和全局变量,局部变量是在他当前的函数中产生作用,当该函数结束之后,该变量内存会被释放,全局变量的话会一直存在,直到浏览器关闭为止。
3.js垃圾回收方式
有两种方式: 标记清除、引用计数
标记清除:大部分浏览器使用这种垃圾回收,当变量进入执行环境(声明变量)的时候,垃圾回收器将该变量进行了标记,当该变量离开环境的时候,将其再度标记,随之进行删除。
引用计数:这种方式常常会引起内存的泄露,主要存在于低版本的浏览器。它的机制就是跟踪某一个值得引用次数,当声明一个变量并且将一个引用类型赋值给变量得时候引用次数加1,当这个变量指向其他一个时引用次数减1,当为0时出发回收机制进行回收。
逐进增强和优雅降级
逐进增强
针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高版本浏览器进行效果、交互等改进和追加功能达到更好的用户体验。
优雅降级
一开始就构建完整的功能,然后再针对低版本浏览器进行兼容
什么是单线程,和异步的关系?
单线程 :只有一个线程,只能做一件事
原因 : 避免 DOM 渲染的冲突
浏览器需要渲染 DOM
JS 可以修改 DOM 结构
JS 执行的时候,浏览器 DOM 渲染会暂停
两段 JS 也不能同时执行(都修改 DOM 就冲突了)
webworker 支持多线程,但是不能访问 DOM
解决方案 :异步
说说异步编程的实现方式?
回调函数
- 优点:简单、容易理解
- 缺点:不利于维护、代码耦合高
事件监听
- 优点:容易理解,可以绑定多个事件,每个事件可以指定多个回调函数
- 缺点:事件驱动型,流程不够清晰
发布/订阅(观察者模式)
类似于事件监听,但是可以通过‘消息中心’,了解现在有多少发布者,多少订阅者
Promise 对象
- 优点:可以利用 then 方法,进行链式写法;可以书写错误时的回调函数
- 缺点:编写和理解,相对比较难
Generator 函数
- 优点:函数体内外的数据交换、错误处理机制
- 缺点:流程管理不方便
async 函数
- 优点:内置执行器、更好的语义、更广的适用性、返回的是 Promise、结构清晰
- 缺点:错误处理机制
js数组和对象的遍历方式
- for in
- for
- forEach
- for-of
数组去重有什么方法?
// 使用 `Set`
const newArr = Array.from(new Set([1, 2, 3, 4, 4, 4, 1]));
// 使用 `indexOf`
const unique = function (arr) {
const newArray = [];
arr.forEach((item) => {
if (newArray.indexOf(item) === -1) {
newArray.push(item);
}
});
return newArray;
};
// 使用 `sort`
const unique = function (data) {
const newArray = [];
let arr = data;
arr.sort();
for (let i = 0; i < arr.length; i++) {
if (arr[i] !== arr[i + 1]) {
newArray.push(arr[i]);
}
}
return newArray;
};
如何实现节流函数?
function throttle(fn, delay) {
let canUse = true;
return function () {
if (canUse) {
canUse = false;
fn.call();
setTimeout(() => {
canUse = true;
}, delay);
}
};
}
const throttled = throttle(() => console.log("throttled"), 1000);
如何实现防抖函数?
function debounce(fn, delay) {
let timerId = null;
return function () {
const context = this;
if (timerId) clearTimeout(timerId);
timerId = setTimeout(() => {
fn.apply(context, arguments);
}, delay);
};
}
const debounced = debounce(() => console.log("debounced"), 3000);
vue3和vue2的钩子函数有什么区别?
vue2 --------------- vue3
beforeCreate -> setup()
Created -> setup()
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeDestroyed -> onBeforeUnmount
destroyed -> onUnmounted
activated -> onActivated
deactivated -> onDeactivated
vue更新数组时触发视图更新的方法
push();
pop();
shift();
unshift();
splice();
sort();
reverse()
vue优点
- 轻量级
- 速度快
- 简单易学
- 低耦合
- 可重用性
- 独立开发
- 文档齐全,且文档为中文文档
v-if和v-show有什么区别?
v-show
隐藏是为该元素添加css display:none
, v-if
显示隐藏是将dom
元素整个添加删除。
vue组件的通信方式
props/$emit
父子组件通信
父->子props
,子->父$on
、$emit
获取父子组件实例parent
、children
Ref
获取实例的方式调用组件的属性或者方法 父->子孙Provide
、inject
官方不推荐使用,但是写组件库时很常用$emit/$on
自定义事件 兄弟组件通信Event Bus
实现跨组件通信Vue.prototype.$bus = new Vue()
自定义事件vuex 跨级组件通信
Vuex
、$attrs
、$listeners
Provide
、inject
var && let && const的区别
ES6之前创建变量用的是var,之后创建变量用的是let/const
三者区别:
- var定义的变量,没有块的概念,可以跨块访问, 不能跨函数访问。
let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问。
const用来定义常量,使用时必须初始化(即必须赋值),只能在块作用域里访问,且不能修改。 - var可以先使用,后声明,因为存在变量提升;let必须先声明后使用。
- var是允许在相同作用域内重复声明同一个变量的,而let与const不允许这一现象。
- 在全局上下文中,基于let声明的全局变量和全局对象GO(window)没有任何关系 ;
var声明的变量会和GO有映射关系; - 会产生暂时性死区:
暂时性死区是浏览器的bug:检测一个未被声明的变量类型时,不会报错,会返回undefined
如:console.log(typeof a) //undefined
而:console.log(typeof a)//未声明之前不能使用
let a let /const/function
会把当前所在的大括号(除函数之外)作为一个全新的块级上下文,应用这个机制,在开发项目的时候,遇到循环事件绑定等类似的需求,无需再自己构建闭包来存储,只要基于let的块作用特征即可解决