耗时一周整理的前端面试题,干货为主

websocket

Websocket同http一样都是是基于tcp的,可靠性的双向通信协议,是建立在tcp之上的,并且是持久化的协议。

前端面试知识点目录整理

websocket 和http区别?

  • 相同点

    • 都是应用层的协议
    • 都是基于tcp,可靠的协议
  • 不同点

    • websocket是持久化的协议.
    • websocket是双向通信协议,模拟socket协议,可以双向发送信息,而HTTP是单向的
    • websocket可以在服务器端主动向客户端发送信息,而http的服务端,只能通过客户端主动请求

请描述一下cookie、sessionStorage和localStorage的区别?

  • 相同点:都存储在客户端
  • 不同点

    1. 存储大小
      cookie数据大小不能超过4k。
      sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。
    2. 有效时间
      localStorage 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据;
      sessionStorage 数据在当前浏览器窗口关闭后自动删除。
      cookie 设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭
    3. 数据与服务器之间的交互方式
      cookie的数据会自动的传递到服务器,服务器端也可以写cookie到客户端
      sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存

JS的类型?

  • 基本类型

    • undefined
    • null
    • Number
    • String
    • Boolean
  • 复杂类型

    • Object

js变量按照存储方式区分,有哪些类型,并表述其特点

  • 值类型:

    • undefined string number Boolean
    • 拷贝形式,
  • 引用类型:

    • array , function
    • 指针指向,共用空间
    • 可无限扩展属性,极大节省命名空间。
  • 特殊引用类型:function

    • 同引用类型↑
    • 特殊引用类型只有function,由于function的特殊性,使得它有点不同

JS中的typeof能得到的那些类型? 6种

  • number
  • string
  • undefined
  • object : null和数组 都是object
  • function
  • boolean

注意:typeof无法详细区分引用类型的类型,除了function. 只能准确区分值类型的类型
比如:




 typeof {} //object
 typeof [] //object
 typeof null //object
 typeof console.log // function 

function是一个比较特殊的类型,所以typeof能够区分

何时使用===何时使用==?

  • 尽可能使用 === 原因如下

    • 一致性:使用 ==对一致性没有任何好处,所以提前避免
    • 一般来说,===是最简单的操作符,因为它不用类型转换,所以相对来说,速度也会更快。
    • == 会进行类型转换,很容易懵逼
  • == 的使用情况,可参考

    • 判断对象的属性是否存在



    var obj = {};
    if( obj.a == null ){
        //这里相对于:obj.a === null || obj.a === undefined 的简写形式,JQ源码的推荐写法
    }
  • 判断函数的参数是否存在



    function fn( a, b){
        if( b == null ){
            //这里相当于 b===null || b === undefined 的简写
        }
    }

如何理解JSON?

  • 从纯JS的角度看,JSON就是对象,并且只有两个API




   JSON.stringify({a:10,b:30}) //将对象转为字符串
   JSON.parse('{"a":10,"b":30}') //将JSON格式的字符串转为 对象
  • JSON也是一种轻量级的文本数据交换格式.
  • js中有哪些内置函数 9 种

    • Object
    • Array
    • Boolean
    • Number
    • String
    • Function
    • Date
    • RegExp
    • Error

    判断一个变量会被当做 true 还是 false

    
    
    
    var a = 100; console.log( !!a ); //true
    

    window.onload和DOMContentLoaded的区别?

    • window.onload: 页面中所有数据加载完成后,才会执行,包括图片,css等
    • DOMContentLoaded: DOM结构加载完成后执行,需要等待图片等其他资源加载完成

    简述如何实现一个模块加载器,实现类似requires.js的基本功能

    可参看这篇博文:https://github.com/youngwind/...

    实现数组的随机排序

    
    
    
     //该方法最简单,效果一般,每个元素仍然有很大机率在它原来的位置附近出现
     arr.sort(function () { 
          return Math.random() - 0.5; 
       }); 
    
    

    //Fisher–Yates shuffle费雪耶兹随机置乱算法) !!!推荐

    
    
    
       
        //算法思想:从0~i(i的变化为 n-1到0递减)中随机取得一个下标,和最后一个元素(i)交换。
       var arr = [5,8,59,56];
       function shuffle(arr) { 
        var i = arr.length, t, j; 
        while (i) 
        { 
            j = Math.floor(Math.random() * i--);
            t= arr[i];
            arr[i] = arr[j];
            arr[j]= t;
        } 
    } 
    shuffle(arr)
    console.log(arr);//[56, 8, 5, 59]
    

    原型和原型链

    什么叫原型链

    原型链是针对构造函数的,比如我创建了一个函数并通过变量new了一个函数,那这个函数就会继承创建处理函数的属性,如果访问这个函数的属性时,并没有在new处理的变量中写该属性,那么就会往上,根据protype逐级向上查找,这个查找的过程就叫原型链。

    原型规则

    1. 所有的引用类型(数组,对象,函数),都具有对象的特殊,即可自由扩展属性(除了Null,纯属意外)
    2. 所有的引用类型(数组,对象,函数),都有一个__proto__属性,也可以称为隐式原型,属性值是一个普通的对象
    3. 所有的函数,都有一个prototype属性,也可称之为显式原型,属性值是一个普通的对象
    4. 所有的引用类型(数组,对象,函数),__proto__属性值指向它的构造函数的prototype属性值
    5. 当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的__proto__中去找。

    由于它的隐式原型等于它的显式原型,所以也会去 prototype 中去找。

    构造函数

    
    
    
     function Foo(name,age){
        this.name = name;
        this.age = age;
    }
    var foo = new Foo('h1',25);
    var foo2 = new Foo('h1',250);
    console.log(foo,foo2);
    
    //循环对象自身的属性
    var item;
    for( item in foo)
    {
        //只遍历对象自身的属性,过滤掉该对象的显式原型
        if(foo.hasOwnProperty(item))
        {
            console.log(item)
        }
    
    }
    
    

    描述new一个对象的过程

    1. 创建一个对象
    2. this指向这个新对象
    3. 执行代码,即对this赋值
    4. return this。 默认有return,不用写

    如何判断一个变量是数组类型

    
    
    
    var arr = [1,2,3];
    console.log(Array.isArray(arr)); //true
    
    //instanceof运算符用于测试构造函数的prototype属性是否出现在对象的原型链中的任何位置
    console.log( arr instanceof Array) //true
    

    写一个原型继承的例子

    
    
    
     function Elem(id){
        this.dom = document.getElementById(id);
    }
    
    Elem.prototype.html = function(val){
        var dom = this.dom;
        if(val){
            dom.innerHTML = val;
            return this; //用来链式调用
        }else{
            return dom.innerHTML;
            
        }
    }
    
    Elem.prototype.on = function(type ,fn){
        var dom = this.dom;
        dom.addEventListener( type , fn);
        
    }
    var h1 = new Elem('h1');
    h1.html("你被修改了").on('click', function(){
        console.log(this)
    })
    
    

    作用域和闭包

    什么叫作用域?

    `作用域是针对变量的,比如我创建了一个函数,这个函数中包含了另外一个函数。那么该变量中就有3个作用域
    全局作用域》函数作用域》内层函数的作用域
    作用域的特点就是,先在自己的变量范围中查找,如果找不到,就会沿着作用域往上找。
    `

    变量提升的理解

    • 变量定义
    • 函数声明(注意和函数表达式的区别)
    • 预解析

    this的使用场景

    注意:this要在执行时才能确认值,定义时无法确认

    • 作为构造函数执行
    • 作为对象属性执行
    • 作为普通函数执行
    • call apply bind
    
    
    
     function f1(name,age){
        console.log(name,age)
        console.log(this); //this为x对象
     }
    
    f1.apply({x:'我是this'}, ["seek",20]);
    f1.call({x:'我是this'}, "seek",20);
    
    
    //使用bind改变this时,需用函数表达式
    var f1 = function (name,age){
        console.log(name,age)
        console.log(this); //this为x对象
    }.bind('我是被绑定的this')
    
    f1("seek",20)
    
    

    闭包

    `当一个函数的返回值是另外一个函数,而返回的那个函数如果调用了其父函数内部的其它变量,
    如果返回的这个函数在外部被执行,就产生了闭包。
    表现形式:使函数外部能够调用函数内部定义的变量。`

    • 闭包的使用场景

      1. 函数作为返回值

    
    
    
     function fn(){
        var a = 10;
        return function(){
            console.log(a); //a是自由变量,从父作用域开始找。
        }
    }
    var f1 =  fn();
    var a = 20;
    f1(); //10
    
  • 函数作为参数来传递

  • 
    
    
    function fn(){
        var a = 10;
        return function(){
            console.log(a); 
            }
    }
    var fn1 = fn();
    
    function fn2(fn){
        var a =20;
        fn();
    }
    fn2(fn1); //10
    

    如何理解作用域?

    • 自由变量
    • 作用域链,即自由变量的查找
    • 闭包的两个场景

    JS创建10个a标签,点击时弹出对应的序号 (考点:作用域)

    
    
    
    var str,a;
    for( a=0; a<10;a++){
        str = document.createElement("a");
        str.innerHTML = a + "点我" + "<br/>";
        
        document.body.appendChild(str);
        
        (function(a){
            str.addEventListener("click",function(e){
                e.preventDefault();
                console.log(a)
            })
        })(a)
    }
    

    什么叫异步,什么叫同步?

    同步是阻塞模式,异步是非阻塞模式。

    • 异步:不需要等操作做完,就响应用户请求. 比如:ajax,img的加载,setTimeout,setInterval
    • 同步:必须等待操作做完,才返回结果.

    数组API

    
    
    
     var arr= [2,3,9,0];
    
    • forEach 遍历所有元素
    
    
    
      arr.forEach(function(item,index){
            console.log(item) // 2390
            console.log(index) //0123
    
        })
    
    • every 判断所有元素是否都符合条件
    
    
    
      var result = arr.every(function(item,index){
            if(item < 4)
            {
              return true;
            }
        })
      console.log(result); //false, 因为9并不小于4
    
    • some 判断是否有至少一个元素符合条件
    
    
    
     var result =  arr.some(function(item,index){
            if(item < 4)
            {
              return true;
            }
          })
    console.log(result); //true 因为2,3,0小于4
    
    • sort 排序
    
    
    
     var result =  arr.sort(function(a,b){
              // return a-b; //正序
              return b-a; // 倒序
            // return return Math.random() - 0.5; //最简单的随机数组排序,并不推荐
    
          })
    console.log(result); //  [9, 3, 2, 0]
    
    • map 对元素重新组装,生成新数组
    
    
    
    //map适用范围还是较广的,学会思考
     var result =  arr.map(function(item,index){
                return '<h1>' + item + '</h1>';
          })
    console.log(result);   //  ["<h1>2</h1>", "<h1>3</h1>", "<h1>9</h1>", "<h1>0</h1>"]
    
    • filter 过滤符合条件的元素,较为常用
    
    
    
    var result =  arr.filter(function(item,index){
                if(item >=3){
                  return true;
                }
          })
    console.log(result);   // [3, 9]
    

    获取 2019-03-23格式的日期

    
    
    
       function formatDate(dt) {
            if (!dt) {
                //如果不传参数,则默认为当前时间
                dt = new Date();
            }
    
            var year = dt.getFullYear();
            var month = dt.getMonth() + 1;
            var day = dt.getDate();
    
            if (month <= 10) {
                month = '0' + month;
            }
    
            if (day <= 10) {
                day = '0' + day;
            }
    
            return year + '-' + month + '-' + day;
        }
    
        var date = formatDate();
        console.log(date); //2019-03-23
    
    

    获取随机数,要求长度一致的字符串格式

    
    
    
     var random = Math.random();
        random = random + '0'.repeat(10); //repeat 重复10个0, 防止随机数出现少于10位数的情况
        random = random.slice(0,10)
        console.log(random); //0.70728618  每次返回的只有10位数的字符串
    

    写一个能遍历对象和数组的foreach函数

    
    
    
    function foreach(info, fn)
    {
            //数组处理
            if(info instanceof Array)
            {
              info.forEach(fn)
            }else{
               //对象处理
               for( key in obj){
                  fn(key, obj[key])
                }
            }
      
    }
    
    //使用方法
      var obj = {x: '我是x',y: '我是y'};
       foreach(obj, function(key,value){
        console.log(value); //我是x,我是y
      })
    
    
      var arr = [5,8,9];
      foreach(arr, function(elem,index){
        console.log(elem);//5,8,9
      })
    
    

    Web_API

    编写一个通用的事件监听函数

    
    
    
     function bindEvent(elem,type,fn){
               elem.addEventListener( type ,fn)
     }
     //使用方法
     bindEvent(id,'click', function(e){
        console.log(e)
     })
    
     bindEvent(a,'click', function(e){
        e.preventDefault(); //阻止默认事件
     })
    

    对于一个无限加载流的页面,如何给每个特定的标签添加事件

    
    
    
    //使用代理,由父级帮忙去做
    
     <div id="div1">
        <a href="#">a1</a>
        <a href="#">a2</a>
        <span>ddd</span>
        <a href="#">a5</a>
        <!-- 动态加载更多 -->
    </div>
    
    div1.addEventListener('click', function(e){
        if (e.target.nodeName == "A"){
            alert(e.target.innerHTML)
        }
    })
    

    完善通用绑定事件的函数,包括代理

    
    
    
    //HTML结构
     <div id="div1">
        <a href="#">a1</a>
        <a href="#">a2</a>
        <span>ddd</span>
        <a href="#">a5</a>
        <!-- 动态加载更多 -->
    </div>
    
    <div id="div2">不使用代理</div>
    
    //
    function bindEvent(elem,type,selector, fn){
        if(fn == null){
            fn=selector;
            selector =null;
        }
        elem.addEventListener( type ,function(e){
            var target;
            if(selector){
                target = e.target;
                //matches() 方法用于检测字符串是否匹配给定的正则表达式。
                if(target.matches(selector)){
                    fn.call(target,e);
                }
            }else{
                fn.call(e);
            }
        })
    }
    
    //使用代理
    bindEvent(div1,'click','a',function(e){
        console.log(this)
    })
    //不使用代理
    bindEvent(div2,'click',function(e){
        //call改变了this指向为e
        console.log(this.toElement.innerHTML)
    })
    
    

    可以跨域的三个标签

    
    
    
    <img src="" alt=""> //用于打点统计
    <link rel="stylesheet" href=""> //使用CDN
    <script></script> // 使用JSONP
    

    3月10日面试

    闭包的优缺点

    JS中,在函数外部无法访问函数内部的值,使用闭包就可以做到。

    • 优点:

      1. 使用闭包能够让局部变量模拟全局变量一样,但是,只能被特定函数调用。
      2. 全局变量可能会造成命名冲突,使用闭包不用担心这个问题,因为它是私有化,加强了封装性。
    • 缺点

      1. 由于闭包是驻留在内存中的,会增大内存使用量,使用不当很容易造成内存泄露,降低程序的性能。

    按需引入,模块引入的实现?

    http请求缓存头详解

    1. Expires: http1.0 推出的,指服务器返回的文件有效期,但其实这是有缺陷的,如果把本地的时间改为2118年,那Expires的时间怎么都会过期。
    2. Last-Modified: http1.0推出的,指服务器文件的最后修改时间,浏览器会带上If-Modified-Since向服务器发送请求,与服务器文件修改时间Last-Modified做对比,如果时间不同,则获取数据返回200,否则返回304后调用浏览器本地硬盘的缓存。
    3. Cache-Control: http1.1推出,指文件缓存的有效期。

      • .max-age:单位是s,设置文件最大缓存时间,用得最多。
      • public:缓存可以被多用户共享,例如360浏览器可以登录不同账号,电脑系统可以切换不同账号
      • private:仅单用户私有,不被多用户共享
      • no-cache:不会被缓存。
      • no-store:不允许被存储
    4. ETag: http1.1推出,该版本号是由服务端随机生成的,浏览器会带上If-None-Match向服务器发送请求,与服务器文件修改版本ETag做对比,如果版本号不同,则获取数据返回200,否则返回304后调用浏览器本地硬盘的缓存,这种方式比Last-Modified靠谱。

    来源:https://segmentfault.com/a/1190000018628100

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值