当前位置:首页 » 《随便一记》 » 正文

前端记录3

15 人参与  2024年12月04日 14:01  分类 : 《随便一记》  评论

点击全文阅读


1.了解前端的闭包吗

闭包是 JavaScript 中一个非常重要的概念,理解它有助于我们更好地掌握作用域、内存管理以及异步编程等方面。在面试中,回答闭包时可以从以下几个方面进行阐述:

1. 定义

闭包是指一个函数可以“记住”并访问它定义时的作用域,即使在其外部被调用。换句话说,闭包允许一个函数访问并操作其外部函数的变量,即使外部函数已经返回。

2. 形成闭包的条件

闭包的形成通常涉及以下几个条件:

函数嵌套:在一个函数内部定义另一个函数。外部函数返回内部函数:外部函数返回内部函数的引用。访问外部作用域的变量:内部函数可以访问外部函数的变量。

3. 示例

下面是一个简单的示例,展示了如何创建和使用闭包:

 

javascript复制代码

function outerFunction() { let count = 0; // 外部函数的局部变量 return function innerFunction() { // 返回内部函数 count++; // 修改外部函数的变量 console.log(count); // 打印 count }; } const increment = outerFunction(); // 调用外部函数 increment(); // 输出 1 increment(); // 输出 2 increment(); // 输出 3

在这个例子中,innerFunction 是一个闭包,它能够访问 outerFunctioncount 变量,即使 outerFunction 已经执行完毕。这种机制使得 count 的状态能够被保留。

4. 闭包的应用场景

闭包有很多实际应用场景,包括但不限于:

数据封装:通过闭包可以创建私有变量,只能通过特定的函数来访问和修改这些变量。

 

javascript复制代码

function createCounter() { let count = 0; return { increment: function() { count++; return count; }, decrement: function() { count--; return count; }, getCount: function() { return count; } }; } const counter = createCounter(); console.log(counter.increment()); // 输出 1 console.log(counter.increment()); // 输出 2 console.log(counter.getCount()); // 输出 2

事件处理:在事件回调中使用闭包可以保存特定的数据或状态。

异步编程:在处理异步操作(如 AJAX 请求)时,闭包可以用于保持对某些变量的引用。

5. 注意事项

虽然闭包很强大,但需要注意以下几点:

内存占用:由于闭包会保持对外部作用域的引用,因此可能导致内存泄漏。要谨慎使用,确保不再需要闭包时可以解除引用。

性能问题:过多使用闭包可能影响性能,尤其是在大型循环中频繁创建闭包时。

结论

闭包是 JavaScript 中一个核心概念,理解它有助于我们更好地控制作用域和内存,并且在实际开发中提供了强大的功能。面试时,如果能够结合示例代码和应用场景进行讲解,会让你的回答更加具体和深入。

2.浏览器存储方式

浏览器提供了多种存储机制来保存数据,以便在用户的会话中或者在不同会话之间持久化数据。以下是主要的浏览器存储方式:

1. Cookie

定义:Cookie 是一种小型文本文件,存储在用户的计算机上,用于记录用户的状态和信息。特点: 每个 Cookie 大小限制为 4KB。可以设置过期时间,默认情况下,Cookie 在浏览器关闭后失效(除非设置了过期时间)。支持跨域,但需遵循 Same-Origin Policy。每次 HTTP 请求都会随 Cookie 一起发送,可能影响性能。

2. Local Storage

定义:Local Storage 是一种在用户的浏览器中以键值对形式存储数据的机制。特点: 存储容量相对较大,一般为 5MB 到 10MB(具体取决于浏览器)。数据永久存储,除非主动删除或清空。仅支持同源访问(Same-Origin Policy),即同一协议、主机和端口下的网页可以访问相同的数据。API 比较简单,可以使用 localStorage.setItem()localStorage.getItem() 等方法进行操作。

3. Session Storage

定义:Session Storage 也以键值对形式存储数据,但其生命周期仅限于一个浏览器窗口或标签页。特点: 与 Local Storage 类似,存储容量也在 5MB 到 10MB 之间。数据在页面会话结束时被清除,即当用户关闭标签页或窗口时。只在同一标签页中可用,不同标签页或窗口之间无法共享。使用方式与 Local Storage 相同。

4. IndexedDB

定义:IndexedDB 是一种低级别的 API,用于在客户端存储大量结构化数据。它是异步的并支持事务。特点: 可以存储复杂类型的数据,如对象和数组。存储容量通常比 Local Storage 和 Session Storage 大,可以达到数十MB甚至更高,具体取决于浏览器和设备。支持索引,以及在数据存储时进行搜索和排序。适合需要存储大量数据的 Web 应用,比如离线应用。

5. Web SQL (已废弃)

定义:Web SQL 是一种用于在浏览器中存储数据的SQL数据库接口。特点: 提供了一种使用 SQL 查询数据库的方式。由于缺乏广泛支持(特别是在 Firefox 中),该标准已被废弃,现在不推荐使用。

选择合适的存储方式

选择合适的存储方式通常取决于以下几个因素:

数据量:如果数据量较小且需要跨会话存储,使用 Local Storage。如果数据量很大且需要结构化存储,可以考虑 IndexedDB。数据保留时间:如果数据只需要在当前会话中存在,可以使用 Session Storage。安全性:敏感数据尽量避免使用 Cookie,因为 Cookie 会在每次请求中发送,而 Local Storage 和 Session Storage 则不会。

总结

了解这些存储方式以及它们各自的特性,可以帮助开发者在设计 Web 应用时做出更明智的决策。在面试中,能够清晰地阐述这些存储方式及其适用场景,会给考官留下良好的印象。

3.小程序中分包加载实现

在小程序中,分包加载是一种优化小程序启动速度和减小初始包体积的技术。通过将小程序的代码拆分成多个包,可以实现按需加载,从而提高用户体验。以下是有关小程序中分包加载的实现方法及其步骤:

1. 分包结构

小程序的分包结构大致如下:

project/ ├── app.js ├── app.json ├── app.wxss ├── pages/ │ ├── index/ │ │ ├── index.js │ │ ├── index.wxml │ │ └── index.wxss │ └── ... └── subpackages/ ├── subpackageA/ │ ├── subpackageA.js │ ├── subpackageA.wxml │ └── subpackageA.wxss └── subpackageB/ ├── subpackageB.js ├── subpackageB.wxml └── subpackageB.wxss

2. 配置分包

app.json 文件中,使用 subpackages 字段进行分包配置。每个子包都需要指定一个 root,这是子包的根目录路径。

{ "pages": [ "pages/index/index" ], "subpackages": [ { "root": "subpackages/subpackageA", "pages": [ "subpackageA" // 对应 subpackages/subpackageA/subpackageA.wxml ] }, { "root": "subpackages/subpackageB", "pages": [ "subpackageB" // 对应 subpackages/subpackageB/subpackageB.wxml ] } ] }

3. 访问分包页面

要跳转到分包中的页面,可以使用 wx.navigateTo() 方法,传入分包页面的路径。例如,跳转到 subpackageA 页面:

wx.navigateTo({ url: '/subpackages/subpackageA/subpackageA' });

4. 注意事项

分包限制:小程序分包数量有限制(当前最多可以有 16 个分包),每个分包的大小不能超过 2MB。主包与分包的关系:主包中可以直接调用分包里的代码,但分包之间不能互相引用。不支持 require:在分包中无法使用 require 引入其他分包的模块。异步加载:分包会在用户首次访问时进行异步加载,因此可能会增加首次访问的延迟。合理规划分包内容可以减轻这种影响。

5. 小程序示例

以下是一个简单的小程序示例,演示如何设置和使用分包加载:

app.json

{ "pages": [ "pages/index/index" ], "subpackages": [ { "root": "subpackages/subpackageA", "pages": [ "index" ] } ] }

主页 (pages/index/index.js)

Page({ navigateToSubpackage() { wx.navigateTo({ url: '/subpackages/subpackageA/index' }); } });

分包主页 (subpackages/subpackageA/index.js)

Page({ onLoad() { console.log("Welcome to Subpackage A"); } });

总结

分包加载是提升小程序性能的有效手段,通过合理的结构布局和配置,可以实现高效的资源管理。务必根据业务需求合理划分各个分包,以确保用户体验的流畅性。

4.ES6新特性,列举几个

ES6(也称为 ECMAScript 2015)引入了许多新特性,极大地丰富了 JavaScript 的功能和语法。以下是一些主要的新特性以及简单的介绍:

1. let 和 const

介绍let 和 const 是新的变量声明方式。let 用于声明可变变量,而 const 用于声明常量。特点let:块级作用域,不能在声明之前使用(暂时性死区)。const:必须初始化,并且一旦赋值后不能再修改(但如果是对象,属性仍然可以被修改)。

let x = 10; const y = 20; // y = 30; // TypeError: Assignment to constant variable.

2. 箭头函数

介绍:箭头函数提供了一种更简洁的函数声明方式,并且不绑定自己的 this 值。特点:适用于简短的匿名函数。

const add = (a, b) => a + b; const obj = { value: 10, getValue: function() { setTimeout(() => { console.log(this.value); // this 指向 obj }, 1000); } }; obj.getValue(); // 输出 10

3. 模板字符串

介绍:使用反引号 ` 定义的字符串,可以方便地插入变量和表达式。特点:支持多行字符串和字符串插值。

const name = "Alice"; const greeting = `Hello, ${name}!`; console.log(greeting); // Hello, Alice!

4. 扩展运算符和剩余参数

介绍:扩展运算符(...)可以将数组或对象展开;剩余参数可以将多个参数收集为一个数组。

// 扩展运算符 const arr1 = [1, 2, 3]; const arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5] // 剩余参数 function sum(...args) { return args.reduce((total, num) => total + num, 0); } console.log(sum(1, 2, 3)); // 6

5. 解构赋值

介绍:解构赋值允许从数组或对象中提取值,并将其赋给变量。

// 数组解构 const nums = [1, 2, 3]; const [a, b] = nums; console.log(a, b); // 1 2 // 对象解构 const person = { name: 'Bob', age: 25 }; const { name, age } = person; console.log(name, age); // Bob 25

6. Promises

介绍:Promise 是一种用于处理异步操作的对象,代表一个可能尚未完成的操作及其结果。特点:提供 .then() 和 .catch() 方法来处理成功和失败的结果。

const myPromise = new Promise((resolve, reject) => { setTimeout(() => resolve("Success!"), 1000); }); myPromise.then(result => console.log(result)); // 1秒后输出 "Success!"

7. 

介绍:ES6 引入了类的概念,使得基于原型的继承更加直观。

class Animal { constructor(name) { this.name = name; } speak() { console.log(`${this.name} makes a noise.`); } } class Dog extends Animal { speak() { console.log(`${this.name} barks.`); } } const dog = new Dog('Rex'); dog.speak(); // Rex barks.

总结

ES6 提供的这些新特性使得 JavaScript 编程更加简洁、高效、易于维护。通过合理利用这些特性,开发者可以编写出更优雅和高性能的代码。

5.子父组件的传参

在 Vue 3 中,父组件和子组件之间的参数传递主要有两种方式:通过 props 从父组件向子组件传递数据,以及通过事件从子组件向父组件传递数据。以下是这两种方法的详细介绍及示例。

1. 父组件向子组件传参(使用 Props)

步骤

在子组件中定义 props: 在子组件中使用 defineProps 来定义要接收的 props。

在父组件中使用子组件并传递参数: 在父组件中使用子组件时,通过绑定属性将数据传递给子组件。

示例

子组件 (ChildComponent.vue)

<template> <div> <h2>Hello, {{ name }}!</h2> </div> </template> <script setup> import { defineProps } from 'vue'; const props = defineProps({ name: { type: String, required: true, }, }); </script>

父组件 (ParentComponent.vue)

<template> <div> <h1>Welcome to the Parent Component</h1> <ChildComponent :name="userName" /> </div> </template> <script setup> import ChildComponent from './ChildComponent.vue'; const userName = 'Alice'; </script>

2. 子组件向父组件传参(使用 Emit)

步骤

在子组件中使用 emit 发送事件: 使用 defineEmits 定义要发出的事件,并在适当的时候调用它。

在父组件中监听子组件事件: 在父组件中使用 v-on@ 监听子组件所发出的事件。

示例

子组件 (ChildComponent.vue)

<template> <div> <button @click="sendMessage">Send Message to Parent</button> </div> </template> <script setup> import { defineEmits } from 'vue'; const emit = defineEmits(); function sendMessage() { emit('message-sent', 'Hello from Child!'); } </script>

父组件 (ParentComponent.vue)

<template> <div> <h1>Welcome to the Parent Component</h1> <ChildComponent @message-sent="handleMessage" /> </div> </template> <script setup> import ChildComponent from './ChildComponent.vue'; function handleMessage(message) { console.log(message); // 输出: Hello from Child! } </script>

总结

在 Vue 3 中,父子组件之间的参数传递非常灵活且易于实现。父组件可以通过 props 向子组件传递数据,而子组件则可以通过 emit 事件将数据或消息传回父组件。这种设计使得组件之间的通信清晰且维护简单。


点击全文阅读


本文链接:http://m.zhangshiyu.com/post/196493.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1