web前端面试点整理(持续更新)
Ajax
为什么需要ajaxAjax:
- 是对现有技术的综合利用(xhtml+css;dom动态的显示和交互;xml和json进行数据交换;XMLHttpRequest进行异步数据查询)
- 本质:在HTTP协议的基础上,以异步的方式,通过XMLHttpRequest对象与服务器进行通信。
- 作用:实现页面数据的局部刷新。
异步:
定义:某段程序的执行不阻塞其他程序的执行,程序的执行顺序不依赖于程序本身的书写顺序。
优势:不阻塞其他程序的执行,从而提升整体执行效率。
劣势:如果存在多个异步程序,无法判断它们的执行先后顺序。
- 使用异步对象发送get请求
document.querySelector("#username").onblur = function(){
// 1.获取用户数据
var name = this.value;
// 2,让异步对象发送请求
// 2.1 创建异步对象
var xhr = new XMLHttpRequest();
// 2.2 设置 请求行 open(请求方式,请求url):
// get请求如果有参数就需要在url后面拼接参数,
// post如果有参数,就在请求体中传递
xhr.open("get","validate.php?username="+name);
// 2.3 设置 请求头 setRequestHeader('key':'value')
// get方式不需要设置请求头
// post需要设置 Content-Type:application/x-www-form-urlencoded
// 2.4 设置 请求体:发送请求 send(参数:key=value&key=value)
// 如果有参数,post应该在这个位置来传递参数
// 对于 get请求不需要在这个位置来传递参数
xhr.send(null);
// 响应报文:
// 报文行:响应状态码 响应状态信息 200 ok
// 报文头:服务器返回给客户端的一些额外信息
// 报文体:服务器返回给客户端的数据 responseText:普通字符串 responseXML:符合xml格式的字符串
// xhr.status:可以获取当前服务器的响应状态 200 》成功
console.log(xhr.status);
// 一个真正成功的响应应该两个方面:1.服务器成功响应 2.数据已经回到客户端并且可以使用了
// 监听异步对象的响应状态 readystate
// 0:创建了异步对象,但是还没有真正的去发送请求
// 1.调用了send方法,正在发送请求
// 2.send方法执行完毕了,已经收到服务器的响应内容--原始内容,还不可以使用
// 3.正在解析数据
// 4.响应内容解析完毕,可以使用了
xhr.onreadystatechange = function(){
if(xhr.status == 200 && xhr.readyState == 4){
console.log(xhr.responseText);
console.log("-----------");
document.querySelector(".showmsg").innerHTML = xhr.responseText;;
}
}
};
- 使用异步对象发送post请求
document.querySelector("#username").onblur = function(){
// 1.获取用户数据
var name = this.value;
// 2. 让异步对象发送post请求
// 2.1 创建异步对象
var xhr = new XMLHttpRequest();
// 2.2 设置请求行 open(请求方式,请求url)
// 1.get 需要在url后面拼接参数(如果有参数)
// 2.post请求不需要拼接参数
xhr.open("post","validate.php");
// 2.3 设置请求头:setRequestHeader()
// 1.get不需要设置
// 2.post需要设置请求头:Content-Type:application/x-www-form-urlencoded
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
// .如果没有设置,参数无法正确的传递到服务器(本质上说,如果没有参数,也不一定需要设置,不会影响请求的发送)
// 2.4 设置请求体 send()
// 1.get的参数在url拼接了,所以不需要在这个函数中设置
// 2.post的参数在这个函数中设置(如果有参数)
xhr.send("username="+name);
// 3.让异步对象接收服务器的响应数据
// 一个成功的响应有两个条件:1.服务器成功响应了 2.异步对象的响应状态为4(数据解析完毕可以使用了)
// 当异步对象的响应状态发生改变的时候,会触发一个事件:onreadystatechange
xhr.onreadystatechange = function(){
// 判断服务器是否响应 判断异步对象的响应状态
if(xhr.status == 200 && xhr.readyState == 4){
document.querySelector(".showmsg").innerHTML = xhr.responseText;
}
}
};
Ajax是对上述两种请求的封装。
jQuery中的Ajax参数如下。
$.ajax({
type: "method", //请求方式 get post
url: "url", //请求url
data: "data", //请求需要传递的参数
dataType: "dataType", //服务器返回格式
beforeSend: function (param) {
}, //请求发起前调用
success: function (response) {
}, //请求成功之后的回调
complete: function (param) {
}, //响应完成时调用(包括成功或失败)
timeout: 3000 // 请求超时
});
跨域
同源:域名、协议、端口完全相同。(同源策略:浏览器的安全策略。)
跨域:域名、协议或者端口不同。1.不能发送Ajax请求;2.不能进行DOM操作。
跨域方案
- jsonp
其本质是利用了<script src=""></script>标签具有可跨域的特性,由服务端返回一个预先定义好的Javascript函数的调用,并且将服务器数据以该函数参数的形式传递过来,此方法需要前后端配合完成。 - CROS
header( 'Access-Control-Allow-Origin:*' );
- 服务器的反向代理
一次完整的HTTP请求
- 域名解析
- 发起TCP的3次握手
- 建立TCP连接后发起http请求
- 服务器响应http请求,浏览器得到html代码
- 浏览器解析html代码,对html代码中的资源发起请求(js、css、图片)
- 浏览器对页面进行渲染并呈现给用户
闭包
已知:在javascript中,全局变量太多,容易造成污染。如果是局部变量,根据javascript的垃圾回收机制,当局部作用域的函数执行完毕,里面的变量就会被销毁,其占用内存就被释放。
定义:能够读取其他函数内部变量的函数。由于在javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。
用途:
- 可以在函数外部读取函数内部成员
- 让函数内部成员始终存活在内存中
特点:
- 函数嵌套函数
- 内部函数可以访问外部函数的变量
- 参数和变量不会被回收
for(var i = 0; i < 3; i++) {
setTimeout(function () {
console.log(i)
}, 0)
}
递归
定义: 函数在内部调用自身本身,这个函数就是递归函数。
注意:使用递归时,要防止栈溢出。
function factorial (num) {
if (num <= 1) {
return 1
} else {
return num * factorial(num - 1)
}
}
console.log(factorial(4)) //24
面向对象
定义:面向对象就是对面向过程进行封装。每一个对象都是功能中心,具有明确分工,可以完成接受信息,处理数据,发出信息等任务。
特性:
- 封装性
- 继承性
- 多态性
原型链
定义:实例对象的_proto_属性,指向原型对象。对应构造函数的原型属性prototype,也指向原型对象。当对象查找属性时,如果自身没有,就会根据_proto_向它的原型进行查找,如果也没有,则向原型的原型进行查找,直到查到Object.prototype._proto_为null。这样就构成了原型链。
// 构造函数 -- 属性
function Student(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
// 构造函数 -- 方法
Student.prototype.sayHi = function () {
console.log('大家好,我是' + this.name);
}
// new两个实例
var s1 = new Student('lilei', 18, '男');
var s2 = new Student('hmm', 18, '女');
// s1.__proto__ 等于 Student.prototype
console.log(s1.__proto__ === Student.prototype); // true
// constructor 记录创建该对象的构造函数
console.log(s1.constructor === Student); // true
原型链图
MVVM
M:model -- 数据模型
V:view -- 视图模型
VM:view-model -- 一个同步model和view的对象
MVVM
git常用命令
- 初始化仓库 --
git init
- 下载项目及其代码历史 --
git clone [url]
- 添加本地目录所有文件到暂存区 --
git add .
- 提交暂存区到仓库区 --
git commit -m [msg]
- 上传本地指定分支到远程仓库 --
git push [remote] [branch]
- 取出远程仓库的变化,并与本地分支合并 --
git pull [remote] [branch]
CDN托管
CDN:全称 Content Delivery Network,即内容分发网络。
基本思路: 尽可能避开互联网上影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快,更稳定。
传统网络访问形式
- 用户输入域名
- 浏览器解析域名,得到对应的ip地址
- 浏览器根据ip地址,向域名的主机发起数据访问请求
- 浏览器拿到域名主机返回的数据,而进行网页的渲染
CDN网络访问形式
- 用户输入域名
- 浏览器对域名进行解析,CDN对此过程进行了调整,使用户能够就近访问(CDN服务来提供最近的机器)
解析库函数得到该域名对应的CNAME记录 =》 浏览器再次对CNAME进行解析,得到实际的ip地址 - 浏览器向CDN缓存服务器发起数据请求
- 缓存服务器根据浏览器提供的域名,通过Cache内部专用DNS解析得到域名的实际ip地址,再由缓存服务器向此实际ip地址提交访问请求
- 缓存服务器拿到数据后: 本地保存,以备后用; 把数据返回给浏览器
- 浏览器拿到缓存服务器返回的数据,对页面进行渲染
静态资源放不同域名的原因
- 方便CDN缓存
- 突破浏览器并发限制
并发限制:同一时刻,同一域名下的请求数有一定的限制,超出限制后的请求不被接受。 - 节省cookie带宽
登录需要在请求中携带cookie,请求静态资源不需要,分开放在不同的域名下,可以节省cookie带宽
注意:
- DNS解析也费时间,域名太多,解析时间过长,访问速度变慢
- 如果域名采用https协议,则需要安装更多的证书,加大了操作难度
ES6新增内容(列举常用部分)
- 变量声明
let -- 声明变量,不存变量提升,只在let声明所在的块级作用域里有效
const -- 声明常量,只在const声明所在的块级作用域里有效 - 箭头函数
语法更简洁。
this指向: 1. 箭头函数的this指向不可变; 2.谁定义指向谁,而不是谁调用指向谁 - 模块导出/导入
export
export default
import
jQuery链式编程
链式编程,代码更简洁。原理,获取操作之后,用return this返回获取操作的对象。
function Person (name) {
this.name = name;
this.sayHi = function () {
console.log("你好,我是" + this.name);
return this; //返回当前对象,链式编程的原理
}
this.eat = function () {
console.log("我爱吃韭菜+大蒜");
}
}
var beauty = new Person("西施");
beauty.sayHi().eat(); //你好,我是西施 我爱吃韭菜+大蒜
预解析
定义:在当前作用域下,js运行之前,将var 和 function关键字的声明提升,并在内存中安排好,然后从上往下的执行。
- 声明提升,赋值不会提升。
- 先提升var,再提升function。
DOM节点的基本操作
- 增 -- 添加节点
var body = document.body;
var div = document.createElement('div');
body.appendChild(div);
- 删 -- 删除节点
body.removeChild(div)
- 改 -- 替换节点,插入节点
body.replaceChild(text,div);
body.insertBefore(div, firstEle);
- 查 -- id 标签名 name 类名 选择器
// id
var div = document.getElementById('main');
// 标签名
var div = document.getElementsByTagName('div');
// name
var inputs = document.getElementsByName('hobby');
// 类名
var mains = document.getElementsByClassName('main');
// 选择器
var text = document.querySelector('#text');
var boxes = document.querySelectorAll('.box');
Number String Boolean 转换
- 转换成String
toString()
String()
+ 号进行拼接 - 转换成Number
Number()
parseInt()
parseFloat()
+(正号)或者 - 0 - 转换成Boolean
Boolean()
条件语句的隐式转换
Flex布局 -- 元素水平垂直居中
.parent {
display:flex;
align-items: center;/*垂直居中*/
justify-content: center;/*水平居中*/
width:100%;
height: 500px;
background-color:pink;
}
.children {
background-color:skyblue;
}
内存泄漏 内存溢出
- 内存泄漏 memory leak
程序申请内存后,无法释放已经申请的空间。 - 内存溢出 out of memory
程序申请内存是,没有足够的内存空间供其使用。
两个变量交换值 -- 不使用中间变量
var a = 1;
var b = 2;
a = a + b;
b = a - b;
a = a - b;
console.log(a);
console.log(b);
页面回流重绘
页面呈现流程- 页面呈现流程
- 根据文档生成DOM树
(包括 display: none) - 在DOM树的基础上,根据节点的几何属性(margin/padding/width/height)等生成render树
(不包括 display: none | 包括 visibility: hidden) - 在render树基础上进一步渲染
(包括 color,outline)
-
回流 重绘
回流:reflow。当render树中的内容,因为大小边距等发生改变而需要重建的过程,叫做回流。
重绘:repaint。当元素的部分属性变化,不会引起布局变化,而需要重新渲染的过程,叫做重绘。
回流一定伴随着重绘,但是重绘不一定回流。 -
什么引起回流
- DOM树结构变化
- 元素位置变化
- 元素尺寸变化 -- margin、padding、height、width、border
- 内容改变(文本,图片)而引起的计算值的width和height的改变
- 页面渲染初始化
- 浏览器窗口尺寸改变 -- resize
- 如何减少回流重绘
- 将改变样式的操作一次完成,使用className
- 将要操作的元素进行离线处理,处理完后一起更新
DocumentFragment,不属于DOM树,将其插入DOM树时,插入的是子孙节点。是一个游离在DOM树之外的很有用的占位符。
使用display: none,因为display: none的元素不会出现在render树上。 - 不要经常访问会引起浏览器flush队列的属性,若要高频访问,缓存到变量
- 将需要多次重排的元素,position属性设为absolute或fixed,这样元素脱离了标准流,它的变化不会影响到其他元素
- 尽量不要使用表格布局,没有定宽(高)的表格,宽度(高度)是由最后一行决定的,很可能最后一行的宽度超出之前的列宽,引起整体回流,多次计算才能确定。
js中垃圾回收机制
-
标记清除
当变量进入环境时,垃圾回收器给变量标记“进入环境”;当变量离开环境时,则标记为“离开环境”。标记为“离开环境”的变量,会被回收内存。
标记清除
-
引用计数
跟踪记录每个值被引用的次数,当引用的次数变为0时,它所占用的内存就被释放。
引用计数
this关键字
谁调用指向谁。没调用指向Window。
VUE
<style>
[v-cloak] {
display: none;
}
</style>
<p v-cloak>{{msg}}</p>
给元素加上v-cloak指令,当vue文件加载完毕之后,v-cloak会被删除。
-
v-if 和 v-show 的区别
v-if : 通过添加/删除DOM元素来控制元素的显示/隐藏,异步数据渲染时使用
v-show:通过控制 display: none样式来控制元素的显示/隐藏,涉及大量DOM操作时使用 -
router 和 route 的区别
router:VueRouter的实例,全局路由器对象,里面有很多子属性和子对象
route:当前正在跳转的路由对象,可以从里面获取name,path,params等 -
vue页面跳转
- router-link to
<p>
<!-- 使用 router-link 组件来导航. -->
<!-- 通过传入 `to` 属性指定链接. -->
<!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
<router-link to="/foo">Go to Foo</router-link>
<router-link to="/bar">Go to Bar</router-link>
</p>
- 配置路由
const routes = [
{path: '/foo', component: foo}
]
- 编程式导航
this.$router.push({path: '/foo'})
-
vue操作DOM元素
ref 结合 this.$ref
window.onload 和 $(function(){})的区别
-
window.onload
整个页面加载完毕之后触发(包括页面上的资源);
只执行最后一个,之前的会被最后一个给覆盖掉。 -
$(function(){})
dom加载完毕之后就会执行;
有多个时,按照顺序依次执行。
link 和 @import 引入css区别
- link是xhtml标签,页面载入时同时加载
- @import时在css2.1提出的,低版本的浏览器不支持,页面完全载入以后才加载
媒体查询
<style>
@media screen and (max-width: 1600px) {
body {
background-color:pink;
}
}
@media screen and (max-width: 300px) {
body {
background-color:lightblue;
}
}
</style>
max-width:大 >> 小
min-width:小 >> 大
<!-- 另一种写法 -->
<link rel="stylesheet" media="screen and (max-width: 600px)" href="small.css" />
width:浏览器可视宽度。
device-width:设备屏幕的宽度。