1. JS 将对象看成是属性的无序集合, 每个属性是一个key/value, 属性名是字符串, 值为任意类型; 对象除了键值对, 还从一个称为 "原型" 的 对象 继承属性(为啥是从对象继承呢? ). 对象的方法通常是继承来的, 原型继承是js的核心特征.
2. 对象中不能存在同名的属性(怎么重载呢?), 属性特性:
- 可写: 表示可以设置该属性的值
- 可枚举: 表示可以使用for/in循环返回该属性
- 可配置: 表示可以删除和或修改该属性(名)
3. 对象除了包含属性之外,其他特征:
- 对象的原型: 指向另一个对象, 本对象的属性继承自它的原型对象.
- 对象的类: 是一个标志对象类型的字符串
- 对象的扩展标记: 表明是否可以向该对象添加新的属性.
4. 对对象和属性分类
- 内置对象: ECMAScript规范定义的对象或类, 如: 数组, 函数, 日期和正则
- 宿主对象: 由js解析器嵌入的宿主环境(如web浏览器)定义的. 客户端js中表示网页结构的HTMLElement对象都是宿主对象. 既然宿主环境定义的方法可以当成普通的JavaScript函数对象, 那么宿主对象也可以当成内置对象.
- 自定义对象: 运行中js代码创建的对象
- 自有属性: 直接在对象中定义的属性.
- 继承属性: 对象从原型对象中定义的属性
5. 对象的定义和使用中需要注意的地方.
- 属性名字有空格,连字符等特殊符号/使用保留字时要用引号(单引号双引号均可)表示.
- 属性访问并不总是返回或者设置一个值, 查询一个不存在的属性并不会报错, 而是返回undefined. 但是对象不存在就会报错, 可以使用短路的 && 操作符来先保证对象存在: var len = book && book.subtitle && book.subtitle.length; 避免类型错误异常.
- delete只能删除对象的自有属性, 而不能删除继承属性, 要删除继承属性必须从定义这个属性的原型对象上删除它, 而且这样会影响到所有继承自这个原型的对象). 删除已经删除过的属性什么都不会做,然后依然返回true(如果delete 后面不是一个属性访问表达式, 同样返回true. 如 delete 1). 删除不可配置属性会返回false, 某些内置对象的属性是不可配置的, 如在浏览器中通过变量声明和函数声明创建的全局对象的属性 (在nodejs中就不一定).
o = {x:1}; // 没有var , 创建了一个可配置的全局对象的属性 console.log(delete o.x); console.log(delete o.x); console.log(delete Object.prototype) var x = 1; // 有var , 创建了一个不可配置的全局对象的属性. console.log(delete this.x); function f(){} // 创建了不可配置的全局对象的属性. console.log(delete this.f)
在浏览器和nodejs中得到的结果不一样, 可能是因为内置对象的可配置属性不一样吧, 如果想调试delete的返回结果, 那么可以查询一下你要删除的属性是否为可配置的.
6. 原型
- 除了null外, 每一个js对象都与另一个对象(原型)关联. 通过对象直接量创建的对象都具有同一个原型对象.
- 通过js代码Object.prototype 获取对原型对象的引用. 通过new和构造函数调用创建的对象的原型就是构造函数的prototype属性的值, 也是继承自Object.prototype. (new Date() 创建的对象的原型是: Date.prototype).