1.可选链运算符(?.)
- 允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效;
- ?. 运算符的功能类似于 . 链式运算符,不同之处在于,可选链运算符会在链路上遇到 null 或者 undefined 时,直接返回 undefined,而不会抛出错误异常;
- 与函数调用一起使用时,如果给定的函数不存在,则返回 undefined。MDN
2.空值合并运算符(??)
- 当左侧的操作数为 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数;
- 逻辑或运算符(||)不同,逻辑或运算符会在左侧操作数为假值时返回右侧操作数。
3.为什么 JS 对象内部属性遍历的顺序乱了
- 对象的哪个属性先遍历,哪个属性后遍历是不确定的,需要开发者手动指定,所以对象(Object)没有默认部署 Iterator 接口,所以不会被
for...of循环遍历; - 首先JS代码本身是不会直接被计算机执行,计算机只能接收二进制的汇编代码,所以,中间需要一层转化,而这个转化,在Chrome就是v8引擎;
- Chrome 的 JS 引擎遍历对象属性时,会先提取所有 key 的 parseFloat 值为非负整数的属性,再根据数字顺序对属性排序首先遍历出来,然后按照对象定义的顺序遍历余下的所有属性。
let obj = {
'b': 'testb',
'a': 'testa',
'2': 'test1',
'测': 'test测',
'1': 'test2'
}
console.log(Object.keys(obj));
// [1, 2, 'b', 'a', '测']
- Chrome有这样的表现是因为V8引擎为了提高对象的访问速度,V8 里的对象就维护两个属性,会把数字放入线性的 elements 属性中,并按照顺序存放。会把非数字的属性放入 properties 中,不会排序,寻找属性时先 elements 而后在 properties。
4.枚举属性和可迭代属性
- 枚举属性:指将对象中的所有的属性全部获取,for..in用来遍历可枚举属性。
let obj = {
name: "艾斯",
age: 8,
sex: "男",
address: "五指山",
[Symbol()]: "test", // Symbol添加的属性不能被枚举
[name]: 'chris'
}
for(let proName in obj) {
console.log(proName, obj[proName]) // 因为proName是个变量,变量里面存的属性名,传变量不能用" . "的形式,得用中括号获取属性值
}
- 可迭代属性:for..of用来遍历可迭代属性
const arr = ['孙悟空', '沙僧', '猪八戒', '唐僧'];
for(let value of arr) {
console.log(value)
}
5.Set和WeakSet的区别
- Set在其他语言中又叫集合,是一堆无序的、相关联的、不重复的内存结构的组合,集合中的元素可以是任意类型,键名与键值一致,或者说只有键值,没有键名。
- WeakSet中的元素只能是对象,不能是其他类型的值。WeakSet是弱引用(弱引用是指不能确保其引用的对象不会被垃圾回收器回收的引用),如果该对象不再被其他变量引用,那么垃圾回收机制就会自动回收该对象的内存,由于垃圾回收机制运行机制是不确定的,所以WeakSet是不可遍历的。
【强引用:把一个对象赋给一个引用变量,这个引用变量就是一个强引用,类似var obj = new Object(),当一个对象被强引用变量引用时,它处于可达状态,是不可能被垃圾回收器回收的,即使该对象永远不会被用到也不会被回收。】
6.Map和WeakMap的区别
- Map类似对象,也是键值对的集合,对象的键只能是字符串,Map的键可以是任意类型。
- WeakMap只接受对象作为键名(不包括null),键名所指向的对象,不计入垃圾回收机制(同WeakSet)
7.立即执行函数(IIFE)
立即执行函数是一个匿名的函数,并且只会调用一次;可以利用IIFE创建一个一次性的函数,避免变量冲突。
js解析成(...)(...)这样的结构,由于括号有计算优先级,还是函数调用的一种方式;这里把前一个当成函数去调用,所以报错。所以在前一个立即执行函数后面加上“ ; ”,这样就可以规避这样问题,虽然js解析器会自动尝试在合适位置补上分号,但有时也会出现问题。(这里js解析器在第二个IIFE后面加“ ; ”所以说别偷懒,分号好好加)
在实际开发中应尽量减少在全局作用中编写代码,防止被意外修改,尽量编写局部作用域,可以使用let创建代码块,也可用IIFE创建作用域
8.变量的可变类型和不可变类型
- 简单数据类型属于不可变类型,一旦创建不可更改;在内存中不会创建重复的原始值;
- 复杂数据类型属于可变类型,对象创建完成后,可以任意的添加删除修改对象中的属性;
- 如果有两个变量同时指向一个对象,对另外一个变量也会产生影响。
- 当对两个对象进行全等或相等比较时,返回false,比较的内存地址。
修改对象时,如果有其他变量指向该对象,则所有其他指向该对象的变量都会受到影响;修改变量时,只会影响当前的变量。
const只能赋值一次,只是禁止变量被重新赋值,对对象的修改没有影响。
9.Object.hasOwn()
指定的对象自身有指定的属性,则静态方法 Object.hasOwn() 返回 true。如果属性是继承的或者不存在,该方法返回 false。
【Object.hasOwn() 旨在取代 Object.hasOwnProperty()】