我遇见的前端基础面试题1期

常见的基础前端面试题

最近离职了,经验不足


前言

最近遇到的一些前端基础面试题,我选了一些经典的题目


以下是本篇文章正文内容,下面案例可供参考

一、常用web浏览器缓存机制有哪几种?分别有什么区别

  1. cookielocalStorage(本地持久化存储)、sessionStorage(本地会话级存储)
  • 相同点
    1、都是浏览器的缓存机制
    2、都是前端操作
    3、都只能存储字符串

  • 不同点:
    1、操作api不同
    2、cookie是以前的缓存机制,localStorage、sessionStorage是h5的缓存机制,浏览器的兼容性不一样
    3、存储大小不一样,cookie可以存储4kb,20条(chrome),localStorage是5mb,不限制条数
    4、存储时间不一样,cookie如果不设置限制时间,关闭浏览器后就会消失,localStorage不手动删除的情况下,永久存储,sessionStorage关闭消失
    5、localStorage可以在当前浏览器的多个页面卡存储,sessionStorage只会在当前页面存储

二、事件对象的currentTarget和target有什么区别

	currentTarget 是返回其事件监听器触发该事件的元素/返回绑定该事件的元素
	Target  返回触发该事件的元素

三、函数柯里化实现add(1)(2)(3)等于6

代码如下(示例):

function curry(fn,args=[]){return function(){
  let arr = [...args,...arguments]
		  if(arr.length < fn.length){//判断是否获取到了全部的数据
			  return curry.call(this,fn,arr)//没有就继续调用自己
	  	  }else{
			  return fn.apply(this,arr)
		  }
	  }
}

  let add = curry(function(a,b,c){
	  let arr = Array.from(arguments)
	  return arr.reduce((a,b)=>{
		  return a + b
	  })
})

console.log(add(1)(2)(3))

四、优雅降级和渐进增强

优雅降级 先写最高版本的代码,然后向下兼容
​渐进增强 先写最低版本的代码,然后向上兼容


五、浅克隆和深克隆

1)​克隆指的是复制数据,浅克隆指的是复制第一层数据,深克隆是复制所有层的数据 let obj = {name:“小明”,obj:{}}
2)浅克隆可直接使用Object原型上的 Object.assign() 方法
3)深克隆 数据结构较简单可使用 JSON.parse(JSON.stringify())

代码如下(示例):

/*
* 数据结构复杂可以使用递归等方式手动实现,也可使用新的api 
* structuredClone(value, { transfer })
* 该方法接收两个参数
* value     是被克隆的对象。可以是任何结构化克隆支持的类型。
* transfer  是一个可转移对象的数组,里面的 值 并没有被克隆,而是被转移到被拷贝对象上。
*/
  const obj1 = {
    a: {
      b: 'c'
    }
  }
  const obj2 = structuredClone(obj1)
  console.log(obj1 == obj2); // false
  console.log(obj1 === obj2); // false

/*
*递归实现
*/
  
function deepClone(target) {
    const map = new WeakMap()
    function isObject(target) {
      return (typeof target === 'object' && target) || typeof target === 'function'
    }
    
    function clone(data) {
      if (!isObject(data)) {
        return data
      }
      if ([Date, RegExp].includes(data.constructor)) {
        return new data.constructor(data)
      }
      if (typeof data === 'function') {
        return new Function('return ' + data.toString())()
      }
      const exist = map.get(data)
      if (exist) {
        return exist
      }
      if (data instanceof Map) {
        const result = new Map()
        map.set(data, result)
        data.forEach((val, key) => {
          if (isObject(val)) {
            result.set(key, clone(val))
          } else {
            result.set(key, val)
          }
        })
        return result
      }
      if (data instanceof Set) {
        const result = new Set()
        map.set(data, result)
        data.forEach(val => {
          if (isObject(val)) {
            result.add(clone(val))
          } else {
            result.add(val)
          }
        })
        return result
      }
      const keys = Reflect.ownKeys(data)
      const allDesc = Object.getOwnPropertyDescriptors(data)
      const result = Object.create(Object.getPrototypeOf(data), allDesc)
      map.set(data, result)
      keys.forEach(key => {
        const val = data[key]
        if (isObject(val)) {
          result[key] = clone(val)
        } else {
          result[key] = val
        }
      })
      return result
    }
    return clone(target)
  }

六、call,bind,apply的区别

相同点:
1、都可以更改函数的this指针,都可以调用函数
2、都可以传参数
不同点:
​ 1、参数类型不同,call和bind的参数都是选项形式的,apply的参数是数组
​ 2、call和apply都是直接返回值,bind是返回函数,需要手动调用


七、js事件传播有哪几个阶段

js事件的三个阶段分别为:捕获阶段、事件派发阶段、冒泡阶段
1.捕获阶段:事件由页面元素接收,逐级向下,到具体的元素
2.事件派发阶段
3.冒泡阶段:跟捕获相反,具体元素本身,逐级向上,到页面元素
事件捕获:当使用事件捕获时,父级元素先触发,子元素后触发
事件冒泡:当使用事件冒泡时,子级元素先触发,父元素后触发


八、响应状态码1xx-5xx有什么区别?

1xx 是 响应中
2xx 是 响应成功
3xx 是 重定向
304是 请求的资源有问题
4xx 是 客户端出错
400是无效信息
403是请求的资源不被允许访问
404是请求的资源不存在 405是请求方法不被服务器允许
5xx 是 服务端出错
500是服务器内部错误


九、请写出ajax的流程以及相应的代码

	//先写兼容性  兼容ie5  ie6
		if (window.XMLHttpRequest) {
			var xmr = new XMLHttpRequest()
		} else { //ie5 ie6
			var mar = new ActiveXObject("Microsoft.XMLHTTP");
		}
		// // 与后端建立连接
		// //发送链接
		xmr.open("GET/POST", "http://vt.ossjk.com/goods/getIndexInfo", true)
		//设置请求头   时json文件还是form文件
		//json 格式
		xhr.setRequestHeader("content-type", "application/json");
		//form 格式
		xhr.setRequestHeader("content-type", "application/x-www-form-urlencoded");
		//发送请求给后端
		xmr.send()
		//后端返回
		xmr.onreadystatechange = function() {
			if (xmr.readyState === 4 && xmr.status === 200) {
				console.log(JSON.parse(xmr.response)) //response  获得响应数据
			}
		}

十、跨域的解决方案

1.跨域是什么?
跨域:指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。
2. 有哪几种解决方案?
1)jsonp:只支持 GET,不支持 POST 请求,不安全 XSS 兼容性好
2)cors:需要后端配置相关的代码 可能造成安全隐患
3)postMessage:配合使用 iframe,需要兼容 IE6、7、8、9
4)document.domain:仅限于同一域名下的子域
5)websocket:需要后台配合修改协议,不兼容
6)proxy:使用代理去避开跨域请求,需要修改 nginx、apache 等的配置


十一、节流和防抖函数的区别

相同点:都是防止事件高频率的重复执行
​不同点:节流函数是看第一次 防抖函数是看最后一次

代码如下(示例):

	//节流函数function throttle(fn,time){let lastTime = 0return function(){let nowTime = +new Date()if(nowTime - lastTime > time){
​			lastTime = nowTime
​			fn.apply(this,arguments)}}}
let throttleHandler = throttle(function(){
		console.log(123)
	},3000)
	
	let div = document.querySelector("div")
	div.addEventListener("click",throttleHandler)
	
	
	//防抖函数
	function debounce(fn,time){
		let endTime = 0
		let timeHandler
		return function(){
			
			let nowTime = +new Date()
			if(nowTime - endTime <= time){
				clearTimeout(timeHandler)
				
				timeHandler = setTimeout(function(){
					endTime = nowTime
					fn.apply(this,arguments)
				},time)
			}else{
				clearTimeout(timeHandler)
				endTime = nowTime
				fn.apply(this,arguments)
			}
		}
	}
	
	let debounceHandler = debounce(function(){
		console.log(222)
	},3000)
	
	let div = document.querySelector("div")
	div.addEventListener("click",debounceHandler)

十二、js模块化有哪些标准!!!

amd、cmd、commonJs(nodejs)、ES6
amd和cmd是比较老旧的了,我也没怎么用过,所以就不过多介绍,这里我们主要说一下现在常用的CommonJS ,和ES6
1.CommonJS 规范—module.exports
前端浏览器还不支持,Nodejs中使用的是这个规范
2.ES6—export/import
在ES6中,我们可以使用 import 关键字引入模块,通过 exprot 关键字导出模块,功能较之于前几个方案更为强大,也是我们所推崇的,但是由于浏览器还不支持ES6目语法,所以,我们只能通过babel将不被支持的import编译为当前受到广泛支持的 require。


十三、聊一聊什么是闭包?

闭包就是让开发者可以从内部函数访问外部函数的作用域 ---- MDN社区

优点:

  1. 变量的持久化
  2. 变量的私有化
  3. 避免变量污染全局

缺点:

  1. 对内存消耗有影响。因内部函数保存了对外部变量的引用,频繁的引用闭包内的变量可能导致无法被垃圾回收,增大内存使用量,所以使用不当会导致内存泄漏

十四、数组去重

要求:数组内值相同的对象也是重

    let a = { a: 1, b: undefined, };
    let b = { b: undefined, a: { ac: 1 }, };
    let ccc = { c: undefined, a: { ac: 1 }, };
    let e = { b: undefined, a: 2, ss: null, };
    let cc = { a: { ac: 1 }, b: undefined, };
    let dd = { b: undefined, a: { ac: 1 }, };

    let arr = [e, 1, a, b, '1', 2, 1, 2, cc, dd, ccc, { b: undefined, a: { ac: 1 }, }]
    
//实现

    function uniqueArray(array) {
      const rest = [];
      ossa: for (const element of array) {
        for (const r of rest) {
          if (isObj(element, r)) {
            continue ossa;
          }
        }
        rest.push(element)
      }
      return rest;
    }

    function isPrimitive(value) { //判断是否为原始值
      return value !== Object(value)
    };

    function isObj(value1, value2) {

      if (isPrimitive(value1) || isPrimitive(value2)) {
        return Object.is(value1, value2)
      }
      // 对象去重
      const entries1 = Object.entries(value1);
      const entries2 = Object.entries(value2)

      if (entries1.length !== entries2.length) return false;

      const bool = new Array();

      for (const [key, value] of entries1) {

        if (!(key in value2)) { //判断两个对象中是否有相同的key
          return false
        }

        if (isObj(value, value2[key])) {
          bool.push(true)
        }
      }

      if (bool.length !== entries2.length) {
        return false;
      }
      return true;

    };

    console.log(uniqueArray(arr));
    

总结

以上就是今天要讲的内容,本文仅介绍本人所遇到的一些常见的题目和个人理解的答案,希望大家能得到自己想要的答案,本文仅供参考,如有雷同纯属意外。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值