前端基础面试题1
- 盒模型的理解
- BFC的理解
- 高度塌陷
- 布局-两栏布局
- 布局-三栏布局
- 水平垂直居中
- 弹性布局(Flex 布局)
- flex布局和grid布局的区别
- 自适应和响应式
- rem、em、vw、%
- 数据类型判断方式
- typeof、instanceof的区别
- 会改变原数组的方法、不会改变原数组的方法
- ES6中数组常用方法
- ES5中数组常用方法
- 构造函数new
- 作用域、作用域链
- 原型、原型链
- 深拷贝和浅拷贝
- 深拷贝-递归底层
- 闭包
- 垃圾回收机制
- H5新特性
- CSS3新特性
- ES6新特性
- this指向
- call/apply/bind 自定义方法,作用,应用场景
- 回流 重绘
- 跨域
- 浏览器的存储方式
- 浏览器输入网址后
- js事件三个阶段和顺序
- 事件循环
- 同步、异步的理解
- 对ajax 的理解
- Promise
- async/await
- 节流防抖
- 对http协议的理解
- http状态码
- http 与 https 区别
- get和post区别
- CSS预处理器
- 网页的优化
- 常见的 Web 攻击手段
- 浏览器兼容性问题
- AJAX
- JSON
- canvas 画布
- 画三角形
盒模型的理解
网页布局中CSS布局的思想模型,主要规定元素和元素之间的关系。
如:内容(content)、内边距(padding)、边框(border)、外边距(margin)
拓展:标准盒模型、怪异盒模型的理解
用box-sizing告诉浏览器如何计算一个元素的总宽度和总高度
1. 标准盒模型:box-sizing:content-box
一个块的总宽度为 = width + margin(左右) + padding(左右) + border(左右)
2. IE盒模型或怪异盒模型:box-sizing:border-box
一个块的总宽度 = width(已包含padding和border)+ margin(左右)
BFC的理解
BFC是什么:(Block formatting context)直译为"块级格式化上下文",是一个独立的布局环境
BFC能干吗:形成一个完全独立的空间,让空间中的子元素不会影响外面的布局,反之也如此
BFC特性(独立空间内元素/标签的布局规则)
1 垂直方向上的距离由margin决定,属于同一个BFC的两个相邻的块级元素会发生margin合并,不属于同一个BFC的两个相邻的块级元素不会发生margin合并(应用:防止margin重叠);
2 BFC的区域不会与float box重叠(应用:自适应两栏布局)
3 计算BFC的高度时,浮动元素也参与计算(应用:清除内部浮动)
4 内部的Box会在垂直方向,一个接一个地放置。
5 每个盒子(块盒与行盒)的margin box的左边,与包含块border box的左边相接触(对于从左往右的格式化,否则相反);即使存在浮动也是如此。(说明:就是子盒子排列时候从父盒子左上角开始)
6 BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
触发BFC
float:除 none 以外的值
position为 absolute、fixed
display 为 inline-block、table、table-row、table-cell、flex等等
overflow 除了 visible 以外的值 (hidden、auto、scroll)
column-count等
BFC应用
- 自适应两栏、三栏布局
- 清除内部浮动
- 利用BFC避免margin重叠(案例:京西商城后台首页头部导航
高度塌陷
概念:父高自适应,子浮动,父高为0的表现
解决方法:
方法1:clear: both + 空标签(不推荐 代码冗余)
方法2:父级添加overflow属性(父元素添加overflow:hidden)(不推荐 超出隐藏)
方法3:伪元素清除浮动(推荐使用)
方法4:双伪元素清除浮动(推荐使用)
布局-两栏布局
方法1:左固定浮动、右触发BFC
方法2:左固定浮动、右margin-left
方法3:左固定定位、右margin-left
方法4:父弹性盒、左固定、右flex:1
<style>
*{padding:0px;margin:0px;}
.test {width:50px;height:50px;background: black;color:#fff;}
</style>
<!-- 方法1:左固定浮动、右触发BFC -->
<style>
.left1 {width:200px;height:100px;background:#ccc;float:left;}
.right1 {height:100px;background:red;overflow: hidden;}
</style>
<div class="left1">你好</div>
<div class="right1"><div class="test">中国</div></div>
<!-- 方法2:左固定浮动、右margin-left -->
<style>
.left2 {width:200px;height:100px;background:#ccc;float:left;}
.right2 {height:100px;background:red;margin-left:200px;}
</style>
<div class="left2">你好</div>
<div class="right2"><div class="test">中国</div></div>
<!-- 方法3:左固定定位、右margin-left -->
<style>
.left3 {width:200px;height:100px;background:#ccc;position:absolute;}
.right3 {height:100px;background:red;margin-left:200px;}
</style>
<div class="left3">你好</div>
<div class="right3"><div class="test">中国</div></div>
<!-- 方法4:父弹性盒、左固定、右flex:1 -->
<style>
.main {display: flex;}
.left4 {width:200px;height:100px;background:#ccc;}
.right4 {height:100px;background:red;flex:1;}
</style>
<div class="main">
<div class="left4">你好</div>
<div class="right4"><div class="test">中国</div></div>
</div>
布局-三栏布局
方法1:左右固定浮动、中间触发BFC
方法2:左右固定浮动、中间margin-left/right后自适应
方法3:左右固定定位、中间margin-left/right后自适应
方法4:弹性盒 左固定 右侧flex:1
方法5:圣杯布局、双飞翼布局
<style>*{padding:0px;margin:0px;}</style>
<!-- 方法1:左右固定浮动、中触发BFC -->
<style>
.left1{width:200px;background:green;float:left;}
.right1{width:200px;background:#ccc;float:right;}
.center1{background:red;overflow:hidden;}
</style>
<div class="left1">左侧</div>
<div class="right1">右侧</div>
<div class="center1">中间</div>
<!-- 方法2:左右固定浮动、中间margin-left/right后自适应 -->
<style>
.left2 {width:200px;background:green;float:left;}
.right2 {width:200px;background:#ccc;float:right;}
.center2 {background:red;margin:0px 200px 0px 200px}
</style>
<div class="left2">左侧</div>
<div class="right2">右侧</div>
<div class="center2">中间</div>
<!-- 方法3:左右固定定位、中间margin-left/right后自适应 -->
<style>
.box3 {position: relative;}
.left3 {width:200px;background:green;position:absolute;top:0px;left:0px;}
.right3 {width:200px;background:#ccc;position:absolute;top:0px;right:0px;}
.center3 {background:red;margin:0px 200px}
</style>
<div class="box3">
<div class="left3">左侧</div>
<div class="center3">中间</div>
<div class="right3">右侧</div>
</div>
<!-- 方法4:圣杯布局-有定位 -->
<style>
.box4{padding:0 200px;}
.content4{width:100%;background:red;float:left;}
.left4{width:200px;background:green;float:left;margin-left:-100%;position: relative;left:-200px;}
.right4{width:200px;background:#ccc;float:left;margin-left:-200px;position: relative;right:-200px;}
</style>
<div class="box4">
<div class="content4">中间</div>
<div class="left4">左侧</div>
<div class="right4">右侧</div>
</div>
<!-- 方法5:双飞翼布局-无定位 -->
<style>
.box5 {width:100%;float:left;background:red;}
.box5 .content5{padding:0 200px;}
.left5{width:200px;background:green;float:left;margin-left:-100%;}
.right5{width:200px;background:#ccc;float:left;margin-left:-200px;}
</style>
<div class="box5">
<div class="content5">中间</div>
</div>
<div class="left5">左侧</div>
<div class="right5">右侧</div>
水平垂直居中
- 利用flex弹性布局,justify-content/align-items为center
- 利用position定位,top/left 50%,margin-top/margin-left 为负自身一半
- 利用position定位,top/right/bottom/left =0,然后margin:auto
- 利用position定位,transform translate(-50%,-50%)
水平居中
- 利用flex弹性布局,justify-content 为center
- 利用position定位,left 50%,margin-left 为负自身一半
- 利用position定位,right/left =0,然后margin:auto
- 利用position定位,transform translate(-50%,0)
- text-align:center (行内元素)
- margin:auto (块级元素)
垂直居中
- 利用flex弹性布局,align-items 为center
- 利用position定位,top 50%,margin-top 为负自身一半
- 利用position定位,top/bottom =0,然后margin:auto
- 利用position定位,transform translate(0,-50%)
- line-height (文本居中)
弹性布局(Flex 布局)
flex 是 Flexible Box 的缩写,是弹性盒子布局,可以自动弹性伸缩来适配不同大小的屏幕,和移动端。
常用的自适应布局技术,用来为盒状模型提供最大的灵活性。任何一个容器都可以指定为 Flex 布局。
采用 Flex 布局的元素,称为 Flex 容器(flex container),简称"容器"。容器默认存在两根轴: 默认水平显示的主轴 和 始终要垂直于主轴的侧轴(也叫交叉轴)。它的所有子元素自动成为容器成员,称为 Flex 项目(flex item),简称"项目"。
Flex 容器属性:
flex-direction 设置主轴方向
justify-content 主轴对齐方式
align-items 侧轴对齐方式
align-content 设置侧轴上的子元素的排列方式
flex-wrap 属性规定flex容器是单行或者多行
flex-flow 是 flex-diretion 和 flex-wrap 的简写属性
flex布局优缺点:
1、操作方便,布局及其简单,移动端使用比较广泛
2、pc端浏览器支持情况比较差
3、IE11或更低版本不支持flex或仅支持部分
补充:
flex实际上是flex-grow(放大的比例)、flex-shrink(缩小的比例)和flex-basis(具体的长度)三个属性的缩写;
flex: 1;相当于设置了flex:1 1 auto 表示该盒子自动占满剩余空间;
flex布局和grid布局的区别
flex是一维布局,只能处理一个维度上的布局,一行或者是一列。
grid布局是二维布局 ,将容器划分成了“行”和“列”,产生了一个个的网格,可以将网格元素放在行和列相关的位置上,从而达到了布局的目的。
自适应和响应式
1、自适应:为了使网页自适应的显示在不同大小终端设备上的网页设计方式及技术,需要开发多套界面来适应不同的终端。(典型的写法是让每个元素通过相对的宽度,如% vw em 来改变容器大小、字体大小)
2、响应式:在不同屏幕不同分辨率上实现不同的展示方式。使一个网站能兼容多个终端,浏览体验更好。(典型的写法是通过media判断,在不同的设备、分辨率下展示不同的页面效果)
两者区别:
1、自适应布局,是通过检测视口分辨率来判断当前访问的设备屏幕大小,从而请求服务层返回不同的页面。
响应式布局,是通过检测视口分辨率针对不同客户端在客户端做代码处理,来展现不同的布局和内容;
2、自适应布局需要开发多套界面,而响应式布局只需要开发一套界面就可以了;
3、自适应布局如果屏幕太小会发生内容过于拥挤,响应式布局可以自动识别屏幕宽度并作出相应的调整页面设计;
4、自适应对页面做的屏幕适配是在一定范围:比如pc端一般要大于1024像素,手机端要小于768像素,而响应式布局是一套页面全部适应。
rem、em、vw、%
都是相对单位
rem 相对于根元素root,可理解为”root em”,绕开了复杂的层级关系
em 相对于父元素的font-size,1em = 父字体的
% 相对于父元素
vw 可视窗口(viewport)宽度的1%
数据类型判断方式
1.typeof
2.instanceof
3.constructor
4.Object.prototype.toString
typeof、instanceof的区别
typeof | instanceof | |
---|---|---|
作用: | 检测数据类型 | 检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上 |
返回: | 小写字母字符串 | 布尔值 |
操作数: | 简单数据类型、函数或对象 | 左边必须是引用类型,右边必须是函数 |
操作数数量 | 1个 | 2个 |
举例:
typeof 12 => “number”
typeof NaN => “number”
typeof ‘a’ => “string”
typeof true => “boolean”
typeof undefined => “undefined”
typeof [] => “object”
typeof {} => “object”
typeof null => “object”
let fn = function(){}; typeof fn => “function”
[] instanceof Array => true
可以看出数组、对象都是object,就需要instanceof判断一个引用类型的变量类型,instanceof可以看作typeof的补充
会改变原数组的方法、不会改变原数组的方法
会改变原数组的方法:
push、pop、shift、unshift、sort、splice、reverse;
不会改变原数组的方法:
concat、join、reduce、map、forEach、filter、slice、findIndex、some
some :检测数组中的元素是否满足指定条件,有一个元素符合条件,则返回true,后面不会再检测。不会改变原数组;
every:检测数组中所有元素是否都符合指定条件,才返回true。
ES6中数组常用方法
find:返回第一个满足条件的元素;
findIndex:返回第一个满足条件的元素对应索引;
values:仅遍历值;
keys:仅遍历index;
entries:遍历index和值;
ES5中数组常用方法
forEach:没有返回值;
map:返回新数组;
filter:过滤,返回符合条件的元素数组;
some:返回布尔值,有一个满足条件就返回true;
every:返回布尔值,全部满足条件才返回true;
reduce:累加器,返回总和;
构造函数new
1 创建空对象 let obj = {}
2 在obj中添加__proto__属性并指向 构造函数.prototype
3 将构造函数中的this指向obj this = obj
4 执行构造函数内语句
5 返回对象
function Stu(name, age) {
this.name = name;
this.age = age;
}
function _new(...args) {
let constructor = args[0];//获取构造函数
let obj = Object.create(constructor.prototype);//创建空对象,并将原型指向构造函数的原型
let res = constructor.call(obj, ...args.slice(1));//call强行将this指向第一个参数
if ((typeof res === 'object' || typeof res === 'function') && res != null) {
return res;
} else {
return obj;
}
}
let data1 = _new(Stu, '张三', 20);
let data2 = new Stu('张三', 20);
console.log(data1, data2);
//运行结果:
Stu { name: '张三', age: 20}
Stu { name: '张三', age: 20}
作用域、作用域链
javascript中的作用域:是可以有效访问变量或函数的区域。js中有三种类型的作用域:全局作用域、函数作用域、块级作用域。
作用域链:一般情况使用的变量取值是在当前执行环境的作用域中查找,如果当前作用域没有查到这个值,就会向上级作用域查找,直到查找到全局作用域,这样一个查找的过程叫做作用域链。
全局作用域
在全局命名空间中声明的变量或函数位于全局作用域中,因此在代码的任何地方都可以访问它们。
函数作用域
在函数中声明的变量,函数和参数可以在函数内部访问,但不能在函数外部访问。
块级作用域
在块{ } 中声明的变量,{ let,const } 只能在其中访问。
原型、原型链
原型:js给每个函数分配的公共空间
,为了减少内存占用。
原型链:多个原型的集合,当调用对象的属性或方法时,先自身找,找不到去原型链上找,一直找到Object构造函数的原型链。
深拷贝和浅拷贝
深拷贝 拷贝 值,拷贝多层;
浅拷贝 拷贝地址,拷贝一层
深拷贝的方法:
1.lodash库里的cloneDeep方法
2.JSON.parse(JSON.stringfy(obj))
【缺点:对象里面的函数会丢失,同时undefined 也会丢失,正则等也会丢失 会把原型上面所有的属性都拷贝出来,性能消耗比递归还大】
3.递归
4.immutable
浅拷贝的方法:
1.使用es6的扩展运算符 …(一维)
2.ES6的 Object.assign(target, …sourceObj) 合并对象(一维)
3. slice拷贝数组
4. concat 拷贝数组
深拷贝-递归底层
// data是要进行拷贝的对象
function deepCopy(data){
let newObj = {};
let arr = []
// 进行判断,判断data是不是一个引用数据类型,要区分对象和数组
if(typeof data === 'object' && !Array.isArray(data)){
for(k in data){
if(typeof data[k] === 'object'){
newObj[k] = deepCopy(data[k])
}else {
newObj[k] = data[k]
}
}
return newObj
}else if(Array.isArray(data)){
for(let i=0;i<data.length;i++){
if(typeof data[i] === 'object'){
arr.push(deepCopy(data[i]))
}else {
arr.push(data[i])
}
}
return arr
}
}
闭包
闭包:两个函数相互嵌套,内部函数使用外部函数的变量 就会产生闭包
作用:保存局部变量避免丢失,保护变量避免受外部影响
应用场景:只要有函数嵌套、节流防抖封装、定时器特效、jq源码、forEach循环绑定事件等等
// 例子1:说明闭包不一定return
function fn1(){
let count=1;
function fn2(){
count++;
console.log(count,'count');
}
fn2();
}
fn1();
// 例子2
function fn1() {
let i=0; // i私有
function fn() {
i++;
console.log(i,'i');
}
return fn;
}
const fun = fn1();
// 控制台手动多次输入 fun(); //结果依次为: 1,2,3。。。
// 闭包:两个函数嵌套,内部函数(指fn)使用外部函数(指fn1)的变量
// 应用闭包,实现数据的私有
// 闭包使外部(指全局)可以使用变量(i),但不能修改这个变量
// 注意区分上面的两个“外部”
垃圾回收机制
垃圾回收:不再使用的变量,然后释放掉其占用的内存
回收目的:内存占用越来越高,轻则影响系统性能,重则导致进程崩溃。
回收机制:
- 标记清除
- 引用计数
内存泄漏(Memory Leak)
占用的内存没有及时释放。
常见的内存泄露:
1)意外的全局变量引起的内存泄露
function fn1() { a = 1 console.log(a) } fn1() 由于变量提升而导致a变成全局变量 函数执行完a还占着空间
2)闭包
3)定时器或者回调函数没有及时清理
4)没有清理的DOM元素引用
5)子元素存在引起的内存泄露
内存泄露积累多了就容易导致内存溢出。
内存溢出(Out Of Memory – OOM)
- 一种程序运行出现的错误。
- 当程序运行时需要的内存超过剩余的内存时,就会内存溢出的错误。 内存不够
H5新特性
1)语义化标签
头部标签:header、导航标签:nav、内容标签:article、块级标签:section、侧边栏标签:aside、尾部标签:footer
2)视频 video、音频 audio
3)表单控件 tel 、email、url、range
4)绘图 canvas
拓展:
canvas 和 svg的区别:
1、 canvas 基于h5,用js绘制图形;
2、 svg直接写标签;
CSS3新特性
- CSS3实现圆角(border-radius),阴影(box-shadow)
- 对文字加特效(text-shadow),线性渐变(gradient)、转换(transfrom)
- 媒体查询(@media 规则在媒体查询中用于为不同的媒体类型/设备应用不同的样式),多栏布局
- 增加了更多的css选择器,属性选择器、结构伪类选择器、伪元素选择器等
- border-image
- 在CSS3中唯一引入的伪元素是 ::selection
ES6新特性
-
变量声明 let const
-
箭头函数
-
模板字符串 : 使用反引号``;在模板字符串里面支持换行,并可以在里面使用${}来包裹一个变量或表达式
-
对象简写 : 对象赋值时如果属性名和变量名一致可以简写
-
解构赋值 : 有数组解构和对象解构;可以快速获取数组和对象的值;
-
展开运算符 :… 可以将数组或者对象进行展开
-
promise :解决异步编程,解决了异步回调地狱问题,底层是构造函数,3个原型方法then catch finally ,几个静态方法 resolve、 reject 、race、all
-
模块化语法 export 和 export default
this指向
- 普通函数 ----------> window
- 定时器函数 -------> window
- 事件函数 ----------> 事件源
- 对象函数 ----------> 对象本身
- 箭头函数 ----------> 箭头函数没有自己的this,父function中的this, 父没有function就是window
- 构造函数 ----------> new出来的对象
- call/apply/bind —> 自定义
call/apply/bind 自定义方法,作用,应用场景
call、apply、bind都是改变this指向的,三者传参第一个参数都是this指向的对象,
如果没有这个参数或者为undefined或null的话,指向全局的window;
call第二个参数开始传的是以逗号分隔的参数列表;
apply第二个参数接收的是数组;
bind第二个参数开始传的也是以逗号分隔的参数列表。
call/apply都是直接执行并改变this指向,
bind不会立马执行,而是返回绑定this之后的新函数
回流 重绘
回流:重新布局(width、height、border、top、margin、display:none
重绘:重新绘制样式不影响布局(color、background、visibility
跨域
跨域:受浏览器同源策略的限制
同源策略:当前页面的url和请求的url 协议、域名、端口号 均相同
【http协议默认端口80,https协议默认端口443】
解决跨域的方法:
- jsonp:使用script标签的src属性。类似前端声明一个函数,后端返回执行函数。只支持get请求;
- CORS方式:后端配置响应头;
- node正向代理:webpack的devServer的proxy对象中配置,前端;
- nginx的反向代理:nginx的全局server块的location块中配置,后端;
- 浏览器安装插件:http-proxy-middleware
- 浏览器允许跨域设置:在属性页面中的目标输入框里加上 --disable-web-security
浏览器的存储方式
H5 与 cookie
性能角度:相对而言H5存储性能比COOKIE高
存储空间:H5单条数据5M左右、COOKIE单条数据4KB
生命周期:
cookie — 自己设置,如果不设置浏览器关闭销毁
h5 localStorage — 永久
h5 sessionStorage — 窗口
浏览器输入网址后
浏览器输入网址回车 —》
到DNS服务器找网址对应的IP地址 —》
根据IP地址加端口访问服务器软件 —》
服务器返回数据 —》
浏览器Renderer渲染进程处理,其中,GUI渲染线程进行页面布局,由js引擎解析js代码。
js事件三个阶段和顺序
1.捕获阶段(事件捕获):事件对象从目标的祖先节点Window开始传播直至目标。
2.目标阶段:事件对象传递到事件目标。 如果事件的type属性表明后面不会进行冒泡操作,那么事件到此就结束了。
3.冒泡阶段(事件冒泡):事件对象以一个相反的方向进行传递,从目标开始,到Window对象结束。
事件循环
事件循环:同步任务先放到执行栈中执行,异步任务由任务进程处理放到任务队列中,执行栈中的任务执行完毕会去任务队列中查看是否有异步任务执行,由于主线程不断地获取任务,执行任务,再获取,再执行,这种机制被称为事件循环event loop。
异步任务 又被称为 微任务(microtask)-- promise、async/await ,宏任务(macrotask)-- 定时器、ajax、dom事件,先微任务,再宏任务。
注:new Promise在实例化的过程中所执行的代码都是同步进行的,而 Promise.then 中注册的回调才是异步执行的。
微任务与宏任务的根本区别:
微任务 – ES6语法规定的API
宏任务 – 浏览器定义的API
执行顺序:同步–> 微任务–> 触发DOM渲染–> 宏任务
同步、异步的理解
同步:任务一个一个执行,第一个执行完了才能执行下一个
异步:任务同时执行,第一个任务没有执行完,可以执行下一个
对ajax 的理解
异步javascript和xml ,是js和后端语言交互的方式。
- ajax的好处:
异步的,页面不用刷新(局部刷新)就发送请求,可以减少HTTP请求 减轻后端服务器压力,提高了性能和速度 - 应用场景:
用ajax进行数据验证;按需取数据;自动更新页面
Promise
概念:ES6中异步编程的解决方案
作用:解决传统异步请求XHR横向太深问题
原理:底层创建了Promise构造函数,在这个构造函数上有3个原型方法then、catch、finally,还有几个静态方法 如 resolve、reject、all、race等,第一个then可以交给下一个then处理,由于then返回了新的promise所以可以链式调用。
// 笔试
class Promise{
PromiseState="pending"
PromiseResult=null
constructor(callback){
function resolve(){}
function reject(){}
callback(resolve,reject)
}
then(){}
catch(){}
finally(){}
}
Promise.resolve=function(){}
Promise.reject=function(){}
Promise.all=function(){}
Promise.race=function(){}
let p = new Promise((resolve, reject) => {
resolve(data)
})
async/await
概念:ES7中异步编程的解决方案
可以直接将所有异步代码改为同步
async修饰function,await修饰promise
原理:async/await是generator的语法糖
节流防抖
节流防抖都是用来进行项目优化,减少代码触发的频率,同时又不影响实际效果。
节流:一段时间内,代码仅执行一次。使用return中断
【如:高频事件-快速点击、鼠标滑动】
判断定时器,直接返回 if (t) return
防抖:一段时间内代码可重复执行,但是必须清除上一次的代码。清除定时器
【如:搜索框搜索输入请求】
判断定时器,清除定时器 if(t) clearTimeout(t)
// 节流
let t
标签对象.事件类型 = function(){
if(t) return // return返回,不再继续往下执行
t=setTimeout(()=>{
// 异步代码
t=null
})
}
// 防抖 ,一直触发事件是不会执行定时器中的代码的,会随着定时器被清除,停下来之后到了定时器的时间,才会执行定时器中的代码
let t
标签对象.事件类型 = function(){
if(t) clearTimeout(t)
t=setTimeout(()=>{
// 异步代码
})
}
应用场景:
节流:鼠标不断点击触发,mousedown(单位时间内只触发一次),监听滚动事件,比如是否滑到底部自动加载更多。
防抖:search搜索联想,用户在不断输入值时,用防抖来节约请求资源。
开发一般用lodash库里的throttle(节流)、debounce(防抖)来做。
对http协议的理解
概念:超文本传输协议
作用:规定客户端和服务端通信技术
场景:网页、APP等
请求组成:请求行(地址/状态码/请求方式)、请求头(请求的编码方式、cookie)、请求体(接口参数
响应组成:响应行(同上)、响应头(是否允许跨域、响应的编码方式)、响应体(接口数据调试错误
http状态码
200 成功
201 成功并创建新资源
301 永久重定向
302 临时重定向
304 浏览器缓存
400 参数有误
401 密码错误
403 没有权限
404 文件不存在
405 请求方式有误
500 服务器错误
http 与 https 区别
安全角度:http 明文传输,数据都是未加密的,安全性较差,https (SSL+http ) 数据传输过程是加密的,安全性较好
端口角度:http 默认端口80,https 默认端口443
get和post区别
1、安全角度:get相对没有post安全,因为如果登录账号密码会在历史记录中找到;
2、数据角度:get相对没有post多,get不同浏览器限制地址栏长度不同,post根据后端服务器配置普遍2M~8M;
3、按照规范,定义 get请求是用来获取资源的,也就是进行查询操作的;而 post请求是用来传输实体对象的,因此会使用 post来进行添加、修改等操作;
4、按照约定,get和 post的参数传递不同,get请求是将参数拼到 URL 上进行参数传递; post是将请参数写入到请求正文中传递的;
CSS预处理器
CSS预处理:专门为CSS提供的编程语言,先用另一种方式写CSS,再转换为真的CSS
好处:减少代码冗余,提高代码复用,便于团队开发,加快项目开发速度
sass、less区别:
相同点都是css预处理器;
不同点:
1、开发角度
- Sass是基于Ruby的,是在服务器端处理;
- Less是基于javascript,是在客户端处理的;
2、语法角度
- sass使用$声明变量,less使用@声明变量
- 混入语法不同, sass使用@mixin ,less使用点 .
- 实现方式
网页的优化
-
使用CDN资源
-
keep-alive组件懒加载
-
路由懒加载
-
图片懒加载
-
UI框架按需加载
图片优化补充 :css精灵图
1)CDN
unpkg.com/库名
前端公共的CDN服务
CDN: 能够加快静态资源访问的技术
原理 : 缓存机制 将用户访问的文件缓存到用户所在处城市
2)图片懒加载原理
先将img标签的src链接设为同一张图片(比如空白图片),然后给img标签设置自定义属性(比如 data-src),然后将真正的图片地址存储在data-src中,当JS监听到该图片元素进入可视窗口时,将自定义属性中的地址存储到src属性中,达到懒加载的效果。
条件:判断每张图片到网页左上角的距离 <= 可视窗口高度 + 浏览器卷去的高度
offset().top <= (window).height() + (window).scrollTop();
参考链接:https://www.jianshu.com/p/8e2a73638153
3)路由懒加载
路由懒加载是由 vue的异步组件 结合 代码切割功能 实现的
原理: 使用了webpack提供的代码切割功能,将这个页面单独分离成一个包,
好处是 当前页面被访问的时候才会被加载出来,
这样做的目的是 加快首页的渲染速度,提高用户体验
实现 :使用箭头函数
常见的 Web 攻击手段
- XSS
XSS 攻击的全称为 跨站脚本攻击(Cross Site Scripting),(为了不跟层叠样式表CSS混淆,命名为XSS)
攻击者常常在网页中嵌入了恶意的脚本程序,当用户打开该网页的时候,脚本程序便开始在客户端的浏览器后台执行,常用于盗取客户端的 cookie,用户名密码,下载执行病毒的木马程序,以及获取客户端 Admin 权限。
防护手段:对入参进行校验,比如 <、>、“、”、’、’ 这些特殊字符我们很有必要进行转义与校验。 - CSRF 攻击
CSRF 攻击全称 跨站请求伪造 (Cross site request forgery)。是一种对网站的恶意利用,我们上面说到的 XSS攻击 是利用站点内的信任用户,自己去触发脚本而导致的攻击。而 CSRF 则是通过伪装来自受信任用户的请求去利用受攻击的网站。
防护手段:将 cookie 设置为 HttpOnly;增加随机生成的 token;通过 Referer - SQL 注入攻击
通过把 SQL 命令伪装成正常的请求参数,传递到服务端,欺骗服务器最终执行恶意的 SQL命令,达到入侵的目的。
攻击者常常利用 SQL 注入的漏洞,来查询非授权的关键信息,修改数据库服务器的数据,改变表结构,危害极大! - 文件上传漏洞
文件上传的时候,没有对于文件的类型进行处理,从而导致攻击者上传了一些恶意的脚本程序,从而达到攻击的目的
浏览器兼容性问题
1.不同浏览器的标签默认的外补丁(margin)和内补丁(padding)不同
解决:经常需要加一个重置文件reset.css,将margin、padding置为0
2.CSS3兼容前缀表示不同,前缀分为:-webkit-,-ms-,-moz-,-o-
解决: -webkit-:主要兼容的浏览器是:谷歌的Chrome和苹果的Safari浏览器;
-ms-:主要兼容的浏览器是:微软的Internet Explorer、Edge浏览器;
-moz-:主要兼容的浏览器是:火狐的Firefox浏览器;
-o-:主要兼容的浏览器是:欧朋的Opera浏览器;
AJAX
AJAX (异步 JavaScript 和 XML)。是一种用于创建快速动态网页的技术。 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新.
ajax请求有几个步骤?分别是什么
//创建 XMLHttpRequest 对象
var ajax = new XMLHttpRequest();
//规定请求的类型、URL 以及是否异步处理请求。
ajax.open('GET',url,true);
//发送信息至服务器时内容编码类型
ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
//发送请求
ajax.send(null);
//接受服务器响应数据
ajax.onreadystatechange = function () {
if (obj.readyState == 4 && (obj.status == 200 || obj.status == 304)) {
}
};
XML
XML是扩展标记语言,能够用一系列简单的标记描述数据
AJAX优点、缺点
优点:
1、最大的一点是页面无刷新,用户的体验非常好。
2、使用异步方式与服务器通信,具有更加迅速的响应能力。
3、可以把以前一些服务器负担的工作转嫁到客户端,利用客户端闲置的能力来处理,减轻服务器和带宽的负担,节约空间和宽带租用成本。并且减轻服务器的负担,ajax的原则是“按需取数据”,可以最大程度的减少冗余请求,和响应对服务器造成的负担。
4、基于标准化的并被广泛支持的技术,不需要下载插件或者小程序。
缺点:
1、ajax不支持浏览器back按钮。
2、安全问题 AJAX暴露了与服务器交互的细节。
3、对搜索引擎的支持比较弱。
4、破坏了程序的异常机制。
5、不容易调试。
JSON
JavaScript Object Notation 【JavaScript 对象表示法】
JSON是一种轻量级的数据交换格式。
简单说就是javascript中的对象和数组,常用的json就是将json转换成字符串,字符串转换成对象。
JSON 要求在字符串和属性名称周围使用双引号。单引号无效。
json常用API:
parse():以文本字符串形式接受 JSON 对象作为参数,并返回相应的对象。
stringify():接收一个对象作为参数,返回一个对应的 JSON 字符串。
canvas 画布
canvas绘图是通过在HTML文档中创建一个画布(canvas)来进行的。canvas本身没有任何外观,它的宽度和高度可以通过canvas的属性设置。在绘图时,可以使用JavaScript的Canvas API来绘制各种形状和图像。
需要注意的是,canvas的宽度和高度应该直接在canvas的属性中设置,而不是在CSS中定义。
// 定义canvas元素(写在html文件的body中):
// id 是canvas元素的标识;
// width、height是canvas画布的宽、高,单位为像素;
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>canvas</title>
<style type="text/css">
#canvas {
background-color:yellow;
}
</style>
</head>
<body>
<!-- 定义canvas元素 -->
<!-- id 是canvas元素的标识 -->
<!-- width、height是canvas画布的宽、高,单位为像素 -->
<canvas id="canvas" width="1000" height="500">
<script>
let mycanvas = document.getElementById('canvas'); // 获取对象的方法
let ctx = mycanvas.getContext('2d'); // 获取canvas对象的2D绘图上下文
// 绘制三角形
ctx.beginPath(); // 指示开始绘图路径
ctx.moveTo(100,200); // 将坐标移至起点
ctx.lineTo(400,200); // 绘制直线
ctx.lineTo(50,300);
ctx.closePath(); // 指示闭合绘图路径
ctx.strokeStyle="red";
ctx.stroke(); // 绘制图形的边界轮廓
</script>
</canvas>
</body>
</html>
画三角形
<div style="display: flex;width: 200px;justify-content: space-between;">
<div class="triangle1"></div>
<div class="triangle2"></div>
<div class="triangle3"></div>
<div class="triangle4"></div>
</div>
<style>
.triangle1{
width:0;
height:0;
border-right:30px solid transparent;
border-left:30px solid transparent;
border-bottom:30px solid red;
}
.triangle2{
width:0;
height:0;
border-right:30px solid transparent;
border-left:30px solid transparent;
border-top:30px solid red;
}
.triangle3{
width:0;
height:0;
border-top:30px solid transparent;
border-bottom:30px solid transparent;
border-right:30px solid red;
}
.triangle4{
width:0;
height:0;
border-top:30px solid transparent;
border-bottom:30px solid transparent;
border-left:30px solid red;
}
</style>
<!--
向上三角形,不设置 border-top
向下三角形,不设置 border-bottom
向左三角形,不设置 border-left
向右三角形,不设置 border-right
-->