对象以及基本的数据类型
-
对象的内容
对象的存取使用默认的 [[GET]] 和 [[SET]] ,必要的时候也会检查原型链。
可以进行人为使用 Getter 和 Setter 干预对象的存取 -
对象的属性(注意不可枚举的) + 属性值的操作
对象的属性描述符可是确定对象的属性特点,有四个方法层层递进设置对象的不可变级别
-
对象的方法
属性不一定包含值,他们或许是存在 getter 或者 setter 的访问描述符,
属性是可枚举或者不可枚举的,这决定了他们 是否可以在遍历时被找到 -
对象的遍历
建议使用 for ... of 遍历数组,使用 for .... in 遍历对象
数据类型
- JavaScript 的数据类型分类
-
简单基本类型(
本身并不是对象
)JavaScript 万物皆对象不正确
string、boolean、number、null、undefined
typeof null == 'object' 其实是语言本身的一个 bug, 需要明确的是 null 是基本类型
-
复杂类型(
作为对象的子类型存在
)复杂类型本身也是对象,更像是对象的子对象函数(可调用的对象)、数组(具备额外行为的对象)
-
JavaScript 内置对象 *** 内置对象只是一些内置函数/或者称之为内置的构造函数 ***
-
String、Number、Boolean、Object、Function、Array、Date、RegExp、Error
有些内置函数看起来很像基础类型,其实他们并不是同一个东西,只是类型之间可以相互转化和拥有更加复杂的关系
-
-
举例说明 (
可以自动转换的类型
)“I am a string” 只是一个字面量,若需要获取其长度,语言会自动将其转为 String 类型后进行操作
结论:
1. 字面量和对象是有很大的不同
2. 必要时语言本身或者人为可以很方便的进行转换 -
内置函数分类详解
null 和 undefined 没有构造函数的形式,只有文字形式
Date 只有构造形式,没有文字形式
Object、Array、Function、RegExp、无论使用文字形式或者是字面量形式,他们都是对象,不是字面量。
String、Number、Boolean 可是使用文字或者对象形式,但是应首选更为简单的文字形式
Error 一般是抛出异常时自动被创建,也可以 new Error() 进行创建,很少用到
对象的内容 (对象的属性值 是作为引用的存在
)
- 对象的内容及其
值的
存储和引用 (属性作为指针指向使用
)
对象的内容为对象中的属性和值
** 对象值的
存储多种多样,对象容器内只存储对象的属性,其属性相当于指针
,指向存储值的地方**
-
对象的属性名称(
对象赋值
和对象取值
时的属性名称)*** 目前可采用各种花样的对象的取值与赋值 ***
es6 新增可计算的 对象赋值 功能
对象取值可使用 可计算的属性
举例:
var myObj = { [Symbol.Someting]: "hello world" // 可计算的赋值 } myObj[myObj] = 'baz' // 特殊的计算赋值 myObj[true] = 'bool' myObj[Symbol.Someting] // hello world myObj["[object Object]"] // "baz" 可计算的取值 myObj["true"] // "bool" 特殊的取值
-
对象的属性与方法 (** 当函数作为对象的属性值存在时 **)
函数作为对象的属性值存在时:
最多扯上 this 的隐式绑定
** 因为对象的值是引用,引用。。**
** 所以该函数与对象只存在引用关系,**
** 若内部有this,最多加一层 this 的隐式绑定
,其他无任何瓜葛。**
** 并且这个函数可以随时被外层访问到**
-
对象的属性是一个函数,到底应该称呼其为
属性值
好还是方法
好??因为对象的属性值都是引用,所以当一个对象的属性值是函数时,
其实本身并没有和对象产生任何关系,只是多了一个引用地址
。所有函数还是函数本身。
对象的扩展
复制对象 ** 专开一个章节专门讲复制对象 **
-
对象和数组的关系
-
数组不接受非数值下标的数据存储,写了非数值下标的存储不会报错,但没用。
var myArr = ['foo', 42, 'bar']; myArr.koo = 'baz'; myArr.length // 3 不接受非数值类型的下标
-
对象的属性详解 (可枚举和不可枚举的对象属性 + 属性值的操作)
使用 delete 可以删除对象的属性,若此属性是对象的最后一个属性,且该对象无其他引用。则删除对象的最后一个属性后,该对象会被垃圾回收
-
属性的四个描述符
var myObj = {a: 2} Object.getOwnPropertyDescriptor(myObj, "a"); { value: 2, writable: true, enumerable: true, configurable: true }
使用 defineProperty(...) 可以为对象 添加或者设置
属性的描述信息,
configurable: false 是不可逆的
-
对象的不可变性(通过属性描述符设置对象不可变)
四个方法,层层递进
有级别限制- 对象常量 ( writable: fasle 和 configurable: false 可以创建一个真正的常量属性 )
不可修改,重定义,删除
var myObj = {}
Object.defineProperty(myObj, "FAVORITE_NUMBER", {
value: 2,
writable: false,
configurable: fasle
})
- 对象常量 ( writable: fasle 和 configurable: false 可以创建一个真正的常量属性 )
-
禁止扩展( Object.preventExtensions(...) )
表现特点:禁止添加新的属性,但是可以删除
-
密封 ( Object.seal(...) ) 在
禁止扩展
的基础上 + 设置对象属性的configurable: false
表现特点禁止添加属性,禁止删除属性,禁止重新配置属性,但是可以修改属性
-
冻结( Object.freeze(...) )
密封
+writable: false
禁止任何操作
对象的方法详解
-
[[GET]] 和 [[PUT]] 用于对象属性值的 获取和设置
var myObj = { a: 2 } myObj.a // 2
myObj.a 实际上是实现了[[GET]]操作,并且会遍历可能存在的原型链
-
Getter 和 Setter
访问描述符
var myObj = { get a() { return this._a; }, set a(val) { this._a = val * 2; } }
[[GET]] 和 [[PUT]] 是
语言内置且默认
的属性值的存取方法, Getter 和 Setter 是提供给人为
的数据存取的方法,且人为的操作优先级更高
不同之处
Getter 和 Setter 是
访问控制符
writable、configurable 等是属性修饰符
- 属性存在性的检查
可枚举属性(是否可以出现在对象的属性遍历中
) 表示 是否可出现在 for in 循环中
var obj = {}
Object.defineProperty(obj, "a", {
value: 2,
enumerable: false
})
"a" in obj // true
obj.a // 2
obj.hasOwnProperty("a") // true
看: 不可枚举的属性是可以访问其值,且可以使用 in 操作符判真。
只是不能 被遍历到而已
** 遍历时 对象会 使用 propertyIsEnumerable(....)检验 属性的 enumable 的属性,并决定其是否可遍历 **
-
存在性检查的
五个
方法详解 是否可枚举 + 是否检测原型链propertyIsEnumerable(...) 用于检查给定的属性名称
是否可枚举
+ 不检测原型链返回 boolean 值
Object.key() 返回一个数组 只包含可枚举属性 不检测原型链
Object.getOwnPropertyNames(...) 包含不可枚举的属性 + 不检测原型链
in 操作符 包含不可枚举属性 + ** 检测原型链**
- hasOwnProperty(..) 包含不可枚举属性 + 不检测原型链
对象的遍历
对象遍历和数组遍历的不一致性
数组的下标是确定且有序的,对象的属性的顺序是不确定的
-
数组循环建议使用 for ... of 遍历
for ... of 会自动调用系统的迭代器( 具体表现为: 使用指针 + next() 进行数据访问 )
。。