阅读 6941

最新前端面试题攻略

一、html和css部分

1、如何理解CSS的盒子模型?

  • 每个HTML元素都是长方形盒子。 
  • (1)盒子模型有两种:IE盒子模型、标准W3C盒子模型;IE的content部分包含了border和pading。 
  • (2)标准W3C盒模型包含:内容(content)、填充(padding)、边界(margin)、边框(border)。

2、用纯 CSS 创建一个三角形的原理是什么?

  • 把上、左、右三条边隐藏掉
  • 颜色设为 transparent
  • #demo { width:0; height: 0; border-width: 20px; border-style: solid; border-color: transparent transparent red transparent; }

3、CSS3中translate、transform、translation和animation的区别

  • translate 移动 通过 translate() 方法,元素从其当前位置移动,根据给定的 left(x 坐标) 和 top(y 坐标) 位置参数:
  1. transform: translate(50px, 100px);
  2. -ms-transform: translate(50px,100px);
  3. -webkit-transform: translate(50px,100px);
  4. -o-transform: translate(50px,100px);
  5. -moz-transform: translate(50px,100px);
  • transform 改变、变形
  1. 旋转:rotate() 顺时针旋转给定的角度,允许负值 rotate(30deg)
  2. 扭曲:skew() 元素翻转给定的角度,根据给定的水平线(X 轴)和垂直线(Y 轴)参数:skew(50deg,20deg)
  3. 缩放:scale() 放大或缩小,根据给定的宽度(X 轴)和高度(Y 轴)参数: scale(2,4)
  4. 移动:translate() 平移,传进 x,y值,代表沿x轴和y轴平移的距离
  • animation 动画 语法 animation: name duration timing-function delay iteration-count direction;
  1. animation-name 规定需要绑定到选择器的 keyframe 名称。。
  2. animation-duration 规定完成动画所花费的时间,以秒或毫秒计。
  3. animation-timing-function 规定动画的速度曲线。
  4. animation-delay 规定在动画开始之前的延迟。
  5. animation-iteration-count 规定动画应该播放的次数。
  6. animation-direction 规定是否应该轮流反向播放动画。

4、使用flex布局使一个div水平垂直局中

父级:#container{
    display:flex;
    justify-content:center;
    align-items: center;
    width: 200px;
    height: 200px;
}
子级:#center{
    width: 100px;
    height: 100px;
    background: red;
}
复制代码

5、使用过flex布局吗?flex-grow和flex-shrink属性的作用是什么? 

  • flex-grow: 属性决定了父元素在空间分配方向上还有剩余空间时,如何分配这些剩余空间。其值为一个权重(也称扩张因子),默认为 0(纯数值,无单位),剩余空间将会按照这个权重来分配。  
  • flex-shrink:这个属性其实就是定义一个子容器的压缩比例(当父容器放不下子容器时,不会自动换行,每个子容器会适当的压缩,这个值就是设置压缩的比例的)。他的默认值是1

二、js代码面试题

1、数组slice()和splice()方法的区别

  • slice() 方法:可从已有的数组中返回选定的元素。slice(开始截取位置,结束截取位置)

var movePos=[11,22,33];
var arr=movePos.slice(1,2);
document.write(arr)  //返回截取的元素:[22]
document.write(arr.length)  //返回数组长度1,截取的数组的长度复制代码

  • splice() :方法向/从数组中添加/删除项目,然后返回被删除的项目。

var movePos=[11,22,33,44];
var arr=movePos.splice(1,2);//movePos.splice(开始删除的下表位置,删除数组元素的个数);
document.write(arr) ; //返回新的数组:[22,33]
11document.write(arr.length) ;//返回数组长度2复制代码

splice() 方法可删除从 index 处开始的零个或多个元素,并且用参数列表中声明的一个或多个值来替换那些被删除的元素。

var movePos =[111,222,333,444];    
movePos.splice(2,1,"666")
//movePos.splice(开始删除的下表位置,删除数组元素的个数,向数组添加的新项目。);
//从下标2开始删除一位,并用666替换删除下表位置的元素复制代码

2、实现add(3)(4)和add(3,4)都输出7,请实现add方法

function add(x,y){
	var sum = x;
    if(y){
        return (sum + y);
    }
    else
    {
        var add2 = function(z){
            return (sum + z);
        }
        return add2;
    }
} 复制代码

but这个方法不能扩展成add(3)(4)(5)...和add(3,4,5...)都输出他们的和,欢迎大家评论区留言,写一个扩展后的。

3、求n的阶乘值n!?

  • 方案一:利用while循环

function factorial(num){
    var result = 1;
    while(num){
        result *= num;
        num--;
    }
    return result;
}复制代码

  • 方案二:使用递归

function factorial(num){
    if(num <= 0){
        return 1;
    }else{
        return num*arguments.callee(num-1);
    }
}复制代码

4、求1234567890.32格式化为:1,234,567,890.32。

  • 方法一:利用字符串截取的方法

function formatNumber(str) {
    let arr = [];
    let lastStr = str.substring(str.indexOf('.'));
    let formatStr = str.substring(0,str.indexOf('.'))
    let count = formatStr.length
    while (count >= 3) {
        arr.unshift(formatStr.slice(count - 3, count))
        count -= 3
    }
    // 如果是不是3的倍数就另外追加到上去
    formatStr.length % 3 && arr.unshift(formatStr.slice(0, formatStr.length % 3))
    return arr.toString()+lastStr;
}复制代码

  • 方法二:使用reduce函数

function formatNumber(str) {
    let lastStr = str.substring(str.indexOf('.'));
    let formatStr = str.substring(0,str.indexOf('.'))
    // ["0", "9", "8", "7", "6", "5", "4", "3", "2", "1"]
    return formatStr.split("").reverse().reduce((prev, next, index) => {
        return ((index % 3) ? next : (next + ',')) + prev
    })+lastStr;
}复制代码

5、评价一下三种方式实现继承的有缺点并改进;

function Animal(){}
function Cat(){}
方法1:
Cat.prototype = new Animal();方法2:
Cat.ptototype = Animal.prototype;方法3:
Cat.prototype = Object.create(Animal.prototype);复制代码

方法1:

  • 优点
  1. 正确设置原型链实现继承
  2. 父类实例属性得到继承,原型链查找效率提高,也能为一些属性提供合理的默认值
  • 缺点
  1. 父类实例属性为引用类型时,不恰当地修改会导致所有子类被修改 
  2. 无法传递参数

方法二:

  • 优点
  1. 正确设置原型链实现继承
  • 缺点
  1. 父类构造函数原型与子类相同。修改子类原型添加方法会修改父类

方法三:

  • 优点
  1. 正确设置原型链且避免方法1.2中的缺点
  • 缺点
  1. ES5方法需要注意兼容性

改进:

  • 所有三种方法应该在子类构造函数中调用父类构造函数实现实例属性初始化

function Cat() {    
    Animal.call(this);
}复制代码

  • 封装一个原型继承的方法

function extend(Child, Parent) {
    var F = function(){};
    F.prototype = Parent.prototype;
    Child.prototype = new F();
    //用新创建的对象替代子类默认原型,设置Rect.prototype.constructor = Rect;保证一致性
    Child.prototype.constructor = Child;  
}复制代码

6、写出下列代码执行的输出值

var a = 100;
 function test(){
    alert(a);
    var a = 10;
    alert(a);
}
test();复制代码

输出:undefined,10

var a = 100;
 function test(){
    alert(a);
    var a = 10;
    alert(a);
}
test();复制代码

输出:undefined,10

var a = 100;
function test2(){
    alert(a);
    let a = 10;
    alert(a);
}复制代码

输出:报错 a is not defined,10

alert(3>2>1);复制代码

输出:false 3>2是true,隐式类型转换,变成1,1>1肯定是false啦

 7、谈一谈JavaScript作用域链

  • 当执行一段JavaScript代码(全局代码或函数)时,JavaScript引擎会创建为其创建一个作用域又称为执行上下文(Execution Context),在页面加载后会首先创建一个全局的作用域,然后每执行一个函数,会建立一个对应的作用域,从而形成了一条作用域链。每个作用域都有一条对应的作用域链,链头是全局作用域,链尾是当前函数作用域。
  • 作用域链的作用是用于解析标识符,当函数被创建时(不是执行),会将this、arguments、命名参数和该函数中的所有局部变量添加到该当前作用域中,当JavaScript需要查找变量X的时候(这个过程称为变量解析),它首先会从作用域链中的链尾也就是当前作用域进行查找是否有X属性,如果没有找到就顺着作用域链继续查找,直到查找到链头,也就是全局作用域链,仍未找到该变量的话,就认为这段代码的作用域链上不存在x变量,并抛出一个引用错误(ReferenceError)的异常。

8、如何理解JavaScript原型链

  • JavaScript中的每个对象都有一个__proto__属性(函数对象即有__proto__,又有prototype,prototype指向自己的原型而__proto__指向父级的原型)我们称之为原型,而原型的值也是一个对象,因此它也有自己的原型,这样就串联起来了一条原型链,原型链的链头是Object.prototype.__proto_,它的值比较特殊,值为null。
  • 原型链的作用是用于对象继承,函数A的原型属性(prototype property)是一个对象,当这个函数被用作构造函数来创建实例时,该函数的原型属性将被作为原型赋值给所有对象实例,比如我们新建一个数组,数组的方法便从数组的原型上继承而来。
  •  当访问对象的一个属性时, 首先查找对象本身, 找到则返回; 若未找到, 则继续查找其原型对象的属性(如果还找不到实际上还会沿着原型链向上查找, 直至到根). 只要没有被覆盖的话, 对象原型的属性就能在所有的实例中找到,若整个原型链未找到则返回undefined;

9、js闭包

  • 闭包,官方对闭包的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
  • 闭包的特点:
  1. 作为一个函数变量的一个引用,当函数返回时,其处于激活状态。
  2. 一个闭包就是当一个函数返回时,一个没有释放资源的栈区。
  简单的说,Javascript允许使用内部函数---即函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。

10、js为什么是单线程语言,怎么模拟多线程

  • JavaScript的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?
  • 为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质。

11、const a = 1 a = 2 这样会报错,但是 对于复合类型来说 const foo = {a:1} foo.a = 2 这样就不会报错,为什么?

  • 复合类型的变量,变量名不指向数据,而是指向数据所在的地址。const命令只是保证变量名指向的地址不变,并不保证该地址的数据不变,所以将一个对象声明为常量必须非常小心。

以下是其它面试题的详细

1、深拷贝和浅拷贝

juejin.im/post/5c400a…

2、Object.defineProperty()的用法 

juejin.im/post/5c3870…

3、JS实现AOP 面向切面编程 

juejin.im/post/5c3865…

4、http请求头以及响应头详解

juejin.im/post/5c17d3…

5、浏览器输入一个网址回车后,发生了什么

juejin.im/post/5c1c52…

6、call,apply和bind模拟实现

juejin.im/post/5c7fe2…


关注下面的标签,发现更多相似文章
评论