现代JavaScript 教程( Object(对象):基础知识)总结
对象
对象是具有一些特殊特性的关联数组。
它们存储属性(键值对),其中:
- 属性的键必须是字符串或者 symbol(通常是字符串)。
- 值可以是任何类型。
我们可以用下面的方法访问属性:
- 点符号:
obj.property。 - 方括号
obj["property"],方括号允许从变量中获取键,例如obj[varWithKey]。
其他操作:
- 删除属性:
delete obj.prop。 - 检查是否存在给定键的属性:
"key" in obj。 - 遍历对象:
for(let key in obj)循环。
对象的引用和复制
对象通过引用被赋值和拷贝。换句话说,一个变量存储的不是“对象的值”,而是一个对值的“引用”(内存地址)。因此,拷贝此类变量或将其作为函数参数传递时,所拷贝的是引用,而不是对象本身。
所有通过被拷贝的引用的操作(如添加、删除属性)都作用在同一个对象上。
为了创建“真正的拷贝”(一个克隆),我们可以使用 Object.assign 来做所谓的“浅拷贝”(嵌套对象被通过引用进行拷贝)
使用 Object.assign 方法,语法是:
Object.assign(dest, [src1, src2, src3...])
- 第一个参数
dest是指目标对象。 - 更后面的参数
src1, ..., srcN(可按需传递多个参数)是源对象。 - 该方法将所有源对象的属性拷贝到目标对象
dest中。换句话说,从第二个开始的所有参数的属性都被拷贝到第一个参数的对象中。 - 调用结果返回
dest。
或者使用“深拷贝”函数,例如 _.cloneDeep(obj)。
垃圾回收
- 垃圾回收是自动完成的,不能强制执行或是阻止执行。
- 当对象是可达状态时,它一定是存在于内存中的。
- 被引用与可访问(从一个根)不同:一组相互连接的对象可能整体都不可达。
对象方法,"this"
- 存储在对象属性中的函数被称为“方法”。
- 方法允许对象进行像
object.doSomething()这样的“操作”。 - 方法可以将对象引用为
this。
this 的值是在程序运行时得到的。
- 一个函数在声明时,可能就使用了
this,但是这个this只有在函数被调用时才会有值。 - 可以在对象之间复制函数。
- 以“方法”的语法调用函数时:
object.method(),调用过程中的this值是object。
注意箭头函数有些特别:它们没有 this。在箭头函数内部访问到的 this 都是从外部获取的。
构造器和操作符"new"
- 构造函数,或简称构造器,就是常规函数,但大家对于构造器有个共同的约定,就是其命名首字母要大写。
- 构造函数只能使用
new来调用。这样的调用意味着在开始时创建了空的this,并在最后返回填充了值的this。
构造器模式测试
💡可以使用 new.target 属性来检查它是否被使用 new 进行调用了。对于常规调用,它为空,对于使用 new 的调用,则等于该函数。
构造器的return
如果构造器有return 语句,则:带有对象的 return 返回该对象,在所有其他情况下返回 this。
可选链"?."
可选链 ?. 语法有三种形式:
obj?.prop—— 如果obj存在则返回obj.prop,否则返回undefined。obj?.[prop]—— 如果obj存在则返回obj[prop],否则返回undefined。obj.method?.()—— 如果obj.method存在则调用obj.method(),否则返回undefined。
正如我们所看到的,这些语法形式用起来都很简单直接。?. 检查左边部分是否为 null/undefined,如果不是则继续运算。
?. 链使我们能够安全地访问嵌套属性。
但是,我们应该谨慎地使用 ?.,仅在当左边部分不存在也没问题的情况下使用为宜。以保证在代码中有编程上的错误出现时,也不会对我们隐藏。
⚠
?.前的变量必须已声明如果未声明变量
user,那么user?.anything会触发一个错误
Symbol类型
Symbol 是唯一标识符的基本类型
Symbol 是使用带有可选描述(name)的 Symbol() 调用创建的。
Symbol 总是不同的值,即使它们有相同的名字。如果我们希望同名的 Symbol 相等,那么我们应该使用全局注册表:Symbol.for(key) 返回(如果需要的话则创建)一个以 key 作为名字的全局 Symbol。使用 Symbol.for 多次调用 key 相同的 Symbol 时,返回的就是同一个 Symbol。
Symbol 有两个主要的使用场景:
-
“隐藏” 对象属性。 如果我们想要向“属于”另一个脚本或者库的对象添加一个属性,我们可以创建一个 Symbol 并使用它作为属性的键。Symbol 属性不会出现在
for..in中,因此它不会意外地被与其他属性一起处理。并且,它不会被直接访问,因为另一个脚本没有我们的 symbol。因此,该属性将受到保护,防止被意外使用或重写。因此我们可以使用 Symbol 属性“秘密地”将一些东西隐藏到我们需要的对象中,但其他地方看不到它。
-
JavaScript 使用了许多系统 Symbol,这些 Symbol 可以作为
Symbol.*访问。我们可以使用它们来改变一些内置行为。例如,在本教程的后面部分,我们将使用Symbol.iterator来进行 迭代 操作,使用Symbol.toPrimitive来设置 对象原始值的转换 等等。
从技术上说,Symbol 不是 100% 隐藏的。有一个内置方法 Object.getOwnPropertySymbols(obj) 允许我们获取所有的 Symbol。还有一个名为 Reflect.ownKeys(obj) 的方法可以返回一个对象的 所有 键,包括 Symbol。所以它们并不是真正的隐藏。但是大多数库、内置方法和语法结构都没有使用这些方法。
对象--原始值转换
对象到原始值的转换,是由许多期望以原始值作为值的内建函数和运算符自动调用的。
这里有三种类型(hint):
"string"(对于alert和其他需要字符串的操作)"number"(对于数学运算)"default"(少数运算符)
规范明确描述了哪个运算符使用哪个 hint。很少有运算符“不知道期望什么”并使用 "default" hint。通常对于内建对象,"default" hint 的处理方式与 "number" 相同,因此在实践中,最后两个 hint 常常合并在一起。
转换算法是:
- 调用
obj[Symbol.toPrimitive](hint)如果这个方法存在, - 否则,如果 hint 是
"string"- 尝试
obj.toString()和obj.valueOf(),无论哪个存在。
- 尝试
- 否则,如果 hint 是
"number"或者"default"- 尝试
obj.valueOf()和obj.toString(),无论哪个存在。
- 尝试
在实践中,为了便于进行日志记录或调试,对于所有能够返回一种“可读性好”的对象的表达形式的转换,只实现以 obj.toString() 作为全能转换的方法就够了。
原文地址:Object(对象):基础知识

浙公网安备 33010602011771号