对象是JavaScript的基本数据类型:属性的无序集合。每一个属性key: value
和属性描述符descripter
组成。数组
属性名key
:字符串或合法的变量标识符;ide
属性值value
:能够是任意JavaScript值(number
、string
、boolean
、null
、undefined
和数组、对象).value
能够是getter
和setter
。函数
属性描述符descripter
:每一个属性的三个相关特性writable
、enumerable
、configurable
,其值都是布尔类型,默认都为true
工具
建立对象有三种方法:对象字面量{a: 1}
,new Constructor()
、Object.create()
测试
var book = { "main title": "JavaScript", //有空格或其余非标识符、关键字,必须使用双引号 "sub-title": "The Definitive Guide", "for": "all audiences", author: { firstname: "David", lastname: "Flanagan" } }
new
操做符调用构造函数可使用new
操做符调用一个构造器函数Constructor()
建立一个对象。ui
var o = new String(); var d = new Date();
Object.create()
方法原型:每一个JS对象都有一个与之相关联的原型对象prototype
,对象其原型对象上继承属性。(当前对象中的__proto__
属性是其原型对象的连接)this
全部经过字面量建立的对象的原型都是Object.prototype
,一个字面量对象{}
至关于调用new Object()
。prototype
Object.prototype
的原型是null
,因此null
是原型的出口。rest
Object.create()
是一个静态函数(不是提供给对象调用的方法),用于建立对象:code
第一个参数:原型对象,建立的新对象以该参数为原型;
第二个参数:可选,用于对对象属性的描述
建立一个没有原型的对象:Object.create(null);
建立一个普通空对象({}
或new Object()
):Object.create(Object.prototype);
每一个对象都有与之相关的3个属性:原型prototype
、类属性calss attribute
、可扩展性extensible attribute
每一个JS对象都与另外一个原型对象(prototype
),利用原型能够实现继承。
字面量的原型是:Object.prototype
new
操做符建立的对象其原型:构造器函数的原型(prototype
属性)
Object.create()
建立的对象,其原型:第一个参数
ES5中定义了Object.getPrototypeOf()
函数,来查询对象的原型
利用new
建立的对象会继承constructor
属性,指向建立该对的构造器函数,全部该对象的原型是:obj.constructor.prototype
字面量{}
的constructor
属性指向Object()
使用isPrototypeOf()
方法查看一个对象是否为另外一个对象的原型(或处于原型链中)
Array.prototype.isPrototypeOf([]); // ==> true
对象的类属性class attribute
是一个字符串,用来表示对象的信息。ES3与ES5均为提供设置类属性的API,只能经过继承自Object.prototype
的toString()
方法来简洁查询。
{}.toString(); // ==> "[object Object]"
经过对返回字符串切片:第8位到倒数第2位便可得到对象的类型。可是许多对象重写了toString()
方法,须要间接调用Function
的call()
方法
function classof(o) { if(o === null) {return "Null";} if(o === undefined) {return "Undefined"} return Object.prototype.toString.call(o).slice(8, -1); }
classof()
方法能够返回传递给它的任意对象的类型,参数为number
、string
、boolean
时,使用包装类型将其转化为对象,再进行操做。
classof(null); // ==> "Null" classof(2); // ==> "Number" classof(false); // ==> "Boolean" classof(new Date()); // ==> "Date" classof(""); // ==> "String" classof({}); // ==> "Object" classof([]); // ==> "Array" classof(/./); // ==> "RegExp" classof(window); // ==> "Window",宿主对象 function F() {}; //自定义一个构造器函数 classof(new F()); // ==> "Object"
extensible attribute
对象的课扩展性用来描述对象是否能够添加新的属性。全部的内置对象和自定义对象都是可扩展的,除非将其转化为不可扩展
Object.esExtensible()
函数判断传入对象是否能够扩展;
Object.preventExensible()
函数将传入的对象设置为不可扩展,而且过程不可逆;只影响对象自己的可扩展性
Object.seal()
函数将对象设置为不可扩展,属性描述符configurable
设置为false
(不能添加新属性,已有的属性不能删除或配置,可是对于writable: true
时,能够修改属性的值);过程不可逆
Object.isSealed()
函数判断一个对象是否封闭
Object.freeze()
函数将对象设置为不可扩展,属性描述符configurable: false;
,writable: false;
只读。value
为accessor property
含有setter
函数,不受影响
每一个对象是无需的属性集合,属性名能够是合法的变量标识符或字符串;变量值能够是任意JavaScript值;属性由描述符descripter
来控制特性;
属性能够经过.
和[]
来访问:
使用.
访问时,其右侧必须是属性名称命名的简单标识符
使用[]
访问时,括号内必须是计算结果为字符串的表达式,字符串是属性的名字。变量名为关键字、含有空格或属性名是变量时,必须使用[]
var author = book.author; var name = author.surname; var title = book["main title"];
属性的设置:与访问类似,将其放在赋值表达式的左侧
book.edtion = 6; book["main title"] = "ECMAScript";
在查询一个对象是否存在时,先查看自身属性,若是没有;经过原型链逐层向上查找,直到原型链顶端null
为止。
若是自身属性与原型链中均为找到,属性访问返回undefined
,不报错
若是查询不存在对象的属性,会报错
为null
和undefined
设置属性会报错
使用delete
操做符,能够删除对象的属性(其描述符中configurable
为true
),而且只能删除自有属性,不能删除继承属性
判断某个属性是否在某个对象中,JS有三种方法:in
、hasOwnProperty()
、propertyIsEnumerable()
in
:若是对象自身属性或继承属性中包含该属性,返回true;
hasOwnProperty()
:只有对象自身属性包含该属性时,才返回true
propertyIsEnumerable()
:只有对象自身属性包含该属性,而且该属性是能够枚举(描述符中enumerable: true;
)
var o = {a : 1}; "a" in o; // ==> true o.hasOwnProperty("a"); // ==> true o.propertyIsEnumerable("a"); // ==> true
使用for-in
循环能够遍历对象中全部可枚举的属性(包括自身属性与继承属性),把属性名赋值给循环变量。ES5定义了Object.keys()
和Object.getOwnPropertyNames()
两个函数用来枚举属性名称。
Object.keys()
:返回对象中可枚举的自有属性名组成的数组
Object.getOwnPropertyNames()
:返回对象全部的自有属性名组成的数组,包括不可枚举的属性
对象继承的内置方法都是不可枚举的,给对象中增长的属性均可以枚举(除非设置其enumerable: false
)
有许多使用工具库为Object.prototype
增长新的属性,这些属性能够被全部对象继承使用,可是在ES5以前,不能将其设置为不可枚举,因此在for-in
循环时会被枚举出来。
//过滤继承的属性 for(p in o) { if(!o.hasOwnProperty(p)) {continue;} } //跳过方法 for(p in o) { if(typeof p === "function") {continue;} }
操做对象属性的工具函数:
/** * 枚举属性的工具函数 * 将对象p中可枚举的属性复制到对象o中,返回对象o; * 若是p和o含有同名的属性,则覆盖o中的属性 * 不处理getter和setter以及复制属性 */ function extend(o, p) { for(let prop in p) { o[prop] = p[prop]; } return o; } /** * 将对象p中可枚举的属性复制到对象o中,返回对象o; * 若是o和p有同名属性,不影响o中的属性 * 不处理getter和setter以及复制属性 */ function merge(o, p) { for(let prop in p) { if(o.hasOwnProperty(prop)) { continue; } o[prop] = p[prop]; } return o; } /** * 若是o中的属性在p中没有同名属性,从o中删除这个属性,并返回o */ function restrict(o, p) { for(let prop in o) { if(!(prop in p)) { delete o[prop]; } } return o; } /** * 若是o中的属性在p中存在同名属性,从o中删除这个属性,并返回o */ function substrict(o, p) { for(let prop in o) { if(prop in p) { delete o[prop]; } } return o; } /** * 返回一个数组,包含o中可枚举的自有属性的名字 */ function keys(o) { //o必须是对象 if(typeof o !== 'object') { throw TypeError(); } var result = []; for(let prop in o) { if(o.hasOwnProperty(prop)) { result.push(prop); } } return result; }
setter
和getter
属性的组成:key
、value
、descripter
。在ES5中,value
能够用一个或两个方法替代(getter
和setter
方法)
全部JavaScript的value
叫作数据属性data property
getter
和setter
定义的属性叫作存取器属性:accessor property
不一样于data property
,accessor property
的读写属性由getter
和setter
决定。
若是属性同时有getter
和setter
,它是一个可读写的属性;
若是属性只有getter
,它是一个只读的属性;
若是属性只有setter
,它是一个只写的属性;读取只写属性老是返回undefined
getter
和setter
定义var o = { data_prop: value; //普通数据属性 //存取器属性是成对定义的函数,函数名是该属性名,没有冒号分隔函数体以属性名 get accessor_prop() {...}, set accessor_prop(value) {...} }
var p = { //x、y是普通可读写的数据属性 x: 1.0, y: 1.0, //r是可读写的存取器属性,具备getter和setter //函数结束后要带上逗号 get r() {return Math.sqrt(this.x * this.x + this.y * this.y)}, set r(newvalue) { var oldvalue = Math.sqrt(this.x * this.x + this.y * this.y); var ratio = newvalue / oldvalue; this.x *= ratio; this.y *= ratio; }, //theta是只读存取器属性,只有getter方法 get theta() {return Math.atan2(this.y, this.x)} };
函数体内的this
指向表示这个点的对象
descripter
属性除key
、value
,还有一组用于描述其特性的descripter
,其中有writable
、enumerable
和configurable
三个属性,其值都为布尔类型,默认为true
假设将setter
和getter
看作descripter
,同理将属性的value
也看作descripter
data property
的四个特性:value
、writable
、enumerable
、configurable
accessory property
的四个特性:getter
、setter
、enumerable
、configurable
ES5提供操做descripter
的API:
调用Object.getOwnPropertyDescripter()
函数,获取某个对象中特定自有属性的descirpter
调用Object.getPrototypeOf()
函数能够获取继承属性的descirpter
调用Object.defineProperty()
函数能够设置属性的特性,或者新建属性,使其具备某种特性
//返回{ value: 1, writable: true, enumerable: true, configurable: true } Object.getOwnPropertyDescriptor({a: 1}, "a"); //继承属性和不存在的属性,返回undefined Object.getOwnPropertyDescriptor({}); Object.getOwnPropertyDescriptor({}, "toString");
var o = {}; //建立空对象 //添加一个不可枚举的属性,其值为1 Object.defineProperty(o, "x", {value: 1, writable: true, enumerable: false, configurable: true}); o.x; //属性存在,但不可枚举, ==>1 Object.keys(o); // ==> [] //对x属性进行修改,使其变为只读 Object.defineProperty(o, 'x', {writable: false}); o.x = 2; //操做失败,但不报错;在严格模式下抛出类型错误 o.x; // ==> 1 //属性的值能够配置 Object.defineProperty(o, 'x', {value: 2}); o.x; // ==> 2 //将x从数据属性修改成存取器属性 Object.defineProperty(o, 'x', {get function() {return 0;}}); o.x; //==> 0
序列化对象指将对象的状态转化为字符串,同时能够将JSON
字符串转化为对象。ES5内置JSON
对象的JSON.stringgify()
和JSON.parse()
能够完成序列化和解析。
var o = {x: 1, y: {z: [false, null, ""]}}; //测试对象 var s =JSON.stringify(o); // '{"x":1,"y":{"z":[false,null,""]}}' var p = JSON.parse(s); //p是s的深拷贝
JSON
是JavaScript的子集,不能表示JavaScript中全部值。
能够表示:object
、Array
、string
、number
、boolean
、null
,能够序列化与还原。infinity
、NaN
序列化结果是null
,Date
对象序列化结果是日期字符串
不能表示:函数、RegExp
、Error
对象和undefined
JSON.stringify()
只能序列化对象自有的可枚举属性。
Object.prototype
对象的方法hasOwnProperty()
:检测该属性是否为对象自有属性
propertyIsEnumerable()
:检测该属性是不是对象自有,而且可枚举的属性
isPrototypeOf
:检测某对象是否为另外一个对象的原型
toString()
:无参数,返回调用该方法对象值的字符串,因为功能有限,某些对象重写了该方法:Array.toString()
、Date.toString()
、Function.toString()
toLoaclString()
:Object
中的toLoaclString()
只是调用toString()
,只有Date
和Number
类对toLoaclString()
定制,能够对数字、日期和时间进行本地化处理
JS中对象是属性的无序集合,每一个对象有三个相关特性:原型prototype
、类属性class property
、可扩展性extensible
对象的建立三种方法:对象字面量、new
调用构造函数和Object.create()
每一个属性由三个部分组成:key
、value
和descripter
key
只能是字符串或者值为字符串的变量标识符
value
能够是任意JavaScript值(数据属性data property
);能够是一个或两个方法,getter
和setter
(控制区属性accessor property
)
descripter
:writable
、enumerable
、configurable
,其值都是布尔类型,默认都为true
。可使用Object.defineProperty()
操做描述符特性。
writable
指该属性是否能够写入数据;enumerable
指该属性是否能够枚举,(使用for-in
循环能够列出,ES5提供Object.keys()
和Object.getOwnPropertyNames()
);configurable
指该属性是否能够用delete
操做符删除和配置。