Git Product home page Git Product logo

awesome_interview_question's People

Stargazers

6666666666622222222 avatar  avatar 九天逍 avatar  avatar weiwu avatar kebin avatar Yangs avatar  avatar  avatar 能不能给我换个名儿 avatar diasa avatar

Watchers

diasa avatar

awesome_interview_question's Issues

【leetcode】给定一个一维数组,转变成m*n列的二维数组, m和n都是整数。

给定一个一维数组,转变成m*n列的二维数组, m和n都是整数。
如无法构成这样的二维数组,返回一个空的二维数组。

const arr = [1, 3, 5, 7, 13, 9, 14, 12, 11, 9, 4, 2]

var construct2DArray = function(arr, m, n) {
  if (arr.length !== m * n) {
      return [];
  }
  let result = []
  for(let i=0; i< m; i++) {
    let smallArr = []
    for(let j=0; j< n; j++) {
      smallArr.push(arr[j + i*n])
    }
    result.push(smallArr)
  }
  return result
};
console.log(construct2DArray(arr, 4, 3))

运行结果:
image

【排序】- 冒泡排序

const arr = [1,3,6,5,2,4,7]

const bubbleSort = (list = []) => {
    if (list.length <= 1) return list
    for (let i = list.length - 1; i > 0; i--) {
        for (let j = 0; j < i; j++) {
            const temp = list[j]
            if (list[j] > list[j + 1]) {
                list[j] = list[j + 1]
                list[j + 1] = temp
            }
        }
    }
    return list
}

console.log(bubbleSort(arr)) // [1, 2, 3, 4, 5, 6, 7]

leetcode练习地址

image

react17之前和之后的jsx有什么区别?

1、React17之后的版本不需要再手动导入React, import React from 'react'
因为新版本的jsx编译之后会自动引入react环境
2、节点转译优化,children直接放到属性里,不是在参数后面在一个个累加,使用上更加方便

var { jsxDEV } = require("react/jsx-dev-runtime");
jsxDEV("h1", {
  children: [
    "hello",
    jsxDEV("span", {
      style: {
        color: "red",
      },
      children: "world",
    }),
  ],
});

css代码场景面试题

1、实现一个三角形

/* 三角形:绘制一个正方形,border,transparent掉某个边 */
/* .triangle {
  width: 0;
  height: 0;
  border: 100px solid;
  border-color: rebeccapurple red goldenrod yellowgreen;
  border-top-color: transparent;
  border-bottom-color: transparent;
  border-right-color: transparent;
} */

.triangle {
  width: 0;
  height: 0;
  border-bottom: 100px solid burlywood;
  border-top: 100px solid transparent;
  border-right: 100px solid transparent;
  border-left: 100px solid transparent;
}

2、实现一个扇形

/* 圆形:绘制一个圆,隐藏三个边,通过旋转确定方向 */
/* .circle {
  width: 0;
  height: 0;
  border: 100px solid;
  border-color: rebeccapurple red goldenrod yellowgreen;
  border-radius: 50%;
  border-top-color: transparent;
  border-bottom-color: transparent;
  border-right-color: transparent;
  transform: rotate(45deg);
} */

.circle {
  width: 0;
  height: 0;
  border-top: 100px solid transparent;
  border-right: 100px solid transparent;
  border-left: 100px solid transparent;
  border-bottom: 100px solid yellowgreen;
  border-radius: 50%;
  transform: rotate(45deg);
}

3、实现一个宽高自适应的正方形

/* vw实现 */
.square {
  width: 10%;
  height: 10vw;
  background: tomato;
}

4、画一条0.5px的线

/* 1、移动端 */
<meta name="viewport" content="width=device-width,initial-scale=0.5, minimum-scale=0.5, maximum-scale=0.5"/>

/* 2、transform */
transform: scale(0.5,0.5);


/* 3、boxshadow */
.boxshadow {
  height: 1px;
  background: none;
  box-shadow: 0 0.5px 0 #000;
}

5、设置小于12px的字体

/* 两个div,字体单独放在一个div里面 */
/* 比较一下缩小后的12px是否一样大 */
.fontDiv {
  font-size: 12px;
}
.fontSection {
  font-size: 24px;
  transform: scale(0.5);
}

6、布局

  • 两栏布局:左边定宽,右边自适应
/* 左边定宽,右边自适应。
* 1、float+margin: 左边给定宽度,浮动。右边给定margin-left为宽度
*/
.wrapper {
  width: 100vw;
  height: 100vh;
}
.left {
  width: 200px;
  height: 100%;
  background-color: rosybrown;
  float: left;
}
.right {
  height: 100%;
  background-color: greenyellow;
  margin-left: 200px;
}
  • 三栏布局:左右定宽,中间自适应
/* 三栏布局,中间自适应 */
/* float+margin */
.app {
  width: 100vw;
  height: 100vh;
  background-color: greenyellow;
}
/* 左栏左浮动 */
.left {
  background: red;
  width: 100px;
  float: left;
  height: 100%;
}

/* 中间自适应 */
.main {
  background: blue;
  height: 100%;
  margin: 0px 200px 0px 100px;
}

/* 右栏右浮动 */
.right {
  background: red;
  width: 200px;
  float: right;
  height: 100%;
}
  • 九宫格
<div class="wrapper">
 <div class="list">1</div>
 <div class="list">2</div>
 <div class="list">3</div>
 <div class="list">4</div>
 <div class="list">5</div>
 <div class="list">6</div>
 <div class="list">7</div>
 <div class="list">8</div>
 <div class="list">9</div>
</div>
 
.wrapper {
 width: 100%;
 display: grid;
 grid-template-columns: 33.33% 33.33% 33.33%;
 grid-template-rows: 200px 200px 200px;
}

.list {
 background: #f4979a;
 margin: 5px;
}

7、清除浮动

/* 清除浮动 */
.clearfix::after {
  content: '';
  height: 0;
  display: block;
  clear: both;
}

【排序】- 插入排序

const insertSort = (list) => {
    if (list.length <= 1) return list

    for (let i = 1; i < list.length; i++) {
        const base = list[i]
        let j = i - 1
        while (j >= 0 && list[j] > base) {
            list[j + 1] = list[j]
            j--
        }
        list[j + 1] = base
    }
    return list
}
insertSort([1,5,3,2,4])
// [1, 2, 3, 4, 5]

三次握手,四次挥手

seq、ack、ACK、SYN、FIN
tcp报文固定长度为20byte
三次握手:
第一次握手:客户端CLOSED =》SYN = 1,seq = x =》 服务器CLOSED、LISTEN
第二次握手: 服务器SYN-RCVD=》 SYN = 1, ACK = 1, seq = y, ack = x+ 1 =》 客户端SYN-SENT,ESTABLISHED
第三次握手: 客户端ESTABLISHED => ACK = 1, seq = x + 1, ack = y + 1 => 服务器SYN-RCVD、ESTABLISHED

数据传输

四次挥手
第一次挥手:客户端ESTABLISHED => FIN = 1, seq = u => 服务器ESTABLISHED、CLOSE-WAIT
第二次挥手:服务器端CLOSE-WAIT =》 FIN=1,seq = y, ack = u + 1 =》 客户端FIN-WAIT-1
第三次挥手:服务器端CLOSE-WAIT =》 FIN=1,ACK=1,seq = w, ack = u + 1 =》 客户端FIN-WAIT-1
第四次挥手: 客户端FIN-WAIT-2 =》 ACK=1,seq=u+1,ack=w+1 => 服务器端LAST-ACK、CLOSED
等待一会后,客户端CLOSED

OSI模型、物联网叔会试用
物理层、数据链路层、网络层、传输层、会话层、表示层、应用层

image
image

箭头函数的缺点

  • 没有arguments
  • 无法通过 apply call bind 改变this
  • 不能实例化
  • this指向当前函数所在的作用域

两个数组的交集

// 解题思路:先排序后再遍历数组
// 第二个数组的元素如果在第一个数组中存在,则删除存在数组中的值 继续遍历

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
let nums1 = [4,9,5], nums2 = [9,4,9,8,4]
var intersect = function(nums1, nums2) {
  nums1.sort((a, b) => a - b);
  nums2.sort((a, b) => a - b); // 先排序,使得重复的元素相邻出现
  const list = []
  nums1.forEach(v =>{
    if(nums2.indexOf(v) !== -1){
      list.push(v)
      nums2.splice(nums2.indexOf(v), 1)
    }
  })
  return list
};

intersect(nums1, nums2)

【排序】- 插入排序

const insertSort = (list) => {
    if  (list.length <= 1) return list
    for  (let i = 1; i < list.length; i++). {
        const pivot = list[i]
        let j = i - 1
        while  (j >= 0 && list[j] > pivot) {
            list[j + 1] = list[j]
            j--
        }
        list[j + 1] = pivot
    } 
    retur list
}

insertSort([1,2,6,5,4,3,9,0])
// [0, 1, 2, 3, 4, 5, 6, 9]

Ajax、Fetch、Axios的区别?

  • Ajax是异步请求的一个统称(内部可以通过XMLHttpRequest或者fetch来实现)
  • fetch是一个浏览器的Api
  • axios是一个请求的库,可以在浏览器和node中使用

判断数据类型

  • typeof
    可以判断出Number,String,Boolean,Undefined,Symbol,BigInt,Function。
    缺点:不能判断null,typeof null返回的是object。普通对象、数组、日期对象等均返回object

  • constructor
    通过constructor找到自己的构造函数
    缺点:可以被改写,不一定准确。null,undefined没有构造函数
    使用:

    [0,1].constructor === Array
    undefined.constructor === Array
    
  • instanceof
    检测某个对象是否属于某个构造函数,是通过原型链查找。
    确定:不能检测基本数据类型。
    使用:
    [] instanceof Array

  • Object.prototype.toString.call
    使用:

toString.call(1) // [object Number]
toString.call(function(){}) // [object Function]
toString.call(null) // [object Null]
  • Object.prototype.isPrototypeOf
    类似instanceof

  • Array.isArray

// 检测数组
Array.isArray([])
  • Number.isNaN
Number.isNaN(NaN) // true
Number.isNaN(12) // false
  • == 和 ===

  • 正则判断

function myTypeof(data) {
    const str = JSON.stringify(data)
    if (/^{.*}$/.test(data)) {
        return 'object'
    }
    if (/^\[.*\]$/.test(data)) {
        return 'array'
    }
}

React中的setstate是批量还是非批量执行?

image
react版本16.8
setState如果是在react合成事件中执行的,那么会进行批量操作(异步),直接跳过了1那一步的变化,合并到了2
image
如果不是在合成事件中执行的,比如settimeout中,那么就会进行非批量(同步)操作,输出了3,4
batchingStrategy 的isBatchingUpdates状态若为true,会被放进dirtyComponents(批量执行)
isBatchingUpdates状态若为false:遍历dirtyComponents、调用updateComponent、更新state(非批量执行)

react版本18.0.0
与上面相同的代码,只输出了2,4;表现1,3都被批量执行覆盖了,即不论是合成事件还是非合成事件中,react都将setstate更新成了批量更新操作
image

px % em rem vm/vh 区别

  • px基本单位,绝对单位
  • %是相对于父元素
  • em是相对于当前元素的font-size
  • rem是相对于根节点的font-size
  • vw屏幕宽度的1%
  • vh屏幕高度的1%

什么是防抖?什么是节流?手写一个

防抖:n秒后在执行该事件,若在n秒内被重复触发,则重新计时

    // ---------------------------------------------------------防抖函数
    function debounce(func, delay) {
      let timeout
      return function () {
        let arg = arguments
        if (timeout) clearTimeout(timeout)
        timeout = setTimeout(() => {
          func(arg)
        }, delay);
      }
    }

    // ---------------------------------------------------------立即执行防抖函数
    function debounce2(fn, delay) {
      let timer

      return function () {
        let args = arguments
        if (timer) clearTimeout(timer)


        let callNow = !timer
        timer = setTimeout(() => {
          timer = null
        }, delay);
        if (callNow) { fn(args) }
      }
    }
    // ---------------------------------------------------------立即执行防抖函数+普通防抖
    function debounce3(fn, delay, immediate) {
      let timer

      return function () {
        let args = arguments
        let _this = this
        if (timer) clearTimeout(timer)

        if (immediate) {
          let callNow = !timer
          timer = setTimeout(() => {
            timer = null
          }, delay);

          if (callNow) { fn.apply(_this, args) }
        } else {
          timeout = setTimeout(() => {
            func.apply(_this, arguments)
          }, delay);
        }

节流:n秒内只运行一次,若在n秒内重复触发,只有一次生效

   // ---------------------------------------------------------节流 ,时间戳版

    function throttle(fn, wait) {

      let previous = 0
      return function () {
        let now = Date.now()
        let _this = this
        let args = arguments
        if (now - previous > wait) {
          fn.apply(_this, arguments)
          previous = now
        }
      }
    }

    // ---------------------------------------------------------节流 ,定时器版
    function throttle2(fn, wait) {
      let timer
      return function () {
        let _this = this
        let args = arguments
        if (!timer) {
          timer = setTimeout(() => {
            timer = null
            fn.apply(_this, arguments)
          }, wait);
        }
      }
    }

谈谈Promise 的理解?

Promise 的理解:

1.Promise 是一种为了避免回调地狱的异步解决方案 2. Promise 是一种状态机: pending(进行中)、fulfilled(已成功)和rejected(已失败) 只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。

回调地狱:

回调函数中嵌套回调函数的情况就叫做回调地狱。
回调地狱就是为是实现代码顺序执行而出现的一种操作,它会造成我们的代码可读性非常差,后期不好维护。

Promise是什么?

Promise是最早由社区提出和实现的一种解决异步编程的方案,比其他传统的解决方案(回调函数和事件)更合理和更强大。
ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。
ES6 规定,Promise对象是一个构造函数,用来生成Promise实例。

Promise是为解决什么问题而产生的?

promise是为解决异步处理回调金字塔问题而产生的

Promise的两个特点?

1、Promise对象的状态不受外界影响
1)pending 初始状态
2)fulfilled 成功状态
3)rejected 失败状态
Promise 有以上三种状态,只有异步操作的结果可以决定当前是哪一种状态,其他任何操作都无法改变这个状态
2、Promise的状态一旦改变,就不会再变,任何时候都可以得到这个结果,状态不可以逆,只能由 pending变成fulfilled或者由pending变成rejected

Promise的三个缺点

1)无法取消Promise,一旦新建它就会立即执行,无法中途取消
2)如果不设置回调函数,Promise内部抛出的错误,不会反映到外部
3)当处于pending状态时,无法得知目前进展到哪一个阶段,是刚刚开始还是即将完成

Promise在哪存放成功回调序列和失败回调序列?

1)onResolvedCallbacks 成功后要执行的回调序列 是一个数组
2)onRejectedCallbacks 失败后要执行的回调序列 是一个数组

以上两个数组存放在Promise 创建实例时给Promise这个类传的函数中,默认都是空数组。
每次实例then的时候 传入 onFulfilled 成功回调 onRejected 失败回调,如果此时的状态是pending 则将onFulfilled和onRejected push到对应的成功回调序列数组和失败回调序列数组中,如果此时的状态是fulfilled 则onFulfilled立即执行,如果此时的状态是rejected则onRejected立即执行

上述序列中的回调函数执行的时候 是有顺序的,即按照顺序依次执行

【排序】- 快速排序

const quickSort = (list) => {
    if (list.length <= 1) return list
    const pivot = list.at(-1)

    const left = [] 
    const right = []
    const middle = []

    for (let i = 0; i <= list.length - 1; i++) {
        if (list[i] < pivot) {
            left.push(list[i])
        }
        if (list[i] > pivot) {
            right.push(list[i])
        }
        if (list[i] === pivot) {
            middle.push(list[i])
        }
        
    }
    return [...quickSort(left), ...middle,...quickSort(right)]
}

quickSort([1,5,4,2,3,9,6,7,1,2])
// [1, 1, 2, 2, 3, 4, 5, 6, 7, 9]

如果数组中没有重复的数字

const quickSort = (list) => {
    if (list.length <= 1) return list
    const pivot = list.at(-1)
    let left = []
    let right = []
    for (let i = 0; i < list.length - 1; i++) {
        if (list[i] > pivot) {
            right.push(list[i])
        } else {
            left.push(list[i])
        }
    }
    return quickSort(left).concat([pivot], quickSort(right))
}

quickSort([4,6,5,1,2,3])
// [1, 2, 3, 4, 5, 6]

手写一个setTimeout

let timer
const setTimeout = (fn, interval) => {
  let startTime = Date.now()
  const loop = () => {
    timer = requestAnimationFrame(loop)
    let now = Date.now()
    if (now - startTime >= interval) {
      fn()
      cancelAnimationFrame(timer)
    }
  }
  requestAnimationFrame(loop)
}

const clearTimeout = () => {
  cancelAnimationFrame(timer)
}

【算法】- 数组向右移动K步

返回一个移动K步的数组 arr = [1, 2, 3, 4, 5, 6, 7] K = 3 res = [5, 6, 7, 1, 2, 3, 4]

  • 方法1

每次移除一个再前面添加一个

     function rotate(arr, k) {
        const len = arr.length;
        if (!k || len === 0) return arr;
        const step = Math.abs(k % len);
        for (let i = 0; i < step; i++) {
          const n = arr.pop();
          if (n!==null) {
            arr.unshift(n);
          }
        }
        return arr;
      }

  • 方法2

数组截取再拼接

     function rotate(arr, k) {
        const len = arr.length;
        if (!k || len === 0) return arr;
        const step = Math.abs(k % len);
        const left = arr.slice(-step);
        const right = arr.slice(0, len - step);
        return left.concat(right);
      }

BFS

const node = {
    value: "A",
    children: [
        {
            value: "B",
            children: [{ value: "B1" }, { value: "B2" }]
        },
        {
            value: "C",
            children: [{ value: "C1" }, { value: "C2" }]
        }
    ]
}

const bfs = (node) => {
    console.log(node.value)
    node.children?.forEach(bfs)
}
bfs(node)
// A 
// B
// B1
// B2
// C
// C1
// C2

DFS

const node = {
    value: "A",
    children: [
        {
            value: "B",
            children: [{ value: "B1" }, { value: "B2" }]
        },
        {
            value: "C",
            children: [{ value: "C1" }, { value: "C2" }]
        }
    ]
}
const dfs = (node) => {
   const stack = [node]
   let current
   while ((current = stack.shift())) {
        console.log(node.value)
        current.children?.forEach(child => {
             stack.push(child)
        })
   }
}
dfs(node)
// A
// B
// C
// B1
// B2
// C1
// C2

0.1+0.2!==0.3

因为计算机传输是二进制传输的,而0.1和0.2在转换为二进制的时候是无限循环的。又因为JS是64位的浮点数表示法,会舍弃掉一些位数,最终造成的精度不准。所以0.1+0.2!==0.3

function equal(a, b) {
  return Math.abs(a - b) < Number.EPSILON;
}

父组件和子组件生命周期钩子执行顺序是什么?

加载渲染过程
父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate -> 子 created -> 子 beforeMount -> 子 mounted -> 父 mounted

子组件更新过程
父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated

父组件更新过程
父 beforeUpdate -> 父 updated

销毁过程
父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed

怎么实现网站都变成灰色?

code:

html{
    -webkit-filter: grayscale(100%);
    -moz-filter: grayscale(100%);
    -ms-filter: grayscale(100%);
    -o-filter: grayscale(100%);
    filter: grayscale(100%);
    filter: progid:DXImageTransform.Microsoft.BasicImage(grayscale=1);
}

comment:

grayscale 是一个 CSS 函数,可以把图像转成灰色,参数是个百分比,结果返回一个 filter 函数
目前的主流浏览器版本都支持 grayscale 函数, PC 端的 Chrome、edge、Firefox、Opera、Safari 等等,除了 IE
filter 函数可以用来改变图像的显示效果,用于 CSS 的 filter 属性。可选项有以下:

grayscale()将图像转换为灰度
blur()模糊图像
brightness()使图像更亮/更暗
contrast()增加/减少图片对比度
drop-shadow()在图像后面应用阴影
hue-rotate()更改图像整体色调
invert()反转图像颜色
opacity()使图像透明
saturate()对输入图像进行饱和/去饱和处理
sepia()将图像转为棕褐色

Antv G2/Plot如何实现文本自适应?

一般情况下,文本的fontSize属性是在style里面处理的,直接通过rem,如: 1rem,即可实现
但是在plot中存在部分实例如label,yAxis,xAxis等,fontSzie只能使用数字类型,不能使用字符串类型,即使设置成1rem也不会生效
解决方案
通过update方法修改文本大小

// 获取根节点fontSize大小,即1rem的大小
const getRemFontSize = () =>
Number(document.documentElement.style.fontSize.replace('px', ''))
// 调用update方法更新文本大小
chart.update({
  label: {
    style: {
       fontSize: getRemFontSize() * 1.25
    }
  },
})

搜索插入位置

搜索插入位置

/**
* 知识点:二分查找
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var searchInsert = function(nums, target) {
    // 初始化左开始位置,右边开始位置
    let left = 0, right = nums.length - 1, ans = nums.length;
    while (left <= right) {
        let mid = parseInt((right + left)/2);
        // 目标元素小于等于中间元素,右移,否则左移
        if (target <= nums[mid]) {
            ans = mid;
            right = mid - 1;
        } else {
            left = mid + 1;
        }
    }
    return ans;
};

https和http有什么区别,https的实现原理?

http无状态无连接,而且是明文传输,不安全
https传输内容加密,身份验证,保证数据完整性

https实现原理

首先客户端向服务端发起一个随机值,以及一个加密算法
服务端收到后返回一个协商好的加密算法,以及另一个随机值
服务端在发送一个公钥CA
客户端收到以后先验证CA是否有效,如果无效则报错弹窗,有过有效则进行下一步操作
客户端使用之前的两个随机值和一个预主密钥组成一个会话密钥,在通过服务端传来的公钥加密把会话密钥发送给服务端
服务端收到后使用私钥解密,得到两个随机值和预主密钥,然后组装成会话密钥
客户端在向服务端发起一条信息,这条信息使用会话秘钥加密,用来验证服务端时候能收到加密的信息
服务端收到信息后返回一个会话秘钥加密的信息
都收到以后SSL层连接建立成功

object.assign和扩展运算法是深拷贝还是浅拷贝,两者区别

扩展运算符:

let outObj = {
  inObj: {a: 1, b: 2}
}
let newObj = {...outObj}
newObj.inObj.a = 2
console.log(outObj) // {inObj: {a: 2, b: 2}}

Object.assign():

let outObj = {
  inObj: {a: 1, b: 2}
}
let newObj = Object.assign({}, outObj)
newObj.inObj.a = 2
console.log(outObj) // {inObj: {a: 2, b: 2}}

可以看到,两者都是浅拷贝。
Object.assign()方法接收的第一个参数作为目标对象,后面的所有参数作为源对象。然后把所有的源对象合并到目标对象中。它会修改了一个对象,因此会触发 ES6 setter。
扩展操作符(…)使用它时,数组或对象中的每一个值都会被拷贝到一个新的数组或对象中。它不复制继承的属性或类的属性,但是它会复制ES6的 symbols 属性。

介绍一下浏览器的页面缓存机制?

浏览器的缓存机制其实就是http的缓存机制,它是根据http的缓存标志来进行的。

浏览器每次向服务器发送请求,都会在浏览器中查找缓存以及缓存标志。浏览器每次拿到服务器返回的请求结果,都会将结果和缓存标志存入浏览器缓存中。

浏览器缓存以是否需求每次向服务器发送http请求为区分,将缓存分为 强缓存协商缓存

  • 强缓存

利用响应头的express和cache-control控制缓存,如果两者共存,cache-control优先级高于express

  1. express原理

    express的原理是利用客户端时间和服务器返回的时间做对比,是绝对时间

    弊端:可能由于时区不同或者其他原因产生一些误差。

  2. cache-control

    cache-control是相对时间,取值可以分为以下几种:

    • public:所有内容(客户端和代理服务器)都被缓存
    • private:只客户端被缓存,默认值
    • no-cache:如果设置了该字断需要先向服务端确认该返回的资源是否发生了变化,如果未发生变化,走协商缓存
    • must-revalidate:如果缓存的内容失效,请求必须发送到服务器/代理以进行重新验证
    • no-store:不使用任何缓存
    • max-age=xxx:缓存在xx秒后失效,只在http1.1中生效
  • 协商缓存

    协商缓存由服务器端决定资源是否可用。

    客户端向服务器端发起一次请求,如果命中协商缓存,服务器返回304

    • Last-Modified/If-Modified-Since:二者的值都是 GMT 格式的时间字符串。

      Last-Modified(服务端)标记文件最后的修改时间,在下一次请求时请求头带上If-Modified-Since(客户端),其值为本地保存的Last-Modified,告诉服务器我本地缓存最后的修改时间,服务器如果判断文件未修改,则命中协商缓存,返回304 Not Modified状态码,浏览器就不再请求资源,直接使用本底的缓存;如果文件修改,则返回资源内容,新的 Last-Modified 会在 response header 返回,并在下次请求之前更新本地缓存的 Last-Modified,下次请求时,If-Modified-Since会启用更新后的 Last-Modified。缺点是最小判断步长为1秒,无法判断1秒内的多次变化。

    • Etag/If-None-Match:对于每一个文件,服务器根据文件本身算出一个哈希值(一般来说是哈希结构)并通过 Etag字段返回给浏览器,然后下一次请求后请求头带上 If-None-Match 字段,服务器会通过比较两者是否一致来判定文件内容是否被改变。与 Last-Modified 不一样的是,当服务器返回 304 Not Modified 的响应时,由于在服务器上ETag 重新计算过,response header中还会把这个 ETag 返回,即使这个 ETag 跟之前的没有变化。缺点是计算Etag值有性能损耗。

js的new做了哪些事

1、创建一个空对象
2、将空对象的__proto__指向构造函数的原型
3、将this指向空对象
4、返回新对象

代码实现
function newFun(Con, ...args){ // 1、创建一个空对象 let newObj = {} // 2、将空对象的__proto__指向构造函数的原型 newObj.__proto__ = Con.prototype // 3、将this指向空对象 let result = Con.apply(newObj, args) // 4、返回新对象 return result instanceof Object ? result : newObj }

v-for和v-if同时使用的问题

v-for比v-if优先级高,每次v-for都会执行v-if,造成不必要的计算,影响性能,尤其是当之需要渲染很小一部分的时候。必要时可以用computed,或者将if条件放在父级元素上,没有父级可以使用<template></template>

Code:

<ul>
  <li v-for="item in activeList" :key="item"></li>
</ul>
export default {
  data() {
    return {
      list: [78, 90, 20, 45, 66, 120, 136]
    }
  },
  computed: {
    activeList() {
      return this.list.filter((item) => item < 100)
    }
  }
}

实现继承的几种方式?

1.原型链继承
父类的实例作为子类的原型

function Woman(){ 
}
Woman.prototype= new People();
Woman.prototype.name = 'haixia';
let womanObj = new Woman();

优点:
简单易于实现,父类的新增的实例与属性子类都能访问
缺点:
可以在子类中增加实例属性,如果要新增加原型属性和方法需要在new 父类构造函数的后面
无法实现多继承
创建子类实例时,不能向父类构造函数中传参数

2.借用构造函数继承(伪造对象、经典继承)
复制父类的实例属性给子类

function Woman(name){
 //继承了People
  People.call(this); //People.call(this,'wangxiaoxia'); 
  this.name = name || 'renbo'
}
let womanObj = new Woman();

优点:
解决了子类构造函数向父类构造函数中传递参数
可以实现多继承(call或者apply多个父类)
缺点:
方法都在构造函数中定义,无法复用
不能继承原型属性/方法,只能继承父类的实例属性和方法

3.实例继承(原型式继承)

function Wonman(name){
  let instance = new People();
  instance.name = name || 'wangxiaoxia';
  return instance;
}
let wonmanObj = new Wonman();

优点:
不限制调用方式
简单,易实现
缺点:不能多次继承

介绍一下前端的标准盒模型与怪异盒模型?

每个物体都有,content,padding,border,margin这些属性
IE标准盒模型,只包含content
怪异盒模型,包含了content,padding,border

css中可以通过box-sizing属性切换
box-sizing: content-box表示标准盒模型(默认值)
box-sizing: border-box表示 IE 盒模型(怪异盒模型)

数组去重的方法

const duplicateRemove = (list) => {
    if (list.length <= 1) return list
    let map = new Map() 
    for (i = 0; i < list.length; i++) {
        map.set(list[i], list[i])
    }
    const res = []
    map.forEach(item => res.push(item))
    return res
}
const list = [1,2,3,1,4,5,6,3,2,4]
duplicateRemove(list)
// [1, 2, 3, 4, 5, 6]
const duplicateRemove = (list) => {
    return Array.from(new Set(list))
}
const list = [1,2,3,1,4,5,6,3,2,4]
duplicateRemove(list)
// [1, 2, 3, 4, 5, 6]
const duplicateRemove = (list) => {
    const res = []
    for (let i = 0; i < list.length; i++) {
        if (!res.includes(list[i])) res.push(list[i])
    }
    return res
}
const list = [1,2,3,1,4,5,6,3,2,4]
duplicateRemove(list)
// [1, 2, 3, 4, 5, 6]

手写一个setInterval

let timer

const setInterval = (fn, interval) => {
  let start = Date.now() 
  const loop = () => {
    timer = requestAnimationFrame(loop)
    const now = Date.now()
    if (now - start >= interval) {
      fn && fn()
      start = now
    }
  }
  
 timer = requestAnimationFrame(loop)
}

const clearInterval = (currentTimer) => {
  cancelAnimationFrame(currentTimer)
}

OWASP top10(10项最严重的Web应用程序安全风险列表)都有哪些?

1.SQL注入

在输入框里输入sql命令

2.失效的身份验证

拿到别人的cookie来向服务端发起请求,就可以做到登陆的目的

3.敏感数据泄露

明文传输状态下可能被抓包拦截,这时候就造成数据泄露
想做到抓包,比如在网吧,共享一个猫上网,这时候抓包就可行,方法网上一搜一大把
不过此风险大部分网站都能得到很好的解决,https或者md5加密都可以

4.XML 外部实体

5.失效的访问控制

6.安全配置错误

7.XSS

8.不安全的反序列化

9.使用含有已知漏洞的组件

10.不足的日志记录和监控

如何在浏览器空闲的时候执行任务?

使用requestIdleCallback

// 浏览器一秒60帧,一帧约16.66毫秒
const fn = (deadline) => {
    const hasTimeRemaining = deadline.timeRemaining()
    console.log('浏览器剩余的时间:' + hasTimeRemaining)
    console.log('执行任务')
}
// requestIdleCallback 第二个参数 { timeout: number }
// 如果指定了 timeout,并且有一个正值,而回调在 timeout 毫秒过后还没有被调用,那么回调任务将放入事件循环中排队,即使这样做有可能对性能产生负面影响。
const d = requestIdleCallback(fn)
// 浏览器剩余的时间:50
// 执行任务
// d 132
// 可以通过执行cancelIdleCallback的方法取消执行该任务
cancelIdleCallback(d)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.