前端面试总结

170 阅读6分钟

javaScript

  • JavaScript简介 JavaScript一种动态类型、弱类型、基于原型的客户端脚本语言,用来给HTML网页增加动态功能。 JavaScript由三部分组成: ECMAScript(核心)+DOM(文档对象模型)+BOM(浏览器对象模型) ECMAScript作为核心,规定了语言的组成部分:语法、类型、语句、关键字、保留字、操作符、对象
  • 类型检测篇 1.typeof 使用快速简单 但是不能区分{}、[]、null 检测是都是object
console.log(typeof []);              // object 
console.log(typeof {});              // object
console.log(typeof null);            // object
  1. instanceof 能够区分Array、Object和Function,适合用于判断自定义的类实例对象 Number,Boolean,String基本数据类型不能判断
console.log(2 instanceof Number);                    // false
console.log(true instanceof Boolean);                // false 
console.log('str' instanceof String);                // false  
console.log([] instanceof Array);                    // true
console.log(function(){} instanceof Function);       // true
console.log({} instanceof Object);                   // true

3.Object.prototype.toString.call()精准判断数据类型 缺点:写法繁琐不容易记,推荐进行封装后使用 window.onload和$(document).ready()的区别 window.onload是在页面中包含图片在内的所有元素全部加载完成再执行; (document).ready()DOM树加载完成之后执行,不包含图片,其他媒体文件;因此(document).ready()是DOM树加载完成之后执行,不包含图片,其他媒体文件; 因此(document).ready()快于window.onload执行;

  • 0.1+0.2!=0.3怎么处理计算机是采用二进制来表示十进制的 以IEEE 754 双精度64位浮点数
   (0.1*10 + 0.2*10)/10 == 0.3 //true
  • 深克隆就是让引用类型的value值从赋址变成赋值 让两个应用类型的值互相不影响
    let obj ={
    name:"xxxx",
    arr:[1]
}

function deepClone(data){
    let type = Object.prototype.toString.call(data)
    if(type!=='[object Array]'&&type!=='[object Object]') return null;
     let result = Array.isArray(data)?[]:{};
     for(let key in data){
         if(data.hasOwnProperty(key)){
             if(typeof data[key] === 'object'&&data[key]!==null){
                 result[key] = deepClone(data[key])
             }else{
                 result[key] = data [key]
             }
         }
     }
     return result
}
let arr = deepClone(obj)
arr.arr.push(2)
console.log(arr,obj);

image.png

当然有种简单的方法:JSON.parse(JSON.stringify());undefined、function、symbol 会被忽略;

image.png

base64:26个大小写 加1234567890加+/ 只转码 体积增加1/3

 
['1', '2', '3'].map(parseInt)
// console.log(['1', '2', '3'].map(parseInt));   [ 1, NaN, NaN ]  parseInt('1',0) 0是基数代表进制


// 防抖
// 触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间

// function debounce(fn,time=2000){
//     let timer =null
//    return function(){
//        clearInterval(timer)
//        timer=setTimeout(()=>{
//               fn.call(this)
//        },time)
//    }
// }
// function sum(){
//     console.log('do something')
// }
//document.addEventListener('click',debounce(sum),false)

// 节流
// 高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率

function throttle(fn,time=2000){
    let flag = false
    console.log('throttle',this);
    return function(){
        if(flag)return
        flag=true
        setTimeout(()=>{
            console.log('setTimeout',this);
            flag = false
            fn.call(this,1)
        },time)
    }
}
function sum(data){
    console.log('do something',this,data)
}
document.addEventListener('click',throttle(sum),false)


// var arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10];
// console.log([...new Set(arr.toString().split(',').map(item=>Number(item)))].sort((a,b)=> a-b));
// console.log([...new Set(arr.flat(Infinity))].sort((a,b)=> a-b));

async await ES2017 标准引入了 async 函数,它就是ES2016 Generator 函数的语法糖。 Generator 异步编程解决方案 async 函数返回值是一个promise对象 并且返回值会是promise对象中resolve方法的参数

 function*helloWorldGenerator(){
       yield'xia';
       yield  'lin';
       yield 'hui';
       return '你好'
   }  
      let grt = helloWorldGenerator()
     let a = grt.next()   
     let b = grt.next()
     let c = grt.next()
     let d = grt.next()
     let f= grt.next()   
    //  console.log(Object.prototype.toString.call(grt),a,b,c,d,f);
     //[object Generator]   abc {value: "xia", done: false}  d {value:"你好", done: true}  
     f {value: undefined, done: true}

  function*helloWorldGenerator(){
    [].forEach(item=>{
        yield  1+1;  //会报错  yield只能在Generator 函数中  可以使用for循环改进 async 一样
    })

   } 

浏览器http缓存

浏览器缓存:把http请求回来的数据存储在本地的一种行为。

作用减少了服务器的负担,大大提升了网站的性能 加快了客户端加载网页的速度

分类

看是否命中强缓存,再判断是否命中协商缓存!

强缓存:http1.0时使用的是Expires,通过一个绝对时间 ,缺点很明显 服务器与客户端时间偏差较大时,就会导致缓存混乱。 http1.1是Cache-Control max-age=多少秒, 同时启用的时候 Cache-Control 优先级高。 不会发送请求如果命中,则返回 200 协商缓存:会发送请求如果命中,则返回 304
当服务器返回文件时在response header中添加 Last-Modified ,当浏览器请求发现 Last-Modified, 于是添加If-Modified-Since这个request-header,值就是Last-Modified中的值 , 服务器收到 If-Modify-Since 后,根据资源的最后修改时间判断是否命中缓存 命中则返回 304
服务器response header中添加 Etag一种唯一标识,浏览器会将上一次返回的Etag值放到request header里的If-None-Match里,服务器发现ETag匹配一致返回 304服务器会优先验证 ETag

浏览器本地缓存

1.localStorage,sessionStorage和cookie,WebSql和IndexDB

image.png

websql兼容性好 但是已经被废弃了 IndexDB:浏览器提供的本地数据库 ,提供查找接口,还能建立索引。

面向对象

把具有相同的特征的代码抽象出来,归为一类,把描述这个类的细节、功能挂在这个类的原型上的一种设计开发编程思想。 面向对象有三个特点:封装继承与多态

继承

A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法

1.原型链继承 : Student.prototype = new Person() // 子类型的原型为父类型的一个实例对象。 优点:简单,易于实现 缺点:继承单一,创建子类实例时,无法向父类构造函数传参,所有新实例都会共享父类实例的属性。(原型上的属性是共享的,一个实例修改了原型属性,另一个实例的原型属性也会被修改!)constructor 被修改 2.借用构造函数继承(call继承):在子类型构造函数中通用call()调用父类型构造函数

  function Person(name, age) {
    this.name = name,
    this.age = age,
    this.setName = function () {}
  }
  Person.prototype.setAge = function () {}
  function Student(name, age, price) {
    Person.call(this, name, age)  // 相当于: this.Person(name, age)
    /*this.name = name
    this.age = age*/
    this.price = price
  }
  这种方式只是实现部分的继承,如果父类的原型还有方法和属性,子类是拿不到这些方法和属性的。
  console.log(s1.setAge())//Uncaught TypeError: s1.setAge is not a function

优点:可以向父类传参,没有修改constructor 缺点:只能继承父类的实例属性和方法,不能继承原型属性和方法 3.组合继承(组合原型链继承和借用构造函数继承)(常用)

 function Person(name, age) {
            this.name = name,
            this.age = age,
            this.setAge = function () { }
        }
        Person.prototype.setAge = function () {
            console.log("111")
        }
        function Student(name, age, price) {
            Person.call(this,name,age)
            this.price = price
            this.setScore = function () { }
        }
        Student.prototype = new Person()   Object.create(Person.prototype)//优化
        Student.prototype.constructor = Student//组合继承也是需要修复构造函数指向的
        Student.prototype.sayHello = function () { }
        var s1 = new Student('Tom', 20, 15000)
        var s2 = new Student('Jack', 22, 14000)

优点:不存在引用属性共享问题,可传参,函数可复用,可以继承实例属性/方法,也可以继承原型属性/方法 缺点:调用了两次父类构造函数,生成了两份实例

4.ES6中class 的继承 class Student extends Person

优点:语法简单易懂,操作更方便 缺点:并不是所有的浏览器都支持class关键字

this 问题

image.png