对象
对象是JavaScript的基础数据范例:属性的无序鸠合。每一个属性key: value
和属性形貌符descripter
构成。
属性名
key
:字符串或正当的变量标识符;属性值
value
:可所以恣意JavaScript值(number
、string
、boolean
、null
、undefined
和数组、对象).value
可所以getter
和setter
。属性形貌符
descripter
:每一个属性的三个相干特征writable
、enumerable
、configurable
,其值都是布尔范例,默许都为true
1 建立对象
建立对象有三种要领:对象字面量{a: 1}
,new Constructor()
、Object.create()
1.1 对象字面量
var book = {
"main title": "JavaScript", //有空格或其他非标识符、关键字,必需运用双引号
"sub-title": "The Definitive Guide",
"for": "all audiences",
author: {
firstname: "David",
lastname: "Flanagan"
}
}
1.2 new
操纵符挪用组织函数
能够运用new
操纵符挪用一个组织器函数Constructor()
建立一个对象。
var o = new String();
var d = new Date();
1.3 Object.create()
要领
原型:每一个JS对象都有一个与之相干联的原型对象prototype
,对象其原型对象上继续属性。(当前对象中的__proto__
属性是其原型对象的链接)
一切经由历程字面量建立的对象的原型都是Object.prototype
,一个字面量对象{}
相当于挪用new Object()
。
Object.prototype
的原型是null
,所以null
是原型的出口。
Object.create()
是一个静态函数(不是供应给对象挪用的要领),用于建立对象:
第一个参数:原型对象,建立的新对象以该参数为原型;
第二个参数:可选,用于对对象属性的形貌
建立一个没有原型的对象:
Object.create(null);
建立一个一般空对象(
{}
或new Object()
):Object.create(Object.prototype);
2 对象三个特别属性
每一个对象都有与之相干的3个属性:原型prototype
、类属性calss attribute
、可扩大性extensible attribute
2.1 原型
每一个JS对象都与另一个原型对象(prototype
),应用原型能够完成继续。
字面量的原型是:
Object.prototype
new
操纵符建立的对象其原型:组织器函数的原型(prototype
属性)Object.create()
建立的对象,其原型:第一个参数
查询对象的原型
ES5中定义了
Object.getPrototypeOf()
函数,来查询对象的原型应用
new
建立的对象会继续constructor
属性,指向建立该对的组织器函数,一切该对象的原型是:obj.constructor.prototype
字面量
{}
的constructor
属性指向Object()
运用
isPrototypeOf()
要领检察一个对象是不是为另一个对象的原型(或处于原型链中)Array.prototype.isPrototypeOf([]); // ==> true
2.2 类属性
对象的类属性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"
2.3 可扩大性extensible attribute
对象的课扩大性用来形貌对象是不是能够增添新的属性。一切的内置对象和自定义对象都是可扩大的,除非将其转化为不可扩大
Object.esExtensible()
函数推断传入对象是不是能够扩大;Object.preventExensible()
函数将传入的对象设置为不可扩大,而且历程不可逆;只影响对象本身的可扩大性Object.seal()
函数将对象设置为不可扩大,属性形貌符configurable
设置为false
(不能增添新属性,已有的属性不能删除或设置,然则关于writable: true
时,能够修正属性的值);历程不可逆Object.isSealed()
函数推断一个对象是不是关闭Object.freeze()
函数将对象设置为不可扩大,属性形貌符configurable: false;
,writable: false;
只读。value
为accessor property
含有setter
函数,不受影响
3 构成对象的属性
每一个对象是无需的属性鸠合,属性名可所以正当的变量标识符或字符串;变量值可所以恣意JavaScript值;属性由形貌符descripter
来掌握特征;
3.1 属性的查询与设置
属性能够经由历程.
和[]
来接见:
运用
.
接见时,其右边必需是属性称号定名的简朴标识符运用
[]
接见时,括号内必需是计算结果为字符串的表达式,字符串是属性的名字。变量名为关键字、含有空格或属性名是变量时,必需运用[]
var author = book.author; var name = author.surname; var title = book["main title"];
属性的设置:与接见类似,将其放在赋值表达式的左边
book.edtion = 6;
book["main title"] = "ECMAScript";
继续与毛病
在查询一个对象是不是存在时,先检察本身属性,假如没有;经由历程原型链逐层向上查找,直到原型链顶端null
为止。
假如本身属性与原型链中均为找到,属性接见返回
undefined
,不报错假如查询不存在对象的属性,会报错
为
null
和undefined
设置属性会报错
3.2 属性删除
运用delete
操纵符,能够删除对象的属性(其形貌符中configurable
为true
),而且只能删除自有属性,不能删除继续属性
3.3 属性检测
推断某个属性是不是在某个对象中,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
3.4 罗列属性
运用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;
}
3.5 属性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
指向示意这个点的对象
3.6 属性的形貌符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
4 序列化对象
序列化对象指将对象的状况转化为字符串,同时能够将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()
只能序列化对象自有的可罗列属性。
5 Object.prototype
对象的要领
hasOwnProperty()
:检测该属性是不是为对象自有属性propertyIsEnumerable()
:检测该属性是不是是对象自有,而且可罗列的属性isPrototypeOf
:检测某对象是不是为另一个对象的原型toString()
:无参数,返回挪用该要领对象值的字符串,因为功用有限,某些对象重写了该要领:Array.toString()
、Date.toString()
、Function.toString()
toLoaclString()
:Object
中的toLoaclString()
只是挪用toString()
,只要Date
和Number
类对toLoaclString()
定制,能够对数字、日期和时候举行本地化处置惩罚
6 总结
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
操纵符删除和设置。