【javaScript】对象基础梳理

36 阅读3分钟

垃圾回收

什么是垃圾

简单来说就是不被别人需要的,垃圾可能是单独的,也可能是抱团的,比如有个对象user = {name:'garbage'},后面将user置为null,user = null,这样一来对象{name:'garbage'}不被其他引用,无法访问到,所以成了垃圾(单独),又比如,a1 = {a1:'1',a2:a2}, a2 = {a2:'2',a3:a3}, a3 = {a3:'3'},再将a1置为null,此时{a1:'1',a2:a2}a2,a3也无法访问到了,于是都成了垃圾(抱团)

如何找到垃圾

垃圾回收的基本算法被称为mark-and-sweep,定期执行以下“垃圾回收”步骤

  • 标记根
  • 从根出发标记所有引用
  • 遍历引用,若到了对象再重复以上步骤,直到最后
  • 这样一来所有能访问的都能被标记
  • 没有被标记的就会被回收

内部算法

  • 分代收集:简单来说就是分组,分为“新的”和“旧的”,旧的降低检查频次
  • 增量收集:将整个对象集拆成多个部分,逐一清除
  • 闲时收集:垃圾收集器只会在 CPU 空闲时尝试运行,以减少可能对代码执行的影响

构造函数和操作符new

构造函数有两个约定:

  • 命名以大写字母开头
  • 只能由 "new" 操作符来执行

当一个函数被new操作符执行时,会按照以下步骤:

  1. 创建一个新的空对象,并分配给this
  2. 执行函数体(通常会修改this,添加新属性)
  3. 返回this的值
function Animal(name) {
    // 1、this = {} 隐式创建
    
    //执行函数体
    this.name = name;
    
    // 3、return this; 隐式返回
}
const cat = new Animal('cat');

构造函数的主要目的就是实现可重用的对象创建代码,像上述想创建其他动物,直接调用new Animal('dog')

构造函数一般没有return,它们的任务是将所有必要的东西写入this,并自动转换为结果,如果出现return,则按照以下规则

  • 如果 return 返回的是一个对象,则返回这个对象,而不是 this
  • 如果 return 返回的是一个原始类型,则忽略

Symbol数据类型

对象属性键只有两种数据类型,字符串和Symbol,若用了其他数据类型,会自动转换为字符串,比如obj[1]obj['1']相同,obj[true]和obj['true']相同

Symbol表示唯一的标识符,symbol保证是唯一的。即使我们创建了许多具有相同描述的symbol,它们的值也是不同

symbol属性不参与循环,所以for..inObjecct.keys会忽略symbol,但Object.assign会同时复制字符串和 symbol 属性

let sym1 = Symbol('sym');
let sym2 = Symbol('sym');
alert(sym1 === sym2); //false
let user = {
    [sym1]: 'test',
    age: 18
}
alert(user[sym1]);
for(let key in user) {
    console.log(key); //age
}
console.log(Object.keys(user))//['age']
let user_ = Object({},user)
console.log(user_); //{age: 18, Symbol(sym): 'test'}

全局symbol

有时想要一个应用程序范围内的 symbol,可以在代码中随处访问,这时需要全局Symbol,介绍一下两个api

  • Symbol.for(key):根据给定的key,来从运行时的 symbol 注册表中找到对应的 symbol,如果找到了,则返回它,否则,新建一个与该键关联的 symbol,并放入全局 symbol 注册表中
  • Symbol.keyFor(sym):获取全局 symbol 注册表中与某个 symbol 关联的键
const sym1 = Symbol.for('sym');
const sym2 = Symbol.for('sym');
console.log(sym1 === sym2); // true

const symDes = Symbol.keyFor(sym1);
console.log(symDes); // 'sym'

Symbol使用场景

如果我们想要向“属于”另一个脚本或者库的对象添加一个属性,我们可以创建一个 symbol 并使用它作为属性的键,这样,该属性将受到保护,防止被意外使用或重写

总结

  • symbol 是唯一标识符的基本类型
  • 使用Symbol(name)创建,name可选
  • 如果我们希望同名的 symbol 相等,那么我们应该使用全局注册表
  • 当有诉求希望对象的属性不被重写收到保护,应使用Symbol