一、闭包
《JavaScript高级程序设计》:
闭包是指有权访问另一个函数作用域中的变量的函数
《JavaScript权威指南》:
1、函数嵌套函数
2、函数内部可以引用外部的参数和变量
3、参数和变量不会被垃圾回收机制回收
闭包更准确的说是一项技术或者一个特性
闭包的主要是为了解决ES6之前JavaScript只有全局作用域和局部作用域的问题,解决全局作用域下变量易被污染,函数作用域下由于JavaScript垃圾回收机制函数调用结束后变量随之销毁的问题。通过函数嵌套并将返回的函数赋值给一个变量,形成一个作用域链,使得被赋值的变量不被销毁之前函数也不会销毁,这种技术或者特性应该被称为“闭包”。
应用场景
1、防抖节流
2、创建私有函数、变量或方法
3、给某些(框架等)定义好的函数额外传参,如element-ui可搜索输入框的fetch-suggestions方法
getName(id) {
return (val, callback) => {
let result = []
if (val === '' || !val) { // 还没输入,则不发请求
return callback(result)
}
}
},
缺陷
1、由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
2、可能造成内存泄漏,部分人认为IE浏览器会,新的不会,部分人认为会。
要知道内存泄漏的原因——通常来讲是引用无法被释放。
比如你构造了一个lambda,其会持有一份上下文引用,如果这个lambda无法被释放的话,其持有的上下文引用也无法被释放,这样就会造成内存泄漏,久而久之就会撑爆客户的内存。因此要避免「局部构造,全局持有」的情况,这样就不容易出现内存泄漏,通常随着局部上下文的销毁,其中的所有资源都能被回收。但如果出现了「局部构造,全局持有」的情况,则就算局部上下文被「销毁」,也无法回收其资源,比较常见的例子就是你在某个组件里mounted时创建了一个定时器,并且没有unmounted 或 beforeDestroy 时销毁这个定时器,这就会造成内存泄漏。setimeout会自动销毁,但interval不会,interval会一直触发,直到被销毁。
内存泄漏 —— 王一鹏
二、BFC
定义
BFC(Block formatting context)直译为"块级格式化上下文"。它是一个独立的渲染区域,只有Block-level box参与, 它规定了内部的Block-level Box如何布局,并且与这个区域外部毫不相干。
Formatting Context
Formatting context 是 W3C CSS2.1 规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。最常见的 Formatting context 有 Block fomatting context (简称BFC)和 Inline formatting context (简称IFC)。
BFC是一个独立的布局环境,其中的元素布局是不受外界的影响,并且在一个BFC中,块盒与行盒(行盒由一行中所有的内联元素所组成)都会垂直的沿着其父元素的边框排列。
BFC的布局规则
* 内部的Box会在垂直方向,一个接一个地放置。
* Box垂直方向的距离由margin决定。属于**同一个**BFC的两个相邻Box的margin会发生重叠。
* 每个盒子(块盒与行盒)的margin box的左边,与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
* BFC的区域不会与float box重叠。
* BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
* 计算BFC的高度时,浮动元素也参与计算。
创建BFC
* 1、float的值不是none。
* 2、position的值不是static或者relative。
* 3、display的值是inline-block、table-cell、flex、table-caption或者inline-flex
* 4、overflow的值不是visible
应用场景
1、清除浮动
2、两栏自适应布局
3、避免外边距塌陷
引自 https://blog.csdn.net/sinat_3...
三、清除浮动
定义
在非IE浏览器下,当容器的高度为auto,且容器的内容中有浮动(float为left或right)的元素,在这种情况下,容器的高度不能自动伸长以适应内容的高度,使得内容溢出到容器外面而影响(甚至破坏)布局的现象,这种现象叫做浮动溢出。为了防止这个现象的出现而进行的CSS处理,成为CSS清除浮动。
清除浮动的方法可以分为两类:
1、是利用clear属性,在浮动元素末尾添加一个带有clear:both属性的空元素
2、是触发浮动元素父元素的BFC,使得该父元素可以包含浮动元素。
使用带clear属性的空元素
1、在浮动元素后面使用一个空元素比如<div class="clear"></div>,并在CSS中赋予.clear { clear: both;}属性即可清除浮动
2、使用CSS的:after伪元素。给浮动元素的容器添加一个clearfix的class,然后给这个class添加一个:after伪元素实现元素末尾添加一个看不到的块元素清除浮动
/* 浮动元素的父元素 */
.clearfix {
/* 兼容IE,触发hasLayout*/
zoom: 1;
}
/* 添加一个块级的空元素,并且设置clear属性 */
.clearfix:after {
content: '';
display: block;
clear: both;
}
3、给浮动元素后面的元素添加clear属性
触发父元素的BFC
1、设置浮动元素的父元素的overflow: hidden或overflow: auto。触发BFC。另外在IE6中还需要触发hasLayout,例如为父元素设置宽高或者zoom:1。
2、给浮动元素的容器也添加浮动,整体浮动,不推荐
引自 https://www.yuque.com/4amgodv...
四、<script>的defer和async
script
标签用于加载脚本与执行脚本,在前端开发中可以说是非常重要的标签了。直接使用script
脚本的话,html
会按照顺序来加载并执行脚本,在脚本加载&执行的过程中,会阻塞后续的DOM
渲染。
defer定义
`defer`属性规定是否对脚本执行进行延迟,直到页面加载为止。如果`script`标签设置了该属性,则浏览器会异步的下载该文件并且不会影响到后续`DOM`的渲染;如果有多个设置了`defer`的`script`标签存在,则会按照顺序执行所有的`script`。`defer`脚本会在文档渲染完毕后,`DOMContentLoaded`事件调用前执行。
async定义
`async`的设置,会使得`script`脚本异步的加载并在允许的情况下执行`async`的执行,并不会按着`script`在页面中的顺序来执行,而是谁先加载完谁执行。
区别
async属性是HTML5新增的。作用和defer类似,但是它将在下载后尽快执行,不能保证脚本会按顺序执行。它们将在onload 事件之前完成。
引自 https://www.cnblogs.com/jiasm...
五、cookie储存及其原理
https://blog.csdn.net/chao821...
六、sessionStorage、localStorage、cookie异同
- 存储位置: cookie是网站为了标识用户身份而保存在客户端中的数据,它始终在同源的HTTP请求中携带,也就是会在客户端与服务端之间来回传递。而sessionStorage和localStorage不会主动把数据发送给服务端,仅在本地保存。
- 存储大小: cookie数据大小不能超过4K,而sessionStorage和localStorage虽然也有存储大小的限制,但是远比cookie大,可以达到5M甚至更大。
- 生命周期: cookie在设置的过期时间之前一直有效,即使窗口或者浏览器关闭,sessionStorage数据在当前浏览器关闭后自动删除,localStorage存储持久数据,浏览器关闭后数据不丢失除非主动删除。
- 共享:cookie在同源和符合path规则的文档之间共享,而sessionStorage不能共享,localStorage在同源的文档之间共
七、判断数据类型及数组的方法
typeof
typeof 表达式
typeof 1; // number
结果为字符串
- 对于基本类型,除 null 以外,均可以返回正确的结果。
- 对于引用类型,除 function 以外,一律返回 object 类型。
- 对于 null ,返回 object 类型。
- 对于 function 返回 function 类型
- 不可判断数组
instanceof
instanceof 检测的是原型,表达式为:A instanceof B。如果 A 是 B 的实例,则返回 true,否则返回 false。
数组:[] instanceof Array
constructor
A.constructor === B
1. null 和 undefined 是无效的对象,因此是不会constructor 存在的,这两种类型的数据需要通过其他方式来判断。
2. 函数的 constructor 是不稳定的,这个主要体现在自定义对象上,当开发者重写 prototype 后,原有的 constructor 引用会丢失,constructor 会默认为 Object。
数组:[].constructor === Array
toString
Object.prototype.toString.call(value);
返回格式为 [object XXX]
数组:Object.prototype.toString.call([]) 【object Array】
isArray()
function myFunction() {
var fruits = ["Banana", "Orange", "Apple", "Mango"];
var x = document.getElementById("demo");
x.innerHTML = Array.isArray(fruits);
}
isArray() 方法用于判断一个对象是否为数组。
如果对象是数组返回 true,否则返回 false。
等等。。。
八、拷贝
最简单的深拷贝。。。吧:
// 克隆传入的对象
easyClone(entity) {
return JSON.parse(JSON.stringify(entity))
},
缺点:拷贝其他引用类型、拷贝函数、循环引用等情况无法实现。因为这两者基于JSON.stringify和JSON.parse处理后,得到的正则就不再是正则(变为空对象),得到的函数就不再是函数(变为null)了。
let arr = [1, 3, {
username: ' kobe'
},function(){}];
let arr4 = JSON.parse(JSON.stringify(arr));
arr4[2].username = 'duncan';
console.log(arr, arr4)
浅拷贝
1、let obj2 = Object.assign({}, obj1)
2、let obj2= {... obj1}
3、let arr2 = arr.concat()
4、let arr3 = arr.slice()
深拷贝
不包含set map function 正则版
function forEach(array, iteratee) {
let index = -1
const length = array.length
while (++index < length) {
iteratee(array[index], index)
}
return array;
}
function isObject(target) {
const type = typeof target
return target !== null && (type === 'object' || type === 'function')
}
function clone(target, map = new WeakMap()) {
// 克隆原始类型
if (!isObject(target)) {
return target
}
//undefind
if (typeof target === 'undefined') return null
// 初始化
const isArray = Array.isArray(target)
let cloneTarget = isArray ? [] : {}
// 防止循环引用
if (map.get(target)) {
return map.get(target);
}
map.set(target, cloneTarget);
// 克隆对象和数组
const keys = isArray ? undefined : Object.keys(target)
forEach(keys || target, (value, key) => {
if (keys) {
key = value
}
cloneTarget[key] = clone(target[key], map);
});
return cloneTarget
}
部分引自 https://juejin.cn/post/684490...
部分引自 https://segmentfault.com/a/11...
九、事件委托的优点
1、节省内存占用,减少事件注册
2、新增子元素时无需再对其绑定事件,适合动态添加元素
十、vue 组件通信方式
1、props/$emit
2、$children/$parent
3、provide/inject
4、ref
5、eventBus
6、loaclStorge/sessionStorge
7、$attrs/$listeners
8、VueX
详见 https://juejin.cn/post/684490...
详见 https://segmentfault.com/a/11...
总结
常见使用场景可以分为三类:
- 父子组件通信:
props
;$parent
/$children
;provide
/inject
;ref
;$attrs
/$listeners
- 兄弟组件通信:
eventBus
; vuex - 跨级通信:
eventBus
;Vuex;provide
/inject
、$attrs
/$listeners
十一、服务端渲染和客户端渲染
详见 https://www.cnblogs.com/zhuzh...
十二、herf和src区别
总结:href用于建立当前页面与引用资源之间的关系(链接),而src则会替换当前标签。遇到href,页面会并行加载后续内容;而src则不同,浏览器需要加载完毕src的内容才会继续往下走。
引自 https://www.cnblogs.com/kuai-...
十三、Map和Set
数组方法 map()
1、 map()
对数组的每一项都运行给定的函数,返回每次函数调用的结果组成一个新数组
var numbers = [1, 5, 10, 15];
var doubles = numbers.map(function(x) {
return x * 2;
});
// doubles is now [2, 10, 20, 30]
// numbers is still [1, 5, 10, 15]
数据结构 Map()和Set()
1、Map()
ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合。
但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以作键。
Map 也实现了iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历。Map 的属性和方法:
(1)size返回 Map 的元素个数
(2)set增加一个新元素,返回当前 Map
(3)get返回键名对象的键值
(4)has检测 Map 中是否包含某个元素,返回 boolean 值
(5)clear 清空集合,返回 undefined
2、Set()
ES6 提供了新的数据结构 Set(集合)。
它类似于数组,但成员的值都是唯一的,集合实现了 iterator 接口.
所以可以使用『扩展运算符』和『for…of…』进行遍历,集合的属性和方法:
1) size 返回集合的元素个数
2) add 增加一个新元素,返回当前集合
5)delete 删除元素,返回 boolean 值
6)has检测集合中是否包含某个元素,返回 boolean 值
7)clear 清空集合,返回 undefined
十四、vue 组件化
定义
用户对项目程序中具有独立逻辑、具有复用性的功能模块单独提取出来进行封装,这就是组件化的定义。组件化开发能大幅提高应用开发效率、测试性、复用性等。
优点
- 组件是独立和可复用的代码组织单元。组件系统是 Vue 核心特性之一,它使开发者使用小型、独立和通常可复用的组件构建大型应用;
- 组件化开发能大幅提高应用开发效率、测试性、复用性等;
- 组件使用按分类有 :页面组件、业务组件、通用组件;
- vue的组件是基于配置的,我们通常编写的组件是组件配置而非组件,框架后续会生成其构造函数,它们基于VueComponent,扩展于Vue;
- vue中常见组件化技术有: 属性prop,自定义事件,插槽等,它们主要用于组件通信、扩展等;
- 合理的划分组件,有助于提升应用性能;
- 组件应该是高内聚、低耦合的;
- 遵循单向数据流的原则。
引自 https://blog.csdn.net/qq_3678...
十五、vue 响应式原理
初始化
当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data
选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty
把这些 property 全部转为 getter/setter。
收集依赖
每个组件都对应一个Watcher,当外界通过Watcher读取数据时,便会触发getter从而将Watcher添加到依赖中,哪个Watcher触发了getter,就把哪个Watcher收集到Dep中。当数据发生变化时,会循环依赖列表,把所有的Watcher都通知一遍。
派发更新
在修改对象的值的时候,会触发对应的setter
, setter
通知之前依赖收集得到的 Dep 中的每一个 Watcher,告诉它们自己的值改变了,需要重新渲染视图。这时候这些 Watcher就会开始调用 update
来更新视图。
部分引自 https://cn.vuejs.org/v2/guide...
部分引自 https://www.cnblogs.com/funde...
参考 https://zhuanlan.zhihu.com/p/...
十六、浏览器同源、跨域
同源
同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说 Web 是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
所谓同源是指:域名、协议、端口相同。
跨域
1、AJAX 跨域
* JSONP
* WebSocket
* CORS
2、其他
* document.domain 跨域
* window.name 跨域
* location.hash 跨域
* postMessage 跨域
参考 http://www.ruanyifeng.com/blo...
参考 http://www.ruanyifeng.com/blo...
参考 https://www.cnblogs.com/laixi...
参考 https://www.cnblogs.com/2050/...
十七、重绘回流
https://segmentfault.com/a/11...
十八、防抖节流
https://mp.weixin.qq.com/s/qy...
十九、this指向
https://mp.weixin.qq.com/s/hY...
二十、从输入url到页面呈现
在输入URL后,浏览器首先要找到这个URL中的域名对应的IP地址。浏览器首先会从缓存当中查找,如果缓存中没有会到系统的hosts文件中查找,如果hosts文件中没有则查询DNS服务器。找到IP地址后,浏览器会根据这个IP地址和对应的端口号,构造一个HTTP请求,并且将请求封装在一个TCP包中,这个TCP包依次会经过传输层,网络层,数据链路层,物理层到达服务器,服务器解析这个请求来作出响应,返回相应的HTML给浏览器,浏览器根据这个HTML来构建DOM树,在DOM树的构建过程中如果遇到JS脚本和外部JS链接,则会停止构建DOM树来下载和执行相应的代码,这就是为什么推荐JS代码应该放在HTML代码后面。之后根据外部样式,内部样式,内联样式构建一个CSS对象模型树CSSOM树,构建完成后与DOM树合并为渲染树,这里主要做的是排除非视觉节点,比如script,meta标签和排除display为none的节点。之后进行布局。布局主要是确定各个元素的位置和尺寸,然后是渲染页面。因为HTML文件中会含有图片,视频,音频等资源,在解析DOM的时候,遇到这些都会并行下载。浏览器对每个域的并行下载数量有一定的限制,一般是4-6个
https://www.yuque.com/4amgodv...
二十一、前端性能优化
https://www.cnblogs.com/lanxi...
二十二、flex
http://www.ruanyifeng.com/blo...
二十三、vue 中不能使用箭头函数的情况
1.不应该使用箭头函数来定义一个生命周期方法
2.不应该使用箭头函数来定义 method 函数
3.不应该使用箭头函数来定义计算属性函数
4.不应该对 data 属性使用箭头函数
5.不应该使用箭头函数来定义 watcher 函数
原因:箭头函数绑定了父级作用域的上下文,this 将不会按照期望指向 Vue 实例。也就是说,你不能使用this来访问你组件中的data数据以及method方法了。this将会指向undefined。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。