date
Jan 17, 2024 06:24 AM
type
status
slug
summary
tags
category
updated
Oct 24, 2024 12:52 PM
icon
password
语法
JavaScript
中对象的定义方式有2种,声明或构造的2种方式。- 对象的文字形式
- 对象的构造形式
类型
JavaScript
中的简单基本类型分别为:- string
- number
- boolean
- undefined
- null
- object
简单基本类型不是对象,但是平常使用中能用
"1234".length
这种语法是由于JavaScript
中自动把基本类型转化成了内置类型。
内置类型分别为:- String
- Number
- Boolean
- Array
- Function
- Object
- Date
上面说的只是一部分,其实随着ES6等后续的JS规范更新,像
BigInt
和Symbol
都被加入了。这些内置类型实际上就是一些内置函数,它们可以被当作构造函数使用。值得注意的是由于内置类型和基础类型感觉就像首字母大写了一样,但是其中null 和 undefined 没有对应的构造形式,它们只有文字形式。相反,Date 只有构造,没有文字形式。
内容
对象的内容是有一些存储在特定命名位置的值组成,也就是属性。但是注意的是在JS引擎内部中,这些值的存储位置多种多样的,一般不会存在对象容器内部,存储在对象内部的这个属性名称,他们就像指针一样,指向这些值真正的存储位置。
访问对象属性的值有2种方式,使用
.
或者[]
操作符.a
被称为"属性访问",而[a]
被称为"键访问",实际上他们访问的使用同一个位置。
在对象中,属性名永远都是字符串。即使使用数字作为属性名,它首先会被转换为一个字符串。可计算属性名
ES6 增加了可计算属性名,可以在文字形式中使用 [] 包裹一个表达式来当作属性名
属性和方法
访问的对象属性是一个函数,有的人的叫法是方法,因为在类中通常被称为方法。
作者认为对象内部引用的函数被称为"方法"这不太合适,因为JS中函数永远不会属于一个对象。这主要是由于有些函数具有
this
引用,有时候这些this确实是指向调用位置的对象引用。但是this是在运行的时候根据调用位置动态绑定的,所以函数和对象的关系最多是间接关系。数组
数组是对象,也支持
[]
。不过由于数组有一套更加结构化的存储机制。[]
访问的是下标值,并且下标值是整数。
你也可以给数组添加属性,但是这并不会改变数组的length。
可以把数组当作一个普通的键 / 值对象来使用,并且不添加任何数值索引,但是这并不是一个好主意。数组和普通的对象都根据其对应的行为和用途进行了优化,所以最好只用对象来存储键 / 值对,只用数组来存储数值下标 / 值对。复制对象
- 深拷贝
- 浅拷贝
这2种拷贝的最大区别在于,浅拷贝对基础值复制一遍,但是对内置类型的值仅仅是复制了对象属性上的引用。而深拷贝要复制引用对象上的值。
注意的是如果你在深拷贝仅仅考虑复制所有的值的话,可能会遇到循环引用的对象复制,这样的话会使得程序进入死循环。
而巧妙的复制方法:
浅拷贝:
object.assign(...)
第一个参数是目标对象,之后还可以跟多个源对象。属性描述符
从ES5开始,所有的属性具有了属性描述符。
可以使用
Object.defineProperty
来创建普通属性并且设置属性描述符的值不变性
如果想让属性或者对象是不可改变的,有多种方法可以实现。注意的是,所有的方法创建的都是浅不变性。也就是只会影响目标对象和它的直接属性,如果目标对象引用了其他对象(数组、函数等),其他对象的内容不受影响。
- 对象常量
使用属性描述符种的
writable:false
和configurable:false
创建一个不可以修改,定义和删除的属性。
- 禁止拓展
如果静止一个对象新增属性,并且保留已有属性的话。可以使用
Object.preventExtensions(...)
。
- 密封
Object.seal(..)
会创建一个“密封”的对象,这个方法实际上会在一个现有对象上调用Object.preventExtensions(..)
并把所有现有属性标记configurable:false
。
- 冻结
Object.freeze(..)
会创建一个冻结对象,这个方法实际上会在一个现有对象上调用Object.seal(..) 并把所有“数据访问”属性标记为 writable:false,这样就无法修改它们的值。它是最高级别的不可变性运用,但是这个对象引用的其他对象则不受印象
- Getter和Setter [[Get]]和[[Put]]可以控制属性值的设置和获取。 对象内置的[[Get]]操作首先在对象中查找是否有名称相同的属性,如果找到就会返回这个属性的值。
- 存在性
这里主要的是
in
操作符会检查属性是否存在对象及其[[Prototype]]原型链中,而hasOwnProperty
则只会检查属性是否在对象中,不会检查[[Prototype]]原型链。Object.propertyIsEnumberable(...)
会检查给定的属性是否直接存在于对象中;
Object.keys(...)
会返回一个数组,包含所有可枚举属性;
Object.getOwnPropertyNames(...)
会返回一个数组,包含所有属性,无论它们是否可枚举。