面试题总结

115 阅读6分钟

** # 第一天总结**

1.css选择器优先级

!important>inline>id>class>tag>*>inherit>default
   ·!important:大于其它
   ·行内:1000
   ·id选择器:100
   ·类:伪类和属性选择器:如:.content:10
   ·类型选择器和伪元素选择器:1
   ·通配符、子选择器、相邻选择器:0

注:1.此处的inherit是继承 ; 2.同级别后写的优先级比先写的优先级高; 3.相同的class样式,css中后写的优先级高。

2.设置水平垂直居中

水平垂直居中
   ·文本水平居中:text-algin:center
   ·文本垂直居中:line-height等于容器height;
                 display:flex;
                 algin-items:center;
   ·div水平居中:
         1.margin:0 auto;
         2.已知父元素宽度:margin-left:width/2;                                      transform:tranlateX(-50%);
         3.未知父元素宽度:position:absolute;
                          left:50%;
                          transform:tranlateX(-50%);
         4.display:flex;
           justify-content: center;
   ·div垂直居中:
         1.已知父元素高度:margin-top:height/2;
                         transform:tranlateY(-50%);
         2.未知父元素高度:position:absolute;
                          top:50%;
                          transform:tranlateY(-50%);
         3.display:flex;
           algin-items:center;

           

3.清除浮动

浮动的影响:

(1)由于浮动元素脱离了文档流,所以父元素的高度无法被撑开,影响了与父元素统计的元素; (2)与浮动元素同级的非浮动元素会跟随其后,因为浮动元素脱离文档流不占据原来的位置; (3)如果该浮动元素不是第一个浮动元素,则该元素之前的元素也需要浮动,否则容易影响页面的结构显示

清除浮动的3个方法:
1.使用clear:both清除浮动

在浮动元素后面放一个空的div标签,div设置样式clear:both来清除浮动。

<div style="clear:both"></div>

优点:简单、方便兼容性好; 缺点:会造成结构混乱,不利于后期维护,一般情况下不建议使用该方法。

2.利用伪元素after来清除浮动

给父元素添加了:after伪元素,通过清除伪元素的浮动,达到撑起父元素高度的目的。

.clearfix:after{
        content:"";
        display:block;
        visibility:hidden;
        clear:both;
        }
3.使用CSS的overflow属性

当给父元素设置了overflow样式,不管是overflow:hidden或overflow:auto都可以清除浮动只要它的值不为visible就可以,它的本质就是构建了一个BFC,这样使得达到撑起父元素高度的效果

   .box{border:1px solid #cc;
        background:#f6f7f8;
        overflow:auto}

注:此处的BFC是Block Formatting Context,即块级格式化上下文 ,是用于布局块级盒子的一块渲染区域。
·参考:BFC的拓展

4.JavaScript闭包

闭包是指有权访问另一个函数作用域中的变量的函数。

闭包简单理解就是内嵌函数,也即在函数中嵌套函数。

4.1闭包的形成、

函数嵌套了函数,内部函数使用外部函数的变量或参数,导致参数或者变量长期驻扎在内存中。

由于在JS中,变量的作用域属于函数作用域,在函数执行后作用域就会被清理、内存也会随之回收,但是由于闭包是建立在一个函数内部的子函数,由于其可访问上级作用域的原因,即使上级函数执行完,作用域也不会随之销毁,这时的子函数---也就是闭包,便拥有了访问上级作用域中的变量的权限,即使上级函数执行完后作用域内的值也不会被销毁。

1.变量作用域:指变量的有效范围。

随着代码执行环境创建的作用域链往外层逐层搜索,一直到全局对象为止。

2.变量的生命周期
     ·对于全局变量来说生存周期是永久的,除非主动销毁;
     ·一般对于函数作用域或局部作用域(如:letconst声明的),会随着函数调用结束而被销毁;
     ·当函数内部调用外部变量就产生了闭包,这时候变量的回收处策略可以参考引用计数等垃圾回收机制。
3.内存泄漏
     由于IE的js对象和DOM对象使用不同的垃圾收集方法,因此闭包在IE中会导致内存泄露问题,也就是无法销毁在内存中的DOM元素。
    
4.2.闭包总结

· 形成:函数中嵌套函数;

· 作用:函数内部调用外部函数、构造函数的私有属性、延长变量的生命周期;

· 优点:希望一个变量长期存在内存中、模块化代码避免全局变量的污染、私有属性;

· 缺点:无法回收闭包函数中的引用变量,容易造成内存泄露。

4.3.闭包的应用
简单的有:

1.ajax请求的成功回调

2.事件绑定的回调方法

3.setTimeout的延时回调

4.函数内部返回另一个匿名函数

我们详细讲下以下几个应用场景:

构造函数的私有属性 计算缓存 函数节流、防抖

构造函数的私有属性
 //构造函数的私有属性
        function Person(param){
            var name=param.name;
            this.age=18;

            this.sayname=function(){
                console.log(name);//张三
            }
        }
        const stu=new Person({name:'张三'});
        stu.age+=1;
        console.log(stu.age);//19   共有属性,外部可以更改
        stu.sayname();
        stu.name='李四';//共有属性,外部不可更改
        stu.sayname();//张三
计算缓存
  var square=(function(n){
            var cache={};
            return function(n){
                if(!cache[n]){
                    cache[n]=n*n;
                }
                return cache[n]
            }
        })()
        console.log(square(50));//2500
函数节流、防抖
// 节流
function throttle(fn, delay) {
    var timer = null, firstTime = true;
    return function () {
        if (timer) { return false;}
        var that = this;
        var args = arguments;
        fn.apply(that, args);
        timer = setTimeout(function () {
            clearTimeout(timer);
            timer = null;
        }, delay || 500);
    };
}

// 防抖
function debounce(fn, delay) {
    var timer = null;
    return function () {
        var that = this;
        var args = arguments;
        clearTimeout(timer);// 清除重新计时
        timer = setTimeout(function () {
            fn.apply(that, args);
        }, delay || 500);
    };
}

闭包的代码形式及解决办法:

 //闭包函数
        for (var i = 0; i < 5; i++) {
            setTimeout(function () {
                console.log(i); //5  5  5  5  5
            }, 0)
        }

解决办法: 方法一:使用匿名函数

for ( var i = 0 ; i < 5; i++ ) {
    (function(j){
        setTimeout(function(){
            console.log(j);
        }, 0);
    })(i);//0  1  2  3  4  

方法二:将var改为let

for ( let i = 0 ; i < 5; i++ ) {
    setTimeout(function(){
        console.log(i);////0  1  2  3  4
    },0);
}

5.函数的方法-----call()、apply()和bind()的区别

call()和apply() 这两个方法都是函数对象的方法,需要通过函数对象来调用:

1.对函数调用call()和apply()方法时,都是用来调用函数执行; 2.当调用call()和apply()可以将一个对象指定为第一个参数,此时对象将会成为函数执行的this; 3.call、bind后面的第一个参数是指向的对象,第二个参数是往对象传的值。

call()、apply()和bind()都可以更改this指向。

区别:

call()方法将实参在对象之后依次传递; apply()方法将实参封装到一个数组中统一传递; call()和apply()更改this指向会自动调用,bind需要手动调用。