前端实习八股整理-JavaScript

一、讲讲封装继承多态

封装是基础:通过封装创建独立的类单元。
继承是拓展:通过继承建立类之间的关系。
多态是表现:通过多态实现接口的统一和行为的多样化。(同一接口,不同实现)

二、垃圾回收机制如何实现

自动释放不再使用的内存。
标记-清除算法:
1.标记阶段:垃圾回收器会遍历所有对象,从根对象(如全局对象)开始,将所有可达对象标记为活动的。
2.清除阶段:没有标记的对象将其内存释放。
缺点:1.期间需要暂停程序运行,会影响性能。2。需遍历整个对象图,对大对象图效率较低。
引用计数法:
1.计数2.增加引用3.减少引用4.释放内存(计数器为0)
缺点:两个对象互引/每次更新计数带来性能开销。
分代垃圾回收:
1.标记-清除:对新生代对象进行快速标记和清除。2.标记-压缩:老生代进行标记和压缩。3.增量标记:将垃圾回收拆分成多个小步骤,穿插在正常的程序执行过程中,减少程序暂停时间。
预防措施:1.避免使用全局变量:用var、let和const声明变量。2.移除不再使用的时间监听器。3.清除定时器。
4.及时清理过多的缓存。5.避免使用大量的闭包。

三、闭包的定义、使用场景

闭包是指有权访问另一个函数作用域中的变量的函数。
1.当函数执行时,会创建一个执行上下文(包含变量对象、作用域链等)
2.正常情况下,函数执行完毕后,其执行上下文会被销毁
3.但如果函数内部定义了另一个函数,并且这个内部函数引用了外部函数的变量
4.即使外部函数执行完毕,由于内部函数仍然可能被调用,JavaScript 引擎会保留外部函数的变量对象
5.这样就形成了闭包

闭包的使用场景
1.数据封装与私有状态
在 Vue 中,闭包可以用来封装组件的私有状态,避免外部直接访问和修改内部数据。
例如,使用闭包可以隐藏组件内部的逻辑,只暴露必要的接口。

const MyComponent = {
   
   
  data() {
   
   
    return {
   
   
      privateData: 'This is private'
    };
  },
  methods: {
   
   
    getPrivateData() {
   
   
      return this.privateData;
    }
  }
};

在这个例子中,privateData 是组件内部的私有数据,外部无法直接访问,但可以通过 getPrivateData 方法获取。

2.事件处理与回调函数
闭包常用于事件处理和回调函数中,捕获外部变量并在事件触发时使用。
例如,在 Vue 的事件绑定中,闭包可以捕获 this 的上下文。

<template>
  <button @click="handleClick">Click me</button>
</template>

<script>
export default {
   
   
  data() {
   
   
    return {
   
   
      count: 0
    };
  },
  methods: {
   
   
    handleClick() {
   
   
      this.count++;
      console.log(`Button clicked ${
     
     this.count} times`);
    }
  }
};
</script>

在这个例子中,handleClick 方法捕获了 this.count,即使事件触发时外部函数已经执行完毕,handleClick 仍然可以访问和修改 this.count。

3.异步操作与生命周期钩子
在 Vue 的生命周期钩子中,闭包可以捕获组件的状态,并在异步操作完成时使用。
例如,在 mounted 钩子中发起异步请求,并在请求完成时更新组件的状态。

<template>
  <button @click="handleClick">Click me</button>
</template>

<script>
export default {
   
   
  data() {
   
   
    return {
   
   
      count: 0
    };
  },
  methods: {
   
   
    handleClick() {
   
   
      this.count++;
      console.log(`Button clicked ${
     
     this.count} times`);
    }
  }
};
</script>

在这个例子中,fetch 的回调函数捕获了 this.userData,并在异步请求完成后更新组件的状态。

4.高阶组件与函数式组件
在 Vue 中,高阶组件(HOC)和函数式组件(Functional Components)中也经常使用闭包来封装逻辑。
例如,使用高阶组件封装通用逻辑。

function withUser(Component) {
   
   
  return {
   
   
    data() {
   
   
      return {
   
   
        userData: null
      };
    },
    mounted() {
   
   
      fetch('/api/user')
        .then(response => response.json())
        .then(data => {
   
   
          this.userData = data;
        });
    },
    render() {
   
   
      return <Component userData={
   
   this.userData} />;
    }
  };
}

const UserProfile = withUser({
   
   
  props: ['userData'],
  render() {
   
   
    return <div>{
   
   this.userData.name}</div>;
  }
});

在这个例子中,withUser 是一个高阶组件,它捕获了 userData 并将其传递给子组件。

闭包解决的问题
1.数据封装与隐藏
闭包可以隐藏内部状态,防止外部直接访问和修改,从而保护数据的完整性。
例如,组件内部的私有数据可以通过闭包封装,只暴露必要的接口。
2.异步操作与状态管理
闭包可以捕获异步操作中的状态,确保在异步操作完成时仍然可以访问和修改这些状态。
例如,在 Vue 的生命周期钩子中,闭包可以捕获组件的状态,并在异步请求完成后更新状态。
3.事件处理与回调
闭包可以捕获事件处理函数中的上下文,确保在事件触发时可以访问和修改组件的状态。
例如,在 Vue 的事件绑定中,闭包可以捕获 this 的上下文,确保事件处理函数可以正常工作。
4.代码复用与模块化
闭包可以封装通用逻辑,使其可以在多个地方复用。
例如,高阶组件可以通过闭包封装通用逻辑,并将其传递给子组件。

注意事项
1.内存泄漏
闭包会捕获外部变量,如果这些变量占用大量内存且没有被正确释放,可能会导致内存泄漏。
例如,在 Vue 中,如果组件被销毁但事件监听器没有被移除,可能会导致内存泄漏。
2.上下文问题
在闭包中使用 this 时,需要注意上下文的变化,确保 this 指向正确。
例如,在 Vue 的事件处理函数中,可以使用箭头函数或 bind 方法确保 this 指向组件实例。
3.性能问题
闭包可能会导致函数执行效率降低,尤其是在捕获大量变量或嵌套闭包的情况下。
例如,在 Vue 中,避免在渲染函数中频繁创建闭包,以免影响性能。

四、foreach和map的区别

foreach:用于遍历集合,执行操作,没有返回值。
map:用于转换集合中的元素,返回一个新的集合。

五、js的基本数据类型和typeof后的结果

1.原始类型:
· undefined
· Null
· Boolean
· Number
· String
· Symbol(用于表示唯一的、不可变的值。它常用于对象的属性键,以确保属性名的唯一性,避免命名冲突)
· BigInt(使用 BigInt() 构造函数或在数字后面加上 n 表示。INT 是4字节,BIGINT 是8字节)

存储位置
原始类型的值直接存储在栈内存中。栈内存用于存储变量的值,访问速度快,但空间有限。

2.引用类型(Object)
· Array
· Function
· Date
· RegExp
· 其他:包括Map、Set、WeakMap(必须输入对象、内存回收)、WeakSet(键必须是对象、内存回收)等等

存储位置
引用类型的值存储在堆内存中,变量存储的是指向堆内存中对象的引用(指针)。堆内存用于存储对象的实际数据,访问速度相对较慢,但空间较大。

类型 返回值 备注
Undefined “undefined” 当变量未被定义或未赋值时,返回此值。
Null “object” 历史遗留问题,null 被错误地识别为对象。
Boolean “boolean” 适用于 true 或 false 值。
Number “number” 适用于整数和浮点数(包括特殊值 NaN 和 Infinity)。
String “string” 适用于字符串(例如 “hello”)。
BigInt “bigint” 适用于任意大的整数(例如 10n)。
Symbol “symbol” 适用于 Symbol 类型。
Function(classes) “function” 适用于可调用的对象(如函数和类定义)。
其他对象 “object” 包括数组、普通对象、日期对象、正则表达式等非函数对象。

注意
1.typeof null === “object” 在 JavaScript 最初的实现中,JavaScript 中的值是由一个表示类型的标签和实际数据值表示的。对象的类型标签是 0。由于 null 代表的是空指针(大多数平台下值为 0x00),因此,null 的类型标签是 0,typeof null 也因此返回 “object”
2.实际使用 对于更复杂的类型检测,可以使用工具函数,如 Object.prototype.toString.call() 或第三方库(如 lodash)。

六、什么是内存泄漏?内存泄露的常见原因?如何排查?

内存泄露是指在程序运行过程中,程序未能释放不再使用的内存空间,导致内存资源被浪费。
常见原因:
1.意外的全局变量:忘记使用 var,let,const 声明变量时,变量会被挂载到全局对象上
2.闭包:闭包中引用了不再需要的外部变量,导致这些变量无法被垃圾回收
3.未清理的 DOM 引用:删除 DOM 元素时,未能清理相关的事件监听器或引用
4.定时器和回调:未能清理不再需要的 setInterval(循环执行) 或 setTimeout(延迟执行)回调
排查手段:
1.使用内存分析工具
· 浏览器开发者工具:Chrome 的 DevTools 提供了内存分析工具 Memory,可以监控内存使用情况
· 也可以结合 setInterval 使用 console.memory 查看内存使用的快照
2.代码审查
· 检查代码中是否有未释放的事件监听器,定时器,全局变量,确保不再需要某对象时,即使解除引用
3.性能监控
· 监控应用程序的内存使用情况,观察是否有持续增长的趋势
· 使用日志记录内存使用情况,帮助识别内存泄露的模式

七、Promise方法

Promise 是 JavaScript 中用于处理异步操作的对象。它代表了一个可能尚未完成的操作的最终完成(或失败)及其结果值。Promise 有三种主要状态:

  1. Pending(进行中)
    描述:这是 Promise 的初始状态,表示异步操作尚未完成。
    特点:在这个状态下,Promise 既不是成功也不是失败。
  2. Fulfilled(已成功)
    描述:表示异步操作成功完成。
    特点:在这个状态下,Promise 的结果值被确定,并且可以通过 .then() 方法获取。
  3. Rejected(已失败)
    描述:表示异步操作失败。
    特点:在这个状态下,Promise 的失败原因被确定,并且可以通过 .catch() 方法捕获。

状态流转
Promise 的状态流转是单向的,具体规则如下:

  1. Pending → Fulfilled
    当异步操作成功完成时,Promise 的状态从 Pending 转变为 Fulfilled。
    一旦变为 Fulfilled 状态,Promise 的结果值被确定,不会再改变。
  2. Pending → Rejected
    当异步操作失败时,Promise 的状态从 Pending 转变为 Rejected。
    一旦变为 Rejected 状态,Promise 的失败原因被确定,不会再改变。
    重要特性

不可逆性:Promise 的状态一旦从 Pending 转变为 Fulfilled 或 Rejected,就不能再改变。也就是说,Promise 的状态是不可逆的。

### 前端实习面试常见问题及答案 #### HTML部分 对于HTML的理解不仅仅局限于标签的记忆,更在于如何合理运用这些标签来构建语义化的网页结构。 - **什么是DOCTYPE声明的作用?** DOCTYPE声明位于文档的最前面,在浏览器解析页面之前告知其使用的HTML版本。这有助于确保浏览器按照标准模式渲染页面而不是兼容模式[^1]。 #### CSS部分 掌握CSS不仅意味着能够编写样式表,还涉及对盒模型、布局机制以及响应式设计原理的理解。 - **解释下CSS中的BFC是什么?** BFC (Block Formatting Context) 是一种独立的渲染区域,其中子元素不会影响外部其他元素,并且解决了浮动溢出等问题。创建新的BFC可以防止父级高度塌陷现象的发生。 #### JavaScript部分 JavaScript作为前端的核心技术之一,考察范围广泛,从基本语法到高级特性都会涉及到。 - **闭包的概念及其应用场景有哪些?** 当函数嵌套定义时,内部函数会形成对外部作用域变量的引用关系即构成闭包。利用这一特点可以在回调函数保存状态信息;实现数据封装隐藏私有成员等功能。 #### HTTP协议相关 网络请求是Web应用不可或缺的一环,了解HTTP的工作方式至关重要。 - **GET与POST方法的区别在哪里?** GET主要用于获取资源,参数通过URL传递长度有限制;而POST用于提交数据给服务器处理,支持更大的消息体传输量并具有更高的安全性因为不暴露于地址栏中。 #### Vue框架基础 随着单页应用程序(SPA)的发展趋势日益明显,Vue.js成为许多企业青睐的技术栈选项。 - **组件间通信的方式都有哪些呢?** 子向父传值可通过`$emit()`触发自定义事件携带payload对象完成;反之则借助props属性注入子组件所需的数据流。除此之外还有Vuex全局状态管理库可供选择当面临复杂场景需求时[^3]。 ```javascript // 父组件监听来自子组件的消息 <ChildComponent @child-event="handleEvent"/> ... methods: { handleEvent(payload){ console.log('接收到子组件发送的信息:', payload); } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值