1. 箭头函数和普通函数的区别
a. 箭头函数和普通函数的样式不同,箭头函数语法更加简洁、清晰,箭头函数是=>定义函数,普通函数是function定义函数。
b. 箭头函数会捕获其所在上下文的 this 值,作为自己的 this 值,定义的时候就确定并固定了。
c. 箭头函数不能作为构造函数使用,也不能使用new关键字(因为箭头函数没有自己的this,它的this其实是继承了外层执行环境中的this,且this指向永远不会改变,作为构造函数其的this要是指向创建的新对象)。
d. 箭头函数没有自己的arguments。在箭头函数中访问arguments实际上获得的是外层局部(函数)执行环境中的值。
e. call、apply、bind 并不会影响其 this 的指向。
f. 箭头函数没有原型prototype。
g. 箭头函数不能当作 Generator 函数,不能使用 yield 关键字。
2. var,let和const之间的区别
从以下三个方面说。
变量提升方面:var声明的变量存在变量提升,即变量可以在声明之前调用,值为undefined。
let和const不存在变量提升问题(注意这个‘问题’后缀,其实是有提升的,只不过是let和const具有一个暂时性死区的概念,即没有到其赋值时,之前就不能用),即它们所声明的变量一定要在声明后使用,否则报错。
块级作用域方面:var不存在块级作用域,let和const存在块级作用域
声明方面:var允许重复声明变量,let和const在同一作用域不允许重复声明变量。其中const声明一个只读的常量(因为如此,其声明时就一定要赋值,不然报错)。一旦声明,常量的值就不能改变。
如何使const声明的对象内属性不可变,只可读呢?
如果const声明了一个对象,对象里的属性是可以改变的。
const obj={name:'小黄'};
obj.name='同学';
console.log(obj.name);//同学
因为const声明的obj只是保存着其对象的引用地址,只要地址不变,就不会出错。
使用Object.freeze(obj) 冻结obj,就能使其内的属性不可变,但它有局限,就是obj对象中要是有属性是对象,该对象内属性还能改变,要全不可变,就需要使用递归等方式一层一层全部冻结。
3. defer和async的区别
背景: <script> 文件不在html的<body>下方 会导致页面卡顿,这两个关键字都是解决这个问题的 前者有执行先后顺序 后者是没有顺序 但是两者都是立即下载
defer:中文意思是延迟。用途是表示脚本会被延迟到整个页面都解析完毕后再运行。因此,在<script>元素中设置defer属性,相当于告诉浏览器立即下载,但延迟执行。
HTML5规范要求脚本按照它们出现的先后顺序执行,因此第一个延迟脚本会先于第二个延迟脚本执行,但执行脚本之间存在依赖,需要有执行的先后顺序时,就可以使用defer,延迟执行。我觉得把script脚本放在body底部和defer差不多。
async:中文意思是异步,这个属性与defer类似,都用于改变处理脚本的行为。同样与defer类似,async只适用于外部脚本文件,并告诉浏览器立即下载文件。但与defer不同的是,标记为async的脚本并不保证按照它们的先后顺序执行。
指定async属性的目的是不让页面等待两个脚本下载和执行,从而异步加载页面其他内容,这使用于之间互不依赖的各脚本。
看到这里,就能知道其的一些作用了
当网页交给浏览器的HTML解析器转变成一系列的词语(Token)。解释器根据词语构建节点(Node),形成DOM树。因为JavaScript代码可能会修改DOM树的结构,所以节点是JavaScript代码的话,就需要停止当前DOM树的创建,直到JavaScript的资源加载并被JavaScript引擎执行后才继续DOM树的创建。
这里就会产生阻塞,出现白屏问题(白屏问题优化有很多方面,这里就脚本阻塞这一小点),我们就可以使用async和defer属性来解决JavaScript脚本阻塞问题。
当然最稳妥的办法还是把script标签放置在body的底部,没有兼容性问题,不会因此产生白屏问题,没有执行顺序问题。
4. async await对比promise的优缺点
async/await优点:
a. 它做到了真正的串行的同步写法,代码阅读相对容易
b. 对于条件语句和其他流程语句比较友好,可以直接写到判断条件里面
function a() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(222)
}, 2222)
})
};
async function f() {
try {
if ( await a() === 222) {
console.log('yes, it is!') // 会打印
}
} catch (err) {
// ...
}
}
c. 处理复杂流程时,在代码清晰度方面有优势
async/await缺点:
a. 无法处理promise返回的reject对象,要借助try...catch...
b. 用 await 可能会导致性能问题,因为 await 会阻塞代码,也许之后的异步代码并不依赖于前者,但仍然需要等待前者完成,导致代码失去了并发性。
//promise
Promise.all([ajax1(), ajax2()])
c. try...catch...内部的变量无法传递给下一个try...catch...,Promise和then/catch内部定义的变量,能通过then链条的参数传递到下一个then/catch,但是async/await的try内部的变量,如果用let和const定义则无法传递到下一个try...catch...,只能在外层作用域先定义好。
但async/await确确实实是解决了promise一些问题的。更加灵活的处理异步
promise的一些问题:
a. 一旦执行,无法中途取消,链式调用多个then中间不能随便跳出来
b. 错误无法在外部被捕捉到,只能在内部进行预判处理,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部
c. Promise内部如何执行,监测起来很难,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)
5.高阶函数与普通函数的区别
6.aynsc fetch ajax的区别?
zhuanlan.zhihu.com/p/264912752
7.对称加密 VS 非对称加密
对称加密中A和B会使用一个共享的密钥, A在发送数据之前,用这个密钥对数据加密。B在收到数据之后,用这个密钥对数据解密。因为加密解密用的是同一个密钥,所以这里的加密算法称为对称加密算法。
非对称加密使用两个密钥,一个是public key,一个是private key。通过一个特殊的数学算法,使得数据的加密和解密使用不同的密钥。因为用的是不同的密钥,所以称为非对称加密。非对称加密最著名的是RSA算法,这是以其发明者Rivest, Shamir 和Adleman命名。非对称加密算法里面的public key和private key在数学上是相关的,这样才能用一个加密,用另一个解密。不过,尽管是相关的,但以现有的数学算法,又没有办法从一个密钥,算出另一个密钥。
8.for VS forEach VS for...of VS for...in
关于迭代器Iterator的介绍:juejin.cn/post/699891…
for
for 循环与 forEach, for...of本质上的区别是for 循环是一种循环机制,只是能通过它遍历出数组,而 后两个是负责遍历(Array Set Map)可迭代对象的
forEach
for循环 while循环 for of 循环是可以通过break关键字跳出的,而forEach map这种循环是无法跳出的
首先break是用在循环体中的,forEach虽然是循环,但是代码写在回调函数里,这一点就直接决定forEach不能使用break。forEach其实是一个循环体和一个函数体的结合,循环体包裹着函数体,所以return只是跳出了函数体,但是并没有跳出循环体。
- 只能用作遍历数组,不能遍历对象
- 因为他是一个回调,所以不能使用break,return或continue来中断运行,一旦遍历就会遍历整个数组
for...in
- 用作遍历对象
- 也可以遍历数组,但是不推荐遍历数组,因为迭代的时候不一定是按照原顺序进行的,这无疑会影响数组的下标
- 不仅会遍历对象自身的属性,还会遍历对象原型上的属性,这也是它和Object.keys的区别
for...of
for...of 语句创建一个循环来迭代可迭代的对象。在 ES6 中引入的 for...of 循环,以替代 for...in 和 forEach() ,并支持新的迭代协议。for...of 允许你遍历 Arrays(数组), Strings(字符串), Maps(映射), Sets(集合)等可迭代的数据结构等
- 不能遍历对象
- 是循环,所以可以使用break,return或者continue来中断
- 最简洁、最直接的遍历数组元素的语法,避开了for-in循环的所有缺陷,解决了forEach的不可中断问题。