# 前端面试-基础查漏补缺

176 阅读19分钟

前端面试-基础查漏补缺


1、display:none 与visibility:hidden的异同点?

  • 相同点:都是让元素不可见
  • 不同点:
    • display:none是让元素在渲染树中消失,不可见之后不占空间;visibility:hidden是让元素在渲染树中隐藏,仍然占据空间。
    • display:none 属性不可继承**,子孙节点消失是因为在渲染树中消失了,不能通过改变子孙节点显示属性让子孙节点显示;visibility:hidden属性可以继承,子孙节点消失是因为继承了hidden,可以通过visibility:visible让子孙节点显示;

2.cookies、sessionStorage、localStorage之前 的区别。

  • cookies:网站用来标记用户身份的一段数据,加密的字符串,默认只在同源的HTTP请求中携带;定时关闭;最大4K左右。
  • sessionStorage:本地存储,键值对形式存储,浏览器窗口关闭之后自动删除;最大 5M左右。
  • localStorage:本地存储,键值对形式存储,不主动删除一直存在,最大5M左右。

3、为什么要初始化CSS样式。

  • 清除元素默认样式,而且不同的浏览器这些元素的默认样式会有不一样,会影响到最终布局效果。
  • 不初始化会在不同浏览器中出现页面显示差异。

postcss是什么,它的作用是什么?

  • post是一个平台
  • 基于平台使用一些一些插件来优化css代码。
  • 比如autoprefixer插件,他就需要基于postcss使用,作用是可以帮我们为css加上不同的浏览前缀。

4、闭包

  • 概念:闭包就是能够读取其他函数内部变量的一个函数。通常来说,我们会在一个函数内部去创建另一个函数,通过新创建的这个函数去读取上层函数中的变量;被访问到的局部变量会始终保存在内存中。
  • 通过代码理解:
<body>
    <button>按钮1</button>
    <button>按钮2</button>
    <button>按钮3</button>
    <button>按钮4</button>
    <button>按钮5</button>

    <script>
        console.log("ceshi");
        // 获取所有按钮 元素
        var btns= document.getElementsByTagName("button");
        // 遍历所有的按钮,分别为他们设置点击事件
        for(var i=0 ;i<btns.length; i++){
            // 通过一个自执行函数,获取当前的索引i ,并重命名为index
            btns[i].onclick = (function(index){
                console.log(index);
                // 在这个自执行函数内部返回一个函数,返回的函数在自执行函数内部
                // 返回的函数,可以访问到自执行函数内部的index , 这就是闭包
                return function(){
                    // (1)去掉所有按钮的背景颜色
                    for(var i=0; i< btns.length ; i++){
                        btns[i].style.backgroundColor = "red";
                    }
                    // (2)让当前点击的按钮背景颜色变为粉红色
                    // 方式一就是通过this 获取当前按钮,并设置其颜色
                    // this.style.backgroundColor = "pink"
                    // 方式二就是通过获取到的 index 当前按钮,变为粉色
                    btns[index].style.backgroundColor = "pink";
                }
            })(i);
        }
    </script>
</body>


5、原型与原型链

  • 每个函数都有一个prototype属性,这个属性会指向一个对象,就是通过调用该构造函数而创建的实例的原型,可以通过实例对象的_proto_来访问到这个原型对象。
  • 实例在创建时,就会默认关联原型,并且会从原型继承属性。
  • 而每一个原型对象都会存在一个constructor属性,这个属性会指向关联的这个构造函数。
  • 当访问一个实例对象的属性时,如果这个实例对象中没有这个属性,那么就js引擎就会到关联的原型对象中去找。
  • 如果原型对象中也没有找到,那么就会到原型的原型中去找,一直找到最上层的原型,也就是Object为止。
  • 图解原型与原型链

图解原型与原型链


6、this对象

  • this总是指向函数的直接调用者(而非间接调用者)。
  • 如果有New关键字,那么this就是指向new出来的对象。
  • 在事件中,this指向触发事件这个对象。特殊 的是,在IE中attachEvent指向全局的window。

7、webpack

  • js模块打包工具,管理项目中的js模块依赖。
  • 提供默认的一些配置,比如devServer,我们可以利用devServer快速启动开发时的web服务器。
  • 因为默认只能打包js文件,所以提供了loader来预处理一些文件,并且可以打包除了js之外的任何静态资源。
  • 提供插件,比如可以使用HTMLWebpackPlugin来常见html文件的 插件。

8、promise

  • ES6中提出的一个异步编程解决方案,解决回调地狱并使异步的操作变得更加优雅。
  • promise是一个构造函数,需要new关键字来生成一个promise的实例对象。
  • promise的构造函数能够接受一个函数作为参数,函数中的代码new promise的时候,会立刻执行我们可以在这里执行异步代码的操作。并且该函数默认存在的函数分别是resolve和reject,这两个参数也是函数,用来标记异步执行的状态。
  • resolve,当promise的异步操作执行完成的时候,我们可以调用resolve函数,来标记当前的异步操作已经完成。
  • reject,在异步操作失败的时候进行调用,用来标记当前的异步操作失败了。
  • 这些标记的状态可以通过promise实例对象的 .then 和 .catch 方法接收。其中 .then 方法是接收异步成功的回调; .catch 是异步失败的回调。

9、null 、undefined的区别?

  • undefined:表示不存在这个值,它是一个变量最原始的状态。
  • null :它是一个具体的值,只不过这个值是一个空值而已。

10、同步和异步;进程和线程

  • 同步:线程被阻塞,等待任务返回结果。
  • 异步:线程不会被阻塞,任务完成通知js引擎。
  • 进程是资源分配的最小单位,线程是CPU调度的最小单位
   -   做个简单的比喻:进程=火车,线程=车厢
   -   线程在进程下行进(单纯的车厢无法运行)
   -   一个进程可以包含多个线程(一辆火车可以有多个车厢)
   -   不同进程间数据很难共享(一辆火车上的乘客很难换到另外一辆火车,比如站点换乘)
   -   同一进程下不同线程间数据很易共享(A车厢换到B车厢很容易)
   -   进程要比线程消耗更多的计算机资源(采用多列火车相比多个车厢更耗资源)
   -   进程间不会相互影响,一个线程挂掉将导致整个进程挂掉(一列火车不会影响到另外一列火车,但是如果一列火车上中间的一节车厢着火了,将影响到所有车厢)
   -   进程可以拓展到多机,进程最多适合多核(不同火车可以开在多个轨道上,同一火车的车厢不能在行进的不同的轨道上)
   -   进程使用的内存地址可以上锁,即一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。(比如火车上的洗手间)
   -   "互斥锁"进程使用的内存地址可以限定使用量(比如火车上的餐厅,最多只允许多少人进入,如果满了需要在门口等,等有人出来了才能进去)-“信号量”



11、EventLoop(事件循环)是什么?

  • JavaScript语言的特点就是单线程,同一个时间只能做一件事。
  • 单线程意味着所有的任务需要排队,前一个任务结束,才会执行后一个任务。前面没有执行完成,后面就必须一直等着。
  • 所有任务分为两种,一种是同步任务(synchrnous),另一种就是异步 任务(asynchrnous)。
  • 同步任务就是:在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行下一个任务。
  • 异步任务,不进入主线程,直接进入“任务队列”(task queue)的任务,当“任务队列”通知主线程,某个异步任务可以执行了,该任务就会直接进入主线程执行。(相当于医院有预约,不管前面有没有在排队,当医生叫到你了,就可以直接进入)
  • EventLoop(事件循环),当主线程中的任务完成之后,主线程从“任务队列”中读取事件,这个过程是不断循环的,这就是事件循环(EventLoop)。

12、bind、call、apply三个方法的区别?

  • call和apply都是为了改变this的指向。作用是相同的,但是传参方式不同。
  • 除了第一个参数外,call可以接收一个参数列表;apply可以接受一个数组参数
  • bind和其他两个方法作用是一致的,只是该方法会返回一个函数,并且我们可以通过bind实现柯里化。
  • 代码理解
<body>
    ## call和apply和bind的用法区别
    <script>
        let a = {
            value:1
        }
        function getValue(name,age){
            console.log(name);
            console.log(age);
            console.log(this.value);
        }
        // call传参是参数列表
        getValue.call(a,'dbc','26');
        // apply传参是参数数组
        getValue.apply(a,['dbc34','35']);
        // bind 传参方式也是参数列表, 不过bind 会返回一个函数,需要调用才会执行
        // let getValueBind=getValue.bind(a,'dbc123','123');
        // getValueBind();
        getValue.bind(a,'dbc123','123')();
    </script>
</body>


13、typeof和instanceof的区别

  • typeof:会返回一个一个值的类型。对于基本数据类型,除了null都可以返回正确的类型。而对于null则会返回object,这是js的一个bug。对于引用数据类型,除了函数之外,都会返回object。
    typeof 1;       //'number'
    typeof '1';     //'string'
    typeof undefined;       //'undefined'
    typeof Symbol();        //'symbol'
    typeof null;        //'object'
    typeof [];      //'object'
    typeof {};      //'object'
    typeof console.log();       //'function'

  • instanceof:用来判断一个对象是否是另一个对象的实例。注意:它只能用来判断对象;返回值是true和false。
    1 instanceof Number;        //false
    
    var a = New Number(1);
    a instanceof Number;        //true

14、Vue 生命周期

  • 八个阶段,创建前/后,载入前/后,更新前/后,销毁前/后。

15、Vue实现双向数据绑定的原理。

  • 采用数据劫持结合发布者-订阅者模式的方法。
  • 数据劫持:通过Object.defineProperty()来劫持对象各个属性的setter,getter。
  • 发布者-订阅者模式:在数据变动时发布者发布消息给订阅者,触发相应监听回调。
  • 总的来说:当把一个普通JavaScript对象传给vue实例作为它的data选项时,vue将遍历它的属性,用Object.defineProperty()监听他们的getter/setter方法。这样,它们就可以让vue追踪依赖,在对象的属性被访问(get)和修改(set)时通知变化。

16、vue中如何实现参数的传递?

  • 父组件->子组件:props属性接受数据。
  • 子组件->父组件:$emit方法传递参数。
  • 兄弟组件传值:
    • eventBus方案,建立事件中心,通过它传递事件来进行数据传递。
    • 通过vuex进行数据共享。

17、vue路由实现:hash模式和 history 模式?

  • hash模式:时vue-router的默认模式,使用哈希URL中会出现#号字符,#到#后面的字符称为哈希(hash)。特点:hash虽然在URL 中,但是HTTP请求中不包含hash。
  • history模式:国内项目中比较常用,URL中不会存在#符号。这种模式下,需要后台进行配合,因为vue打包的项目通常是一个单页的应用,也就是任何的URL其实指向的都是一个HTML文件,所以我们需要在apach或者nginx中进行配置,当URL匹配不到资源时,指向同一个HTML 页面的配置。

18、<keep-alive></keep-alive>的作用是什么?

  • <keep-alive></keep-alive>包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态避免重新渲染

19、 深拷贝和浅拷贝

  • 深拷贝和浅拷贝最根本的区别在于是否真正获取一个对象的复制实体,而不是引用。
    假设B复制了A,修改A的时候,看B是否发生变化:
    如果B跟着也变了,说明是**浅拷贝**,拿人手短!(修改堆内存中的同一个值)
    如果B没有改变,说明是**深拷贝**,自食其力!(修改堆内存中的不同的值)
  • 浅拷贝(shallowCopy)只是增加了一个指针指向已存在的内存地址,
  • 深拷贝(deepCopy)是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存,
  • 使用深拷贝的情况下,释放内存的时候不会因为出现浅拷贝时释放同一个内存的错误。
  • 浅复制:仅仅是指向被复制的内存地址,如果原地址发生改变,那么浅复制出来的对象也会相应的改变。
  • 深复制:在计算机中开辟一块新的内存地址用于存放复制的对象。

20、HTML、CSS的中文和英文全称

  • HTML: Hypertxt Markup Language 超文本标记语言
  • CSS: Cascading style sheets 层叠样式表单

21、常用浏览器内核

  • webkit:chrome 、 Safari
  • Trident : IE
  • Gecko: Firefox
  • Blink: Google最新

22、如何检测浏览器是什么内核

  • 百度

23、知道哪些浏览器兼容性?如何解决?

  • 问题一:不同浏览器下标签默认的padding和margin值会不一样,影响整体布局。
  • 解决:初始化设置默认值

  • 问题二:在常见的div+css布局中,块级元素设置浮动float,并且有横行margin的时候,在IE6中显示的Margin比设置的要大,会出现后面的元素被挤下来。
  • 解决:display:inline

  • 问题三:在IE6、IE7、遨游中较小搞丢标签元素高度不受控制,超出自己设置的高度。
  • 解决: overflow:hidden;或者 行高line-height小于设置高度。

  • 问题四:图片有默认边距,当几个img标签放一起的时候,有些浏览器会有默认的边距,因为img是行内属性标签。
  • 解决: 使用float解决

24、一个页面从输入URL到页面加载显示完成,这个过程中都发生了什么?

  • 解析输入的URL提取域名,DNS服务器发起请求,DNS返回域名的IP地址
  • 通过IP地址和端口发起请求,去获取服务器资源
  • 资源以HTTP数据包封装通过网络协议发送到本地。
  • 读取页面文件映射到浏览器,页面会对HTML,css,js进行解析渲染到页面
  • 从第一行代码加载到结束
  • 加载完成页面底部会有加载完毕或者地址栏会有相应变化

25、http状态码

  • 1xx: 请求发送
  • 100: 继续发出请求
  • 101: 切换协议
  • 2xx: 请求发送成功
  • 200: 服务器提供了请求的页面
  • 201: 请求成功并且服务器已创建新的资源
  • 202: 服务器已接受请求,但未处理
  • 3XX: 重定向
  • 300: 多种选择
  • 301: 永久移动
  • 302: 暂时移动
  • 4xx: 客户端错误
  • 404: 文件找不到
  • 5xx: 服务端错误

26、HTML5有哪些新特性,说说对语义化的理解

  • 内容结构化,代码结构化,便于开发者阅读和写出优雅的代码,利于搜索引擎解析

  • 新特性:

    • <section></section>:定义文档主体部分的节或者段
    • <aside></aside>:侧边栏,广告和链接等
    • <article></article>:定义来自外部独立完整的文本,例如论坛或者博客的文章
    • <header></header>:一般用于页眉,但不局限于页眉,用来定义头部的导航信息
    • <footer></footer>定义了文档、页面的页脚,和header类似。
    • <nav></nav>:链接组组成的导航部分
    • <canvas></canvas>:画布,用于绘画绘图
    • <video src=""></video>:视频
    • <audio controls="controls" autoplay="autoplay" src="http://up_mp4.t57.cn/2017/1/11m/11/304112002347.m4a" >追光者</audio>
    • <audio></audio>:音频
    • <mark>戴</mark>:高亮或者突出的词
    • <progress></progress>进度条,运行中的进度。
  • 理解:

    • 为了在没有css的情况下,能更好看出内容结构和代码结构(裸奔时更好看)
    • 用户体验,比如title可以在用户看到元素的注解,alt可以在图片无法显示时知道当前是什么图片
    • 有利于SEO,搜索引擎优化,利于爬虫判断权重
    • 方便其他设备解析(比如阅读器,屏幕阅读器,盲人阅读器,移动设备等)以意义的方式渲染页面
    • 便于团队开发维护,可读性增强

27、Doctype作用?标准模式与兼容模式有什么区别?

  • Doctype告知浏览器的解析器用什么文档标准解析这个文档。DOCTYPE不存在或格式不正确会导致文档以兼容模式呈现。

  • 在严格模式中 :width是内容宽度,元素真正的宽度 = width;

  • 在兼容模式中 :width则是=width+padding+border


  • 在标准模式下,给span等行内元素设置wdith和height都不会生效。并且,一个元素的高度都是由其包含的内容来决定的,如果父元素没有设置高度,子元素设置一个百分比的高度是无效的,而在兼容模式下,则会生效。

  • 兼容模式下可设置百分比的高度和行内元素的高宽

  • 用margin:0 auto设置水平居中在IE下会失效

  • 使用margin:0 auto; 在标准模式下可以使元素水平居中,但在兼容模式下却会失效。但是这个可以用text-align属性来解决的


28、js基本数据类型

  • 8种:Number , string ,null , undefined ,Boolean,object , symbol(ES6新增) ,bigInt(安全存储,操作大整数)
  • 基本数据类型:Number ,String, undefined , null ,boolean
  • 引用类型:object。里面包含Array , function , Date

29、js中promise和async、await有什么关系?

  • async/await使异步代码看起来像同步一样
  • promise是ES6,async/await是ES7
  • async/await相对于promise来讲,写法更加优雅
  • reject状态:
    • 1)promise错误可以通过catch来捕捉,建议尾部捕获错误,
    • 2)async/await既可以用.then又可以用try-catch捕捉
  • async是ES7提出的,解决异步编程的新方法,使异步程序看起来像同步执行一样。async是基于Promise实现的。
  • async/await用法:
    • async用于声明function是异步的,而await认为是 async await 的一个简写,等待一个异步方法执行完成。
    • async和await配对使用,await存在于async的内部。否则会报错。
    • await表示在这里等待一个promise返回,接下来再去执行。
    • await后面应该是跟着一个promise,也可以不是。

30、请一一列举js中Array对象自带的方法

  1. contact()

    • Arr.contact([],[],[]...)
    • 作用:将多个数组连接成一个
    • 返回值:返回一个新的数组
  2. join()

    • Arr.join("分隔符")
    • 作用:将数组中的内容以分隔符连接成一个字符串
    • 返回值:一个新的字符串
  3. pop()

    • 作用:删除数组最后一个元素
    • 返回值:删除被删除的元素
  4. push()

    • Arr.push(元素1,元素2,...)
    • 在数组后面添加元素
    • 返回值:返回新数组长度
  5. reverse()

    • Arr.reverse()
    • 翻转数组
    • 返回值:返回颠倒顺序后的原数组
  6. shift()

    • arr.shift()
    • 作用:移除第一个元素
    • 返回值:返回移除的元素
  7. unshift()

    • arr.unshift(元素1,元素2,...)
    • 作用:在数组前添加元素
    • 返回值:返回添加元素后的数组
  8. slice()

    • arr.slice(start,end);
    • 作用:选取数组中顺序从start开始到end结束的一段数组
    • 返回数组中选取的一段
  9. splice()

    • arr.splice(开始的位置,删除的个数,删除位置添加元素1,删除位置添加元素2,..)
    • 作用:在指定的位置删除元素,并在要删除的位置添加新元素,可以不添加新元素,删除个数为0则可以在指定位置添加元素。
    • 返回值:返回被删除的元素
  10. sort()

    • arr.sort(function)
    • 作用:返回一个已经排序的数组
    • 如果sort里面没有参数,则按字母顺序排序;如果是需要按从小到大排序则:function(a,b){ return a-b };
  11. split()

    • split('分隔符')
    • 作用:将字符串转换为数组
    • 返回值:返回一个数组

31、setTimeout和setInterval区别,如何互相实现

  • setTimeout:在设置的时间到达时执行代码,执行完毕结束,只执行一次。
  • setInterval:循环运行,到设定时间重复执行代码。
  • setInterval设置比较简单;setTimeout设置灵活,可以设置不同的时间间隔来运行,比如第一次1秒,第二次2秒...。
  • 互相实现:
    1. setTimeout模拟setInterval:内部函数testTimeout内部执行外部函数setTime,内部函数一直在循环调用外部函数;
    var timer = 0;        //初始化时间
    var testTimeout;    //定义setTimeout名称
    (function setTime(){
    testTimeout=setTimeout(function(){
            timer++;
            console.log('setTimeout ===> timer: ',timer);
            setTime();  //重复调用
            if(timer>5){
                clearTimeout(testTimeout);
                console.log('clearTimeout ===> timer: null');
            }
        },1000);
    }
    )();
    
    1. setTimeout模拟setInterval:在定时器执行一次后直接清除定时器 clearInterval(testInterval)

32、什么是JSON、JSONP

  • JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。

    • 键值对格式
    • JavaScript原生支持,几乎支出所有后台语言
    • 轻量级数据格式,占用字符数量特别少
    • 可读性强
    • 易编写和解析
  • JSONP(JSON with Padding)是资料格式 JSON 的一种“使用模式”,可以让网页从别的网域要资料。

    • 通过javascript callback的形式实现跨域访问。
    • jsonp只能get请求,不能post。
    • JSON是一种数据交换格式,那么JSONP就是一个跨域交互协议,可以理解为,JSONP约定了JSON的这个数据怎样进行传递。
    • 跨域是指从一个域名去请求另一个域名的资源,我们知道,如果直接用AJAX请求的时候,由于浏览器同源策略的存在,很容易产生跨域问题,同源策略是指域名、协议、端口均相同,如果不同则视为跨域请求,跨域请求一律都是不行的
    • 想要跨域请求资源,除非我们运用js的特性:script标签中的链接可以访问跨域的js文件,于是跨域服务器可以这样做,它把客户端需要的数据动态包装成js文件然后提供给客户端请求。这种数据传递方式慢慢就形成了一种传输协议,这就是JSONP了。

33、移动端适配

  1. @media + rem
  2. 手机淘宝flexible.js
  3. vw/vm适配