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. Bigint和Number的区别
Number类型的数字有精度限制,数值的精度只能到 53 个二进制位(相当于 16 个十进制位,正负9007199254740992),大于这个范围的整数,就无法精确表示了。
Bigint没有位数的限制,任何位数的整数都可以精确表示。但是其只能用于表示整数,且为了与Number进行区分,BigInt 类型的数据必须添加后缀n。BigInt 可以使用负号(-),但是不能使用正号(+)。
另外number类型的数字和Bigint类型的数字不能混合计算。
12n+12;//报错
4. 基本数据类型和引用数据类型的区别
基本数据类型:
a. 基本数据类型的值是不可变的(重新赋值属于改变属性名的指向了,而不是对值进行操作),这里就可以联想到,是不是所有关于字符串和数字的方法都是带有返回值的,而不是改变原字符串或数字。
例如
let a='abc';
a.split('');
console.log(a);//abc
b. 基本数据类型不可以添加属性和方法,虽然不会报错,但也只是一瞬间转为了相应包装对象,操作完又转化回原基本数据类型,不会保存结果。
c. 基本数据类型的赋值是简单赋值,基本数据类型的比较是值的比较。
d. 基本数据类型是存放在栈区的
引用数据类型:
a. 引用类型的值是可以改变的,例如对象就可以通过修改对象属性值更改对象。
b. 引用类型可以添加属性和方法。
c. 引用类型的赋值是对象引用,即声明的变量标识符,存储的只是对象的指针地址。
d. 引用类型的比较是引用(指针地址)的比较。
e. 引用类型是同时保存在栈区和堆区中的,栈区保存变量标识符和指向堆内存的地址。
5. defer
和async
的区别
大家应该都知道在script标签内有这两个属性async和defer,例如<script src="./home.js" async defer></script>
defer
:中文意思是延迟。用途是表示脚本会被延迟到整个页面都解析完毕后再运行。因此,在