小红书凉经(一)

哈喽哈喽,这里是小菜不拖延博主,博主最近开始面试了,刚刚面完小红书,还没出结果先出一篇凉经,总的来说问的不难,但是也不妨碍我不会(sos,平时不注重理论就是这个结果),大抵是凉了的

  • 自我介绍
  • 项目难点
  • 为什么选择做前端
  • 其他:问了实验室的一些情况、做的小程序是什么、做的是什么项目(政府的还是企业的)
  • 代码题数组去重,还有什么别的实现方法吗越多越好
  • src和herf的区别
  • script标签执行有几种形式(当时都没听懂这个是干嘛)
  • 说一下事件循环
  • data为什么是一个函数
  • 还有什么其他的优化技术
  • call、bind、apply函数的区别
  • 强制缓存和协商缓存

ps:由于一个问题补充芝士太多了,我们分成几部分讲叭

代码题

代码题部分没有让我运行通过,直接写完之后问的思路,并且询问我除了当前方法还有哪些方法可以实现的

数组去重

bash 复制代码
输入:
var arr=[{name:'a',id:1},{name:'b',id:2},{name:'c',id:3},{name:'a',id:4},{name:'c',id:5}]
输出:
[{name:'a',id=1},{name:'b',id=2},{name:'c',id=3}]

解题:

方法一:双重for循环

外层遍历输入数组,进行逐个判断,内层循环判断输出的数组当中是否存在该值,如果存在就break,那么j没有遍历完成输出数组,自然就不等于输出数组长度,所以只有j和输出数组长度相等的时候才输出

javascript 复制代码
    let arr1=[]
    let j
    for(let i=0;i<arr.length;i++){
        for(j=0;j<arr1.length;j++){
          if(arr[i]['name']==arr1[j]['name']){
            console.log(arr[i]['name'],i);
            break
          }
        }
        if(j==arr1.length){
          arr1.push(arr[i])
        }
    }

方法二:利用对象

forEach遍历数组,用name作为键,对象作为值,由于一个键只会对应一个值,所以可以去重

javascript 复制代码
    var obj={}
    arr.forEach(item=>{
      obj[item.name]=item
    })
    let arr1=Object.values(obj)

forEach

  • array.forEach(callback(currentValue, index, array), thisArg)
  • array:要遍历的数组。 callback:回调函数,用于对每个元素执行的操作。
  • currentValue:当前元素的值。
  • index:当前元素的索引。
  • array:被遍历的数组。
  • thisArg(可选):在执行回调函数时,用作 this 的值。
js 复制代码
const numbers = [1, 2, 3, 4, 5];

numbers.forEach(function(number, index) {
  console.log(`Element at index ${index} is ${number}`);
});

//输出:
Element at index 0 is 1 
Element at index 1 is 2 
Element at index 2 is 3 
Element at index 3 is 4 
Element at index 4 is 5

Obejct

  • Obejct.keys:获取属性,返回的值是对象
  • Object.values:获取属性的值,返回的是对象

方法三:利用map

  1. 首先arr.map遍历数组,用item.name作为键,item整一个作为值,newMap生成Map的一个集合
  2. 获取到Map的值,此时是一个集合,是{{},{}}的形式
  3. 利用Array.from转换为数组
javascript 复制代码
let uni=Array.from(new Map(arr.map(item=>[item.name,item])).values())

Array.from

Array.from 是一个数组方法,在 JavaScript 中用于从类数组对象或可迭代对象创建一个新的数组。比如我可以传入一个Set对象,他就可以帮我转成数组 栗子:

js 复制代码
// 从字符串创建数组 
const str = 'Hello'; 
const arr = Array.from(str); 
console.log(arr); 
// 输出:["H", "e", "l", "l", "o"] 

// 从 Set 创建数组 
const set = new Set([1, 2, 3]); 
const arr = Array.from(set); 
console.log(arr);
 // 输出:[1, 2, 3] 
 
 // 从 Map 创建数组 
 const map = new Map([ ['key1', 'value1'], ['key2', 'value2'] ]); 
 const arr = Array.from(map); 
 console.log(arr); 
 // 输出:[["key1", "value1"], ["key2", "value2"]]

map

用于存储键值对的有序集合

  • 创建
js 复制代码
const map = new Map(); // 创建一个空的 Map
const map = new Map([[key1, value1], [key2, value2]]); // 创建并初始化一个 Map
  • 添加和删除
js 复制代码
const map = new Map();
map.set(key1, value1); // 添加一个键值对
map.set(key2, value2).set(key3, value3); // 连续添加多个键值对
map.delete(key2); // 删除一个键值对
map.clear(); // 清空 Map 中的所有键值对
  • 获取键值对
js 复制代码
console.log(map.get(key1)); // 获取指定键对应的值
  • 判断是否存在
js 复制代码
console.log(map.has(key1)); // 判断 Map 中是否存在指定键,输出: true

Set

它是一种无序且唯一的集合。Set 中的元素不允许重复,并且可以存储任何类型的值,包括原始类型和对象引用。

  • 创建
js 复制代码
// 创建一个空的 
const set = new Set(); 
// 创建并初始化一个 Set
Set const set = new Set([1, 2, 3]); 
  • 获取大小new Set().size
  • 判断set中是否存在:set.has(2),返回的是true/false

注意!!!!!!!!

Set 中的元素是无序的,不像数组有固定的索引,因此不能通过索引进行访问。访问出来是undefined

方法四:利用filter过滤器

注意!!!这个方法和上面的双重for循环的办法都可以保证只保留重复出现的第一个数据,但是map和对象的那两个是不可以的,需要更多的操作

js 复制代码
      
var uniqueArr = [];
var uniqueObj = {};
      
arr.filter(function(item) {
    //如果不存在item.name的值
    if (!uniqueObj[item.name]) {
        //那么我就存入这个键值对,a:true,如果下一次再出现a的话,那么就不会被push进我的输出数组
      uniqueObj[item.name] = true;
      uniqueArr.push(item);
    }
});

src和href的区别

src通常是指定需要嵌入到我文档中的外部资源,图片视频之类的,他是需要下载的,浏览器解析到src属性的时候,会暂停解析,直到下载解析完成当前的资源,才会继续解析。而href是超文本引用,像一些a标签link会用到,它是建立文档与外部资源之间的关联,一个是嵌入一个是关联,我用a标签只是会跳转,只是指向了一个资源地址,所以不会影响页面的解析。

script标签

由于这部分我没弄懂是问什么,那就直接把script标签复习了吧!

引入js

内联式

直接在script标签当中写js代码

markdown 复制代码
如果在script标签在head当中,那么浏览器执行顺序就是:
1.  暂停 DOM 解析过程
2.  执行 JS 代码
3.  执行完成,继续 DOM 解析过程

如果在body当中写就是

外联式

markdown 复制代码
script标签在head标签当中
1.  暂停 DOM 解析过程
2.  加载 a.js
3.  加载完成后,开始执行该脚本
4.  执行完成,继续 DOM 解析过程

在上面所提到的方式当中,我们会发现dom的解析过后曾都会被打断,也就是同步阻塞 ,如果我们的js脚本过大的话,那我们的解析打断时间就会很长,也就是说用户会看到页面空白,也就是白屏现象,所以解决办法是将script标签插入在body底部,就可以让浏览器先解析script标签之前的内容,再来执行脚本,就能很好的解决白屏问题。

但是要是能解析dom和加载js过程并行,那么就能省下部分时间,也就出现了下面的

defer/async

这个是为了解析dom和加载js同步并行

defer延迟加载

这个属性可以让浏览器在解析dom的同时加载js,但是只有在解析dom完成之后才会执行js脚本

html 复制代码
<html>
<head>
    <script defer src="./a.js"></script>
</head>
</html>

async异步加载

浏览器解析dom的同时加载js,加载完成并立即执行js(也就是会打断dom解析)
async和defer同时出现的话:async 的优先级会比 defer 高,因此 defer 将不会生效

动态引入

通过 innerHTML 方式其实也能添加 script 标签,只是该标签下的 JS 不会运行

js 复制代码
var myScript = document.createElement("script");
myScript.textContent = 'alert("✋")';
document.head.appendChild(myScript);

es modules模块化脚本

通过指定 type="module" 来声明一个外部脚本是一个 es 模块,默认是defer的

js 复制代码
<script type="module" src="./a.mjs"></script>

// a.mjs
import b from "./b.mjs"
import c from "./c.mjs"

浏览器加载 a.mjs 之后,还需要继续加载 b.mjsc.mjs 。只有所有这些依赖模块都分析加载完毕,才能开始执行其中的 js 脚本,而且根据根据 es modules 的规则,浏览器会先执行 b.mjs 中的代码,然后是 c.mjs ,最后才是 a.mjs 的代码。

nomodule

es modules 的浏览器,第一个脚本不会被执行,第二个脚本会被执行。

js 复制代码
<script type="module" src="main.js"></script>
<script nomodule src="fallback.js"></script>

阅读参考:

你知道 script 标签脚本在各种情况下的加载和执行顺序吗? - 知乎 (zhihu.com)

一文搞懂 script 标签 - 掘金 (juejin.cn)

相关推荐
大G哥5 分钟前
python 数据类型----可变数据类型
linux·服务器·开发语言·前端·python
hong_zc29 分钟前
初始 html
前端·html
小小吱34 分钟前
HTML动画
前端·html
Xiao Fei Xiangζั͡ޓއއ39 分钟前
一觉睡醒,全世界计算机水平下降100倍,而我却精通C语言——scanf函数
c语言·开发语言·笔记·程序人生·面试·蓝桥杯·学习方法
Bio Coder1 小时前
学习用 Javascript、HTML、CSS 以及 Node.js 开发一个 uTools 插件,学习计划及其周期
javascript·学习·html·开发·utools
糊涂涂是个小盆友1 小时前
前端 - 使用uniapp+vue搭建前端项目(app端)
前端·vue.js·uni-app
NMBG221 小时前
[JAVAEE] 面试题(四) - 多线程下使用ArrayList涉及到的线程安全问题及解决
java·开发语言·面试·java-ee·intellij-idea
浮华似水1 小时前
Javascirpt时区——脱坑指南
前端
王二端茶倒水1 小时前
大龄程序员兼职跑外卖第五周之亲身感悟
前端·后端·程序员
_oP_i1 小时前
Web 与 Unity 之间的交互
前端·unity·交互