校招前端面经 01

166 阅读11分钟

1.js数据类型,新增数据类型set,map的用法与数据结构,weakmap,weakset

(1条消息) js的数据类型、堆栈存储、多数据类型计算_star@星空的博客-CSDN博客

  • 最重要的区别是,WeakMap 不会阻止在没有对键的引用时对键进行垃圾收集

1、WeakMap只接受对象作为key,如果设置其他类型的数据作为key,会报错。

2、WeakMap的key所引用的对象都是弱引用,只要对象的其他引用被删除,垃圾回收机制就会释放该对象占用的内存,从而避免内存泄漏。

3、由于WeakMap的成员随时可能被垃圾回收机制回收,成员的数量不稳定,所以没有size属性。

4、没有clear()方法/map有

5、不能遍历/map有forEach,keys,entries

2.object.keys;Symbol 作为属性名

js遍历对象篇(一)-for...in和Object.keys - 掘金 (juejin.cn)

  1. 返回一个所有元素为字符串的数组,其元素来自给定的 object 上面可直接枚举的属性。这些属性的顺序与手动遍历该对象属性时的一致。
  2. 如果你想获取一个对象的所有属性,甚至包括不可枚举的,请查看 Object.getOwnPropertyNames
  3. 在 ES5 里,如果此方法的参数不是对象(而是一个原始值),那么它会抛出 TypeError。 在 ES2015 中,非对象的参数将被强制转换为一个对象。
  4. js中原型属性一般是不可枚举的,而自定义的属性一般是可枚举的可以通过propertylsEnumerable()方法判断该属性是否可枚举
  5. !!!Symbol 作为属性名,遍历对象的时候,该属性不会出现在for...infor...of循环中,也不会被Object.keys()Object.getOwnPropertyNames()(包括不可枚举属性)、JSON.stringify()返回
  6. Object.getOwnPropertySymbols()在给定对象自身上找到的所有 Symbol 属性的数组,可获取自身所有Symbol属性,包括不可枚举的Symbol属性
  7. Reflect.ownKeys() 方法返回一个由目标对象自身的属性键组成的数组。它的返回值相等于Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))

枚举:1. 对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行为。

3.定义函数常用的方式

  1. 命名函数/自定义函数/函数声明
  2. 函数表达式/匿名函数
  3. new Function(){} 区别:函数声明会在预解析的时候进行函数提升 (14条消息) Javascript定义一个函数_js定义一个函数_Tarafireworks的博客-CSDN博客

4. DOM事件的绑定与优化??

(3条消息) js中事件委托_star@星空的博客-CSDN博客 绑定很多的点击事件,删除所有点击事件,内存

  1. 事件代理/事件委托:指将事件统一绑定给元素的共同的祖先元素,这样当后代元素上的事件触发时,会一直冒泡到祖先元素,从而通过祖先元素的响应函数来处理事件。
  2. 事件委派是利用了冒泡,通过委派可以减少事件绑定的次数,提高程序的性能
  3. 实现方法:
    • 这样我们就可以做到很多个a链接上的点击事件都添加到父元素div上。
    • 当然还要排除掉不参加事件委托的子元素。/选择参加的元素
  4. 应用场景:vue
    • 我们经常遇到vue中v-for一个列表,列表的每一项都绑定了@click处理事件。我们都知道绑定这么多监听,从性能方面来说是不太好的。那我们我们可以通过把每个item的click事件委托给父元素的形式来实现。
  5. 解绑事件
    1. 传统方式删除事件 eventTarget.onclick = null;
    2. 方法监听注册方式删除(addEventListener注册的事件删除) eventTarget.removeEventListener(type, listener[, useCapture])
    3. attachEvent注册的事件删除 eventTarget.detachEvent(‘onclick’, fn); (3条消息) 删除事件(解绑事件)(三种方式)_禁止想象~的博客-CSDN博客_删除事件

5. 水平垂直居中

  1. flex布局
.wp {
    display: flex;
    justify-content: center;
    align-items: center;
}
  1. absolute+transfrom:translate
  2. absolute+定位全为0+margin:auto;
  3. 行内元素
.father {
text-align:center;
}
.son {
vertical-align:middle;
line-height:inherit;
}

6.单页面应用,后端数据变化后,主动通知前端????

(3条消息) 新手入门:websocket_一只BOY猿的博客-CSDN博客_websocket

  1. 后端通知前端:(服务端定时推送)WebSocket webSocket(一) 浅析 - 掘金 (juejin.cn)
    1. 建立在tcp协议上,与http兼容性良好;
    2. 纯事件驱动,一旦连接建立,通过监听事件可以处理到来的数据和改变的连接状态;一旦连接建立,通过监听事件可以处理到来的数据和改变的连接状态
    3. 没有同源限制
    4. 不用频繁创建及销毁 TCP 请求,减少网络带宽资源的占用,同时也节省服务器资源;
    5. 无超时处理
  2. 前端轮询后端:
    1. 短轮询:短轮询(Polling)的实现思路就是浏览器端每隔几秒钟向服务器端发送http请求,服务端在收到请求后,不论是否有数据更新,都直接进行响应。在服务端响应完成,就会关闭这个Tcp连接(非常消耗资源)
    2. 长轮询:客户端发送请求后服务器端不会立即返回数据,服务器端会阻塞请求连接不会立即断开,直到服务器端有数据更新或者是连接超时才返回,客户端才再次发出请求新建连接、如此反复从而获取最新数据。(有数据、连接超时后,服务端才会返回) webSocket(二) 短轮询、长轮询、Websocket、sse - 掘金 (juejin.cn)

7.js垃圾回收机制

(3条消息) 一文彻底搞懂js垃圾回收和内存泄露_star@星空的博客-CSDN博客 垃圾收集器会定期(周期性)找出那些不在继续使用的变量,然后释放其内存。但是这个过程不是实时的,因为其开销比较大并且GC时停止响应其他操作,所以垃圾回收器会按照固定的时间间隔周期性的执行。

  1. 只有函数内的变量才可能被回收
  2. 标记清除
    • js中最常用的垃圾回收方式就是标记清除。当变量进入环境时,例如,在函数中声明一个变量,就将这个变量标记为“进入环境”。从逻辑上讲,永远不能释放进入环境的变量所占用的内存,因为只要执行流进入相应的环境,就可能会用到它们。而当变量离开环境时,则将其标记为“离开环境”。
    • 垃圾回收器在运行的时候会给存储在内存中的所有变量都加上标记(当然,可以使用任何标记方式)。然后,它会去掉环境中的变量以及被环境中的变量引用的变量的标记(闭包)。而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。最后,垃圾回收器完成内存清除工作,销毁那些带标记的值并回收它们所占用的内存空间。
  3. 引用计数
    • 引用计数的含义是跟踪记录每个值被引用的次数。当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是1。如果同一个值又被赋给另一个变量,则该值的引用次数加 1。相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值的引用次数减 1。当这个值的引用次数变成 0 时,则说明没有办法再访问这个值了,因而就可以将其占用的内存空间回收回来。这样,当垃圾回收器下次再运行时,它就会释放那些引用次数为 0 的值所占用的内存。
function test() {
    var a = {};    // a指向对象的引用次数为1
    var b = a;     // a指向对象的引用次数加1,为2
    var c = a;     // a指向对象的引用次数再加1,为3
    var b = {};    // a指向对象的引用次数减1,为2
}

内存泄漏

  • 不再用到的内存,没有及时释放,就叫做内存泄漏(memory leak)。
vue中的内存泄漏
  1. mounted/created 钩子中使用js绑定了DOM/BOM,第三方库的初始化,就要在beforeDestroy中解绑,销毁;
  2. 组件中使用了setInterval,就要在beforeDestroy中销毁;
js中的内存泄漏
  1. 循环引用::一个DOM对象被一个Javascript对象引用,与此同时又引用同一个或其它的Javascript对象,这个DOM对象可能会引发内存泄露。这个DOM对象的引用将不会在脚本停止的时候被垃圾回收器回收。要想破坏循环引用,引用DOM元素的对象或DOM对象的引用需要被赋值为null。
  2. 闭包
  3. DOM泄漏:当原有的DOM被移除时,子结点引用没有被移除则无法回收。、
  4. 定时器:定时器setInterval或者setTimeout在不需要使用的时候,没有被clear,导致定时器的回调函数及其内部依赖的变量都不能被回收,这就会造成内存泄漏。 解决方式:当不需要interval或者timeout的时候,调用clearInterval或者clearTimeout

8.跨域?新方法

(3条消息) 如何实现跨域?_star@星空的博客-CSDN博客_如何跨域

  1. jsonp :只能针对get
  2. cors res.header('Access-Control-Allow-Origin', 'http://example.com');
  3. Nginx
    1. 反向代理:即所有客户端的请求都必须先经过的处理,nginx作为代理服务器再讲请求转发给node或者java服务,这样就规避了同源策略。 juejin.cn/post/708265… 【nginx】 聊聊代理服务器的那些事 - 掘金 (juejin.cn)
      • 正向代理代理客户端请求,隐藏真实的客户端
      • 反向代理代理服务器请求,隐藏真实的服务器

9.vue2响应式,Object.defineProperty()???

1.Object.defineProperty()

看笔记或者文档 Object.defineProperty() - JavaScript | MDN (mozilla.org)

  • Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
  • Object.defineProperty(obj, prop, descriptor) 要定义的对象,属性,描述
  • descriptor对象:value,enumberable,writable,configurable,get(),set()

vue2响应式原理

看笔记

  1. 监视data中所有层次的数据
  2. 对象新增属性,直接检测不到,需要用vm.$set(obj,prop,value) Vue.set()
  3. 数组:包裹数组更新元素的方法;返回新数组,代替旧数组
  • 实现原理:

    • 对象类型:通过Object.defineProperty()对属性的读取、修改进行拦截(数据劫持)。

    • 数组类型:通过重写更新数组的一系列方法来实现拦截。(对数组的变更方法进行了包裹)。

      Object.defineProperty(data, 'count', {
          get () {}, 
          set () {}
      })
      
  • 存在问题(数据改变了,vue2监听不到):

    • 新增属性、删除属性, 界面不会更新。(数据会改变,vue2监听不到,页面无变化。用this.$set(对象,"属性",值)/Vue.ser()解决。 用this.$delete())
    • 直接通过下标修改数组, 界面不会自动更新。`this.$set(对象,"属性",值)/arr.split()等改变数组的

vue3 响应式,proxy

// 模拟vue2响应式
//`window 身上的内置函数 Proxy`
// person是被代理的对象
const p = new Proxy(person,{
// target 是源对象,这里是传入的person
// prop 读取修改的是那个属性
	get (target, prop) {},//读取
	set (target, prop, value){},//添加、修改
// value 新增/修改属性的值
	deleteProperty (target, prop){} //删除
// delet p.name  //delete删除一个属性,会有一个返回值
})
const p = new Proxy(person,{})

// 打在p身,痛在person身

      new Proxy(data, {
      	// 拦截读取属性值
          get (target, prop) {
          	return Reflect.get(target, prop)
          },
          //target 源对象, prop 被读取n的属性
          // 拦截设置属性值或**添加**新属性
          set (target, prop, value) {
          	return Reflect.set(target, prop, value)
          },
          // 拦截删除属性
          deleteProperty (target, prop) {
          	return Reflect.deleteProperty(target, prop)
          }
      })
      
      proxy.name = 'tom'   

实现原理: (Proxy,Reflect都是window上的)

  1. 通过Proxy(代理): 拦截对象中任意属性的变化, 包括:属性值的读写、属性的添加、属性的删除等。
  2. 通过Reflect(反射): 对源对象的属性进行操作。===>可以提高代码的健壮性
    • Reflect.defineProperty(),可以重复定义属性不会报错,但会返回一个false值。
    • Object.defineProperty()定义重名属性,代码会直接报错,代码会挂掉

11.webpack 更改配置???

  1. vue.config.js 配置proxy跨域

12.防抖节流

1.防抖

防抖:前面的所有的触发都被取消,最后一次执行在规定的时间之后才会触发%%也就是说如果连续快速的触发,只会执行最后一次%%

 <body>
    <button id="debounce">防抖</button>
    <script>
      // 防抖
      /* 函数防抖是指在事件被触发 n 秒后再执行回调,如果在这 n 秒内事件又被触发,则重新计时。这可以使用在一些点击请求的事件上,避免因为用户的多次点击向后端发送多次请求。 */
      function debounce(fn, wait) {
        let timer = null;
        return function () {
          let context = this,
            args = arguments;
          if (timer) {
            clearTimeout(timer);
            //清空timer
            timer = null;
          } else {
            timer = setTimeout(() => {
              // 用apply改变this走向
              fn.apply(context, args);
            }, wait);
          }
        };
      }
      //   防抖测试
      document.querySelector("#debounce").onclick = debounce(() => {
        console.log("debounce");
      }, 2000);
    </script>

2.节流

节流:在规定的间隔时间范围内不会重复触发回调,只有大于这个时间间隔才会触发回调,把频繁触发变为少量触发

 <body>
    <button id="throttle">节流</button>
    <script>
      //   节流
      /* 函数节流是指规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。节流可以使用在 scroll 函数的事件监听上,通过事件节流来降低事件调用的频率。 */
      function throttle(fn, delay) {
        let curTime = Date.now();
        // Date.now() 方法返回自 1970 年 1 月 1 日 00:00:00 (UTC) 到当前时间的毫秒数。
        return function () {
          let nowTime = Date.now(),
            context = this,
            args = arguments;
          // 如果两次时间间隔超过了指定时间,则执行函数
          if (nowTime - curTime >= delay) {
            fn.apply(context, args);
            curTime = Date.now();
          }
        //   !只有触发成功了才会更新时间
        };
      }
      // 节流测试
      document.querySelector("#throttle").onclick = throttle(() => {
        console.log("throttle");
      }, 2000);
    </script>

D:\我的学习\前端\基础算法\手撕\02防抖节流.html

  • 防抖与节流的原理,通过JS实现【闭包 + 延迟器】

13 浏览器缓存

浏览器缓存 storage - 掘金 (juejin.cn)