【前端面试题】我靠它拿到了大厂Offer 一

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: 【前端面试题】我靠它拿到了大厂Offer

新的一天,加油!

每日一道笔试题,遇见不一样的自己!

第102题:请输出下列代码执行的结果

//参考:忍者秘籍第二版
console.log('script start')
let promise1 = new Promise(function (resolve) {
    console.log('promise1')
    resolve()
    console.log('promise1 end')
}).then(function () {
    console.log('promise2')
})
setTimeout(function(){
    console.log('settimeout')
})
console.log('script end')

解释:

输出结果:script start->promise1->promise1 end->script end->promise2->settimeout

当JS主线程执行到Promise对象时,

  • promise1 是 resolved或rejected: 那这个 task 就会放入当前事件循环队列microtask queue
  • promise1 是 pending: 这个 task 就会放入事件循环队列未来的某个(可能下一个)回合的 microtask queue
  • setTimeout 的回调也是个 task ,它会被放入macrotask queue,即使是 0ms 的情况

第101题:请输出下列代码执行的结果

//参考:忍者秘籍第二版
async function async1(){
   console.log('async1 start');
    await async2();
    console.log('async1 end')
}
async function async2(){
    console.log('async2')
}
console.log('script start');
async1();
console.log('script end')

解释:

输出结果:script start->async1 start->async2->script end->async1 end
  • async 函数返回一个 Promise 对象(await通过返回一个Promise对象来实现同步的效果),当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再执行函数体内后面的语句。可以理解为,是让出了线程,跳出了 async 函数体。
  • await的含义为等待,也就是 async 函数需要等待await后的函数执行完成并且有了返回结果(Promise对象)之后,才能继续执行下面的代码。

第100题:请解释下列三个方法在判断 是否是数组类型 时的区别:

- Object.prototype.toString.call()
- instanceof
- Array.isArray()
参考:js高级程序设计第三版

解释

  1. Object.prototype.toString.call()
    每一个继承 Object 的对象都有 toString 方法,如果 toString 方法没有重写的话,会返回 [Object type],其中 type 为对象的类型。但是,当除了 Object 类型的对象外,其他类型直接使用 toString 方法时,会直接返回内容的字符串,所以我们需要使用call或者apply方法来改变toString方法的执行上下文

例如:

const arr = ['abc','bca'];
arr.toString(); // "abc,bca"
Object.prototype.toString.call(arr); // "[object Array]"
  • 结论:这种方法对于所有基本的数据类型都能进行判断,即使是 null 和 undefined 。通常,该方法常用于判断浏览器内置对象。
  1. instanceof
    instanceof 的内部机制是通过判断对象的原型链中是不是能找到类型的 prototype。
    使用 instanceof判断一个对象是否为数组,instanceof 会判断这个对象的原型链上是否会找到对应的 Array 的原型,找到返回 true,否则返回 false
[]  instanceof Array; // true
  1. instanceof 只能用来判断对象类型,原始类型不可以。并且所有对象类型 instanceof Object 都是 true。
    例如:
[]  instanceof Object; // true
  1. Array.isArray()
    Array.isArray()是ES5新增的方法,当不存在 Array.isArray() ,可以用 Object.prototype.toString.call() 实现。
if (!Array.isArray) {
  Array.isArray = function(arg) {
    return Object.prototype.toString.call(arg) === '[object Array]';
  };
}
  1. 同时,Array.isArray()优于instanceof,特别是在检测Array实例时,Array.isArray可以检测出iframes下的Array实例。

例如:

let iframe = document.createElement('iframe');
document.body.appendChild(iframe);
xArray = window.frames[window.frames.length-1].Array;
let arr = new xArray(1,2,3); // [1,2,3]
Array.isArray(arr);  // true
arr instanceof Array; // false

第99题:实现下列功能

输入: [2,3,4,6,7,9]
输出: '2~4,6~7,9'
const nums = [2,3,4,6,7,9];
function example(num) {
  let result = [];
  let temp = num[0]
  num.forEach((value, index) => {
    if (value + 1 !== num[index + 1]) {
      if (temp !== value) {
        result.push(`${temp}~${value}`)
      } else {
        result.push(`${value}`)
      }
      temp = num[index + 1]
    }
  })
  return result;
}
console.log(example(nums).join(','))

第98题:如何优化浏览器的Repaint和Reflow

第97题:解释下Vue是如何进行双向数据绑定的?View->Model和Model-View,原理是什么

第96题:输出下列代码执行结果

String('123') == new String('123'); //true,==时做了隐式转换,调用了toString
String('123') === new String('123');//false,两者的类型不一样,前者是string,后者是object
var name = 'abc';
(function() {
    if (typeof name == 'undefined') {
        name = 'cba';
        console.log(name);
    } else {
        console.log(name);
    }
})();
1、首先进入立即执行函数作用域当中,获取name属性
2、在当前作用域没有找到name
3、通过作用域链找到最外层,得到name属性
4、执行else的内容,输出 abc

第95题:输出下列代码执行结果

2 + "3";
3 * "5";
[6, 3] + [3, 6];
"b" + + "c";  

//解释:

2 + "3";
加性操作符:如果只有一个操作数是字符串,则将另一个操作数转换为字符串,然后再将两个字符串拼接起来
所以值为:“23”
3 * "5";
乘性操作符:如果有一个操作数不是数值,则在后台调用 Number()将其转换为数值
[6, 3] + [3, 6];
Javascript中所有对象基本都是先调用valueOf方法,如果不是数值,再调用toString方法。
所以两个数组对象的toString方法相加,值为:"6,33,6"
"b" + + "c"; 
后边的“+”将作为一元操作符,如果操作数是字符串,将调用Number方法将该操作数转为数值,如果操作数无法转为数值,则为NaN。
所以值为:"bNaN"

第94题:写出如下代码的打印结果

function Foo() {
    Foo.a = function() {
        console.log(1)
    }
    this.a = function() {
        console.log(2)
    }
}
Foo.prototype.a = function() {
    console.log(3)
}
Foo.a = function() {
    console.log(4)
}
Foo.a();
let obj = new Foo();
obj.a();
Foo.a();
  • 解析
function Foo() {
    Foo.a = function() {
        console.log(1)
    }
    this.a = function() {
        console.log(2)
    }
}
// 以上只是 Foo 的构建方法,没有产生实例,此刻也没有执行
Foo.prototype.a = function() {
    console.log(3)
}
// 现在在 Foo 上挂载了原型方法 a ,方法输出值为 3
Foo.a = function() {
    console.log(4)
}
// 现在在 Foo 上挂载了直接方法 a ,输出值为 4
Foo.a();
// 立刻执行了 Foo 上的 a 方法,也就是刚刚定义的,所以
// # 输出 4
let obj = new Foo();
/* 这里调用了 Foo 的构建方法。Foo 的构建方法主要做了两件事:
1. 将全局的 Foo 上的直接方法 a 替换为一个输出 1 的方法。
2. 在新对象上挂载直接方法 a ,输出值为 2。
*/
obj.a();
// 因为有直接方法 a ,不需要去访问原型链,所以使用的是构建方法里所定义的 this.a,
// # 输出 2
Foo.a();
// 构建方法里已经替换了全局 Foo 上的 a 方法,所以
// # 输出 1

第93题:用 JavaScript 写一个函数,输入 int 型,返回整数逆序后的字符串。

如:输入整型 1234,返回字符串“4321”。要求必须使用递归函数调用,不能用全局变量,输入函数必须只有一个参数传入,必须返回字符串。

function fun(num){
    let num1 = num / 10;
    let num2 = num % 10;
    if(num1<1){
        return num;
    }else{
        num1 = Math.floor(num1)
        return `${num2}${fun(num1)}`
    }
}
var a = fun(12345)
console.log(a)

第92题:写出如下代码的打印结果

function changeObjProperty(o) {
  o.siteUrl = "http://www.baidu.com"
  o = new Object()
  o.siteUrl = "http://www.google.com"
} 
let webSite = new Object();
changeObjProperty(webSite);
console.log(webSite.siteUrl);

输出:www.baidu.com //原因:函数的形参是值传递的

第91题:前端加密的常见场景和方法

加密的目的,简而言之就是将明文转换为密文、甚至转换为其他的东西,用来隐藏明文内容本身,防止其他人直接获取到敏感明文信息、或者提高其他人获取到明文信息的难度。

通常我们提到加密会想到密码加密、HTTPS 等关键词

场景-密码传输

前端密码传输过程中如果不加密,在日志中就可以拿到用户的明文密码,对用户安全不太负责。

这种加密其实相对比较简单,可以使用 PlanA-前端加密、后端解密后计算密码字符串的MD5/MD6存入数据库;也可以 PlanB-直接前端使用一种稳定算法加密成唯一值、后端直接将加密结果进行MD5/MD6,全程密码明文不出现在程序中。

  • PlanA
    使用 Base64 / Unicode+1 等方式加密成非明文,后端解开之后再存它的 MD5/MD6
  • PlanB
    直接使用 MD5/MD6 之类的方式取 Hash ,让后端存 Hash 的 Hash 。

场景-数据包加密

应该大家有遇到过:打开一个正经网站,网站底下蹦出个不正经广告——比如X通的流量浮层,X信的插入式广告……(我没有针对谁)

但是这几年,我们会发现这种广告逐渐变少了,其原因就是大家都开始采用 HTTPS 了。

被人插入这种广告的方法其实很好理解:你的网页数据包被抓取->在数据包到达你手机之前被篡改->你得到了带网页广告的数据包->渲染到你手机屏幕。

而 HTTPS 进行了包加密,就解决了这个问题。严格来说我认为从手段上来看,它不算是一种前端加密场景;但是从解决问题的角度来看,这确实是前端需要知道的事情。

  • Plan
    全面采用 HTTPS

场景-展示成果加密

经常有人开发网页爬虫爬取大家辛辛苦苦一点一点发布的数据成果,有些会影响你的竞争力,有些会降低你的知名度,甚至有些出于恶意爬取你的公开数据后进行全量公开……比如有些食谱网站被爬掉所有食谱,站点被克隆;有些求职网站被爬掉所有职位,被拿去卖信息;甚至有些小说漫画网站赖以生存的内容也很容易被爬取。

  • Plan
    将文本内容进行展示层加密,利用字体的引用特点,把拿给爬虫的数据变成“乱码”。
    举个栗子:正常来讲,当我们拥有一串数字“12345”并将其放在网站页面上的时候,其实网站页面上显示的并不是简单的数字,而是数字对应的字体的“12345”。这时我们打乱一下字体中图形和字码的对应关系,比如我们搞成这样:

图形:1 2 3 4 5

字码:2 3 1 5 4

这时,如果你想让用户看到“12345”,你在页面中渲染的数字就应该是“23154”。这种手段也可以算作一种加密。

具体的实现方法可以看一下《Web 端反爬虫技术方案》

参考

第90题:模拟实现一个深拷贝,并考虑对象相互引用以及 Symbol 拷贝的情况

一个不考虑其他数据类型的公共方法,基本满足大部分场景

function deepCopy(target, cache = new Set()) {
  if (typeof target !== 'object' || cache.has(target)) {
    return target
  }
  if (Array.isArray(target)) {
    target.map(t => {
      cache.add(t)
      return t
    })
  } else {
    return [...Object.keys(target), ...Object.getOwnPropertySymbols(target)].reduce((res, key) => {
      cache.add(target[key])
      res[key] = deepCopy(target[key], cache)
      return res
    }, target.constructor !== Object ? Object.create(target.constructor.prototype) : {})
  }
}

主要问题是

  1. symbol作为key,不会被遍历到,所以stringifyparse是不行的
  2. 有环引用,stringifyparse也会报错
    我们另外用getOwnPropertySymbols可以获取symbol key可以解决问题1,用集合记忆曾经遍历过的对象可以解决问题2。当然,还有很多数据类型要独立去拷贝。比如拷贝一个RegExp,lodash是最全的数据类型拷贝了,有空可以研究一下

另外,如果不考虑用symbolkey,还有两种黑科技深拷贝,可以解决环引用的问题,比stringifyparse优雅强一些。

function deepCopyByHistory(target) {
  const prev = history.state
  history.replaceState(target, document.title)
  const res = history.state
  history.replaceState(prev, document.title)
  return res
}
async function deepCopyByMessageChannel(target) {
  return new Promise(resolve => {
    const channel = new MessageChannel()
    channel.port2.onmessage = ev => resolve(ev.data)
    channel.port1.postMessage(target)
  }).then(data => data)
}

无论哪种方法,它们都有一个共性:失去了继承关系,所以剩下的需要我们手动补上去了,故有Object.create(target.constructor.prototype)的操作

第89题:vue 在 v-for 时给每项元素绑定事件需要用事件代理吗?为什么?

事件代理作用主要是 2 个:

  1. 将事件处理程序代理到父节点,减少内存占用率
  2. 动态生成子节点时能自动绑定事件处理程序到父节点
//不使用事件代理,每个 span 节点绑定一个 click 事件,并指向同一个事件处理程序
<div>
      <span 
        v-for="(item,index) of 100000" 
        :key="index" 
        @click="handleClick">
        {{item}}
      </span>
 </div>
//不使用事件代理,每个 span 节点绑定一个 click 事件,并指向不同的事件处理程序 
<div>
      <span 
        v-for="(item,index) of 100000" 
        :key="index" 
        @click="function () {}">
        {{item}}
      </span>
</div>
// 使用事件代理
<div  @click="handleClick">
      <span 
        v-for="(item,index) of 100000"  
        :key="index">
        {{item}}
      </span>
</div>
使用事件代理无论是监听器数量和内存占用率都比前两者要少

第88题:给定两个大小为m和n的有序数组nums1和nums2。 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))

const findMidNum = function(arr1,arr2) {
    for(let i=0;i<arr2.length;i++) {
        arr1.push(arr2[i]);
    }
    arr1 = arr1.sort((a,b)=>{return b-a;})
    if(arr1.length%2===0) {
        return (arr1[arr1.length/2]+arr1[arr1.length/2-1])/2
    }else {
        return arr1[(arr1.length-1)/2]
    }
}
console.log(findMidNum([1,2],[3,5,6]))

第87题:已知数据格式,实现一个函数 fn 找出链条中所有的父级 id

const data = [{
    id: '1',
    name: 'test1',
    children: [
        {
            id: '11',
            name: 'test11',
            children: [
                {
                    id: '111',
                    name: 'test111'
                },
                {
                    id: '112',
                    name: 'test112'
                }
            ]
        },
        {
            id: '12',
            name: 'test12',
            children: [
                {
                    id: '121',
                    name: 'test121'
                },
                {
                    id: '122',
                    name: 'test122'
                }
            ]
        }
    ]
}];
let res = [];
const findId = (list, value) => {
  let len = list.length;
  for (let i in list) {
    const item = list[i];
    if (item.id == value) {
      return res.push(item.id), [item.id];
    }
    if (item.children) {
      if (findId(item.children, value).length) {
        res.unshift(item.id);
        return res;
      }
    }
    if (i == len - 1) {
      return res;
    }
  }
};

第86题:介绍下 HTTPS 中间人攻击

中间人攻击过程如下:

  1. 服务器向客户端发送公钥。
  2. 攻击者截获公钥,保留在自己手上。
  3. 然后攻击者自己生成一个【伪造的】公钥,发给客户端。
  4. 客户端收到伪造的公钥后,生成加密hash值发给服务器。
  5. 攻击者获得加密hash值,用自己的私钥解密获得真秘钥。
  6. 同时生成假的加密hash值,发给服务器。
  7. 服务器用私钥解密获得假秘钥。
  8. 服务器用加秘钥加密传输信息 。

防范方法:

服务端在发送浏览器的公钥中加入CA证书,浏览器可以验证CA证书的有效性


第85题:实现模糊搜索结果的关键词高亮显示

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>auto complete</title>
  <style>
    bdi {
      color: rgb(0, 136, 255);
    }
    li {
      list-style: none;
    }
  </style>
</head>
<body>
  <input class="inp" type="text">
  <section>
    <ul class="container"></ul>
  </section>
</body>
<script>
  function debounce(fn, timeout = 300) {
    let t;
    return (...args) => {
      if (t) {
        clearTimeout(t);
      }
      t = setTimeout(() => {
        fn.apply(fn, args);
      }, timeout);
    }
  }
  function memorize(fn) {
    const cache = new Map();
    return (name) => {
      if (!name) {
        container.innerHTML = '';
        return;
      }
      if (cache.get(name)) {
        container.innerHTML = cache.get(name);
        return;
      }
      const res = fn.call(fn, name).join('');
      cache.set(name, res);
      container.innerHTML = res;
    }
  }
  function handleInput(value) {
    const reg = new RegExp(`\(${value}\)`);
    const search = data.reduce((res, cur) => {
      if (reg.test(cur)) {
        const match = RegExp.$1;
        res.push(`<li>${cur.replace(match, '<bdi>$&</bdi>')}</li>`);
      }
      return res;
    }, []);
    return search;
  }
  const data = ["上海野生动物园", "上饶野生动物园", "北京巷子", "上海中心", "上海黄埔江", "迪士尼上海", "陆家嘴上海中心"]
  const container = document.querySelector('.container');
  const memorizeInput = memorize(handleInput);
  document.querySelector('.inp').addEventListener('input', debounce(e => {
    memorizeInput(e.target.value);
  }))
</script>
</html>

第84题:设计并实现 Promise.race()

Promise.myrace = function(iterator) {
    return new Promise ((resolve,reject) => {
        try {
            let it = iterator[Symbol.iterator]();
            while(true) {
                let res = it.next();
                console.log(res);
                if(res.done) break;
                if(res.value instanceof Promise) {
                    res.value.then(resolve,reject);
                } else {
                    resolve(res.value)
                }
            }
        } catch (error) {
            reject(error)
        }
    }) 
}

第83题:实现 convert 方法,把原始 list 转换成树形结构,要求尽可能降低时间复杂度

先生成新结构map,用原先的结构与其比较,对原结构改造。

function convert(list) {
      const res = []
      const map = list.reduce((res, v) => (res[v.id] = v, res), {})
      for (const item of list) {
        if (item.parentId === 0) {
          res.push(item)
          continue
        }
        if (item.parentId in map) {
          const parent = map[item.parentId]
          parent.children = parent.children || []
          parent.children.push(item)
        }
      }
      return res
    }
    let list =[
        {id:1,name:'部门A',parentId:0},
        {id:2,name:'部门B',parentId:0},
        {id:3,name:'部门C',parentId:1},
        {id:4,name:'部门D',parentId:1},
        {id:5,name:'部门E',parentId:2},
        {id:6,name:'部门F',parentId:3},
        {id:7,name:'部门G',parentId:2},
        {id:8,name:'部门H',parentId:4}
    ];
    const result = convert(list);
    console.table(result);

第82题:在输入框中如何判断输入的是一个正确的网址

主要解析http,https

function isUrl(url) {
  const a = document.createElement('a')
  a.href = url
  return [
    /^(http|https):$/.test(a.protocol),
    a.host,
    a.pathname !== url,
    a.pathname !== `/${url}`,
  ].find(x => !x) === undefined
}

第81题:算法题之–两数之和

给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。

你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。

示例:

给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
  • 解析

(1). 直接遍历两次数组

//:时间复杂度为O(N*N)
find2Num([2,7,11,15],9);
function find2Num(arr,sum){
    if(arr == '' || arr.length == 0){
        return false;
    }
  let result = [];
    for(var i = 0; i < arr.length ; i++){
        for(var j = i + 1; j <arr.length; j++){
            if(arr[i] + arr[j] == sum){
              result.push(i);
              result.push(j);
            }
        }
    }
    console.log(result);
}

(2)

先将整型数组排序,排序之后定义两个指针left和right。

left指向已排序数组中的第一个元素,right指向已排序数组中的最后一个元素, 将 arr[left]+arr[right]与

给定的元素比较,若前者大,right–;若前者小,left++; 若相等,则找到了一对整数之和为指定值的元素。

//时间复杂度为O(NlogN)
function find2Num(arr,sum){
    if(arr == '' || arr.length == 0){
        return false;
    }
    var left = 0, right = arr.length -1,result = [];
    while(left < right){
        if(arr[left] + arr[right] > sum){
            right--;
        }
        else if(arr[left] + arr[right] < sum){
            left++;
        }
        else{
            console.log(arr[left] + " + " + arr[right] + " = " + sum); 
            result.push(left);
            result.push(right);
            left++;
            right--;
        }
    }
    console.log(result);
}

第80题:react-router 里的 标签和 标签有什么区别

  • <Link>react-router 里实现路由跳转的链接,一般配合 <Route> 使用,react-router 接管了其默认的链接跳转行为,区别于传统的页面跳转,<Link> 的“跳转”行为只会触发相匹配的 <Route> 对应的页面内容更新,而不会刷新整个页面。

Link点击事件handleClick部分源码:

if (_this.props.onClick) _this.props.onClick(event);
      if (!event.defaultPrevented && // onClick prevented default
      event.button === 0 && // ignore everything but left clicks
      !_this.props.target && // let browser handle "target=_blank" etc.
      !isModifiedEvent(event) // ignore clicks with modifier keys
      ) {
          event.preventDefault();
          var history = _this.context.router.history;
          var _this$props = _this.props,
              replace = _this$props.replace,
              to = _this$props.to;
          if (replace) {
            history.replace(to);
          } else {
            history.push(to);
          }
        }

Link做了3件事情:

  1. 有onclick那就执行onclick
  2. click的时候阻止a标签默认事件(这样子点击<a href="/abc">123</a>就不会跳转和刷新页面)
  3. 再取得跳转href(即是to),用history(前端路由两种方式之一,history & hash)跳转,此时只是链接变了,并没有刷新页面
  • <a> 标签就是普通的超链接了,用于从当前页面跳转到 href 指向的另一个页面(非锚点情况)。

如何禁掉 <a> 标签默认事件,禁掉之后如何实现跳转

  • 禁掉 a 标签的默认事件,可以在点击事件中执行 event.preventDefault();
  • 禁掉默认事件的 a 标签 可以使用 history.pushState() 来改变页面 url,这个方法还会触发页面的 hashchange 事件,Router 内部通过捕获监听这个事件来处理对应的跳转逻辑。


相关文章
|
3天前
|
缓存 前端开发 JavaScript
"面试通关秘籍:深度解析浏览器面试必考问题,从重绘回流到事件委托,让你一举拿下前端 Offer!"
【10月更文挑战第23天】在前端开发面试中,浏览器相关知识是必考内容。本文总结了四个常见问题:浏览器渲染机制、重绘与回流、性能优化及事件委托。通过具体示例和对比分析,帮助求职者更好地理解和准备面试。掌握这些知识点,有助于提升面试表现和实际工作能力。
13 1
|
2月前
|
Web App开发 前端开发 Linux
「offer来了」浅谈前端面试中开发环境常考知识点
该文章归纳了前端开发环境中常见的面试知识点,特别是围绕Git的使用进行了详细介绍,包括Git的基本概念、常用命令以及在团队协作中的最佳实践,同时还涉及了Chrome调试工具和Linux命令行的基础操作。
「offer来了」浅谈前端面试中开发环境常考知识点
|
3月前
|
存储 XML 移动开发
前端大厂面试真题
前端大厂面试真题
|
14天前
|
Web App开发 JavaScript 前端开发
前端Node.js面试题
前端Node.js面试题
|
2月前
|
存储 移动开发 前端开发
「offer来了」面试中必考的15个html知识点
该文章汇总了前端面试中常见的15个HTML知识点,涵盖了从HTML文档的规范书写、doctype声明的作用到新兴的HTML5标签应用及移动端viewport设置等内容,旨在帮助求职者更好地准备相关技术面试。
「offer来了」面试中必考的15个html知识点
|
2月前
|
Web App开发 前端开发 JavaScript
「offer来了」1张思维导图,6大知识板块,带你梳理面试中CSS的知识点!
该文章通过一张思维导图和六大知识板块系统梳理了前端面试中涉及的CSS核心知识点,包括CSS框架、基础样式问题、布局技巧、动画处理、浏览器兼容性及性能优化等方面的内容。
|
3月前
|
存储 前端开发 JavaScript
44 个 React 前端面试问题
【8月更文挑战第18天】
46 2
|
3月前
|
存储 JavaScript 前端开发
2022年前端js面试题
2022年前端js面试题
36 0
|
3月前
|
存储 前端开发 JavaScript
44 个 React 前端面试问题
44 个 React 前端面试问题
|
14天前
|
存储 人工智能 前端开发
前端大模型应用笔记(三):Vue3+Antdv+transformers+本地模型实现浏览器端侧增强搜索
本文介绍了一个纯前端实现的增强列表搜索应用,通过使用Transformer模型,实现了更智能的搜索功能,如使用“番茄”可以搜索到“西红柿”。项目基于Vue3和Ant Design Vue,使用了Xenova的bge-base-zh-v1.5模型。文章详细介绍了从环境搭建、数据准备到具体实现的全过程,并展示了实际效果和待改进点。