前言
这一部分是在经过了数月的面试准备和将近一个月的大厂实习面试之后,跳出应试心态,以一种真正的求知欲来钻研前端所需要用到的知识并记录下来。
此外,在这个系列的总结中我存储的更像是一张知识的索引图,在需要的时候很快的找到自己想知道的知识点,而不完全是存储知识本身。
let和const
都是属于块级作用域,变量不会提升,在变量声明前或者块级作用域外使用都会报错,因为处于暂时性死区。
let和const不能重复声明,const声明的变量需要赋初值。对于const来说,基本数据类型的值不能修改,但引用数据类型可以修改值,总的来说就是不能修改存放在栈区的地址,可以修改存放在堆区的数值。
globalThis对象
为了统一顶层对象,拿到指向全局环境下的this,从而引入了globalThis对象。
变量的解构赋值
指的是按照一定的匹配模式,从数组和对象中提取值,对变量进行赋值。
这里具一个常见的对象解构赋值
const {log}=console
//等价于下面的写法
const {log:log}=console
rest参数
用来获取函数的多余参数,rest参数和arguments对象的差别在于:rest参数搭配的变量是一个数组,而arguments是一个类似数组的对象。rest参数只能作为尾参数出现。
尾调用优化
尾调用优化主要用来优化递归操作,递归操作可能会形成很深的函数调用栈,影响内存。如果函数f的最后一步是调用函数g,则可以称之为尾调用,这里的关键是最后一步。
数组的扩展运算符
与rest参数形式一样,使用…操作符,但是相当于rest参数的逆运算,把数组打平。
Math.max(...[2,4,6])
//等价于下面的写法
Math.max(2,4,6)
除此之外,扩展运算符还可以
①拷贝并返回新的数组
cosnt a=[1,3]
const copy_a=[...a]
②合并数组
const arr1=[1,2]
const arr2=[3,4]
const newArr=[...arr1,...arr2]
③实现迭代器的接口对象都能由…操作符转化为数组
const go = function*(){
yield 1
yield 2
yield 3
}
[...go()] //[1,2,3]
Symbol
表示独一无二的值,用来避免命名冲突。
作为属性名的Symbol只能放在方括号中,不能使用点运算符。
Symbol.for()用来使用同一个Symbol值,Symbol.keyFor()用来返回一个已登记Symbol类型值的key。
let s1 = Symbol.for("foo");
let s2 = Symbol.for("foo")
s1 === s2 //true
Symbol.keyFor(s1) // "foo"
Symbol.iterator属性指向该对象的默认迭代器方法。
const myIterable = {};
myIterable[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
};
[...myIterable] // [1, 2, 3]
数组去重
[...new Set(array)]
Map
Map比对象的键值对更加广泛,Object提供的是“字符串–值”的对应,Map解构提供的是“值–值”的对应,Map的键可以是一个对象。
WeakSet和WeakMap
都是弱引用,里面只能放对象或者对象作为键,弱引用意味着垃圾回收策略不将其考虑在内。
Proxy代理
receiver = new proxy(target,handler)
receiver是接收者,即proxy的实例对象。taget是被代理的对象,handler是拦截器。
Reflect
①将Object对象的一些明显用于语言内的方法放到Reflect对象上。
②修改某些Object方法的返回结果。
③与proxy对象的方法一一对应,不论proxy怎么修改默认行为,总可以在reflect上获取默认行为。