面试记录与总结(1)

126 阅读5分钟

一、写在前面的话

一只慢慢慢慢变强的前端菜鸟,下面都是自己在面试和学习中的问题的总结,帮助自己巩固知识点的同时也希望能帮助到你们。

二、面试题

这里我会总结出遇到的面试题和一部分学习中遇到的问题,会结合文档和大佬们的博客进行解析,若大家在看到的时候发现错误和不当之处请多多指教。

2.1 数组去重

我的思路是借助对象属性的唯一性来去除重复元素,通过循环将数组中的元素作为对象的key值,相同属性会重复赋值,但是属性不会增加,最后通过遍历对象的属性就能得到唯一元素了。

Array.prototype.unique = function () {
    let res = []
    let temp = {}
    let length = this.length
    for (let i = 0; i < length; i++) {
        if (!temp[this[i]]) {
            temp[this[i]] = true
            res.push(this[i])
        } else if (res.indexOf(this[i]) === -1) {
            res.push(this[i])
        } 
    }
    return res
}

这里需要注意的是通过[]来获取对象属性值的时候,[]内必须是计算结果为字符串的表达式,因此'1'和1会被认为是相同元素,所以我们需要通过数组的indexOf方法确定数据类型为字符串的元素在数组中是否存在,不存在就需要往数组中push该元素。

2.2 flex是什么以及主要属性

flex指的是弹性盒子布局,当我们给元素设置display:flex属性的时候就可以为该元素的子元素开启flex布局,这个父元素称之为flex-container,子元素们称之为flex-items

1.应用在flex-container上的主要属性有:

  • flex-direction 决定主轴的方向,有四个取值:rowrow-reversecolumncolumn-reverse
  • justify-content 决定flex-item在主轴的对齐方式,有六个取值:flex-start(与主轴起点对齐)、flex-end(与主轴终点对齐)、center(居中对齐)、space-between(flex-items彼此距离相等且与主轴起点和终点对齐)、space-evenlyflex-items彼此距离相等且与主轴起点和终点等距)、space-aroundflex-items与起点和终点的距离是flex-items彼此距离的一半)
  • flex-wrap 决定flex-items是否多行排布,有三个取值:normal(单行,默认值)、wrap(多行)、wrap-reverse(多行,反向)
  • align-items 决定单行flex-items在交叉轴的对齐方式,有五个取值:flex-start(与交叉轴起点对齐)、flex-end(与交叉轴终点对齐)、center(居中对齐)、stretch(若flex-item没有设置高度或者为auto则拉伸至整个container的高度),baseline(基准线对齐)
  • align-content 决定多行flex-items在交叉轴的对齐方式,取值参考justify-content,对单行flex-items不起作用

2.应用在flex-items上的主要属性:

  • order 决定该flex-item的排列顺序,order值越小越靠前,默认值是0可为负
  • align-self 决定设置了该属性的flex-item的排布顺序,用来覆盖align-items的属性值,取值通align-items的取值
  • flex-grow 决定了该flex-item如何拓展,只有主轴方向有剩余空间才生效
  • flex-shrink 决定了该flex-item如何收缩,只有主轴方向flex-items的宽度超出空间才生效
  • flex-basic 决定了该flex-item在主轴的宽度

2.3 函数题1

var a = function b() {
    console.log(a == b);
};
a(); // true
b(); // Error: b is not defined

个人感觉从结果上分析,具名的函数表达式,函数名变成了类似于函数内部的局部变量,只有内部才能访问

var test = function tool(){
    console.log(tool)
}
test() //[Function: tool]
console.log(tool) //ReferenceError: tool is not defined

2.4 css实现div旋转

这里可以通过css的animation属性和关键帧以及transform属性完成 首先定义关键帧的名称,关键帧的动画详情

      @keyframes rotate {
        0% {
          transform: rotate(0deg);
        }
        50% {
          transform: rotate(180deg);
        }
        100% {
          transform: rotate(360deg);
        }
      }

然后定义animation属性

animation: rotate 3s infinite;

2.5 函数题2

var obj = {"name":"1"};
(function(obj){
    obj = {"name":"3"};
})(obj);
console.log(obj)

// { name: "1" }

这里主要是以下知识点:

  • 在js中,函数的参数是无论类型都是按照值进行传递的,也就是说将函数外部的值复制给函数内部的参数。
  • 在js中,那么基本类型的值就是简单的复制,而引用类型的值复制的就是保存这个引用类型的地址的指针。
  • js中可以把函数参数理解为局部变量

所以上面的可以理解为:

(function(obj){ 
    obj = 实参对象的指针,指向原对象
    //对obj重新赋值,obj的指针由原对象更改为新对象,且这个新对象在函数执行完被销毁
    obj = {"name":"3"}; 
})(obj);
console.log(obj) // 而全局变量obj一直拥有原对象指针

对比来讲的话:

var obj = {"name":"1"};
(function(obj){
    obj.name = "3";
})(obj);
console.log(obj)
// {"name":"3"}

这里与上面的差别就是obj的指针没有变化,还是指向原对象因此改变属性值会改变原对象的值,而全局变量obj也拥有的是原对象的指针,因此打印的对象就发生了变化。

2.6 行内、块级、行内块级元素的特点

  • 行内元素:默认宽度为内容宽度,不可设置宽高,同行显示(imginput等元素除外,它们可以设置宽高可以看作行内块级元素)
  • 块级元素:默认宽度为父元素的宽度,可以设置宽高,换行显示
  • 行内块级元素:集成了前两者的部分属性,默认宽度为内容宽度,同行显示,可以设置宽高

2.7 js和css加载会造成阻塞吗?

分情况,css文件的加载不会阻塞dom的解析,但是会阻塞dom的渲染(等到加载完才开始渲染),会阻塞js代码的执行,而js加载是会阻塞dom的解析,若不想阻塞可以加上async或者defer标签让js异步加载

2.8 写一个函数实现以下效果:

1
11
111
1111
11111
function print(n) {
    let res = 0
    for (let i = 0; i < n; i++) {
        res += 10 ** i
        console.log(res)
    }
}
print(5)

js中幂运算符号为两个*符号