前端经典面试题(58道前端面试题包含JS、CSS、React、程序题等)

简答题
1、什么是防抖和节流?有什么区别?如何实现?
参考答案
防抖
触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间
思路:
每次触发事件时都取消之前的延时调用方法

function debounce(fn) {
let timeout = null; // 创建一个标记用来存放定时器的返回值
return function () {
clearTimeout(timeout); // 每当用户输入的时候把前一个 setTimeout clear 掉
timeout = setTimeout(() => { // 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 interval 间隔内如果还有字符输入的话,就不会执行 fn 函数
fn.apply(this, arguments);
}, 500);
};
}
function sayHi() {
console.log('防抖成功');
}
var inp = document.getElementById('inp');
inp.addEventListener('input', debounce(sayHi)); // 防抖
节流
高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率
思路:
每次触发事件时都判断当前是否有等待执行的延时函数
function throttle(fn) {
let canRun = true; // 通过闭包保存一个标记
return function () {
if (!canRun) return; // 在函数开头判断标记是否为true,不为true则return
canRun = false; // 立即设置为false
setTimeout(() => { // 将外部传入的函数的执行放在setTimeout中
fn.apply(this, arguments);
// 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。当定时器没有执行的时候标记永远是false,在开头被return掉
canRun = true;
}, 500);
};
}
function sayHi(e) {
console.log(e.target.innerWidth, e.target.innerHeight);
}
window.addEventListener('resize', throttle(sayHi));
2、 get请求传参长度的误区、get和post请求在缓存方面的区别
误区:我们经常说get请求参数的大小存在限制,而post请求的参数大小是无限制的。
参考答案
实际上HTTP 协议从未规定 GET/POST 的请求长度限制是多少。对get请求参数的限制是来源与浏览器或web服务器,浏览器或web服务器限制了url的长度。为了明确这个概念,我们必须再次强调下面几点:
HTTP 协议 未规定 GET 和POST的长度限制
GET的最大长度显示是因为 浏览器和 web服务器限制了 URI的长度
不同的浏览器和WEB服务器,限制的最大长度不一样
要支持IE,则最大长度为2083byte,若只支持Chrome,则最大长度 8182byte
补充补充一个get和post在缓存方面的区别:
get请求类似于查找的过程,用户获取数据,可以不用每次都与数据库连接,所以可以使用缓存。
post不同,post做的一般是修改和删除的工作,所以必须与数据库交互,所以不能使用缓存。因此get请求适合于请求缓存。
3、模块化发展历程
可从IIFE、AMD、CMD、CommonJS、UMD、webpack(require.ensure)、ES Module、 这几个角度考虑。
参考答案
模块化主要是用来抽离公共代码,隔离作用域,避免变量冲突等。
IIFE: 使用自执行函数来编写模块化,特点:在一个单独的函数作用域中执行代码,避免变量冲突
(function(){
return {
data:[]
}
})()
AMD: 使用requireJS 来编写模块化,特点:依赖必须提前声明好
define('./index.js',function(code){
// code 就是index.js 返回的内容
})
CMD: 使用seaJS 来编写模块化,特点:支持动态引入依赖文件
define(function(require, exports, module) {
var indexCode = require('./index.js');
})
CommonJS: nodejs 中自带的模块化。
var fs = require('fs');
UMD:兼容AMD,CommonJS 模块化语法。
webpack(require.ensure):webpack 2.x 版本中的代码分割。
ES Modules: ES6 引入的模块化,支持import 来引入另一个 js 。
import a from 'a';
4、npm 模块安装机制,为什么输入 npm install 就可以自动安装对应的模块?
参考答案
1. npm 模块安装机制:
发出npm install命令
查询node_modules目录之中是否已经存在指定模块
若存在,不再重新安装
若不存在
npm 向 registry 查询模块压缩包的网址
下载压缩包,存放在根目录下的.npm目录里
解压压缩包到当前项目的node_modules目录
2. npm 实现原理
输入 npm install 命令并敲下回车后,会经历如下几个阶段(以 npm 5.5.1 为例):
执行工程自身 preinstall当前 npm 工程如果定义了 preinstall 钩子此时会被执行。
确定首层依赖模块首先需要做的是确定工程中的首层依赖,也就是 dependencies 和 devDependencies 属性中直接指定的模块(假设此时没有添加 npm install 参数)。
工程本身是整棵依赖树的根节点,每个首层依赖模块都是根节点下面的一棵子树,npm 会开启多进程从每个首层依赖模块开始逐步寻找更深层级的节点。
获取模块
获取模块是一个递归的过程,分为以下几步:
获取模块信息。在下载一个模块之前,首先要确定其版本,这是因为 package.json 中往往是 semantic version(semver,语义化版本)。此时如果版本描述文件(npm-shrinkwrap.json 或 package-lock.json)中有该模块信息直接拿即可,如果没有则从仓库获取。如 packaeg.json 中某个包的版本是 ^1.1.0,npm 就会去仓库中获取符合 1.x.x 形式的最新版本。
获取模块实体。上一步会获取到模块的压缩包地址(resolved 字段),npm 会用此地址检查本地缓存,缓存中有就直接拿,如果没有则从仓库下载。
查找该模块依赖,如果有依赖则回到第1步,如果没有则停止。
模块扁平化(dedupe)
上一步获取到的是一棵完整的依赖树,其中可能包含大量重复模块。比如 A 模块依赖于 loadsh,B 模块同样依赖于 lodash。在 npm3 以前会严格按照依赖树的结构进行安装,因此会造成模块冗余。
从 npm3 开始默认加入了一个 dedupe 的过程。它会遍历所有节点,逐个将模块放在根节点下面,也就是 node-modules 的第一层。当发现有重复模块时,则将其丢弃。
这里需要对重复模块进行一个定义,它指的是模块名相同semver 兼容。每个 semver 都对应一段版本允许范围,如果两个模块的版本允许范围存在交集,那么就可以得到一个兼容版本,而不必版本号完全一致,这可以使更多冗余模块在 dedupe 过程中被去掉。
比如 node-modules 下 foo 模块依赖 lodash@^1.0.0,bar 模块依赖 lodash@^1.1.0,则 ^1.1.0 为兼容版本。
而当 foo 依赖 lodash@^2.0.0,bar 依赖 lodash@^1.1.0,则依据 semver 的规则,二者不存在兼容版本。会将一个版本放在 node_modules 中,另一个仍保留在依赖树里。
举个例子,假设一个依赖树原本是这样:
node_modules
-- foo
---- lodash@version1
-- bar
---- lodash@version2
假设 version1 和 version2 是兼容版本,则经过 dedupe 会成为下面的形式:
node_modules
-- foo
-- bar
-- lodash(保留的版本为兼容版本)
假设 version1 和 version2 为非兼容版本,则后面的版本保留在依赖树中:
node_modules
-- foo
-- lodash@version1
-- bar
---- lodash@version2
安装模块
这一步将会更新工程中的 node_modules,并执行模块中的生命周期函数(按照 preinstall、install、postinstall 的顺序)。
执行工程自身生命周期
当前 npm 工程如果定义了钩子此时会被执行(按照 install、postinstall、prepublish、prepare 的顺序)。
最后一步是生成或更新版本描述文件,npm install 过程完成。
5、ES5的继承和ES6的继承有什么区别?
6、定时器的执行顺序或机制?
7、['1','2','3'].map(parseInt) 输出什么,为什么?
8、Doctype作用? 严格模式与混杂模式如何区分?它们有何意义?
9、fetch发送2次请求的原因
http、浏览器对象 1、HTTPS 握手过程中,客户端如何验证证书的合法性
2、TCP三次握手和四次挥手
3、img iframe script 来发送跨域请求有什么优缺点?
4、http和https的区别?
5、什么是Bom?有哪些常用的Bom属性?
6、Cookie、sessionStorage、localStorage的区别
7、Cookie如何防范XSS攻击
8、浏览器和 Node 事件循环的区别?
9、简述HTTPS中间人攻击
10、说几条web前端优化策略
11、你了解的浏览器的重绘和回流导致的性能问题
react、Vue 1、写 React / Vue 项目时为什么要在列表组件中写 key,其作用是什么?
2、React 中 setState 什么时候是同步的,什么时候是异步的?
3、下面输出什么
4、为什么虚拟dom会提高性能?
css 1、分析比较 opacity: 0、visibility: hidden、display: none 优劣和适用场景
2、清除浮动的方式有哪些?比较好的是哪一种?
3、css sprite 是什么,有什么优缺点
4、link与@import的区别
5、display: block; 和display: inline; 的区别
6、容器包含若干浮动元素时如何清理浮动
7、PNG,GIF,JPG 的区别及如何选
8、display,float,position 的关系
9、如何水平居中一个元素
JavaScript 1、JS有几种数据类型,其中基本数据类型有哪些?
2、Promise 构造函数是同步执行还是异步执行,那么 then 方法呢?
3、JS的四种设计模式
4、列举出集中创建实例的方法
5、简述一下前端事件流
6、Function._proto_(getPrototypeOf)是什么?
7、简述一下原型 / 构造函数 / 实例
8、简述一下JS继承,并举例
9、函数柯里化
10、说说bind、call、apply 区别?
11、箭头函数的特点
程序阅读题 1、下面程序输出的结果是什么?
function sayHi() {
console.log(name);
console.log(age);
var name = "Lydia";
let age = 21;
}
sayHi();
A: Lydia 和 undefined
B: Lydia 和 ReferenceError
C: ReferenceError 和 21
D: undefined 和 ReferenceError
2、下面代码输出什么
var a = 10;
(function () {
console.log(a)
a = 5
console.log(window.a)
var a = 20;
console.log(a)
})()
3、下面的输出结果是什么?
class Chameleon {
static colorChange(newColor) {
this.newColor = newColor;
}
constructor({ newColor = "green" } = {}) {
this.newColor = newColor;
}
}
const freddie = new Chameleon({ newColor: "purple" });
freddie.colorChange("orange");
A: orange
B: purple
C: green
D: TypeError
4、下面代码中什么时候会输出1?
var a = ?;
if(a == 1 && a == 2 && a == 3){
conso.log(1);
}
5、下面的输出结果是什么?
var obj = {
'2': 3,
'3': 4,
'length': 2,
'splice': Array.prototype.splice,
'push': Array.prototype.push
}
obj.push(1)
obj.push(2)
console.log(obj)
6、下面代码输出的结果是什么?
var a = {n: 1};
var b = a;
a.x = a = {n: 2};
console.log(a.x)
console.log(b.x)
7、下面代码的输出是什么?
function checkAge(data) {
if (data =https://www.it610.com/article/== { age: 18 }) {
console.log("You are an adult!");
} else if (data =https://www.it610.com/article/= { age: 18 }) {
console.log("You are still an adult.");
} else {
console.log(`Hmm.. You don't have an age I guess`);
}
}
checkAge({ age: 18 });
8、下面代码的输出是什么?
const obj = { 1: "a", 2: "b", 3: "c" };
const set = new Set([1, 2, 3, 4, 5]);
obj.hasOwnProperty("1");
obj.hasOwnProperty(1);
set.has("1");
set.has(1);
9、下面代码的输出是什么?
// example 1
var a={}, b='123', c=123;
a[b]='b';
a[c]='c';
console.log(a[b]);
---------------------
// example 2
var a={}, b=Symbol('123'), c=Symbol('123');
a[b]='b';
a[c]='c';
console.log(a[b]);
---------------------
// example 3
var a={}, b={key:'123'}, c={key:'456'};
a[b]='b';
a[c]='c';
console.log(a[b]);
10、下面代码的输出是什么?
(() => {
let x, y;
try {
throw new Error();
} catch (x) {
(x = 1), (y = 2);
console.log(x);
}
console.log(x);
console.log(y);
})();
11、下面代码的输出结果是什么?
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();
因为文章过长,答案不能一一的发出来,所以想要获取这些答案和下图资料的可以私信我+【前端资料】
【前端经典面试题(58道前端面试题包含JS、CSS、React、程序题等)】

前端经典面试题(58道前端面试题包含JS、CSS、React、程序题等)
文章图片
前端经典面试题(58道前端面试题包含JS、CSS、React、程序题等)
文章图片
前端经典面试题(58道前端面试题包含JS、CSS、React、程序题等)
文章图片

    推荐阅读