1.数据类型
- 基础数据类型(存储在栈内存中,有固定的大小,按值访问)
String,Number,Null,undefined,Boolean,Symbol,BigInt
其中 Symbol 和 BigInt 是ES6 中新增的数据类型:
Symbol代表创建后独一无二且不可变的数据类型,主要为了解决可能出现的全局变量冲突问题。
BigInt是一种数字类型的数据,可以安全地存储和操作大整数。 - 复杂数据类型(存储在堆内存中,无固定大小,栈内存存储对象的访问地址,堆空间中存储对象的值,按址访问)
Array,Object,Function
2.this指向
- 默认调用,指向window
- 对象调用,指向该对象
- 做构造函数使用,指向实例对象(即被创建的新对象)
- 箭头函数,指向函数所在词法作用域
- call、apply、bind会将this指向传入的第一个参数
- DOM事件,this指向触发事件的元素
3.作用域、作用域链
作用域是一个变量或函数可访问范围,作用域控制着变量或函数的可见性和生命周期。
- 全局作用域:可以全局访问
最外层函数和最外层定义的变量拥有全局作用域
window上的对象属性方法拥有全局作用域 - 函数作用域:只能再函数中访问使用
在函数中定义的变量,都只能在内部使用,外部无法访问
内层作用域可以访问外层,外层不能访问内层作用域 - 块级作用域:只在代码块中访问使用
作用域链:变量在指定的作用域中没有找到,会依次向外一层作用域进行查找,直到全局作用域。这个查找的过程被称为作用域链。
4.闭包
- 含义:闭包是内层函数可以访问到外层函数的一个作用域。
- 优点:可以重复使用变量,并且不会造成变量污染。
- 缺点:比普通函数更占用内存,会导致网页性能变差,在IE下容易造成内存泄漏。
- 解决方案:在退出函数之前,把不用的局部变量全部删除。
- 使用场景:防抖,节流
防抖函数:
function debounce(func, time) {
let timer = null;
return function (...args) {
clearInterval(timer);
timer = setTimeout(() => {
func.apply(this, args)
}, time)
}
}
节流函数:
function throttle(func, time) {
let timer = null;
return function (...args) {
if (timer) return;
timer = setTimeout(() => {
func.apply(this, args);
timer = null;
}, time)
}
}
5.浅拷贝、深拷贝
- 浅拷贝
在拷贝一个对象时,只拷贝对象的引用,在新对象或者原对象改变后,另一个对象都会随之改变 - 深拷贝
在拷贝一个对象时,不仅拷贝对象的引用,连对象的值也一起拷贝。新对象与原对象的改变互不影响。
拷贝方法:
(1)JSON.stringify()
(2)jQuery.extend()
(3)_cloneDeep()
deepClone(source){
const targetObj = source.constructor === Array ? [] : {}; // 判断复制的目标是数组还是对象
for(let keys in source){ // 遍历目标
if(source.hasOwnProperty(keys)){
if(source[keys] && typeof source[keys] === 'object'){ // 如果值是对象,就递归一下
targetObj[keys] = source[keys].constructor === Array ? [] : {};
targetObj[keys] = deepClone(source[keys]);
}else{ // 如果不是,就直接赋值
targetObj[keys] = source[keys];
}
}
}
return targetObj;
},
6.原型、原型链
-
原型
每一个函数都有一个特殊属性,叫做原型(prototype),每一个引用类型都有一个_proto_属性,该属性指向对象(实例)所属构造函数的原型prototype
-
原型链
每个实例的_proto_指向对象的prototype,同时对象prototype的_proto_又指向上层对象的prototype。
-
作用
Javascript的原型与原型链就是该编程语言为了实现面对对象编程的一种设计,基于原型链,可以让Javascript对象拥有封装、继承、多态等众多面向对象的特性。
7.异步任务
浏览器会先执行一个宏任务,紧接着执行当前执行栈产生的微任务,再进行渲染,然后再执行下一个宏任务。
- 宏任务
主代码块
setTimeout
setTimeInterval
setImmediate()
requestAnimationFrame
postMessage
I/O
UI交互事件 - 微任务
process.nextTick()
Promise.then()
catch
finally
Object.observe
MutationObserver
8.强缓存、协商缓存
- 强缓存
浏览器在加载资源时,根据请求头expires和cache-control判断是否命中强缓存,是则直接从缓存读取资源,不会发送请求到服务器。 - 协商缓存
如果没有命中强缓存,浏览器会发送一个请求到服务器,通过last-modified和etag验证资源是否命中协商缓存,如果命中服务器将请求返回,但不会返回资源数据,依然从缓存读取资源。 - 如果两者都没有命中,则从服务器加载资源
9.跨域
- 什么是跨域
浏览器行为,非同源请求,即协议、域名、端口任一不同,就会发生跨域。 - 解决方法
(1)jsonp
原理:利用script不受同源策略的限制,script引入外部js没有跨域限制
优点:兼容性比较好,IE支持
缺点:只支持get请求,某些浏览器url会有长度限制,不能上传文件或者一些复杂的请求
实现:
// 1.在发请求前,准备一个全局的接收函数
window.myCallback = (res) => {
console.log(res)
}
// 2.客户端解析道外联的Script标签,发出请求
<html>
....
<script>
window.myCallback = (res)=>{ //这里为上一步定义的全局函数
console.log(res)
}
</script>
<script url="xxx?callback=myCallback">
//script标签的请求必须在写在定义全局函数之后
//这里需将全局函数的函数名作为参数callback的value传递
//这里callback这个键名是前后端约定好的
</script>
</body>
</html>
// 3.服务端收到请求,返回函数的调用
myCallback({
name: 'ahreal',
age: 18,
})
// 4.客户端收到数据,执行回调
<html>
....
<script>
window.myCallback = (res)=>{ //这里为上一步定义的全局函数
console.log(res)
}
</script>
<script> //将接收到的数据作为script标签里面的内容展开执行
myCallback({
name:'ahreal',
age:18
})
</script>
</body>
</html>
(2)cors(跨域资源共享)
原理:它允许浏览器向跨源服务器发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的策略。
浏览器支持:IE10+及其他所有浏览器
普通跨域请求:只服务端设置Access-Control-Allow-Origin即可,前端无须设置,若要带cookie请求:前后端都需要设置。由于同源策略的限制,所读取的cookie为跨域请求接口所在域的cookie,而非当前页。
(3)代理
原理:把非同源请求变为同源请求。前端发送请求给代理服务器,代理服务器再向后端服务器请求。
缺点:需要额外的代理服务器。
10. Promise
- 含义
语法上来说,Promise是一个构造函数,从功能上来说,Promise对象用来封装一个异步操作并可以获取结果。
Promise是目前前端解决异步问题的统一方案。 - 三个状态
pending,fulfilled,reject - reject和catch
reject用来抛出异常,catch用来处理异常
reject是Promise的方法,而catch是Promise实例的方法
reject后的东西,一定会进入then中的第二个回调,如果then中没有写第二个回调,则进入catch
网络异常(比如断网),会直接进入catch而不进会进入then的第二个回调 - 特点
对象的状态不受外界影响
一旦状态改变,就不会再变,任何时候都可以得到这个结果(从进行中变成已成功或已失败) - 优点
Promise对象,可以将异步操作以同步操作的流程表达出来,支持链式调用,避免回调地狱。 - 缺点
无法取消Promise,一旦新建就会立即执行,无法中途取消
如果不设置回调函数,Promise内部抛出的错误,不会反应到外部
当处于pending状态,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成) - Promise内部是同步的,但是then方法是异步的