2023年11月28日发(作者:)
100道前端近年⾯试题(内含详细答案)
⼗⼀.作⽤域链
function a(){
var n=0;
function b(){
(n);
}
return b;
}
var fn=a();//fn获得b函数的引⽤
var n=1;
fn();//fn()相当于执⾏b(),结果是0
(作⽤域是在创建定义的时候就确定了的,函数创建在谁的作⽤域下,谁就是它的⽗作⽤域 ,该例⼦中b函数的⽗作⽤域是a函数,a函数的
作⽤域是全局)因此js在寻找的时候,就会沿着这条线寻找下去,哪⾥找到就哪⾥停⽌寻找,直到全局还找不到,就表⽰不存在。⽽这条
线,便叫做作⽤域链。
基础:
java的作⽤域是是以块区分的,也就是{},这个没啥说的。
⽽JavaScript的作⽤域,是以⽅法来区分的。
javascript并没有所谓的块级作⽤域,javascript的作⽤域是相对函数⽽⾔的,可以称为*函数作⽤域*
变量的作⽤域:
全局作⽤域和局部作⽤域(函数内部声明变量的时候,⼀定要使⽤var命令)
只要函数内定义了⼀个局部变量,函数在解析的时候都会将这个变量“提前声明”
⼗⼆.购物车的实现过程(包括怎么布局,可以⽤vue、react、jq等)
购物清单:全选、商品、数量、单价、⾦额、操作
删除所选商品、继续购物、去结算、绑定跟单员
Js实现淘宝购物车类似功能:
主要有添加商品
增加和减少商品数量
根据增加、减少或选择的商品获取⾦额
实现商品价格的计算
全选按钮:
这⾥⽤⼀个computed(计算属性)就好(如果productList中每⼀条数据的select都为true,
返回true,否则返回false;)。
⼗三.购物车详情页优化(⽤户商品加⼊太多导致页⾯卡顿)(懒加载、分页)
初始第⼀屏图⽚>获取滚动条的滚动距离和⽬录对象离 document ⽂档顶部的距离>若前者⼤于后者,滚动时执⾏加载图⽚的⽅法>按需加载
图⽚
= function () {
var lazyImg = mentsByTagName("img");
var lazyImgLen = ;
var lazyImgArray = [];
var winowBroswerHeight = Height;
// 初始第⼀屏图⽚
loadImg();
// 滚动时执⾏加载图⽚的⽅法
ll = loadImg;
// 按需加载图⽚
function loadImg() {
for (var i = 0; i < lazyImgLen; i++) {
var getTD = getTopDistance(lazyImg[i]);
var getST = getScrollTop();
if (!lazyImg[i].loaded && getST < getTD && getTD < (getST + winowBroswerHeight)) {
lazyImg[i].src = lazyImg[i].getAttribute("_src");
lazyImg[i].("animated", "fadeIn");
lazyImg[i].loaded = true; // 标记为已加载
}
}
}
// 获取⽬录对象离 document ⽂档顶部的距离
function getTopDistance(obj) {
var TopDistance = 0;
while (obj) {
TopDistance += Top;
obj = Parent;
}
return TopDistance;
}
// 获取滚动条的滚动距离
function getScrollTop() {
return Top || Top;
}
}
⼗四.页⾯渲染过程
渲染时,⼤致的流程如下:
(解析html以构建dom树->解析CSS,得到CSSOM树->构建render树->布局render树->绘制render树)
具体的流程如下:
1:浏览器会将HTML解析成⼀个DOM树,DOM树的构建过程是⼀个深度遍历过程,
当前节点的所有⼦节点都构建好后才会去构建当前节点的下⼀个兄弟节点,
2:将CSS解析成CSS规则树;
3:根据DOM树和CSS来构造render树,渲染树不等于DOM树,像header和display:none;
这种没有具体内容的东西就不在渲染树中;
4:根据render树,浏览器可以计算出⽹页中有哪些节点,各节点的CSS以及从属关系,
然后可以计算出每个节点在屏幕中的位置;
5:遍历render树进⾏绘制页⾯中的各元素。
页⾯发⽣重排(回流)的话,会重新加载DOM树,影响页⾯加载速度。会导致页⾯重排的原因如下:
1:页⾯初始化;
2:操作DOM时;
3:某些元素的尺⼨变了;
因为其他位置会推迟或者意外的进⾏预渲染。
具体原因:解析到body中的第⼀脚本前,浏览器就会认为已经解析得差不多了,可以进⾏⼀次预渲染。所以script如果放在head⾥,会推迟预渲染。如果放在b
ody的⼀开头,后⾯的⼀⼤堆标签还没解析,等于欺骗浏览器说已经“差不多了”,也就等于违背了设计预渲染的初衷,会影响页⾯的效果。放在body中间也是⼀
样的道理,所以还是放在最尾巴上⽐较好。
⼗五.闭包
函数和对其周围状态的引⽤捆绑在⼀起构成闭包。也就是说,闭包可以让你从内部函数访问外部函数作⽤域。在 JavaScript 中,每当函数
被创建,就会在函数⽣成时⽣成闭包。
闭包很有⽤,因为它允许将函数与其所操作的某些数据(环境)关联起来。这显然类似于⾯向对象编程。因此,通常你使⽤只有⼀个⽅法的
对象的地⽅,都可以使⽤闭包。
function makeAdder(x) {
return function(y) {
return x + y;
};
}
var add5 = makeAdder(5);
var add10 = makeAdder(10);
(add5(2)); // 7
(add10(2)); // 12
//add5 和 add10 都是闭包。它们共享相同的函数定义,但是保存了不同的词法环境。
在 add5 的环境中,x 为 5。⽽在 add10 中,x 则为 10。
⼗六.http协议
http(超⽂本传输协议)是⼀个基于请求与响应模式的、⽆状态的、应⽤层的协议,常基于TCP的连接⽅式
http请求由三部分组成,分别是:请求⾏、消息报头、请求正⽂
HTTP消息报头包括普通报头、请求报头、响应报头、实体报头。
HTTP协议的主要特点可概括如下:
1.⽀持客户/服务器模式。
2.简单快速:客户向服务器请求服务时,只需传送请求⽅法和路径。请求⽅法常⽤的有GET、HEAD、POST。每种⽅法规定了客户与服务器联系的类型不同。
由于HTTP协议简单,使得HTTP服务器的程序规模⼩,因⽽通信速度很快。
3.灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
4.⽆连接:⽆连接的含义是限制每次连接只处理⼀个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采⽤这种⽅式可以节省传输时间。
5.⽆状态:HTTP协议是⽆状态协议。⽆状态是指协议对于事务处理没有记忆能⼒。缺少状态意味着如果后续处理需要前⾯的信息,则它必须重传,这样可能导
致每次连接传送的数据量增⼤。另⼀⽅⾯,在服务器不需要先前信息时它的应答就较快。
请求⽅法(所有⽅法全为⼤写)有多种,各个⽅法的解释如下:
GET 请求获取Request-URI所标识的资源
POST 在Request-URI所标识的资源后附加新的数据
HEAD 请求获取由Request-URI所标识的资源的响应消息报头
PUT 请求服务器存储⼀个资源,并⽤Request-URI作为其标识
DELETE 请求服务器删除Request-URI所标识的资源
TRACE 请求服务器回送收到的请求信息,主要⽤于测试或诊断
CONNECT 保留将来使⽤
OPTIONS 请求查询服务器的性能,或者查询与资源相关的选项和需求
状态代码有三位数字组成,第⼀个数字定义了响应的类别,且有五种可能取值:
1xx:指⽰信息--表⽰请求已接收,继续处理
2xx:成功--表⽰请求已被成功接收、理解、接受
3xx:重定向--要完成请求必须进⾏更进⼀步的操作
4xx:客户端错误--请求有语法错误或请求⽆法实现
5xx:服务器端错误--服务器未能实现合法的请求
常见状态代码、状态描述、说明:
200 OK //客户端请求成功
400 Bad Request //客户端请求有语法错误,不能被服务器所理解
401 Unauthorized //请求未经授权,这个状态代码必须和WWW-Authenticate报头域⼀起使⽤
403 Forbidden //服务器收到请求,但是拒绝提供服务
404 Not Found //请求资源不存在,eg:输⼊了错误的URL
500 Internal Server Error //服务器发⽣不可预期的错误
503 Server Unavailable //服务器当前不能处理客户端的请求,⼀段时间后可能恢复正常
⼗七.http中的⽅法,除了get⽅法、post⽅法
请求⽅法(所有⽅法全为⼤写)有多种,各个⽅法的解释如下:
GET 请求获取Request-URI所标识的资源
POST 在Request-URI所标识的资源后附加新的数据
HEAD 请求获取由Request-URI所标识的资源的响应消息报头
PUT 请求服务器存储⼀个资源,并⽤Request-URI作为其标识
DELETE 请求服务器删除Request-URI所标识的资源
TRACE 请求服务器回送收到的请求信息,主要⽤于测试或诊断
CONNECT 保留将来使⽤
OPTIONS 请求查询服务器的性能,或者查询与资源相关的选项和需求
⼗⼋.数据结构(排序算法,冒泡以外的)
数据结构是指相互之间存在着⼀种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成 。常⽤的数据结构有:数组,栈,链
表,队列,树,图,堆,散列表(哈希表)
⼗⼤经典算法排序总结对⽐:
冒泡排序(正序最快,反序最慢):
function bubbleSort(arr) {
var len = ;
for (var i = 0; i < len; i++) {
for (var j = 0; j < len - 1 - i; j++) {
if (arr[j] > arr[j+1]) { //相邻元素两两对⽐
var temp = arr[j+1]; //元素交换
arr[j+1] = arr[j];
function shellSort(arr) {
var len = ,
temp,
gap = 1;
while(gap < len/3) { //动态定义间隔序列
gap =gap*3+1;
}
for (gap; gap > 0; gap = (gap/3)) {
for (var i = gap; i < len; i++) {
temp = arr[i];
for (var j = i-gap; j >= 0 && arr[j] > temp; j-=gap) {
arr[j+gap] = arr[j];
}
arr[j+gap] = temp;
}
}
return arr;
}
2、数据流的不同
Vue中默认是⽀持双向绑定的。在Vue1.0中我们可以实现两种双向绑定:
1.⽗⼦组件之间,props 可以双向绑定(Vue2.x 中去掉了第⼀种)
2.组件与DOM之间可以通过 v-model 双向绑定
React 从诞⽣之初就不⽀持双向绑定,React⼀直提倡的是单向数据流,他称之为 onChange/setState()模式。
3、mixins 和 HoC
在 Vue 中我们组合不同功能的⽅式是通过 mixin,⽽在React中我们通过 HoC (⾼阶组件)。
4、组件通信的区别
在Vue 中有三种⽅式可以实现组件通信:
1.⽗组件通过 props 向⼦组件传递数据或者回调,虽然可以传递回调,但是我们⼀般只传数据,⽽通过 事件的机制来处理⼦组件向⽗组件的通信
2.⼦组件通过 事件 向⽗组件发送消息
3.通过 V2.2.0 中新增的 provide/inject 来实现⽗组件向⼦组件注⼊数据,可以跨越多个层级。
在 React 中,也有对应的两种⽅式:
1.⽗组件通过 props 可以向⼦组件传递数据或者回调
2.可以通过 context 进⾏跨层级的通信,这其实和 provide/inject 起到的作⽤差不多。
可以看到,React 本⾝并不⽀持⾃定义事件,Vue中⼦组件向⽗组件传递消息有两种⽅式:事件和回调函数,⽽且Vue更倾向于使⽤事件。
但是在 React 中我们都是使⽤回调函数的,这可能是他们⼆者最⼤的区别。
5、模板渲染⽅式的不同
在表层上, 模板的语法不同
Vue是通过⼀种拓展的HTML语法进⾏渲染。
React 是通过JSX渲染模板(表⾯现象,毕竟React并不必须依赖JSX。);
在深层上,模板的原理不同,这才是他们的本质区别:
Vue是在和组件JS代码分离的单独的模板中,通过指令来实现的,
⽐如条件语句就需要 v-if 来实现。
React是在组件JS代码中,通过原⽣JS实现模板中的常见语法,
⽐如插值,条件,循环等,都是通过JS语法实现的;
React的好处:
react中render函数是⽀持闭包特性的,所以我们import的组件在render中可以直接调⽤。但是在Vue中,由于模板中使⽤的数据都必须挂
在 this 上进⾏⼀次中转,所以我们import ⼀个组件完了之后,还需要在 components 中再声明下,这样显然是很奇怪但⼜不得不这样的
做法。
6、Vuex 和 Redux 的区别
从表⾯上来说,store 注⼊和使⽤⽅式有⼀些区别。
在 Vuex 中,$store 被直接注⼊到了组件实例中,因此可以⽐较灵活的使⽤:
使⽤ dispatch 和 commit 提交更新;
通过 mapState 或者直接通过 this.$store 来读取数据。
在 Redux 中,我们每⼀个组件都需要显⽰的⽤ connect 把需要的 props 和 dispatch 连接起来。另外 Vuex 更加灵活⼀些,组件中既可以 dispatch action 也可
以 commit updates,⽽ Redux 中只能进⾏ dispatch,并不能直接调⽤ reducer 进⾏修改。
从实现原理上来说,最⼤的区别是两点:
使⽤的是不可变数据,⽽Vuex的数据是可变的。Redux每次都是⽤新的state替换旧的state,⽽Vuex是直接修改
其实和Vue的原理⼀样,是通过 getter/setter来⽐较的(如果看Vuex源码会知道,其实他内部直接创建⼀个Vue实例⽤来跟踪数据变化)Redux 在检测数
据变化的时候,是通过 diff 的⽅式⽐较差异的,⽽
相⽐之下,Vue更偏向于简单迅速的解决问题,更灵活,不那么严格遵循条条框框。因此也会给⼈⼀种⼤型项⽬⽤React,⼩型项⽬⽤ Vue
的感觉。
⼆⼗.⽹页上哪⾥可以看到请求的所有信息
审查元素>network
拓展更多⾯试题(100道前端⾯试题练⼿):
发布评论