前端面试题(数据结构、浏览器、业务、网络、wepack、性能优化、小程序、react、vue、JS、CSS)

文章目录

css

如何让一个盒子在水平方向和垂直方向都居中
less或者sass相比于css有什么优势?
  • 嵌套和定义变量
如何做响应式布局或者如何适配
  • flex盒子 、百分比布局 、媒体查询 、rem
css sprite(雪碧图或者精灵图) 有什么优缺点?
  • 优点减少http请求次数、缺点不易维护
你知道哪些css3新特性和h5新特性
  • 圆角  文字阴影 、渐变 、过渡 、媒体查询
  • 绘画  语义化标签  input的 emial和color 、本地存储 localStorage sessionStorage 、拖拽 carver 、video audio 、section header footer
rgba()和opacity的透明效果有什么不同

​ rgba() 和 opacity 都能实现透明效果,但最⼤的不同是 opacity 作⽤于元素,以及元

素内的所有内容的透明度,

⽽ rgba() 只作⽤于元素的颜⾊或其背景⾊。(设置 rgba 透明的元素的⼦元素不会继承

透明效果!)

js

js数据类型有哪些?有什么区别
  • 存储方式不同
  • 基本类型:string /number /boolean/undefined /null/symbol/bigInt
  • 引用类型:object
谈一下你对作用域的理解
  • 标识符(变量和函数) 作用的范围
  • 全局作用域、局部(函数)作用域、块级作用域
  • 作用域链:查找标识符所形成的的查找路径
谈一下你对原型的理解
  • 每一函数身上,都有一个 prototype(显示原型) 的属性,称为“原型”。prototype里面有个constant指向函数本身,通过函数new出来的实例对象会有一个-proto-(隐式原型)指向的是该函数的原型对象。

  • 原型链:原型链就是由对象的 __proto__ 和函数的 prototype 组成的一个链条。

    原型链的作用就是,当一个对象在使用自己身上不存在的属性或方法时,就可以沿着原型链到函数的 prototype 身上去查找。

什么是闭包
  • 能够读取其他函数内部变量的函数
  • 优点:能够延长变量的生命周期、变量私有化,缺点:可能导致内存泄露
如何修改函数的this指向,这些方法之间有什么区别?
  • call、apply、bind,call和apply会立即执行bind不会,
  • call和apply传参的方式不一样call以逗号隔开,apply是以数组传递
事件委托或者事件代理的原理是什么?
  • 事件委托是一种借助event对象.target以及事件执行阶段实现的一种编程技巧。
  • 事件执行阶段按照执行顺序分为三个阶段
    • 第一阶段-捕获:完整的一次捕获事件流
    • 第二阶段-事件目标处理阶段:指的是对具体触发事件的子标签进行处理
    • 第三阶段-冒泡阶段:完整的一次冒泡事件流
  • event对象:JavaScript在每触发一个事件的时候,都会自动生成一个对象来记录当前触发事件的有关信息,并作为事件处理程序的实际参数传入其中。
事件冒泡和事件捕获的区别是什么?
  • 事件冒泡:一个由里到外,冒泡,向上层延申。

  • 事件捕获:一个由外到里,前往捕获,形成向下趋势。

    • 需要使用DOM2级的事件处理程序才能使用,dom0级的事件处理程序只支持冒泡。

      • a:写在标签内的onclick事件都是DOM0级事件     b:获取元素,绑定onclick等事件也是DOM0级事件
你知道的es6新特性有哪些?
  • let、const、class、箭头函数、扩展运算符、promise、async 、
js异步编程方式有几种
  • 三种:ajax回调函数 、promise 、async await
promise有几种状态

​ pending fulfilled rejected 当我们创建一个Promise对象的时候,它的状态默认是pending ,要修改它的状态必须调用resolve方法或者reject方法

const myPromiseObj = new Promise((resolve,reject)=>{
	setTimeout(()=>{
		resolve()
	})
})
myPromiseObj.then(()=>{}).catch(()=>{})
js如何浅拷贝和深拷贝一个对象

​ 浅拷贝:Object.assign 或者拓展运算符...

​ 深拷贝:const deepCopiedObj = JONS.parse(JSON.stringify(obj))

rem和em和px的区别

​ px是固定单位,rem和em是响应式单位,1rem的大小取决于根节点html的字体大小(即font-size属性),1em的大小取决于其父节点的字体大小,在移动端我们一般用rem,但是要注意:这时html的fontSize属性应该是动态计算的,而不是写死,一般是把当前可视窗口的宽度除以一个经验值得到的比值作为html的fontSize属性值的。

for循环中break和continue的区别是什么?

break:跳出整个循环

continue:跳出档次循环,继续执行后面的循环

如何用原生js给一个按钮的点击事件绑定两个事件处理函数

​ addEventListener

js引擎如何实现异步的?

​ js引擎是通过事件循环(Event Loop)实现异步的

​ 什么是事件循环??

​ js引擎里面有两个非常重要的部分:执行栈和任务队列

​ 所有的代码都要加载到执行栈里面进行执行

​ 在执行过程中如果发现有异步任务,则js引擎会把这个异步任务交给浏览器的其他线程去处理,比如在执行的时候遇到

​ 接口发送,则js引擎会把它交给http请求线程去处理,然后js引擎继续执行后边的同步任务,但是同http请求线程也在同时

​ 运作,当请求发送成功之后,即数据拿到之后,http请求线程会将我们之前在js里面设置的回调函数推送到js引擎的任务队列里面

​ 当js引擎在执行栈里面把任务清空之后,则回到任务队列里面去寻找有没有待执行的回调函数,有则拿到执行栈里面去执行

​ 执行完了之后,又会到任务队列里面去寻找有没有待执行的回调,如此循环往复的过程就是事件循环,理解了事件循环就理解了

  * 浏览器是多线程的,js引擎只是其中一个线程,除此之外还有http请求线程,定时触发线程,事件处理线程,GUI渲染线程
什么是函数柯理化?

​ 通过函数返回函数的方式(闭包),让一个一次性接受多个参数的函数,分解为一次只接受一个参数的若干函数的组合

​ 其作用是为了参数的复用,

function towSum(a,b){
	return a + b;
}

//现在对上面的函数进行柯理化
function towSum(a){
	return function(b){
		return a + b;
	}
}
或者
const res = (a)=>(b)=>a+b;
微任务和宏任务的区别
  • 微任务的优先级高于宏任务
DOMContentLoaded和load事件的区别
  • 前者的执行时机要早一点
防抖和节流有什么区别,如何实现

​ 在高频触发的事件中,可能会导致一些性能问题,比如在PC端浏览器缩放时(resize事件),我们在事件处理函数里面如果操作DOM,则用户缩放的时候,可能会导致浏览器卡顿,这是我们就可以通过防抖节流来控制操作DOM的频率,避免过快的操作DOM,但是这两者的区别在于:

​ 防抖的思路是:设置一个延时器,延时n秒在执行相应的逻辑(即频繁执行可能会影响性能的逻辑),如果在n秒内,再次执行了,则清空延时器,并从当下开始从新设置延时器,n秒后再执行。

​ 节流的思路是:在特定的时间段内,相应的逻辑必须有且只能执行一次。

//防抖
function debunce(func,time){
	let timer = null;
	return function(){
		if(timer)clearInterval(timer);
		timer = setTimeout(()=>{
			func.apply(this,arguments)
		},time);
	}
}
//节流
function throttle(func,time){
	let preTime = +new Date()
	return function(){
		const curTime = +new Date()
		if(curTime - preTime >= time){
			func.apply(this,arguments);
			preTime = curTime;
		}
	}
}
代码题
var a = {};
var b = {key:"b"};
var c = {key:"c"};
a[b] = "b";
a[c] = "c";
console.log("a[b]",a[b]);//???

var age = 100;
let years = 6;
if(age > 12){
    let age = 10;
    var years = age*3;
}
//问:以上代码有问题吗?
 componentDidMount() {
        this.setState({ count: this.state.count + 1 });
        console.log('1', this.state.count);
        this.setState({ count: this.state.count + 1 });
        console.log('2', this.state.count);
        setTimeout(() => {
            this.setState({ count: this.state.count + 1 });
            console.log('3', this.state.count);
            this.setState({ count: this.state.count + 1 });
            console.log('4', this.state.count);
        }, 0);

    }
    
    //打印结果
    
 function Cat() {
           let showName = function () {
                console.log(1);
            }
            return this;
 }
       
        Cat.showName = function () { console.log(2) };
        Cat.prototype.showName = function () { console.log(3) };
        var showName = function () { console.log(4) };
        function showName() { console.log(5) };
        Cat.showName();
        showName();
        Cat().showName();
        showName();
        new Cat.showName();
        new Cat().showName();
        new new Cat().showName();
        //打印结果??
 function Cat() {
           showName = function () {
                console.log(1);
            }
            console.log('this',this)
            return this;
           
 }
       
        Cat.showName = function () { console.log(2) };
        Cat.prototype.showName = function () { console.log(3) };
        var showName = function () { console.log(4) };
        function showName() { console.log(5) };
        Cat.showName();
        showName();
        Cat().showName();
        showName();
        new Cat.showName();
        new Cat().showName();
        new new Cat().showName();
        
        //打印结果,注意跟上一题的区别
  1. 这段代码有什么问题吗?

    this.setState((state,props)=>{
    	return {total:state.total + props.count}
    });
    
  2. 查看一下代码:如果你在页面中创建了一个React元素,请完成他的组件定义?

    <Profile username="sofn">
    	{user=>user===null ? <Loading/> : <Badge info={user}/>}{" "}
    </Profile>
    
    import React ,{Component} from 'react';
    import PropTypes from 'prop-types';
    import fetchUser from 'utils';
    //fetchUser接收用户名,并返回promise
    //当得到用户数据的时候返回resolve状态
    class Profile extends Component{
    	//在这里写下你的代码
    	
    }
    

vue

vue2和vue3的区别
  • 底层的响应式api不一样了
    • vue2:object.definePropery
    • vue3: proxy
      • 好处:vue2中对于数组 对象 的改变有些监听不到
  • vue2是选项式api(options api)vue3是组合式api(composition api)
  • vue3可以有多个根节点。 vue2是将数据放在data属性中,vue3是使用setup()。 生命周期钩子不同。vue3中取消了beforeCreate和created。
vue组件中watch和computed的区别
1. watch中一个值的变化可能会引起多个值的变化,而compouted中多个值的变化会只会影响一个值的变化(即该计算属性返回的值)
2. 在watch中我们可能会有副作用,比如发送请求等,而computed则没有副作用,仅仅是根据母体数据衍生出新的数据而已。
3、功能:computed是计算属性,watch是监听一个值的变化而执行对应的回调
是否调用缓存:computed函数所依赖的属性不变的时候会调用缓存;watch每次监听的值发生变化时候都会调用回调
4、是否调用return:computed必须有;watch可以没有
5、使用场景:computed当一个属性受多个属性影响的时候;例如购物车商品结算;watch当一条数据影响多条数据的时候,例如搜索框
6、是否支持异步:computed函数不能有异步;watch可以

vue常用的生命周期钩子函数有哪些?分别有什么作用?
钩子函数 created mounted updated beforeDestory
执行时机 数据初始化完毕之后 DOM渲染完毕之后 数据更新完毕并且DOM更新完毕之后 组件卸载之前
作用 发送请求 发送请求、获取DOM等 发送请求(注意加上条件判断)、获取DOM等 性能优化相关,比如清除定时器、延时器、解绑事件等
vue如何实现组件通信(组件传值)? 父子 兄弟 复杂组件关系

组件关系 父子 兄弟 复杂组件关系
通信方式 props/绑定自定义事件、$emit 状态提升、事件总线 状态机vuex

vue项目如何做路由拦截?

​ 全局路由守卫(router.beforeEach)、局部(页面内部)路由守卫

vue的响应式原理 Object.defineProperty

1、数据劫持:给所有的数据添加get和set

2、发布订阅者模式(观察者模式):每一个data中的数据都对应值一个订阅者当被节点渲染后就会产生一个观察者(一个数据只有一个订阅者,可以有多个观察者)

​ vue组件中data里面的数据,在初始渲染之前都会被Object.defineProperty转化成响应式数据,然后这些数据的访问和修改就能够被监听了,每当数据被访问的时候就会触发getter,接着会通知watcher,watcher这是会做一次依赖的收集或者更新,然后watcher会负责通知渲染界面(先转化为虚拟DOM,在映射为真正的DOM)。每当数据被设置的时候会触发setter,接着setter也会通知watcher,watcher在去通知渲染界面

v-if和v-show的区别
  • v-if是节点的渲染与销毁,v-show是样式的隐藏和显示

1、v-if有更高的切换开销,v-show有更高的初始渲染开销。
如果需要频繁的切换,使用v-show比较好,如果运行条件很少改变,使用v-if比较好。

2、v-show比v-if性能更高,因为v-show只能动态的改变样式,不需要增删DOM元素。
所以当程序不是很大时候,v-if和v-show区别都不大,如果项目很大,推荐多用v-show,较少浏览器后期操作的性能。

v-if和v-for能一起用吗
  • 可以但不推荐,v-for的优先级比v-if高
keep-alive组件有什么作用
  • 缓存组件:可以让组价中的数据可以不被销毁
  • 被包含在<keep-alive>中的组件,会比普通组件多出两个生命周期函数:activateddeactivated
this.$nextTick有什么作用
  • 获取数据更新后的,最新dom节点的状态

类似updated,你可以称作移动版的updated,如果你想获取数据更新过后,DOM的最新状态,则可以使用该方法(如果你直接获取DOM状态是拿不到的,因为在vue里面数据更新虽然是同步的,但是DOM的更新是异步的),当然你也可以利用updated生命周期钩子函数,但是不方便

this.$set有什么作用

​ 在组件data中预定义的数据,一定是响应式的,但是我们后续,通过常规的方式(比如someObject.propName = xxx)为data中某些对象添加新的属性时,这些新的属性并不是响应式的,这是可以使用该方法。 this.$set(target,prop,value) 这里的prop属性就是响应式的

data(){
   
    return{
   
        a:{
   
            name:"张三"
        }
    }
}mounted(){
   
    //this.a.sex='男' 这样更改的数据不能更新到页面上
    this.$set(this.a,'sex','男')//这时可以用这个
    console.log(this.a)
}
vuex核心概念
  • state、getters、mutations、actions、modules
vue如何做路由懒加载

​ 路由配置中component属性的值修改为:()=>import(组件路径)

你认为vue 框架和jquery有什么区别?

开发思想不同,vue是数据驱动,并且可以组件化开发,jquery则是DOM驱动的,开发效率低

vue如何自定义指令
  • 全局指令 : 通过 Vue.directive () 函数注册一个全局的指令。
如何封装一个vue插件
  • 通过全局方法 Vue.use() 使用插件
  • Vue.js 的插件应该暴露一个 install 方法
vue中什么是过滤器(filter)
  • Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式

  • 组件内过滤器

    filters: {
         
      capitalize: function (value) {
         
        if (!value) return ''
        value = value.toString
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值