一、总结建议

1.平时的积累很重要:工作中遇到的一些问题及其解决方式,我们可以记录下来,抽空做个总结。最好就是找个平台写博客,掘金、GitHub、博客园、CSDN都可以,好记性不如烂笔头,自己写一遍比看一遍好使的多。在线博客不进方便自己查阅,面试玩意碰到记不太清的知识点还能说——我博客上有总结过。

2.简历不要给自己挖坑:会啥就写啥,写啥就会啥。正常的面试官都会根据简历来提问,所以简历上不要出现自己不懂的名词——不懂就去查,去背,哪怕不特别理解到时候也能说个一二三来。不然一问三不知真的尴尬。

3.面试之前要做准备:面试就是考试,考试我们就得复习。前端的知识体系还是很明朗的——页面、样式、JS、框架、项目打包及构建,先掌握自己拿手的,然后扫除盲点。

别在一个坑掉进去两次:和面试官切磋,为了了解目前的就业形势。了解并正视自己的不足;当这个面试有些问题你答不上来时,没关系,回去查资料,看视频,做复盘,一定要记住它,下次你就可以游刃有余了。怕忘的话可以录音。

4.不要裸辞!不要裸辞!不要裸辞!:重要事情说三遍,如果有房贷车贷的话,裸辞找工作压力真的很大——手里有粮,心里不慌。当然,土豪随意……

5.尽量不要把时间线拖太久:一边上班一般找工作是蛮辛苦的,要想请假理由,下班要准备面试。所以要一鼓作气,尽量突击半个月多拿几家offer,时间线拉太长可能会懈怠(我就是拖得有些久了)。尽量有选择则的、找匹配(薪资、能力、通勤之类)的公司去面试,决不能接到面试邀请就去,不然只是浪费自己的时间。

6.端正心态,坚持学习:技术日新月异,框架层出不穷。既然选择了这个行业,就要端正心态,努力学习,提升技术,熟悉业务,深入行业,别让后浪拍死。

二、经典前端面试题附加

1、三栏布局的实现及优缺点

布局方案实现优点缺点
Float布局左右中三列,左列左浮动,右列右浮动,中间列设置左右margin比较简单,兼容性也比较好浮动元素脱离文档流,使用的时候只需要注意一定要清除浮动。
Position布局左中右三列(无顺序),根据定位属性去直接设置各个子元素位置快捷,设置很方便元素脱离了文档流,后代元素也脱离了文档流,高度未知的时候,会有问题,有效性和可使用性比较差
Table布局左中右三列,父元素display: table;子元素display: table-cell;居中子元素不设宽度使用起来方便,兼容性也不存在问题①无法设置栏边距;②对seo不友好;③当其中一个单元格高度超出的时候,两侧的单元格也是会跟着一起变高的
Flex布局左中右三列,父元素display: flex;两侧元素设宽;居中子元素flex: 1;比较完美存在IE上兼容性问题,只能支持到IE9以上
Grid布局左中右三列,父元素display: grid;利用网格实现最强大和最简单兼容性不好,IE10+上支持,而且也仅支持部分属性

2. 文字单行显示/三行显示

单行文本溢出隐藏变为…

 p {
    /* 隐藏元素溢出内容 */
    overflow: hidden;
    /* 单行显示 */
    white-space: nowrap;
    /* 溢出显示省略号 */
    text-overflow: ellipsis;
  }

多行文本溢出隐藏变为…

  p {
    overflow: hidden;
    /* 将对象作为弹性伸缩盒子模型显示 。 */
    display: -webkit-box;
    /* 限制在一个块元素显示的文本的行数,即行数设置 */
    -webkit-line-clamp: 3;
    /* 规定框从上向下垂直排列子元素 */
    -webkit-box-orient: vertical;
  }

3. 重绘和回流
回流:当render tree中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建。这就称为回流(其实我觉得叫重新布局更简单明了些)。每个页面至少需要一次回流,就是在页面第一次加载的时候。
重绘:当render tree中的一些元素需要更新属性,这些属性只是影响元素的外观,风格,而不会影响布局的,比如background-color。则就叫称为重绘。
区别:

  • 回流必将引起重绘,而重绘不一定会引起回流。比如:只有颜色改变的时候就只会发生重绘而不会引起回流
  • 当页面布局和几何属性改变时就需要回流

比如:添加或者删除可见的DOM元素,元素位置改变,元素尺寸改变——边距、填充、边框、宽度和高度,内容改变

  • 回流往往伴随着布局的变化,代价较大:
  • 重绘只是样式的变化,结构不会变化

4. 手写斐波那契数列及其优化
什么是斐波那契数列: 斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列以如下被以递归的方法定义:F(0)=1,F(1)=1, F(n)=F(n-1)+F(n-2)(n>2,n∈N*), 这个数列从第3项开始,每一项都等于前两项之和

function Fibonacci (n) {
  if ( n <= 1 ) {return 1};
  return Fibonacci(n - 1) + Fibonacci(n - 2);
}

这个方法算是代码最少也容易理解,但是当n较大时很快产生栈溢出,引发原因是“调用帧”过多,出现浏览器假死现象。详情参阅函数扩展之尾调用优化——阮一峰。

2.递归(优化版)

function Fibonacci2 (n , ac1 = 1 , ac2 = 1) {
  if( n <= 1 ) {return ac2};
  return Fibonacci2 (n - 1, ac2, ac1 + ac2);
}

此方式是函数尾调用优化之后的写法(默认参数ES6及以后版本支持,ES5请使用常规默认值写法),理解上稍微复杂,但是不会发生栈溢出,推荐使用。

3.普通循环版

function Fibonacci3(n) {
  if (n===1 || n===2) {
        return 1;
    }
    var n1 = 1, n2 = 1, sum;
    for (let i = 2; i < n; i++) {
        sum = n1 + n2
        n1 = n2
        n2 = sum
    }
    return sum
}

循环版本最好理解,就是给初始值,然后不断的累加即可

4.解构赋值版

var Fibonacci4 = function (n) {
  if (n===1 || n===2) {
        return 1;
    }
    let n1 = 1; n2 = 1;
    for (let i = 2; i < n; i++) {
        [n1, n2] = [n2, n1 + n2]
    }
    return n2
}

5.编写javascript深度克隆函数deepClone

// 深拷贝
/**
 * 深拷贝对象,可以正确序列化日期
 * @param {*} obj
 */
export const DEEP_CLONE = function (obj) {
  let objClone = Array.isArray(obj) ? [] : {}
  if (obj && typeof obj === 'object') {
    for (let key in obj) {
      if (obj.hasOwnProperty(key)) {
        // 判断ojb子元素是否为对象,如果是,递归复制
        if (obj[key] && typeof obj[key] === 'object') {
          // 深拷贝日期类型
          if (obj[key] instanceof Date) {
            objClone[key] = new Date(obj[key].valueOf())
            // console.log('deepClone', objClone[key])
          } else {
            objClone[key] = DEEP_CLONE(obj[key])
          }
        } else {
          // 如果不是,简单复制
          objClone[key] = obj[key]
        }
      }
    }
  }
  return objClone
}


7. 手写去重函数

  const arr = [1, '1', '1', 'NaN',NaN,'NaN', {a: 1}, '{a: 1}', {a: 1}]

// 利用for嵌套for,然后splice去重(ES5中最常用)
function unique2(arr) {
   for (var i = 0; i < arr.length; i++) {
     for (var j = i + 1; j < arr.length; j++) {
       if (arr[i] == arr[j]) {         //第一个等同于第二个,splice方法删除第二个
         arr.splice(j, 1);
         j--;
       }
     }
   }
   return arr;
 }

  // 利用hasOwnProperty
  function unique7(arr) {
   var obj = {};
   return arr.filter(function (item, index, arr) {
     return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true)
   })
 }


// 利用filter
function unique4(arr) {
   return arr.filter(function (item, index, arr) {
     //当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素
     return arr.indexOf(item, 0) === index;
   });
 }


8.手写ajax

// 手写ajax
function get(){  
  var req = new XMLHTTPRequest();  
  if(req){  
      req.open("GET", "http://test.com/?keywords=手机", true);  
      req.onreadystatechange = function(){  
          if(req.readyState == 4){  
              if(req.status == 200){  
                  alert("success");  
              }else{  
                  alert("error");  
              }  
          }  
      }  
      req.send();  
  }  
}


9.Pomise实例

// Promise
function fn(){ 
  var promise = new Promise(function(resolve,reject){
    // ... some code
    if(/*异步操作成功*/) {
    resolve(value) // 成功调用resolve 往下传递参数 且只接受一个参数
    }else {
    reject(error)  // 失败调用reject  往下传递参数 且只接受一个参数
    }   
  });
  return promise
}

fn.then(function (r) {
  console.log('成功: ' + r);
}).catch(function (reason) {
  console.log('失败: ' + reason);
});
// 全部成功调用
Promise.all([promise1,promise2]).then(sucess1,fail1)
// 有一个成功就调用
Promise.race([promise1,promise2]).then(sucess1,fail1)

10.Vue路由传参--------params和query的区别
背景:项目中需要跨页面传值,如试题id,遇到了刷新后,传的值消失,所以研究了以下两者的区别

1.params只能用name来引入路由,query用path来引入
2.params类似于post,query更加类似于我们ajax中get传参,说的再简单一点,前者在浏览器地址栏中不显示参数,后者显示,所以params传值相对安全一些。
3.取值用法类似分别是this.route.params.name和this.route.params.name和this.route.params.name和this.route.query.name。
4.params传值一刷新就没了,query传值刷新还存在

this.$router.push({
path:"/detail",
params:{
name:'nameValue',
code:10011
}
});
this.$router.push({
path:'/xxx'
query:{
id:id
}
})

希望对你有所帮助,欢迎加群讨论进行技术性的探讨, 群号:954314851在这里插入图片描述

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐