CSS/HTML
1.flex布局
采用Flex布局的元素,称为Flex容器(flex container),简称"容器"。它的所有子元素自动成为容器成员,称为Flex项目
适用场景:多列盒子浮动时可以采用弹性盒
2.grid布局
CSS Grid(网格)布局,是一个二维的基于网络的布局系统。Flexbox 的出现很大程度上改善了我们的布局方式,但它的目的是为了解决更简单的一维布局,而不是复杂的二维布局(实际上 Flexbox 和 Grid 能协同工作,而且配合得非常好)。Grid(网格) 布局是第一个专门为解决布局问题而创建的 CSS 模块
采用grid布局的元素,被称为grid容器(grid container),简称“容器”。其所有直接子元素(直接子元素的子元素不包含在内)自动成为容器成员,称为grid项目(grid item),简称“项目”
3.常见的行内元素和块级元素都有哪些?
行内元素 inline
不能设置宽高,多个元素共享一行,占满的时候会换行
span、input、img、textarea、label、select
块级元素block
可以设置宽高,一个元素占满一整行
p、h1/h2/h3/h4/h5、div、ul、li、table
inline-block
可以设置宽高,多个元素共享一行,占满的时候会换行
4.请说明px,em,rem,vw,vh,rpx等单位的特性
- px
- 像素
- em
- 当前元素的字体大小
- rem
- 根元素字体大小
- vw
- 100vw是总宽度
- vh
- 100vh是总高度
- rpx
- 750rpx是总宽度
5.常见的替换元素和非替换元素?
- 替换元素
- 是指若标签的属性可以改变标签的显示方式就是替换元素,比如input的type属性不同会有不同的展现,img的src等
- img、input、iframe
- 非替换元素
- div、span、p
6.doctype
标签和meta
标签
doctype
- 告诉浏览器以什么样的文档规范解析文档
- 标准模式和兼容模式
- 标准模式 ->正常,排版和js运作模式都是以最高标准运行
- 兼容模式->非正常
7.script标签中defer和async都表示了什么
众所周知script会阻塞页面的加载,如果我们要是引用外部js,假如这个外部js请求很久的话就难免出现空白页问题,好在官方为我们提供了defer和async
defer
不会阻止页面解析,并行下载对应的js文件
下载完之后不会执行
等所有其他脚本加载完之后,在DOMContentLoaded事件之前执行对应d.js、e.js
async
不会阻止DOM解析,并行下载对应的js文件
下载完之后立即执行
补充,DOMContentLoaded事件
是等HTML文档完全加载完和解析完之后运行的事件
在load事件之前。
不用等样式表、图像等完成加载
8.如何清除浮动
1.父级div 定义height
2.结尾处加空div 标签clear:both
3.父级div 定义伪类:after 和zoom(推荐)
4.父级div 定义overflow:hidden
5.父级div 也浮动,需要定义宽度
6.结尾处加br 标签clear:both
9.什么是DOM事件流?什么是事件委托
DOM事件流
分为三个阶段
捕获阶段
目标阶段
冒泡阶段
在addeventListener()的第三个参数(useCapture)设为true,就会在捕获阶段运行,默认false 冒泡
事件委托
利用冒泡原理(子向父一层层穿透),把事件绑定到父元素中,以实现事件委托
10.link标签和import标签的区别
- link属于html,而@import属于css
- 页面被加载时,link会同时被加载,而@import引用的css会等到页面加载结束后加载。
- link是html标签,因此没有兼容性,而@import只有IE5以上才能识别。
- link方式样式的权重高于@import的。
javascript/jquery
11.JavaScript中什么是基本数据类型什么是引用数据类型?以及各个数据类型是如何存储的?
基本数据类型有
- Number
- String
- Boolean
- Null
- Undefined
- Symbol(ES6新增数据类型)
- bigInt
引用数据类型统称为Object类型,细分的话有
- Object
- Array
- Date
- Function
- RegExp
基本数据类型的数据直接存储在栈中;而引用数据类型的数据存储在堆中,在栈中保存数据的引用地址,这个引用地址指向的是对应的数据,以便快速查找到堆内存中的对象。
栈内存是自动分配内存的。而堆内存是动态分配内存的,不会自动释放。所以每次使用完对象的时候都要把它设置为null,从而减少无用内存的消耗
12.判断数据类型有几种方法
typeof
缺点:typeof null的值为Object,无法分辨是null还是Object
instanceof
缺点:只能判断对象是否存在于目标对象的原型链上
constructor
Object.prototype.toString.call()
一种最好的基本类型检测方式 Object.prototype.toString.call() ;它可以区分 null 、 string 、
boolean 、 number 、 undefined 、 array 、 function 、 object 、 date 、 math 数据类型。
缺点:不能细分为谁谁的实例
call、apply、bind
call和apply实现思路主要是:
判断是否是函数调用,若非函数调用抛异常
通过新对象(context)来调用函数
给context创建一个fn设置为需要调用的函数
结束调用完之后删除fn
bind实现思路
判断是否是函数调用,若非函数调用抛异常
返回函数
判断函数的调用方式,是否是被new出来的
new出来的话返回空对象,但是实例的__proto__指向_this的prototype
完成函数柯里化
Array.prototype.slice.call()
13.什么是作用域,什么是作用域链?
- 规定变量和函数的可使用范围称作作用域
- 每个函数都有一个作用域链,查找变量或者函数时,需要从局部作用域到全局作用域依次查找,这些作用域的集合称作作用域链。
14.什么是闭包?闭包的作用?闭包的应用?
函数执行,形成私有的执行上下文,使内部私有变量不受外界干扰,起到保护和保存的作用
作用:
保护
避免命名冲突
保存
解决循环绑定引发的索引问题
变量不会销毁
可以使用函数内部的变量,使变量不会被垃圾回收机制回收
应用:
设计模式中的单例模式
for循环中的保留i的操作
防抖和节流
函数柯里化
缺点
会出现内存泄漏的问题
15.什么是原型?什么是原型链?如何理解
原型: 原型分为隐式原型和显式原型,每个对象都有一个隐式原型,它指向自己的构造函数的显式原型。
原型链: 多个__proto__组成的集合成为原型链
所有实例的__proto__都指向他们构造函数的prototype
所有的prototype都是对象,自然它的__proto__指向的是Object()的prototype
所有的构造函数的隐式原型指向的都是Function()的显示原型
Object的隐式原型是null
16.说一说 JS 中的常用的继承方式有哪些?以及各个继承方式的优缺点
原型继承、组合继承、寄生组合继承、ES6的extend
原型继承 : 把父类的实例作为子类的原型
缺点:子类的实例共享了父类构造函数的引用属性 不能传参
组合继承
在子函数中运行父函数,但是要利用call把this改变一下,
再在子函数的prototype里面new Father() ,使Father的原型中的方法也得到继承,最后改变Son的原型中的constructor
缺点:调用了两次父类的构造函数,造成了不必要的消耗,父类方法可以复用
优点可传参,不共享父类引用属性
ES6的extend(寄生组合继承的语法糖)
子类只要继承父类,可以不写 constructor ,一旦写了,则在 constructor 中的第一句话必须是 super 。
17.什么是内存泄漏
内存泄露是指不再用的内存没有被及时释放出来,导致该段内存无法被使用就是内存泄漏
18.为什么会导致的内存泄漏
内存泄漏指我们无法在通过js访问某个对象,而垃圾回收机制却认为该对象还在被引用,因此垃圾回收机制不会释放该对象,导致该块内存永远无法释放,积少成多,系统会越来越卡以至于崩溃
19.垃圾回收机制都有哪些策略?
标记清除法
垃圾回收机制获取根并标记他们,然后访问并标记所有来自它们的引用,然后在访问这些对象并标记它们的引用…如此递进结束后若发现有没有标记的(不可达的)进行删除,进入执行环境的不能进行删除
引用计数法
当声明一个变量并给该变量赋值一个引用类型的值时候,该值的计数+1,当该值赋值给另一个变量的时候,该计数+1,当该值被其他值取代的时候,该计数-1,当计数变为0的时候,说明无法访问该值了,垃圾回收机制清除该对象
缺点: 当两个对象循环引用的时候,引用计数无计可施。如果循环引用多次执行的话,会造成崩溃等问题。所以后来被标记清除法取代。
20.深拷贝和浅拷贝
JS数据类型分别基本数据类型和引用数据类型,基本数据类型保存的是值,引用类型保存的是引用地址(this指针)。浅拷贝共用一个引用地址,深拷贝会创建新的内存地址。
浅拷贝方法
直接对象复制
Object.assign
深拷贝
JSON.stringify转为字符串再JSON.parse
深度递归遍历
21.为什么JS是单线程的?
因为JS里面有可视的Dom,如果是多线程的话,这个线程正在删除DOM节点,另一个线程正在编辑Dom节点,导致浏览器不知道该听谁的
22.如何实现异步编程
回调函数
23.var let const 有什么区别
var
var声明的变量可进行变量提升,let和const不会
var可以重复声明
var在非函数作用域中定义是挂在到window上的
let
let声明的变量只在局部起作用
let防止变量污染
不可在声明
const
具有let的所有特征
不可被改变
如果使用const声明的是对象的话,是可以修改对象里面的值的
24.箭头函数和普通函数的区别?箭头函数可以当做构造函数 new 吗?
箭头函数是普通函数的简写,但是它不具备很多普通函数的特性
第一点,this指向问题,箭头函数的this指向它定义时所在的对象,而不是调用时所在的对象
不会进行函数提升
没有arguments对象,不能使用arguments,如果要获取参数的话可以使用rest运算符
没有yield属性,不能作为生成器Generator使用
不能new
没有自己的this,不能调用call和apply
没有prototype,new关键字内部需要把新对象的_proto_指向函数的prototype
25.说说你对代理的理解
代理:保护真实成员,增强真实成员的能力,代替真实成员做事情。
程序中的代理一般指:客户端调用代理的功能(不直接调用真实成员保护),增强真实成员的功能(增加额外的功能增强)。
代理可以为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如,异常处理、日志、计算方法的运行时间、事务管理、等等。
编写一个与目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码。
26.为什么要使用模块化?都有哪几种方式可以实现模块化,各有什么特点?
为什么要使用模块化
- 防止命名冲突
- 更好的分离,按需加载
- 更好的复用性
- 更高的维护性
几种方式:
立即执行函数,使用立即执行函数实现模块化是常见的手段,通过函数作用域解决了命名冲突、污染全局作用域的问题
AMD 和 CMD,
CommonJS,CommonJS 最早是 Node 在使用,目前也仍然广泛使用,比如在 Webpack 中你就能见到它,当然目前在 Node 中的模块管理已经和 CommonJS有一些区别了
ES Module,ES Module 是原生实现的模块化方案
27.跨域的方式都有哪些?他们的特点是什么
1、JSONP 2、代理 3、PHP端修改头部 4、iframe 5.通过 window.name 实现跨域
常用JSONP进行跨域,jsonp形式的ajax请求:并且通过get请求的方式传入参数,
需要注意:跨域请求只能使用get请求不能使用post请求。
-
JSONP
通过同源策略涉及不到的"漏洞",也就是像img
中的src
,link
标签的href
,script
的src
都没有被同源策略限制到。JSONP
只能get请求 -
document.domain 只能跨一级域名相同的域
-
location.hash
+iframe
因为hash传值只能单向传输,所有可以通过一个中间网页,a若想与b进行通信,可以通过一个与a同源的c作为中间网页,a传给b,b传给c,c再传回a
window.name
+iframe
利Access用window.name
不会改变(而且很大)来获取数据, a要获取b的数据,b中把数据转为json格式放到window.name
中
- postMessage
- CORS
- nginx代理跨域
28.数组如何去重
-
ES6 Set去重
-
利用Object key去重
-
两层循环逐一对比,生成新数组
-
indexOf去重
-
sort排序,再单层循环前后对比
29.数组如何排序
-
数组sort排序
-
冒泡排序(两层循环,两两互换)
-
选择排序
-
插入排序
30.防抖和节流
防抖和节流都是希望在同一时间内,不要重复触发请求。一般场景用在搜索和网页滚动事件中。
区别:
防抖主要是在规定时间内只触发一次,如果再次调用,时间从新计算。
节流主要是在固定时间内只触发一次。比如每间隔1秒触发一次。
31.js性能优化
一.两层for循环优化:
数据长度长list的放内层。循环的长度先计算,再放到for循环条件中。比如:var length=arr. length.
for(var i=0;i<length;i++){}
二.页面关闭时,释放不必要的资源。否则造成内存泄露。
三.少用全局变量
四.尽量使用原生方法。
五. 用switch代替if-else.
图片优化,节流,防抖,预渲染,懒加载
32.前端性能优化
前端性能优化的目的:
1. 从用户角度而言:优化能够让页面加载得更快、对用户的操作响应的更及时,能够给用户提供更为良好的体验。
2. 从服务商角度而言:优化能够减少页面请求数,、或者减小请求所占带宽,能够节省可观的资源。
减少HTTP请求
减少DNS查找次数(DNS缓存)
CSS放在 head里面,JS放在body最下面
尽早开始执行js,用DOMContentLoaded触发
懒加载,图片懒加载,上滑加载更多
对DOM查询进行缓存
节流throttle 防抖 debounce
1.封装组件
把所有需要复用的功能或网页模板封装成组件,在需要的时候调用它。
2.图片
压缩图片的质量,或者使用打包工具来压缩图片的质量,当图片过小时(小于12k)可以把它转成base64(代码图片,转成base64的好处:减少http请求),或者使用 sprites(精灵图)把网页中需要用的到图片整合到一张图片中,减少http请求的次数。
3.压缩html,js减小大小,去除空白
4.懒加载(lazy load)
网页不拖动时,未展示的栏目不去(加载)请求,良好的利用服务器资源。
5.设置http缓存
6.减少DOM操作
dom操作是脚本中最耗性能的一个操作,例如:元素的增删改或dom集合的进行的操作
7.将外部脚本置底
不影响html的加载
8.减少作用域链查找
9.不要使用全局变量(能不用的情况下最好不用)
10.少用闭包