1. 关于设计一点事
点点滴滴慢慢积累设计干货: mp.weixin.qq.com/s/TGkjEV0F7…
- 图片设计: 利用墙壁阴影与相框(添加植物增强生活气氛)
- UI准备工作:UI配色、 背景模块设计、 字体大小颜色规范、 图片大小格式规范、 留白规范、 按钮样式统一
2. 好用的新特性
-
指数运算: 2**(3**2) ==> 512
-
扩展运算符: (浅拷贝)
- 复制数组
let a = [1,3,32] let a1 = [...a1] // [1,3,32]
- 合并数组:
let a2 = [...a,...a1] // [1,3,32,1,3,32]
- 将字符串转换为数组:
let str = 'str'; [..str] // ['s','t','r']
3. 浅拷贝vs深拷贝
一、堆和栈的区别
深拷贝和浅拷贝的主要区别就是其在内存中的存储类型不同。
堆和栈都是内存中划分出来用来存储的区域
栈(stack)为自动分配的内存空间,它由系统自动释放;而堆(heap)则是动态分配的内存,大小不定也不会自动释放。
二、 数据类型
基本数据类型
- 基本数据类型主要是:undefined,boolean,number,string,null
- 基本数据类型存放在栈中
- 基本数据类型值不可变
- 基本类型的比较是值的比较
引用类型
- 引用类型存放在堆中
- 引用类型值可变
- 引用类型的比较是引用的比较
深拷贝:将 B 对象拷贝到 A 对象中,包括 B 里面的子对象,
浅拷贝:将 B 对象拷贝到 A 对象中,但不包括 B 里面的子对象
和原数据是否指向同一对象 | 第一层数据为基本数据类型 | 原数据中包含子对象 | |
---|---|---|---|
赋值 | 是 | 改变会使原数据一同改变 | 改变会使原数据一同改变 |
浅拷贝 | 否 | 改变不会使原数据一同改变 | 改变会使原数据一同改变 |
深拷贝 | 否 | 改变不会使原数据一同改变 | 改变不会使原数据一同改变 |
三、 浅拷贝缺陷
由于对象、数组是引用型数据,特点是该数据是存放在堆中,通过指针引用地址获取值,因而赋值时,只是将 aObj 的指针 赋予 bObj (let bObj = aObj),实际上aObj与bObj存储的地址是一样的,也就是说,若bObj.value = 2 , aObj.value也会等于2,同理,改变aObj的值也影响bObj,这就是浅拷贝所带来的缺点
如果将浅拷贝转为深拷贝
典型案例就是经常遇见的数组对象赋值问题,因为对象的深度不一,类型也不一,经常赋值时,因为浅拷贝原因而影响到了源数据数值
常见的解决方案:
-
解构赋值
只适用于只有一层数组或对象,若数组里包括对象,则依然有影响
-
JSON.parse( JSON.stringify( Array || Object ) )
这个是最易用的解决方案,原理是将引用型数据(数组、对象)转化为 字符串,改变存储位置从而达到深拷贝效果,但是缺点也很明显,在项目中,常常会因为其中包括特殊符号而赋值失败,如:在对象中含有富文本、对象中包括了函数
-
深拷贝转浅拷贝方法
原理: 分为基本类型数据和引用类型数据进行赋值处理
function deepClone(obj) {
let res = null;
const reference = [Date, RegExp, Set, WeakSet, Map, WeakMap, Error];
if (reference.includes(obj?.constructor)) {
res = new obj.constructor(obj);
} else if (Array.isArray(obj)) {
res = [];
obj.forEach((e, i) => {
res[i] = deepClone(e);
});
} else if (typeof obj === "object" && obj !== null) {
res = {};
for (const key in obj) {
if (Object.hasOwnProperty.call(obj, key)) {
res[key] = deepClone(obj[key]);
}
}
} else {
res = obj;
}
return res;
}
4. 浏览器解析渲染页面:
不用浏览器使用的内核不同,所以他们的渲染过程也是不一样的。目前主要有两个:
webkit渲染过程
Gecko渲染过程
-
根据HTML解析出DOM树
根据 HTML 的内容,将标签按照结构解析成为DOM 树,DOM 树解析的过程是一个深度优先遍历。即先构建当前节点的所有子节点,再构建下一个兄弟节点
在读取 HTML 文档,构建 DOM 树的过程中,若遇到 script 标签,则 DOM 树的构建会暂停,直至脚本执行完毕。 -
根据 CSS 解析生成 CSS 规则树
解析 CSS 规则树时 js 执行将暂停,直至 CSS 规则树就绪
解析 CSS 规则树时 js 执行将暂停,直至 CSS 规则树就绪 -- CSS加载会影响DOM渲染 -
结合DOM树和CSS规则树,生成渲染树
DOM 树和 CSS 规则树全部准备好了以后,浏览器才会开始构建渲染树。
精简 CSS 并可以加快 CSS 规则树的构建,从而加快页面相应速度。 -
根据渲染树计算每一个节点的信息
布局:通过渲染树中渲染对象的信息,计算出每一个渲染对象的位置和尺寸
回流:在布局完成后,发现了某个部分发生了变化影响了布局,那就需要倒回去重新渲染。 -
根据计算好的信息绘制页面
绘制阶段,系统会遍历呈现树,并调用呈现器的“paint”方法,将呈现器的内容显示在屏幕上。
重绘:某个元素的背景颜色,文字颜色等,不影响元素周围或内部布局的属性,将只会引起浏览器的重绘。
回流:某个元素的尺寸发生了变化,则需重新计算渲染树,重新渲染。
5. CSS 加载会造成阻塞吗?
在浏览器的工作中,DOM解析和CSS解析是两个并行的进程,所以这也解释了为什么CSS加载不会阻塞DOM的解析。
-
然而,由于Render Tree是依赖于DOM Tree和CSSOM Tree的,所以他必须等待到CSSOM Tree构建完成,也就是CSS资源加载完成(或者CSS资源加载失败)后,才能开始渲染。因此,CSS加载是会阻塞Dom的渲染的。
-
由于js可能会操作之前的Dom节点和css样式,因此浏览器会维持html中css和js的顺序。因此,样式表会在后面的js执行前先加载执行完毕。所以css会阻塞后面js的执行。
对于浏览器来说,页面加载主要有两个事件,一个是DOMContentLoaded,另一个是onLoad。
onLoad : 等待页面的所有资源都加载完成才会触发
onLoad : 当页面的内容解析完成后,则触发该事件
- 如果页面中同时存在css和js,并且存在js在css后面,则DOMContentLoaded事件会在css加载完后才执行。
- 其他情况下,DOMContentLoaded都不会等待css加载,并且DOMContentLoaded事件也不会等待图片、视频等其他资源加载。
6. 如何提高首频加载速度
- js外联文件放到body底部,css外联文件放到head内
- http静态资源尽量用多个子域名
- 服务器端提供html和http静态资源时最好开启gzip
- 在js,css,img等资源响应的http headers里设置expires,last-modified
- 尽量减少http requests的数量
- js/css/html/img资源压缩
- 使用css spirtes,可以减少img请求次数
- 大图使用lazyload懒加载
- 避免404,减少外联js
- 减少cookie大小可以提高获得响应的时间
- 减少dom elements的数量
- 使用异步脚本,动态创建脚本
7. 请描述一下 cookies,sessionStorage 和 localStorage 的区别?
cookie是网站为了标示用户身份而储存在用户本地终端(Client Side)上的数据(通常经过加密)。
cookie数据始终在同源的http请求中携带(即使不需要),记会在浏览器和服务器间来回传递。
sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。
存储大小:
-
cookie数据大小不能超过4k。
-
sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。
有期时间:
- localStorage : 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据;
- sessionStorage : 数据在当前浏览器窗口关闭后自动删除。
- cookie : 设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭
8. 介绍一下标准的CSS的盒子模型?低版本IE的盒子模型有什么不同的?
(1)有两种, IE 盒子模型、W3C 盒子模型;
(2)盒模型: 内容(content)、填充(padding)、边界(margin)、 边框(border);
(3)区 别: IE的content部分把 border 和 padding计算了进去;
9. 让overflow:scroll平滑滚动?
-webkit-overflow-scrolling: touch;
10. Ajax 解决浏览器缓存问题
1、在ajax发送请求前加上 anyAjaxObj.setRequestHeader("If-Modified-Since","0")。
2、在ajax发送请求前加上 anyAjaxObj.setRequestHeader("Cache-Control","no-cache")。
3、在URL后面加上一个随机数: "fresh=" + Math.random();。
4、在URL后面加上时间戳:"nowtime=" + new Date().getTime();
5、如果是使用jQuery,直接这样就可以了$.ajaxSetup({cache:false})
。这样页面的所有ajax都会执行这条语句就是不需要保存缓存记录
来源: