js
- 浏览器渲染原理
- https如何进行加密
- spa首屏加载慢优化
- vue双向郷定原理
- vuex设计与实现
- vue-router底层原理
- mvvm设计与实现
- async,await底层实现
- promise底层实现
- js垃圾回收机制
- 前端缓存机制
spa
常见的SPA框架包括React、Angular和Vue.js
SPA缺点,例如对SEO的不友好、初始加载时间可能较长、处理大量数据时性能可能受到影响等。
SPA(Single Page Application)是一种前端架构模式,它通过动态地更新当前页面而不是加载整个新页面来提供用户交互体验。
传统的多页面应用程序在用户导航期间会加载新的HTML页面,而SPA则在初始加载后将应用程序的全部或大部分代码加载到浏览器中,并通过JavaScript操作DOM来更新页面内容。
SPA的核心思想是在浏览器中创建一个单一的HTML页面,然后使用JavaScript处理页面的路由、数据获取和渲染等任务。通过使用AJAX或WebSocket等技术,SPA能够与后端服务器进行异步通信,从而获取数据并更新页面的部分内容,而无需重新加载整个页面。
SPA的优点包括:
用户体验:SPA可以提供更快的页面切换和响应速度,因为它只需要更新页面的一部分而不是整个页面。 交互性:SPA通过AJAX等技术实现与后端服务器的异步通信,可以实时获取和展示数据,提供更加交互式的用户体验。 代码复用:SPA可以通过组件化的方式组织代码,使得代码的复用性更高,提高开发效率。 跨平台开发:由于SPA主要运行在浏览器中,因此可以跨平台使用,无论是桌面还是移动设备。
事件循环
箭头函数
闭包
ts熟悉?
axios封装
ES6新增哪些特性
前端缓存
原型和原型链
垂直居中的方式
怎么理解回流和重绘
promise
事件循环说说,宏任务和微任务有哪些
讲一下你对 EventLoop 的理解
了解axios的原理吗? 怎么实现的
讲一下你所知道的设计模式
说说你对作用域链的理解
自定义hooks
type和 interface的区别
javaScript中执行上下文和执行栈是什么?
new操作符具体干了什么
实现一下new
function mynew(Func, ...args) {
// 1.创建一个新对象
const obj = {}
// 2.新对象原型指向构造函数原型对象
obj.__proto__ = Func.prototype
// 3.将构建函数的this指向新对象
let result = Func.apply(obj, args)
// 4.根据返回值判断
return result instanceof Object ? result : obj
}
深拷贝和浅拷贝,怎么实现一个深拷贝说思路
浅拷贝,指的是创建新的数据,这个数据有着原始数据属性值的一份精确拷贝
如果属性是基本类型,拷贝的就是基本类型的值。如果属性是引用类型,拷贝的就是内存地址
即浅拷贝是拷贝一层,深层次的引用类型则共享内存地址
存在浅拷贝的现象有:
- Object.assign
const target = {};
// 复制源对象的属性到目标对象
const source1 = { name: 'Alice', age: 30 };
Object.assign(target, source1);
console.log(target); // 输出:{ name: 'Alice', age: 30 }
- Array.prototype.slice(), Array.prototype.concat()
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const arr3 = [7, 8, 9];
// 合并多个数组
const mergedArray = arr1.concat(arr2, arr3);
console.log(mergedArray); // 输出:[1, 2, 3, 4, 5, 6, 7, 8, 9]
- 使用拓展运算符实现的复制
数组合并有哪些方法
// concat
const array1 = [1, 2, 3];
const array2 = [4, 5, 6];
const newArray = array1.concat(array2);
// ...
const array1 = [1, 2, 3];
const array2 = [4, 5, 6];
const newArray = [...array1, ...array2];
// push() 方法用于向一个数组的末尾添加一个或多个元素,并返回修改后的数组:
const array1 = [1, 2, 3];
const array2 = [4, 5, 6];
for (const item of array2) {
array1.push(item);
}
// Array.from() 方法:
const array1 = [1, 2, 3];
const array2 = [4, 5, 6];
const newArray = Array.from(array1).concat(array2);
// Array.prototype.push.apply():
const array1 = [1, 2, 3];
const array2 = [4, 5, 6];
Array.prototype.push.apply(array1, array2);
数组去重的方法?
// set
const arr = [1, 2, 2, 3, 4, 4, 5];
const uniqueArr = [...new Set(arr)];
console.log(uniqueArr); // 输出 [1, 2, 3, 4, 5]
// filter
const arr = [1, 2, 2, 3, 4, 4, 5];
const uniqueArr = arr.filter((value, index, self) => {
return self.indexOf(value) === index;
});
console.log(uniqueArr); // 输出 [1, 2, 3, 4, 5]
// reduce
const arr = [1, 2, 2, 3, 4, 4, 5];
const uniqueArr = arr.reduce((acc, currentValue) => {
if (!acc.includes(currentValue)) {
acc.push(currentValue);
}
return acc;
}, []);
console.log(uniqueArr); // 输出 [1, 2, 3, 4, 5]
如何写一个split方法并覆盖数组的原方法
// 扩展 Array 原型
Array.prototype.split = function(separator) {
};
// 示例用法
const inputArray = [1, 2, 3, 4, 5, 0, 6, 7, 8, 9, 0, 10];
const separatorFunction = (item) => item === 0;
const result = inputArray.split(separatorFunction);
console.log(result);
forEach循环和for循环哪个性能高? forEach循环可以中断吗?
forEach 循环是一个高阶函数,它接受一个回调函数作为参数,并对数组中的每个元素执行这个回调函数。因为它是一个函数调用,所以它可以在回调函数中使用 return 语句来退出循环。但需要注意,return 只会退出当前回调函数的执行,而不是退出整个 forEach 循环。这意味着 forEach 循环本身不支持在回调函数中进行中断操作。
在示例中,当 number 的值等于 3 时,return 会中断回调函数的执行,不会执行 console.log(number)。
const numbers = [1, 2, 3, 4, 5];
numbers.forEach((number) => {
if (number === 3) {
return; // 中断回调函数的执行
}
console.log(number);
});
封装的按钮权限组件怎么实现的?
按钮组件通过 map 方法遍历按钮权限数据,然后根据数据渲染按钮。按钮的 disabled 属性根据权限数据来控制是否可点击。当按钮被点击时,会调用 handleButtonClick 方法,该方法会检查按钮是否可点击,如果可以点击,则触发回调函数。
创建一个自定义组件,它接受按钮权限数据,并根据权限数据来渲染按钮。
export default class ButtonPermissions extends React.Component {
handleButtonClick = (button) => {
if (!button.disabled) {
if (this.props.onButtonClick) {
this.props.onButtonClick(button);
}
}
};
render() {
const { buttons } = this.props;
return (
<div>
{buttons.map((button) => (
<button
key={button.id}
onClick={() => this.handleButtonClick(button)}
disabled={button.disabled}
>
{button.label}
</button>
))}
</div>
);
}
}
使用:
import ButtonPermissions from './ButtonPermissions';
class App extends React.Component {
handleButtonClick = (button) => {
// 处理按钮点击逻辑
console.log('Button clicked:', button.label);
};
render() {
const buttonPermissions = [
{ id: 1, label: '编辑', disabled: false },
{ id: 2, label: '删除', disabled: true }
];
return (
<div>
<ButtonPermissions buttons={buttonPermissions} onButtonClick={this.handleButtonClick} />
</div>
);
}
}
说说轮播图的思路
JavaScript 逻辑:使用 JavaScript 来实现轮播图的逻辑。以下是一些关键思路:
初始化:首先,确定轮播图的当前索引,通常设置为0。这个索引将用于跟踪当前显示的图片。
自动播放:如果需要自动播放功能,可以使用定时器来定期调用切换图片函数。
循环播放:如果轮播图到达最后一张后,返回到第一张。确保索引循环,以实现循环播放。
过渡效果:使用 CSS 过渡效果来实现图片之间的平滑切换。
事件处理:添加事件处理程序来处理用户的交互操作,如点击下一个/前一个按钮、点击指示器、鼠标悬停等。
优化和性能:确保代码的性能和用户体验。可以采用一些优化措施,如懒加载图片、预加载图片、延迟加载、图片压缩等。
下面是一个简单的示例,演示了一个基本的轮播图实现的思路:
<!DOCTYPE html>
<html>
<body>
<div class="carousel-container">
<div class="carousel-slide">
<img src="image1.jpg" alt="Image 1">
</div>
<div class="carousel-slide">
<img src="image2.jpg" alt="Image 2">
</div>
<div class="carousel-slide">
<img src="image3.jpg" alt="Image 3">
</div>
</div>
<button id="prevButton">Previous</button>
<button id="nextButton">Next</button>
<script>
// JavaScript 逻辑
const slides = document.querySelectorAll('.carousel-slide');
let currentIndex = 0;
const interval = 3000; // 自动切换间隔时间,单位毫秒
function showSlide(index) {
slides.forEach((slide, i) => {
if (i === index) {
slide.style.display = 'block';
} else {
slide.style.display = 'none';
}
});
}
function nextSlide() {
currentIndex = (currentIndex + 1) % slides.length;
showSlide(currentIndex);
}
function startAutoPlay() {
setInterval(nextSlide, interval);
}
showSlide(currentIndex);
startAutoPlay();
</script>
</body>
</html>
前端异步任务分为哪些
前端异步任务通常分为以下几种:
回调函数(Callbacks):
- 回调函数是最基本的异步模式,通常用于处理异步操作的结果。当异步操作完成后,调用预定义的回调函数来处理结果。
Promise:
- Promise 是一种更灵活和可读性更好的异步模式。它允许你处理异步操作的成功或失败,而不是通过回调函数来处理。
- Promise 有三种状态:待定(pending)、已解决(fulfilled)、已拒绝(rejected)。
Async/Await:
- Async/Await 是基于 Promise 的语法糖,提供了更清晰的方式来处理异步操作。使用
async声明异步函数,然后在函数内使用await来等待 Promise 的解决或拒绝。
- Async/Await 是基于 Promise 的语法糖,提供了更清晰的方式来处理异步操作。使用
Ajax/HTTP 请求:
- 发送网络请求(如 GET 或 POST 请求)是一种异步操作,通常使用 XMLHttpRequest 或 Fetch API 来执行。服务器响应将在未来的某个时间点返回,你需要使用回调函数、Promise 或 async/await 来处理响应数据。
Web Workers:
- Web Workers 允许在后台线程中运行 JavaScript 代码,从而在主线程不被阻塞的情况下执行计算密集型任务。
异步模块加载(AMD,CommonJS,ES6 Modules):
- 模块加载系统允许异步加载 JavaScript 模块,这对于大型应用程序的性能和可维护性非常重要。
IndexedDB 和本地存储:
- 使用 IndexedDB 或本地存储 API 时,读取和写入数据通常是异步的。
定时器(Timers):
- 定时器是一种用于在未来的某个时间点执行代码的异步机制。常见的定时器函数包括
setTimeout和setInterval。 setTimeout在指定时间后执行一次函数,而setInterval在指定时间间隔内重复执行函数。
- 定时器是一种用于在未来的某个时间点执行代码的异步机制。常见的定时器函数包括
事件监听(Event Listeners):
- 事件监听用于在发生事件时执行回调函数。例如,你可以监听鼠标点击、键盘输入、网络请求完成等事件。
动画和过渡:
- 在前端开发中,CSS 动画和过渡通常是异步操作,例如,你可以使用
setTimeout来实现动画效果。
- 在前端开发中,CSS 动画和过渡通常是异步操作,例如,你可以使用
这些异步任务在前端开发中非常常见,了解如何处理它们是开发者的基本技能。根据不同的情况和需求,你可以选择使用适当的异步模式或工具来处理异步任务。
如何实现一个new
new 操作符的主要工作是创建一个新对象,将该对象的原型链与构造函数的原型连接,并将构造函数的上下文绑定到新对象上。
customNew 函数模拟了 new 操作符的行为。它首先创建一个新对象 instance,并将构造函数的原型与该对象的原型链连接。然后,它将构造函数的上下文绑定到新对象上,并调用构造函数,将参数传递给构造函数。最后,它返回构造函数的结果,如果结果是对象,则返回该对象,否则返回新对象。
需要注意的是,这只是一个非常基本的 new 操作符模拟,实际上,new 操作符还有其他一些复杂的行为,如构造函数返回对象时的处理等。
function customNew(constructor, ...args) {
// 创建一个新对象,该对象的原型链与构造函数的原型连接
const instance = Object.create(constructor.prototype);
// 将构造函数的上下文绑定到新对象上
const result = constructor.apply(instance, args);
// 如果构造函数返回一个对象,则返回该对象,否则返回新对象
return result instanceof Object ? result : instance;
}
// 示例构造函数
function Person(name, age) {
this.name = name;
this.age = age;
}
// 使用自定义的 new 操作符创建对象
const person = customNew(Person, "Alice", 30);
console.log(person.name); // 输出 "Alice"
console.log(person.age); // 输出 30
假设要设计一个全局的弹窗组件你会怎么设计?
设计一个全局的弹窗组件在React中通常包括以下步骤:
组件结构设计:首先,设计弹窗组件的结构,包括弹窗内容、标题、按钮、关闭按钮等元素。你可以创建一个独立的React组件,例如
Modal,并在其中渲染这些元素。状态管理:为了在应用的不同部分触发和控制弹窗的显示,需要设计一个状态管理系统。通常可以使用React的状态或者Redux等状态管理库来管理弹窗的显示状态。
全局状态:如果要实现全局的弹窗组件,需要考虑如何在应用的不同组件中触发弹窗的显示。可以将弹窗的显示状态放在全局状态中,例如Redux的store中,以便全局共享。
弹窗触发:设计一种方式来触发弹窗的显示。可以通过在全局状态中设置标志来控制弹窗的显示与隐藏,也可以通过自定义事件或上下文API来实现。
自定义配置:为弹窗组件提供自定义配置选项,允许传递不同的弹窗标题、内容、按钮等属性。这可以通过组件属性(props)或函数参数来实现。
样式设计:设计弹窗的样式,可以使用CSS或CSS-in-JS库来定义样式。确保弹窗可以居中显示并在需要时覆盖整个页面。
事件处理:处理弹窗内部的事件,例如按钮点击事件、关闭按钮点击事件等。可以通过React事件处理程序来实现这些功能。
动画效果:如果需要,可以为弹窗添加动画效果,使其更吸引人。可以使用React动画库,如React Transition Group,来实现动画效果。
测试:编写单元测试和集成测试,以确保弹窗组件的功能正常,并且不会引入潜在的bug。
文档和示例:为弹窗组件编写文档,提供示例代码和用法说明,以便其他开发者能够轻松使用这个组件。
集成到应用:将弹窗组件集成到你的React应用中,根据需要在应用的不同部分触发弹窗的显示。
设计一个全局的弹窗组件需要考虑众多细节,但它可以增加应用的交互性和用户友好性。可以根据项目的需求和规模来确定具体的实现方式。
用js写一个通用的方法来获取地址栏的某个参数对应的值,不能使用正则表达式
function getQueryParam(parameterName) {
const urlParams = new URLSearchParams(window.location.search);
return urlParams.get(parameterName);
}