前端面试题总结
1.作用域和值类型引用类型的传递
第一题:作用域
var num1 = 55;
var num2 = 66;//100
function f1(num, num1) {
// var num =55;
// var num1 = 66;
num = 100;//100
num1 = 100;//100
num2 = 100;//100
console.log(num);//100
console.log(num1);//100
console.log(num2);//100 }
// 55 66
f1(num1, num2);
console.log(num1);//55
console.log(num2);//100
console.log(num);// 报错
第二题:值类型和引用类型的传递
function Person(name, age, salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
function f1(person) {
//var person = p;
person.name = "ls";
person = new Person("aa", 18, 10);
}
var p = new Person("zs", 18, 1000);
console.log(p.name);//zs
f1(p);
console.log(p.name);//ls
2.封装函数将字符串进行驼峰命名
//已知有字符串foo='get-element-by-id',写一个function将其转化成驼峰表示法”getElementById” //自定义函数 function toString(foo) { // var foo = 'get-element-by-id'; //根据某个字符进行切割 var arr = foo.split('-'); //获取每个元素中的第一个字符并转换成大写 console.log(arr[1].charAt(0).toUpperCase() + arr[1].substr(1, arr[1].length - 1)); for(var i = 1; i < arr.length; i++) { arr[i] = arr[i].charAt(0).toUpperCase() + arr[i].substr(1, arr[i].length - 1) } //根据某个字符将数组转成字符串 return arr.join(''); } console.log(toString('get-element-by-id'));
3.冒泡排序
var arr = [32,4,67,82,21,11]; ///轮数 for(var i = 0; i<arr.length-1;i++){ //次数 for(var j = 0;j<arr.length-1-i;j++){ //判断前一个大于后一个数时进行交换 if(arr[j]>arr[j+1]){ //借助第三方变量交换两个变量的值 var temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } console.log(arr);
4.反转数组
var arr = [1,2,3,4,5,6,7,8]; for(var i = 0;i<arr.length/2;i++){ //arr[0] arr[arr.length-1-0]; //arr[1] arr[arr.length-1-1]; //arr[2] arr[arr.length-1-2]; //arr[3] arr[arr.length-1-3]; //借助第三方变量交换两个变量的值 var temp = arr[i]; arr[i] = arr[arr.length-1-i]; arr[arr.length-1-i] = temp; } console.log(arr);
5.去掉数组中重复的数组
/* * 1.创建一个新数组,把原数组中的第一个元素插入到新数组中 * 2.遍历原数组中的每一个元素分别和新数组中的每一个元素进行比较 */ //原数组 var arr = [8,11,20,5,20,8,0,2,4,0,8]; // 新数组 var t = [];//var t = [8,11]; t[0] = arr[0]; //arr中的每个元素 for(var i=0;i<arr.length;i++){ //t中的每个元素 for(var k = 0;k<t.length;k++){ //当原数组中的值和新数组中的值相同的时候,就没有必要再继续比较了,跳出内循环 if(t[k] == arr[i]){ break; } //拿原数组中的某个元素比较到新数组中的最后一个元素还没有重复 if(k == t.length-1){ //将数据插入新数组 t.push(arr[i]); } } } console.log(t);
6.1物理像素
方式一:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no" /> <title></title> <style type="text/css"> *{ margin: 0; padding: 0; } #box{ width: 8rem; height: 8rem; border: 1px solid #000000; } </style> </head> <body> <div id="box"></div> </body> <script type="text/javascript"> var box = document.getElementById('box'); //获取设备像素比 var dpr = window.devicePixelRatio; //比例 var scale = 1/dpr; //获取屏幕宽度 375 var width = document.documentElement.clientWidth; //获取meta标签 var metaNode = document.querySelector('meta[name="viewport"]') metaNode.setAttribute('content','width=device-width,initial-scale='+ scale +',user-scalable=no') //元素比例乘回来 var htmlNode = document.querySelector('html'); htmlNode.style.fontSize = width/16*dpr + 'px'; </script> </html>
方式二:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no" /> <title></title> <style type="text/css"> *{ margin: 0; padding: 0; } #box{ width: 200px; height: 200px; position: relative; } #box:after{ content: ''; position: absolute; left: 0; bottom: 0; width: 100%; height: 1px; background: #000000; } @media screen and ( -webkit-min-device-pixel-ratio:2 ) { #box:after{ transform: scaleY(0.5); } } @media screen and ( -webkit-min-device-pixel-ratio:3 ) { #box:after{ transform: scaleY(0.333333333333); } } </style> </head> <body> <div id="box"></div> </body> </html>
7.实现元素的水平垂直居中
方法一:(利用定位)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style type="text/css"> * { margin: 0; padding: 0; } #wrap { width: 500px; height: 500px; background: grey; position: relative; } #box{ position: absolute; top: 0; left: 0; bottom: 0; right: 0; margin: auto; width: 200px; height: 200px; background: deeppink; } </style> </head> <body> <div id="wrap"> <div id="box"></div> </div> </body> <script type="text/javascript"> window.onload = function () { var box = document.getElementById('box'); } </script> </html>
方法二(利用定位+margin)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style type="text/css"> * { margin: 0; padding: 0; } #wrap { width: 500px; height: 500px; background: grey; position: relative; } #box{ position: absolute; top: 50%; left: 50%; margin-top: -100px; margin-left: -100px; width: 200px; height: 200px; background: deeppink; } </style> </head> <body> <div id="wrap"> <div id="box"></div> </div> </body> <script type="text/javascript"> window.onload = function () { var box = document.getElementById('box'); } </script> </html>
方法三(利用css3属性translate)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style type="text/css">
* {
margin: 0;
padding: 0;
}
#wrap {
width: 500px;
height: 500px;
background: grey;
position: relative;
}
#box{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
width: 200px;
height: 200px;
background: deeppink;
}
</style> </head> <body> <div id="wrap"> <div id="box"></div> </div> </body> <script type="text/javascript"> window.onload = function () { var box = document.getElementById('box'); } </script> </html>
方法四(flex元素新)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style type="text/css"> * { margin: 0; padding: 0; } #wrap { width: 500px; height: 500px; background: grey; display: flex; justify-content: center; align-items: center; } #box{ width: 200px; height: 200px; background: deeppink; } </style> </head> <body> <div id="wrap"> <div id="box"></div> </div> </body> <script type="text/javascript"> window.onload = function () { var box = document.getElementById('box'); } </script> </html>
方法五:(利用flex元素旧)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style type="text/css"> * { margin: 0; padding: 0; } #wrap { width: 500px; height: 500px; background: grey; display: -webkit-box; -webkit-box-pack: center; -webkit-box-align: center; } #box{ width: 200px; height: 200px; background: deeppink; } </style> </head> <body> <div id="wrap"> <div id="box"></div> </div> </body> <script type="text/javascript"> window.onload = function () { var box = document.getElementById('box'); } </script> </html>
8.css实现三角形
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style type="text/css"> * { margin: 0; padding: 0; } #box { width: 0px; height: 0px; border: 100px solid transparent; border-top-color: deeppink; border-left-color: deeppink; /*border-right-color: deeppink;*/ /*border-bottom-color: deeppink;*/ } </style> </head> <body> <div id="box"></div> </body> <script type="text/javascript"> window.onload = function () { var box = document.getElementById('box'); } </script> </html>
9.rem适配
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no" /> <title></title> <style type="text/css"> *{ margin: 0; padding: 0; } #box{ width: 8rem; height: 8rem; background: deeppink; } </style> </head> <body> <div id="box"></div> </body> <script type="text/javascript"> //获取屏幕宽度 var width = document.documentElement.clientWidth; //获取html var htmlNode = document.querySelector('html'); //设置html字体大小 htmlNode.style.fontSize = width/16 + 'px'; </script> </html>
10.背景图片的距离
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style type="text/css"> * { margin: 0; padding: 0; } #box{ width: 100px; height: 200px; background: pink; padding: 100px; border: 80px solid blue; background-image: url("img/1.png"); background-repeat: no-repeat; background-origin: content-box; background-position: -50px 0; } /*答案:130px*/ </style> </head> <body> <div id="box"></div> </body> </html>
11.闭包
/* company: shangguigu author: yanzhiyong content: 闭包 */ /* * 理解:什么是闭包? * 1. 密闭的容器,类似于set,map容器,存储数据的 * 2. 闭包是一个对象,存放数据的格式: key: value * 形成的条件: * 1. 函数嵌套 * 2. 内部函数引用外部函数的局部变量 * 闭包的优点: * 延长外部函数局部变量的生命周期 * 闭包的缺点: * 容易造成内存泄漏 * 注意点: * 1. 合理的使用闭包 * 2. 用完闭包要及时清除(销毁) * */ // function fun() { // var count = 1; // function fun2() { // console.log(count); // } // // fun2(); // } // // fun(); // 闭包的应用场景 // function fun() { // var count = 1; // return function () { // count++; // console.log(count); // } // } // // var fun2 = fun(); // fun2(); // 2 // fun2(); // 3 // /* 说说它们的输出情况 */ function fun(n, o) { // var n = 1, o; console.log(o) return { fun: function (m) { // var m = 1; return fun(m, n) } } } var a = fun(0) a.fun(1) a.fun(2) a.fun(3) //undefined,0,0,0 var b = fun(0).fun(1).fun(2).fun(3).fun(50).fun(22) //undefined,0,1,2,3,50 var c = fun(0).fun(1) c.fun(2) c.fun(3) //undefined,0,1,1
12.微任务和宏任务
/* company: shangguigu author: yanzhiyong content: 宏任务和微任务 */ /* * 宏任务 * 分类: setTimeout setInterval requrestAnimationFrame * 1. 宏任务所处的队列就是宏任务队列 * 2. 第一个宏任务队列中只有一个任务: 执行主线程的js代码 * 3. 宏任务队列可以有多个 * 4. 当宏任务队列的中的任务全部执行完以后会查看是否有微任务队列如果有先执行微任务队列中的所有任务,如果没有就查看是否有宏任务队列 * * 微任务 * 分类: new Promise().then(回调) process.nextTick * 1. 微任务所处的队列就是微任务队列 * 2. 只有一个微任务队列 * 3. 在上一个宏任务队列执行完毕后如果有微任务队列就会执行微任务队列中的所有任务 * */ console.log('----------------- start -----------------'); setTimeout(() => { console.log('setTimeout'); }, 0) new Promise((resolve, reject) =>{ for (var i = 0; i < 5; i++) { console.log(i); } resolve(); // 修改promise实例对象的状态为成功的状态 }).then(() => { console.log('promise实例成功回调执行'); }) console.log('----------------- end -----------------');
13. 比较一下React与Vue
1) 相同点
1) 都有组件化开发和Virtual DOM
2) 都支持props进行父子组件间数据通信
3) 都支持数据驱动视图, 不直接操作真实DOM, 更新状态数据界面就自动更新
4) 都支持服务器端渲染
5) 都有支持native的方案,React的React Native,Vue的Weex
2) 不同点
1) 数据绑定: vue实现了数据的双向绑定,react数据流动是单向的
2) 组件写法不一样, React推荐的做法是 JSX , 也就是把HTML和CSS全都写进JavaScript了,即'all in js'; Vue推荐的做法是webpack+vue-loader的单文件组件格式,即html,css,js写在同一个文件
3) state对象在react应用中不可变的,需要使用setState方法更新状态;在vue中,state对象不是必须的,数据由data属性在vue对象中管理
4) virtual DOM不一样,vue会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树.而对于React而言,每当应用的状态被改变时,全部组件都会重新渲染,所以react中会需要shouldComponentUpdate这个生命周期函数方法来进行控制
5) React严格上只针对MVC的view层,Vue则是MVVM模式
14. 说说Vue组件间通信方式
1) 通信种类
1) 父组件向子组件通信
2) 子组件向父组件通信
3) 隔代组件间通信
4) 兄弟组件间通信
2) 实现通信方式
1) props
2) vue自定义事件
3) 消息订阅与发布
4) vuex
5) slot
3) 方式1: props
1) 通过一般属性实现父向子通信
2) 通过函数属性实现子向父通信
3) 缺点: 隔代组件和兄弟组件间通信比较麻烦
4) 方式2: vue自定义事件
1) vue内置实现, 可以代替函数类型的props
a. 绑定监听: <MyComp @eventName="callback"
b. 触发(分发)事件: this.$emit("eventName", data)
2) 缺点: 只适合于子向父通信
5) 方式3: 消息订阅与发布
1) 需要引入消息订阅与发布的实现库, 如: pubsub-js
a. 订阅消息: PubSub.subscribe('msg', (msg, data)=>{})
b. 发布消息: PubSub.publish(‘msg’, data)
2) 优点: 此方式可用于任意关系组件间通信
6) 方式4: vuex
1) 是什么: vuex是vue官方提供的集中式管理vue多组件共享状态数据的vue插件
2) 优点: 对组件间关系没有限制, 且相比于pubsub库管理更集中, 更方便
7) 方式5: slot
1) 是什么: 专门用来实现父向子传递带数据的标签
a. 子组件
b. 父组件
2) 注意: 通信的标签模板是在父组件中解析好后再传递给子组件的
15. Vuex管理状态的机制
1) 对Vuex基本理解
1) 是什么: Vuex 是一个专为 Vue.js 应用程序开发的状态管理的vue插件
2) 作用: 集中式管理vue多个组件共享的状态和从后台获取的数据
2) Vuex的工作原理
16. 说说Vue的MVVM实现原理
1) 理解
1) Vue作为MVVM模式的实现库的2种技术
a. 模板解析
b. 数据绑定
2) 模板解析: 实现初始化显示
a. 解析大括号表达式
b. 解析指令
3) 数据绑定: 实现更新显示
a. 通过数据劫持实现
2) 原理结构图