总览
1.var const let
var
存在变量提升 即变量可以在声明之前使用 值为undefined var声明的变量没有块级作用域
const
不存在变量提升 存在块级作用域 常用来声明常量,且常量不可修改,必须初始化
let
不存在变量提升 存在块级作用域 不允许在相同作用域内重复声明同一个变量
console.log(a); // 输出undefined
console.log(b); // 报错
console.log(c); // 报错
var a = 1;
let b = 2;
const c = 3;
var声明的全局变量会被挂载到全局window对象上,而let和const不会
var a = 1;
let b = 2;
const c = 3;
console.log(window.a); // 输出1
console.log(window.b); // 输出undefined
console.log(window.c); // 输出undefined
2.Set数据结构
ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
Set本身是一个构造函数,用来生成 Set 数据结构。
通过add()方法向 Set 结构加入成员,结果表明 Set 结构不会添加重复的值。
const s = new Set();
[2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x));
for (let i of s) {
console.log(i);
}
// 2 3 5 4
Set.prototype.add(value):添加某个值,返回 Set 结构本身。
Set.prototype.delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
Set.prototype.has(value):返回一个布尔值,表示该值是否为Set的成员。
Set.prototype.clear():清除所有成员,没有返回值。
s.add(1).add(2).add(2);
// 注意2被加入了两次
s.size // 2
s.has(1) // true
s.has(2) // true
s.has(3) // false
s.delete(2);
s.has(2) // false
Array.from方法可以将 Set 结构转为数组。这就提供了去除数组重复成员的另一种方法。
function dedupe(array) {
return Array.from(new Set(array));
}
dedupe([1, 1, 2, 3]) // [1, 2, 3]
3.map循环
对数组中的每个元素运行给定的回调函数 返回每次函数调用的结果组成的数组
const names = ['abc','def','ghi','jkl']
/*
回调函数有三个参数
参数1:对应元素
参数2:元素对应的下标
参数3:完整的数组对象
*/
const newNames = names.map((item,index,arr) => {
return item + '123'
})
console.log(newNames);
输出结果
4.Object.is()
再ES6之前比较两个值相等只有 == 和 === 两个方法
二者都有缺点 == 会自动转换数据类型 === 判断NaN时不等于自身,以及+0等于-0
ES6的新方法Object.is()解决了这个问题,用来比较两个值是否严格相等
5.延迟加载js的方式
async和defer
<script async src='./test.js'></script>
async会和html一起解析 不是顺次执行js脚本
<script defer src='./test.js'></script>
defer会等html全部解析完后才会执行js代码 顺次执行js脚本
6.null和undefined的区别
在使用typeof时null会返回object 而undefined会返回自己
并且在转换为数值时null会被隐式转换为0 而undefined会被转换为NaN
7.事件循环(微任务与宏任务)
众所周知js是单线程的 js在执行代码时会先执行同步代码 然后进入eventlop事件循环
js对异步代码又进行了细分 分为宏任务和微任务
微任务:Promise.then、Promise.catch和Promise.finally、process.nextTick、queueMicrotask()等
宏任务:setTimeout 、setInterval、setImmediate、异步Ajax等
在执行异步代码时 会先执行微任务 在微任务队列中清空后才会执行宏任务
8.作用域
for(var i=0; i<5; i++){
setTimeout(()=> {
console.log(i)
},i)
}
执行结果为55555
但是将var换为let后结果为 01234
let声明迭代变量时js在后台会为每个迭代循环声明一个新的迭代变量,每个setTimeout引用的都是不同的变量实例
而由于变量提升,var 声明的迭代变量会泄漏到循环外部。
严格来讲,let 在 JavaScript 运行时中也会被提升,但由于“暂时性死区”(temporal dead zone)的缘故,实际上不能在声明之前使用 let 变量
9.new操作符具体做了什么
- 1.创建了一个空对象
- 2.将空对象显式原型指向于构造函数的隐式原型
- 3.将空对象作为构造函数的上下文(改变this指向)
- 4.对构造函数有返回值的处理判断