- 基础
- 一种复合值。属性的无序集合,属性由名/值对组成,看作字符串到值的映射。
- 这种数据结构叫做散列(hash), 散列表(hashtable), 字典(dictionary), 关联数组(associative array)
- 常用来模拟静态对象或静态语言的结构体。也可以模拟json字符串
- 可以基于原型(prototype)继承属性,称作原型式继承(prototypal inheritance)
- 除了字符串、数字、true、false、null、undefined外,js中的值都是对象
- 字符串、数字、布尔值可以自动包装为对象(构造函数的实例)
- 对象操作通过引用(而非值)。
- 常见属性操作
- 创建(create)
- 设置(set)
- 查找(query)
- 删除(delete)
- 检测(test)
- 枚举(enumerate)
- 组成
- 属性的名/值对 + 属性特性(property attribute) + 对象特性(object attribute)
- 属性名可以是空字符串,不能重名
- 属性特性包括: 可写(writable attribute), 可枚举(enumerable attribute), 可配置(configurable attribute)
- 可配置表明是否可以删除或修改该属性
- 通过代码给对象创建的所有属性都是可写、可枚举、可配置的, ECMAScript 5 中可以改变
- 对象特性包括
- 对象原型(prototype) # 指向另外一个对象, 本对象继承它的原型
- 对象的类(class) # 一个标识对象类型的字符串
- 对象的扩展标记(extensible flag) # ECMAScript 5中指明是否可以向该对象添加新属性
- 分类
- 内置对象(native object) # 由ECMAScript定义的对象或类。如数组、函数、日期、正则表达式
- 宿主对象(host object) # js解释器( 如web浏览器)嵌入的宿主环境,如 HTMLElement对象
- 宿主环境定义的方法可当作普通js函数对象, 宿主对象可当作内置对象
- 自定义对象(user-defined object) # 运行中的js代码创建的对象
- 自有属性(own property) # 直接在对象中定义的属性
- 继承属性(inherited property) # 对象的原型对象中定义的属性
- 原型
- 每一个js对象(null除外)都与另一个对象(原型)关联,从原型继承属性。
- 内容
- 对象直接量创建的对象有同一个原型对象Object.prototype
- new的对象原型是构造函数prototype的属性的值 # 于是new Object()创建的对象继承自Object.prototype
- Object.prototype这个对象没有原型
- 具体
- 除Object.prototype的对象是普通对象,都有原型。
- 所有内置构造函数都继承Object.prototype
- 如, new Date()创建的对象同时继承Date.prototype和Object.prototype
- 这一系列的链接的原型对象就是”原型链”(prototype chain)
- 创建对象
- {}
- ECMAScript 5中(ECMAScript3的部分实现), 保留字用作属性名可以不带引号
- ECMAScript 3中保留字作属性名必须用引号
- ECMAScript 3的IE中, 最后一个逗号不可以忽略
- 每次计算对象直接量,都会计算它的每个属性的值
- new # 关键字创建
- new后的函数是构造函数(constructor)。
- Object.create()
- ECMAScript 5中出现的静态函数
- 参数1是原型对象, 参数2可选,对对象属性进一步描述
- Object.create({x:2})
- Object.create(null)
- 传入参数null来创建没有原型的新对象。
- 没有原型的对象没有toString等方法, 所有不能+运算
- Object.create(Object.prototype)
- 对象序列化(serialization) # json(JavaScript Object Notation)
- ECMAScript 5 api # stringify, parse的第二个参数可选,传入属性列表来定制序列化或还原操作
- JSON.stringify()
- 支持对象, 数组, 字符串, 无穷大数字, true, false, null。NaN, Infinity, -Infinity序列化结果是null
- 日期stringify为日期字符串,parse不能还原成对象
- 只序列化对象的可枚举自有属性。不能序列化的属性自动省略掉
- 函数, RegExp, Error对象和undefined不能序列化和还原
- JSON.parse()
- 创建对象 # 函数即对象,本身为构造方法
-
var obj = {};
# var obj = []是数组, 数组中Obj['aa']添加的是属性而非成员, 静态对象
function Obj(a, b){};
new Obj(a, b);
function Obj(a, b){
thisf = new Array();
return new Object(a, b)
};
- Obj(a, b);
- 只能返回Obj里定义的新对象的实例(不能返回本身的实例)
- 内的变量函数静态。指向外部函数可动态
- 内对象为动态
- new Obj(a, b); # 内变量函数动态(内存浪费)
- Obj.prototype.c = ‘c’
- Obj.prototype.d = function(){};
- Obj.prototype.e = new Array(); # prototype函数为静态函数, prototype对象为静态
- function Obj(a, b){ } # 内部prototype, 与外部完全相同
-
if(typeof Obj._initialized == 'undefined'){
Obj.prototype.c = function(){};
Obj._initialized = true;
}
- 最好方式:
- 内部定义变量和对象, prototype定义函数(防止new对象的函数动态)。
- prototype定义函数可以在内部,也可以在外部。
- 扩展对象
- Obj.prototype.extend # 添加或重写当前对象的属性
- Object.prototype.extend # 所有对象上添加属性
- JS 属性
- JS 数组
- JS 集合
- proxy
- 介绍
- 元编程(meta programming), 在对象外层进行代理
- 在obj.proxy上设置Proxy对象,该对象的操作会变成对Proxy对象的操作
-
var obj = new Proxy({}, {
get: function (target, key, receiver) {
return Reflect.get(target, key, receiver);
},
set: function (target, key, value, receiver) {
return Reflect.set(target, key, value, receiver);
}
});
- reflect
- 介绍
- 将Object上一些明显属于语言内部的方法(如Object.defineProperty)放到Reflect上
- 修改Object上原有方法,变得更合理, 如Object.defineProperty在无法定义属性时抛出异常, 而Reflect.definePropert则返回false
- 让Object操作变成函数作为, 如name in obj, delete obj[name]变成Reflect.has, Reflect.deleteProperty
- 让Proxy上方法与Reflect方法对应,让Proxy的对象操作默认行为在Reflect上执行