前端初中级面试题及部分答案
1.什么是webpack
webpack 可以看作是模块打包机,它做的事情是:分析你的项目结构,找到JavaScript 模块以及其他的一下浏览器不能运行的拓展语言(typeScript,Scss等),并将其打包为合适的格式以供浏览器使用。(webpack 基于node,遵循commonjs规范)
构建就是把源代码转换成发布到线上的可执行JavaScript,css ,html 代码;包括内容如下:
代码转换: typescript 编译成JavaScript,scss 编译成css
文件优化:压缩JavaScript,css html 代码,压缩合并图片等。
代码分割:提取uoge页面的公共代码、提取首屏不需要执行部分的代码让其异步加载
模块合并:在采用模块化的项目里会有很多个模块和文件,需要构建功能把模块分类合并成一个文件。
代码校验:在代码被提交到仓库前需要校验代码是否符合规范,以及单元测试是否通过。
自动发布:更新完成代码后,自动构建出线上发布代码并传输个发布系统。
构建其实是工程化、自动化思想在前端开发中的体现,把一系列流程用代码去实现,让代码自动化的执行这一系列复杂的流程。构建给前端开发人员注入了更大的活力,解放了我们的生成力。
2. webpack.config.js 文件
let path = require('path');
let HtmlWebpackPlugin = require('html-webpack-plugin');
let CleanWebpackPlugin = require('clean-webpack-plugin');module.exports ={entry:'', // 入口output:'', // 出口devServer:{ // 开发服务器contentBase:'./build'}, module:{} , // 模块配置plugins:[ // 插件配置//打包html插件,作用:把src目录下的html文件,在打包时生成build 文件下index.html 中导入的 buid.js new HtmlWebpackPlugin({template:'./src/index.html', // 文件位置title:'x', // 文件titleminify:{removeAttributeQutes:true, // 编译后去掉双引号collapseWhitespace:true //文件压缩成一行}}),// 用于清空build 文件new CleanWebpackPlugin(['./build'])], mode:'development' , // 可以更改模式resolve:{}, // 配置解析
}
3.0闭包
3.01 概念
闭包就是能够度去其他函数内部变量的函数,本质上就是:将函数内部和函数外部连接起来的桥梁(或者说定义在一个函数内部的函数!)。
要理解闭包,首先需要理解JavaScript的全局变量和局部变量
JavaScript 语言的特别支持就在于: 函数内部可以直接读取全局变量,但是在函数外部无法读取函数内部的局部变量。
总结: 形成闭包需要满足的条件是返回一个函数且这个函数对局部变量存在引用
3.02 为什么需要闭包
闭包又两个作用: ①可以读取函数内部的变量;②可以让这些变量始终保持在内存中,不会在被调用后自动清除;
总结:局部变量无法共享和长久的保存,而全局变量可能造成变量污染,当我们希望又一种机制既可以长久的保存变量又不会造成造成全局污染的时候,我们就会使用闭包!(这也就印证了为什么滥用闭包会造成内存泄漏的原因了。)
闭包示例:
function f1(){var x= 10;function f2(){x++console.log(x)}return f2
}
var f= f1() // (f2 返回的变量被存储在了全局变量中。)
f() // 运行第一次: 11
f() // 运行第二次: 12
解析: 局部变量,通过闭包导致内存并没有被回收,导致x 的值在不断增加(闭包:为了维护局部变量的状态不被回收!)非闭包示例:
function f3(){var a= 10;a++return a;
}
var ff =f3 // (虽然也存储于全局变量中,但是每次都重新执行f3,a 变量被重新赋值为10)
ff() // 运行第一次 11
ff() // 运行第二次 11// 闭包应用:两人心中,定义一个函数记录两人行走的状态
function f4(){var a= 10;function f5(){a++console.log(a)}return f5
}
var a = f4(); // 甲
var b = f4(); // 乙
a() // 执行第一次: 11
a() // 执行第二次: 12
a() // 执行第三次: 13
b() // 执行第一次: 11
b() // 执行第二次: 12
b() // 执行第三次: 13
4.0 浏览器解析全过程(输入URL到页面展现)
DNS解析,将域名地址解析为ip地址(从上往下寻找,直到找到为止)
浏览器DNS缓存
系统DNS缓存
路由器DNS缓存
网络运营商DNS缓存
递归搜索:blog.aa.com(举例)
.com 域名下查找DNS解析
.aa 域名下查找DNS解析
blog 域名下查找DNS 解析
再查不到就出错了
TCP连接:TCP三次握手
第一次握手:由浏览器发起,告诉服务器,我要发送请求了
第二次握手:由服务器发起,告诉浏览器我准本接收了,你赶紧发送吧
第三次握手:由浏览器发送,告诉服务器,我马上就发了,准备接受吧
解析:之所以需要发送三次请求是因为:如果浏览器只发送一次请求,但是服务器很忙并没有空去处理你这个请求;浏览器并不知道服务器有没有空给处理直接把数据发送给了服务器;但是服务器并没有准备好去接收(没拿到数据);所以需要第二次握手,告诉浏览器我已经准备好接收; 这时候浏览器也不一定准备好了啊!所以还需要浏览器给服务再次发送请求,和服务器说准备接收吧!(三次握手来保证通讯的准确性!)
发送请求
请求报文:http协议的通讯内容
接收响应
响应报文
渲染页面
遇见HTML标记,浏览器调用HTML解析器解析成Token并构建dom树
遇见style/link 标记,浏览器调用css解析器,处理css标记并构建cssom树
遇见script标记,调用javasScript解析器,处理script代码(事件绑定,修改dom树/cssom树)
将dom树和cssom树合并成一个渲染树
根据渲染树来计算布局,计算每个节点的几何信息(布局,每个盒子显示在页面的某个地方)
将各个节点颜色绘制到屏幕上(渲染)
注意:以上这五个步骤不一样按照顺序执行,如果dom树或cssom 树被修改了,可能会执行多次布局和渲染;往往实际页面中,这些步骤都会执行多次的!
断开连接:TCP四次挥手
第一次挥手:由浏览器发起,发送给服务器,我东西发完了(请求报文),你准备关闭吧
第二次挥手:由服务器发起,告诉浏览器,我接收完了(请求报文),我准备关闭了,你也准备吧。
第三次挥手:由服务器发起,告诉浏览器,我东西都发完了(响应报文),你准备关闭吧。
第四次握手:由浏览器发起,告诉服务器,我都系都接收完了(响应报文),我准备关闭了,你也准备吧。
注:一般服务器先关闭,然后再浏览器关闭
5.0原型链
5.1作用域链
window; // 全局作用域对象
function test(){var num = 10function mc(){console.log(num) // 10}mc(); // 作用域对象.mc()
}
test(); // window.test()
// 每个方法都是一个作用域,最外层的是全局作用域;
// 引用方法都是:对象.方法()
// 每一个方法都是有对象的: alert() --> window.alert()
关于以上代码console.log(num)打印解析:
如果mc 方法里面申明:var num= 10; 则 打印: 10
如果test方法里面申明:var num= 100,且mc 方法里面没有申明var; 则 打印: 100
如果申明全局变量: var num = 1000 ,且test 和 mc 方法里面没有申明var; 则打印:1000
总结:每一个方法里面都是一个作用域,其都有自身的作用域对象;
当你在使用某个变量的时候,它会先在自己的作用域中去寻找这个变量,如果当前作用域没有这个变量,它就会向上查找(其父级作用域);最终查找到全局作用;这样子形成的链条就5是:作用域链
5.2 原型链的继承机制
原型链: 首先在自身找,如果没找到就沿着自己的原型链条(对象.--proto--)找到其原型: prototype
class Student {constructor(name,score){this.name = name;this.score = score;}introduce(){console.log(`我是${this.name},考了$(this.score)分。`)}
}
//创建对象
const student = new Student('张三',99)
// 调用子类函数
student.introdece() // 我是张三,考了 99 分原型: 注: Student.prototype === student.__proto__
student.hasOwnProperty(name) // 通过hasOwnProperty这个属性来判断name是否是属于teacher本身的属性。
6.0 函数节流& 函数防抖
6.0.1 函数节流
感念:一个函数执行一次后,只有大于设定的执行周期后才会执行第二次(有个需要频繁处罚函数,储于优化性能角度,在规定时间内,只让函数触发的第一次生效,后面不生效)
--应用示例:(鼠标滚动触发事件)
<style>heml,body{height:200%;}
</style>// 节流函数
// fn 要被节流的函数
// delay 规定的时间
function throttle(fn,delay){var lastTime = 0;// 通过闭包来保存lastTime的状态return function(){// 记录当前函数触发的时间var nowTime = Date.now();if(nowTime- lastTime > delay){fn()// 好的代码: fn.call(this) --让当前this的指向修正到fn// 同步时间lastTime = nowTime;}}
}
// 绑定鼠标滚动事件,触发函数
document.onscroll = throttle(function(){console.log('函数被触发了')
},2000)
6.0.2 防抖函数
概念: 一个需要频繁触发的函数,在规定时间内,只让最后一次生效,前面的不生效;
// 节流函数
// fn 要被防抖的函数
// delay 规定的时间
<button id="btn"></button>function debounce(fn,delay){// 记录上一次的延时器return function(){// 清除上一次延时器clearTimeout(timer);timer = setTimeout(function(){fn.apply(this)},delay)}
}
document.getElementById('btn').onclick = debounce(function(){console.log("点击事件被触发了 !")},1000);
7.0 深浅拷贝
7.0.1浅拷贝
概念: 可以将对象最外层属性全部复制,里层属性仍然是引用关系
var obj = {a:1,b:2,c:{d:10,e:20}}
var obj1 = {}
Object.assign(obj1,obj)
obj.a = 2;
obj.c.d = 100
console.log(obj1) // {a:1,b:2,c:{d:100,e:20}}
// 可以看出a不变, 但是d 的值被 obj 改变了!
7.0.2 深拷贝
举例
// 通过以上的方法可以实现深考贝
obj1 = JSON.parse(JSON.stringify(obj)) // 原理是:把对象转换成字符串,然后再转换成对象;
obj.c.d = 100
console.log(obj1) // {a:1,b:2,c:{d:10,e:20}}
// 但是这种方法是有弊端的(无法实现深拷贝)
//①: 在obj 对象种加入 set get 方法,会导致方法被运算
//②: 对obj 对象通过 Object.defineProperty() 添加属性时无法被拷贝
//例:
Object.defineProperty(obj,"h",{value :30
})
obj1 = JSON.parse(JSON.stringify(obj))
console.log(obj) // {a:1,b:2,c:{d:10,e:20},h:30}
console.log(obj1) // {a:1,b:2,c:{d:10,e:20}}
JSON.parse(JSON.stringify ( ) )
自己写一个深拷贝的方法,然后引用。
lodash 里面的_.cloneDeep() 方法。
8 Promise
8.1 promise().then()
// 创建一个Promise 函数
function getImage(src) {return new Promise (function(res,rej){let img = new = image()img.onload =function(){res(img)};img.onerror = function(){rej('这是错误信息')}img.src = src;})
}
// .then() 调用该函数getImage('img/a.jpg').then(function(img){console.log(img) // 成功回调
},function(){console.log(error) // 失败回调: 这是错误信息
})如果要执行多张图片的加载
getImage('img/b.jpg').then(function(img){console.log(img) // 成功回调
},function(){console.log(error) // 失败回调: 这是错误信息
})
上面的这个函数相当于:
getImage('img/b.jpg').then(function(img){console.log(img) // 成功回调
}).catch(err=>{console.log(err //失败回调)})
// 这样子就会打印两次
// <img src= 'img/a.jpg'>//<img src= 'img/b.jpg'>// 但是以上这么写,代码过于冗余,且不利于解读;优化到以下写法getImage('img/a.jpg').then(function(img){console.log(img) // 成功回调 return getImg('img/b.jpg')
}).then(res => console.log(res))
.catch(res=> console.log(res))// <img src= 'img/a.jpg'>//<img src= 'img/b.jpg'>
8.2 promise.all()
all 并列执行!是几个异步全部完成后,执行的结果!结果是统一返回第一个参数的数组。
// 创建一个Promise 函数
function getImage(src) {return new Promise (function(res,rej){let img = new = image()img.onload =function(){res(src) //这边将在下面放回};img.onerror = function(){rej('这是错误信息')}img.src = src;})
}
Promise.all([getImage('img/a.jpg'),getImage('img/b.jpg'),getImage('img/c.jpg')])
.then(function(list){ // 这个list 数组就promise 成功回调返回的函数console.log(list) //[img/a.jpg,img/b.jpg,img/c.jpg]
})
8.3 promise.race();
race() 并列执行,谁先执行完就输出谁,别的就不管了!
Promise.all([getImage('img/a.jpg'),getImage('img/b.jpg'),getImage('img/c.jpg')])
.then(function(list){ // 这个list 数组就promise 成功回调返回的函数console.log(list) // img/a.jpg
})
8.4 async await 使用
异步转同步;这样子就可以不用 使用promise().then() 函数了,看起来比原来更加简洁!
函数使用之前必须有async , await 后面必须是一个 Promise 函数
await 后面必须是一个 Promise 实例
function loadImg(src){var promise = new Promise((res,rej)=>{resolve(img)})return promise
}
const load = async function(){const result1 = await loadImg(src1)const result2 = await loadImg(src2)
}
load();
前端初中级面试题及部分答案相关推荐
- 最全最详细前端vue面试题+详解答案(拿到高薪offer不是梦)
最全vue面试题+详解答案 1.MVC 和 MVVM 区别 MVC MVC全名是 Model View Controller,时模型 - 视图 - 控制器的缩写,一种软件设计典范. Model(模型) ...
- 前端经典面试题(有答案)
代码输出结果 var a = 10 var obj = {a: 20,say: () => {console.log(this.a)} } obj.say() var anotherObj = ...
- 20道前端高频面试题(附答案)
setTimeout 模拟 setInterval 描述:使用setTimeout模拟实现setInterval的功能. 实现: const mySetInterval(fn, time) {let ...
- 史上最全的前端开发面试题(含详细答案)
本文由我收集网络 自己平时面试的 或者面试别人时的一些前端面试题,初学者阅后也要用心钻研其中的原理,重要知识需要系统学习.透彻学习,形成自己的知识链.万不可投机取巧,切勿临时抱佛脚只求面试侥幸混过关. ...
- Web前端岗位面试题汇总(含答案)
HTML+CSS 1.对WEB标准以及W3C的理解与认识 标签闭合.标签小写.不乱嵌套.提高搜索机器人搜索几率.使用外 链css和js脚本.结构行为表现的分离.文件下载与页面速度更快.内容能被更多的用 ...
- “有意思的前端函数面试题”第一题答案原理解析
if(a == 1 && a == 2 && a == 3){console.log("我走进来了"); }<!--答案1:--> va ...
- 美团前端必会面试题(附答案)
常见的CSS布局单位 常用的布局单位包括像素(px),百分比(%),em,rem,vw/vh. (1)像素(px)是页面布局的基础,一个像素表示终端(电脑.手机.平板等)屏幕所能显示的最小的区域,像素 ...
- 前端面试——那些web前端经典面试题大全及答案(html/css部分)
阅读目录 HTML/CSS部分 JavaScript部分 JQuery部分 开发及性能优化部分 HTML/CSS部分 1.什么是盒子模型 在网页中,一个元素站有空间的大小由几个部分构成,其中包括元素的 ...
- 中级前端常见面试题(附答案),持续更新
文章目录 Q:JS有哪些数据类型? 7种基本类型 1种引用类型 Q:ES6数据结构 Set / Map Set Map Q:call, apply, bind 用法和区别 call() 和 apply ...
最新文章
- python——动态的增加实例方法、类方法、静态方法
- Django之静态文件
- mysql存储引擎中INNODB和MyISAM的区别
- 实习技术员的基本功(四)
- http 文件服务器 性能测试,Http File Server
- 【目标检测】cvpr2021_VarifocalNet: An IoU-Aware Dense Object Detector
- IntelliJ IDEA for Mac 如何设置在HTML和XML文件编辑窗口显示浏览器图标
- vue+node前后端分离接口调用(初学者)
- java openresty 调用_玩转 OpenResty 协程 API
- Python Imaging Library:ImageDraw Module(图像绘制模块)
- Java JDBC中的Statement和PreparedStatement
- 利用TreeView实现C#工具箱效果
- Linux中/etc/rc开头文件详细解释
- 基于珞珈一号夜间灯光数据的GDP空间化
- 原生android ui设计,在拟物和扁平之间寻找平衡 原生安卓UI设计进化史
- 易经六十四卦详解白话文解释——易经64卦全解(上)
- miui11可用的位置模拟器_MIUI11内测体验包
- JAVA编写Word
- 【从零开始学习 SystemVerilog】2.8、SystemVerilog 数据类型—— Unpacked Arrays(非压缩数组)
- python运维必备知识