时代背景下造就JavaScript是单线程语言,因为当时还没有出现多处理器计算机。
js相关
一、基础知识
1.js数据类型(原始类型与对象类型)
- 原始类型(简单数据类型):
- Boolean
- Number
- String
- Undefined
- Null
- Symbol (ECMAScript6新增的-符号)
2.对象类型(复杂数据类型):
- Object
其中null与 undefined的区别是:
“undefined” 表示值未定义,变量被声明了,但没有赋值时,就等于undefined.
“null” 表示定义了一个空值
2.call、apply、bind的用法及区别
相同点:改变函数体内this的指向
不同点:call、apply的区别:接受参数的方式不一样。bind:不立即执行。而apply、call 立即执行。
let testObj = {
name:'Miracle',
sayHi:function(address1,address2){
console.log("Hello",this.name,"坐标",address1+address2);
}
}
testObj.sayHi.call({name:'Root'},"陕西","西安");
testObj.sayHi.apply({name:'Root'},["陕西","西安"]);
testObj.sayHi.bind({name:'Root'},"陕西","西安")();
testObj.sayHi.bind({name:'Root'},["陕西","西安"])();
3.instanceof的作用
MDN Web Docs解释:
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
4.统计页面中用了标签数量
- document.querySelectorAll('*'); //获取当前页面中所有标签元素
Element.querySelectorAll()
document.querySelectorAll('*')
console.log(new Set([...document.querySelectorAll("*")].map(tag=>tag.tagName)).size)
2.查看最高的前三种元素
主要是使用reduce的用法
Object.entries([...document.querySelectorAll("*")].map(tag=>tag.tagName).reduce((ret, i)=>{
ret[i] = (ret[i] || 0) + 1;
return ret;
}, {})).sort((a, b)=>(b[1] - a[1])).slice(0, 3)
.map(a=>(`${a[0]}: ${a[1]}次`)).join(', ')
二、进阶部分
1.节流与防抖
在开发中,我们常常会去监听滚动事件或者用户输入框验证事件,如果事件处理没有频率限制,就会加重浏览器的负担,影响用户的体验感,因此,我们可以采取防抖(debounce)和节流(throttle)来处理,减少调用事件的频率,达到较好的用户体验。
防抖动和节流本质是不一样的。防抖动是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行。
节流
const throttle = function (func, delay) {
let timer = null;
let prev = +new Date(); // 最开始进入滚动的时间
return function () {
let context = this; // this指向window
let args = arguments;
let now = +new Date();
let remain = delay - (now - prev); // 剩余时间
clearTimeout(timer);
// 如果剩余时间小于0,就立刻执行
if (remain <= 0) {
func.apply(context, args);
prev = +new Date();
} else {
timer = setTimeout(func, remain);
}
}
}
防抖
function debounce(fn, wait) {
var wait= wait|| 300;
var timer;
return function () {
var th = this;
var args = arguments;
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(function () {
timer = null;
fn.apply(th, args);
}, wait);
};
}
主要应用:
防抖(debounce)
- search搜索联想,用户在不断输入值时,用防抖来节约请求资源。
- window触发resize的时候,不断的调整浏览器窗口大小会不断的触发这个事件,用防抖来让其只触发一次
节流(throttle)
1.鼠标不断点击触发,mousedown(单位时间内只触发一次)
2.监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断
2.宏任务和微任务以及EventLoop
在 JavaScript 中通过 queueMicrotask() 使用微任务
3.浏览器输入URL之后发生了什么?
大概过程
1.DNS域名解析
2.TCP连接
3.发送HTTP请求
4.服务器处理请求
5.返回响应结果
6.关闭TCP连接
7.浏览器解析
8.浏览器渲染
4.如何理解深浅拷贝?
出现深浅拷贝的问题,本质上是JavaScript对基本类型和引用类型的处理机制不同。
基本类型指的是简单的数据段,而引用类型指的是一个对象,而JS不允许我们直接操作内存中的地址,也就是不能操作对象的内存空间,所以,我们对对象的操作都只是在操作它的引用而已。
在复制一个变量时,如果我们复制的是基本类型的值时,会创建一个新值,并把它保存在新的变量的位置上。而如果我们复制的是引用类型时,同样会把变量中的值复制一份放到新的变量空间里,但此时复制的东西并不是对象本身,而是指向该对象的指针。所以我们复制引用类型后,两个变量其实指向同一个对象,改变其中一个对象,会影响到另外一个。比如对象,数组,函数,正则,时间对象这些都是引用数据类型,是保存在堆中的。所以,引用数据类型的复制,是内存地址的传递,并没有拷贝出一份新的数据。
浅拷贝
//遍历浅拷贝
function shallowCopy(obj) {
let copy = {};
// 只复制可遍历的属性
for (key in obj) {
// 只复制本身拥有的属性
if (obj.hasOwnProperty(key)) {
copy[key] = obj[key];
}
}
return copy;
}
// 使用Object.assign进行浅拷贝
// Object.assign()实际上对每个源对象执行的是浅复制。如果多个源对象都有相同的属性,则使用最后一个复制的值。
function shallowCopy1(origin) {
return Object.assign({},origin)
}
//扩展运算符(...)用于取出参数对象的所有可遍历属性,拷贝到当前对象之中
function shallowCopy2(origin) {
return {
...origin
}
}
深拷贝
最简单就是使用JSON是一种表示结构化数据的格式,只支持简单值、对象和数组三种类型,不支持变量、函数或对象实例。
// 深拷贝 - JSON 正反序列化
function deepClone(origin) {
return JSON.parse(JSON.stringify(origin));
}
5.浏览器缓存
页面的缓存状态是通过设置 HTTP Header 来实现
强缓存
强缓存两个相关字段:Expires Cache-Control。
强缓存分为两种情况,一种是发送HTTP请求,一种不需要发送。
首先检查强缓存,这个阶段不需要发送HTTP请求。通过查找不同的字段来进行,不同的HTTP版本所以不同:
HTTP1.0版本,使用的是Expires
缓存过期时间,用来指定资源到期的时间,是服务器端的具体的时间点。受限于本地时间,如果修改了本地时间,可能会造成缓存失效。
HTTP1.1使用的是Cache-Control
两者同时存在的话,Cache-Control优先级高于Expires;
协商缓存
协商缓存就是强制缓存失效后,浏览器在请求头中携带响应的缓存Tag来向服务器发送请求,服务器根据对应的tag,来决定是否使用缓存。
协商缓存可以通过设置 HTTP Header 实现:Last-Modified 和 ETag 。
服务器端文件的最后修改时间,需要和cache-control共同使用,是检查服务器端资源是否更新的一种方式。当浏览器再次进行请求时,会向服务器传送If-Modified-Since报头,询问Last-Modified时间点之后资源是否被修改过。如果没有修改,则返回码为304,使用缓存;如果修改过,则再次去服务器请求资源,返回码和首次请求相同为200,资源为服务器最新资源。
后续待补充...
css相关
ES6相关
1.async函数
async函数是使用async
关键字声明的函数。 async函数是AsyncFunction
构造函数的实例, 并且其中允许使用await
关键字。async
和await
关键字让我们可以用一种更简洁的方式写出基于Promise
的异步行为,而无需刻意地链式调用promise
。
React相关
- 基本生命周期
- 最新React版本新特性
Vue相关
其他
一、设计模式
1.单例模式(单例就是保证一个类只有一个实例,实现的方法一般是先判断实例存在与否,如果存在直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。在JavaScript里,单例作为一个命名空间提供者,从全局命名空间里提供一个唯一的访问点来访问该对象。)
发布订阅模式和观察者模式区别
二、组件相关
1.组件库建立(提高协作效率)
2.组件类型
- 按照逻辑和视图划分:容器型组件(Container)与展示型组件(stateless)
- 按照状态划分:有状态组件和无状态组件
- 按照 UI 划分:布局组件和内容组件
- 纯组件和非纯组件
3.组件设计的原则 - 单一原则(Single responsibility principle)
参考资料:
1.《JavaScript 高级程序设计(第四版)》