除了字符串、数字、true、false、null 和 undefined 之外,JavaScript 中的值都是对象。引用类型的值(对象)是引用类型的一个实例。在 ECMAScript 中,引用类型是一种数据结构,用于将数据和功能组织在一起。
从宏观的角度讲,对象是对客观事物的抽象,事物的特征可以用属性表示,事物的行为可以用方法表示;
从微观的角度讲,对象就是一种数据类型,通过对象可以方便地对变量和函数进行管理。
对象的创建
JavaScript 对象的创建有三种方式:直接量,new 关键字 和 Object.creat() 方来创建。
对象直接量
对象的直接量就是由若干兼职对组成的映射表,键和值之间用 “:” 分隔,键值对之间用 “,” 分隔,整个映射表用一对花括号包裹,比如通过字面量声明(更加简便)var obj= {};
键值对
键值对就是一种对应关系,通过键能够方便地找到值
键:值 key:value
k:v
例子:
1 | var emptyObj = {}; |
对象的字面量是一个表达式,这个表达式的每次运算都创建并初始化一个新对象。每次计算对象直接量的时候,也会计算它的每个属性的值。也就是说,如果在一个重复调用的函数中的循环体内使用对象直接量,它将创建很多新对象,并且每次创建的对象的属性值可有可能不同。
通过 new 关键字创建对象
new 运算符创建并初始化一个新对象。n关键字 new 后面跟随一个函数调用。
通过构造函数声明(更加通用)var obj= new Object(); // 创建一个空对象,和 {} 一样
对象具有属性和方法
- 属性 用来描述对象的特征 一般是名词 对应变量
- 方法 用来描述对象的行为 一般是动词 对应函数
原型初识
除了 null 以外的每一个 JavaScript 对象都和 原型
相关联。所有通过对象直接量创建的对象对具有同一个原型对象,可通过 Object.prototype 获得对原型对象的引用。通过 new 关键字和构造函数调用创建的对象的原型就是构造函数的 prototype 属性的值。因此,和使用 {} 创建对象一样,通过 new Object() 创建的对象也继承自 Object.prototype。
没有原型的对象有 Object.prototype,它不继承任何属性。其他对象都是普通对象,都有原型。所有的内置构造函数比如:Array(), Date() 都具有一个继承自 Object.prototype 的原型。
Object.create()
ECMAScript 5 定义了一个名为 Object.create() 方法,是一个静态函数,可以用来创建对象。有两个参数:第一个参数是对象,第二个参数可选,用于对属性进行详细描述。
1 | // o1 继承了属性 x 和 y |
可以通过任意原型对象创建新对象,即可以使任意对象继承。
例子: 返回一个继承自原型对象 p 的属性的新对象
1 | function inherit(p){ |
属性和方法的查询和设置
属性
- 属性的定义
- 对象.属性名 = 值;
- 对象[“属性名”] = 值;
- 属性的调用
- 对象.属性名;
- 对象[“属性名”];
方法
- 方法的定义
- 对象.方法名 = function() { //函数体 };
- 对象[“方法名”] = function() { //函数体 };
- 方法的调用
- 对象.方法名();
- 对象[“方法名”];
作为关联数组的对象
对象属性和方法的第二种设置和访问用了 “[]”,只是利用的不是索引访问,而是字符串。这种数据就是关联数组,也叫散列、映射或者字典。
当我们通过 [] 来访问对象的属性时,在程序运行是可以设置和修改或者创建它们。
继承
对象具有自有属性(own property),也有一些属性是从原型对象上继承来的。
还是这个例子:
1 | function inherit(p){ |
属性访问错误
- JavaScript 中,属性访问时,并不总是会话或者设置。
- 在查询不存在的属性时不会报错,而返回 undefined。
- 内置构造函数的原型是只读的。
删除属性
delete 运算符可以删除对象的属性。delete 只是断开属性和宿主对象的联系,而不会操作属性中的属性。
delete 只能删除自有属性,不能删除继承属性。
delete 不能删除可配置属性。
在非严格模式下,删除全局独享的可配置属性时,可以省略对全局对象的引用,直接在 delete 操作符后跟要删除的属性名即可。
在严格模式下,delete x; 报错, delete this.x; 正常运行
属性检测
通过 in 运算符、hasOwnProperty()、propertyIsEnumerable() 方法;
- in 运算符
1 | var o = {x: 1}; |
- hasOwnProperty() 方法
1 | var o = {x: 1}; |
- propertyIsEnumerable() 方法
1 | function inherit(p){ |
除了 in 以外, 另一种简单的判断一个属性是否是 “undefined” 使用 “!==”
1 | var o = {x: 1}; |
但 in 可以区分不存在的属性和存在但值为 undefined 类型的属性
1 | var o = {x: undefined}; |
对象的枚举属性
除了检测对象的属性,我们经常需要遍历对象的属性,通常使用 for-in 遍历;
ECMAScript 5 提供了 Object.keys() 方法,返回值是一个数组,这个数组由对象中可枚举的自有属性的名称组成。
ECMASciript 5 提供的另一种枚举属性的方法是 Object.getOwnPropertyNames(), 和 Object.keys() 类似,只是它返回对象的所有自有属性的名称,而不仅仅是可以枚举的属性。
用来枚举对象属性的工具函数
1 | /** |
属性 getter 和 setter
当程序执行查询存储属性的值的时候,JavaScript 调用 getter 方法(无参数),当设置属性值的时候,调用的是 setter 方法。
属性的特性
属性包含一个属性名和4个特性:
- value 属性值
- writable 可写性
- enumerable 可枚举性
- configurable 可配置性
存取器属性不具有值 value 和 可写性
ECMAScript 5 中定义了属性描述符 Object.getOwnPropertyDesctiptor() 获取某个对象特定的属性,这个方法只能得到自有属性的特性。
让新建的属性具有某种特性,需要调用 Object.definePeoperty() 方法;传入要修改的对象,要创建或修改的属性的名称以及属性描述符对象;
1 | var o = {}; // 创建一个空对象 |
需要同时修改多个属性,使用 Object.defineProperties(),它返回修改后的对象。
1 | /** |
对象的三个属性
每一个对象都有与之相关联的原型 (prototype)、类 (class) 和可扩展性 (extensible attribute)。
原型属性
通过直接量创建的对象使用 Object.prototype 作为它们的原型,而使用 new 创建的对象使用 构造函数的 prototype 属性作为它们的原型。而通过 Object.create() 创建的对象使用第一个参数作为它们的原型,也可以是 null .
ECMAScript 5 中将对象作为参数传入 Object.getPrototypeOf() 方法中可以查询它的原型。
要检测一个对象是否是另一个对象的原型(或处于原型链中),用 isPrototypeOf() 方法。
类属性
对象的类属性是一个字符串,用以表示对象的类型信息。只有一种间接的方法可以访问,即toString() 方法。默认的 toString() 方法继承自 Object.prototype,返回 [object class]
格式的字符串。
如何获得对象的类?
1 | /** |
这个函数可以传入任意的参数。
对象的可扩展性
ECMAScript 5 的 Object.preventExtensions() 方法将对象转为不可扩展的,Object.seal() 还可以设置对象的属性不可配置。
序列化对象(JSON 对象表示法)
是指将对象的状态转为字符串,也可以将字符串还原为对象。
ECMAScript 5 提供了内置函数 JSON.stringify() 和 JSON.parse() 用来序列化和还原JavaScript对象。这两个方法使用 JSON 数据格式。
JSON, 即 JavaScript Object Notation
( JavaScript 对象表示法)是仿照JS中对象字面量的格式去书写的一串用来记录对象数据的字符串,可以用于数据传输。 即 JSON
注意:函数、RegExp、Error 对象和 undefined 值不能序列化和还原
- JSON 转字符串 序列化 JSON.stringfy();
- 字符串转 JSON 反序列化 JSON.parse();
遍历的 JSON 两种方式
通过for可以对集合进行有序的遍历for(var k in json) { 语句 }; k变量代表的是json中的各个属性(key)和 var i = 0中的i是一个意思,名字不同而已
对象的方法
- toString() 方法
- toLocalString() 方法
- toJSON() 方法
- valueOf() 方法