前端知识库JS相关

一、Js的数据类型

基础类型有7个

  1. String
  2. Number
  3. BigInt
  4. Boolean
  5. Symbol
  6. Null
  7. Undefined

引用类型有1个

  1. Object(细分有:Object 类型、Array 类型、Date 类型、RegExp 类型、Function 类型 等)

二、闭包和作用域

闭包是作用域应用的特殊场景。 js中常见的作用域包括全局作用域、函数作用域、块级作用域。要知道js中自由变量的查找是在函数定义的地方,向上级作用域查找,不是在执行的地方。 常见的闭包使用有两种场景:一种是函数作为参数被传递;一种是函数作为返回值被返回。

// 函数作为返回值
function create() {
  let a = 100;
  return function () {
    console.log(a);
  };
}

const fn = create();
const a = 200;
fn(); // 100

// 函数作为参数被传递
function print(fb) {
  const b = 200;
  fb();
}
const b = 100;
function fb() {
  console.log(b);
}
print(fb); // 100

三、Set WeakSet Map WeakMap之间的区别

Set

成员唯一、无序且不重复
[value1, value2, …],键值与键名是一致的(或者说只有键值,没有键名)
可以遍历,方法有:add、delete、has

set可以给基本数据类型去重

const list = [4, 2, 1, 3, 3]

const mySet = new Set(list);

// 将 Set 转换为数组
const Array_ = [...mySet];

console.log(Array_); // 输出排序后的数组

WeakSet

成员都是对象
成员都是弱引用,可以被垃圾回收机制回收,可以用来保存DOM节点,不容易造成内存泄漏
不能遍历,方法有add、delete、has
非常适合 检测循环引用

// 对传入的 subject 对象内部存储的所有内容执行回调
function execRecursively(fn, subject, _refs = new WeakSet()) {
  // 避免无限递归
  if (_refs.has(subject)) {
    return;
  }

  fn(subject);
  if (typeof subject === "object") {
    _refs.add(subject);
    for (const key in subject) {
      execRecursively(fn, subject[key], _refs);
    }
  }
}

const foo = {
  foo: "Foo",
  bar: {
    bar: "Bar",
  },
};

foo.bar.baz = foo; // 循环引用!
execRecursively((obj) => console.log(obj), foo);

Map

本质上是键值对的集合,类似集合
可以遍历,方法很多可以跟各种数据格式转换

const myMap = new Map([
  ['key1', 'value1'],
  ['key2', 'value2'],
  ['key3', 'value3']
]);

// 示例使用对象作为键:
const obj1 = { id: 1 };
const obj2 = { id: 2 };

const myMapWithObjects = new Map([
  [obj1, 'value1'],
  [obj2, 'value2']
]);

WeakMap

只接受对象类型作为键名,不接受其他类型的值作为键名
键名是弱引用,键值可以是任意的,键名所指向的对象可以被垃圾回收,此时键名是无效的,一个对象作为 WeakMap 的键存在,不会阻止该对象被垃圾回收。不能遍历,方法有get、set、has、delete

四、setTimeOut准时吗?

在理论上,setTimeout 是不准时的,因为它的执行时间取决于 JavaScript 引擎的当前负载和其他因素。虽然 setTimeout 的参数是以毫秒为单位的延迟时间,但并不意味着回调函数会在精确的毫秒数后立即执行。

具体来说,setTimeout 的延迟时间只是一个最小值,而不是精确的等待时间。实际上,当 setTimeout 的延迟时间到期后,回调函数会被添加到事件队列中,在 JavaScript 引擎执行主线程上的任务之后尽快执行。但是,如果主线程忙于执行其他任务,可能会导致回调函数的实际执行时间延迟,尤其是在高负载时或者在执行大量计算的情况下。

另外,一些浏览器甚至在隐藏的标签页或后台标签页中对 setTimeout 进行了优化,可能会延迟执行回调函数,以节省资源并提高性能。

因此,在实际应用中,不应该依赖于 setTimeout 的准确性。如果需要精确的时间控制,可以考虑使用 requestAnimationFrame、requestIdleCallback 或 Web Workers 等其他机制。

五、JS打乱数组最简单的方法

JavaScript 中打乱数组最简单的方法之一是使用 Fisher-Yates 洗牌算法(也称为 Knuth 洗牌算法)。这是一种经典的随机置换算法,其思想是从数组的末尾开始,随机选择一个元素并将其与当前位置的元素交换,然后继续向前,直到第一个元素。

function shuffleArray(array) {
  for (let i = array.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1)); // 生成随机索引
    [array[i], array[j]] = [array[j], array[i]]; // 交换元素
  }
  return array;
}

// 示例用法
const myArray = [1, 2, 3, 4, 5];
console.log(shuffleArray(myArray)); // 输出打乱后的数组

六、防抖函数和节流函数

防抖函数

防抖函数的作用是在触发事件后等待一定的时间再执行函数,如果在等待时间内又触发了该事件,则重新计时。在最后一次触发事件之后的一段时间内没有再次触发事件,才会执行函数。
适用于处理频繁触发的事件,例如输入框输入、窗口调整大小等。可以用于优化性能,避免频繁执行重复的操作。

function debounce(func, delay) {
    let timerId;
    return function(...args) {
        clearTimeout(timerId);
        timerId = setTimeout(() => {
            func.apply(this, args);
        }, delay);
    };
}
const debouncedFunction = debounce(function() {
    console.log('Debounced function called');
}, 1000);

// 在一秒内连续调用多次
debouncedFunction(); // 只有在一秒后才会执行
debouncedFunction(); // 在一秒内又调用了,重新计时

节流函数

节流函数的作用是在一定的时间间隔内只执行一次函数,无论该时间段内触发了多少次事件。即在固定的时间间隔内执行函数,而不管触发次数。
适用于控制事件触发的频率,例如滚动事件、鼠标移动事件等。可以用于限制事件处理的频率,防止过多的事件处理导致性能问题。

function throttle(func, delay) {
    let canCall = true;
    return function(...args) {
        if (canCall) {
            func.apply(this, args);
            canCall = false;
            setTimeout(() => {
                canCall = true;
            }, delay);
        }
    };
}
const throttledFunction = throttle(function() {
    console.log('Throttled function called');
}, 1000);

// 连续调用多次
throttledFunction(); // 只有第一次会立即执行
throttledFunction(); // 在一秒内的其他调用会被忽略

七、实现图片懒加载

html

<img class="lazyload" data-src="path_to_image.jpg" alt="Image">

css

.lazyload {
  opacity: 0; /* 默认隐藏 */
  transition: opacity 0.3s ease-in-out; /* 可选的渐变效果 */
}
.lazyloaded {
  opacity: 1; /* 图片加载后显示 */
}

js

document.addEventListener("DOMContentLoaded", function() {
  let lazyloadImages = document.querySelectorAll(".lazyload");
  let imageObserver = new IntersectionObserver(function(entries, observer) {
    entries.forEach(function(entry) {
      if (entry.isIntersecting) {
        let lazyImage = entry.target;
        lazyImage.src = lazyImage.dataset.src;
        lazyImage.classList.remove("lazyload");
        lazyImage.classList.add("lazyloaded");
        imageObserver.unobserve(lazyImage);
      }
    });
  });

  lazyloadImages.forEach(function(image) {
    imageObserver.observe(image);
  });
});

当页面加载完毕后,通过 querySelectorAll 查找所有具有 lazyload 类的图片元素。然后创建一个 IntersectionObserver 实例,用于观察每个图片元素是否进入了视口(即可见区域)。当图片元素进入视口时,触发回调函数,将 data-src 属性的值赋给 src 属性,从而加载图片。同时移除 lazyload 类并添加 lazyloaded 类,以便标识图片已经被加载。最后,通过 unobserve 方法停止观察该图片元素,以减少性能消耗。

八、从输入 URL 到页面展示,这中间发生了什么?

1、解析 URL:

首先,浏览器会解析输入的 URL。这个过程涉及到解析协议(如 HTTP、HTTPS)、域名、路径和查询参数等信息。

2、DNS 解析:

浏览器会查询 DNS 服务器,将输入的域名解析为对应的 IP 地址。如果 DNS 缓存中已经存在该域名的解析结果,则直接使用缓存的结果。

3、建立 TCP 连接:

浏览器与服务器之间通过 TCP 协议建立连接。这个过程涉及到 TCP 的三次握手,包括客户端向服务器发送 SYN,服务器响应 SYN+ACK,最后客户端发送 ACK。

4、发起 HTTP 请求:

一旦建立了 TCP 连接,浏览器就会发送 HTTP 请求。请求的内容包括请求方法(如 GET、POST)、请求头、请求体等信息。

5、服务器处理请求:

服务器收到请求后,根据请求的内容进行处理。处理的过程可能涉及到查询数据库、生成动态内容、读取文件等操作。

6、服务器返回响应:

服务器处理完请求后,会返回一个 HTTP 响应。响应包括状态码、响应头、响应体等信息。

7、接收响应:

浏览器接收到响应后,会根据响应头中的信息确定如何处理响应。如果是 HTML 内容,则继续下一步的渲染过程。

8、解析 HTML 和构建 DOM 树:

浏览器会解析 HTML 内容,并根据 HTML 标记构建 DOM 树。DOM 树表示了文档的结构,包括元素、属性和它们之间的关系。

9、构建 CSSOM 树:

浏览器会解析 CSS 样式表,并构建 CSSOM 树。CSSOM 树表示了文档的样式信息,包括样式规则、选择器和样式声明等。

10、合并 DOM 树和 CSSOM 树,生成渲染树:

浏览器将 DOM 树和 CSSOM 树合并,生成渲染树(Render Tree)。渲染树只包含渲染页面所需的内容,即可视和渲染的元素及其样式信息。

11、布局和绘制:

浏览器根据渲染树中的信息,计算每个元素在页面中的位置和大小,并进行绘制。这个过程称为布局(Layout)和绘制(Painting)。

12、页面展示:

最后,浏览器将绘制好的页面展示给用户。这个过程可能还会涉及到一些额外的步骤,如图层合成、动画渲染等

总结就是
解析 URL 和 DNS 解析 → 建立 TCP 连接 → 发起 HTTP 请求 → 服务器处理请求并返回响应 → 浏览器解析响应并展示页面

九、HTML5 WebStorage 是什么

Web Storage中包含两个关键的对象,分别是localStorage对象和sessionStorage对象,它们都是Web Storage的实例,所以都能使用Web Storage接口提供的方法和属性。localStorage对象用于本地存储,sessionStorage对象用于会话存储。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xl__qd

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值