前言javascript
我先先看一下javascript权威指南中对 object
的定义:java
对象是一种复合值:他将不少值(原始值或者其余对象)聚合在一块儿,能够经过名字访问这些值。对象也能够看作是属性的无序集合,每一个属性都是一个键/值对(key/value
)。 咱们看到的大多数引用类型值都是 Object
类型的实例;并且,Object
也是 ECMAScript
中使用最多的一个类型。对象其实就是一组数据和功能的集合。json
在 JavaScript
中一共有六种主要类型:数组
• string
• number
• boolean
• null
• undefined
• object
复制代码
其中基本数据类型有五种:Undefined
、Null
、Boolean
、Number
和 String
。还有 一种复杂数据类型,也就是对象-----Object
。函数
null其实表示一个空对象的指针。这也是使用 typeof 操做符检测 null 值时会返回"object"的缘由 ui
console.log(typeof null); //object
复制代码
实际上,JavaScript
中还有许多特殊的对象子类型,能够称之为复杂基本类型。this
此外,JavaScript
中还有一些对象子类型,一般被称为内置对象。有些内置对象的名字看起来和简单基础类型同样,不过实际上它们的关系更复杂:spa
• String
• Number
• Boolean
• Object
• Function
• Array
• Date
• RegExp
• Error
复制代码
内置对象将在下篇文章继续讨论。prototype
建立一个名为person
的对象:设计
let person = {
name : "小黄瓜",
age : 22
};
复制代码
在使用对象字面量语法时,属性名也可使用字符串:
let person = {
"name" : "小黄瓜",
"age" : 22,
};
复制代码
这里的数值属性名会自动转换为字符串。
使用对象字面量语法时,若是留空花括号,则能够定义只包含默认属性和方法的对象:
let person = {}; ////与 new Object()相同
person.name = "小黄瓜";
person.age = 22;
复制代码
new
操做符建立并初始化一个新对象,操做符new
后面跟一个构造函数Object
。
let person = new Object();
person.name = "小黄瓜";
person.age = 22;
复制代码
let person = Object.create({name : '小黄瓜'});
person.name //小黄瓜
复制代码
Object.create()
其实是建立了一个空对象,并将原型指针指向了传入的第一个参数。
Object.create = function(new){
let NewObject = {};
NewObject.prototype = new;
return new NewObject();
}
复制代码
let person = {
name : '小黄瓜',
age : 22
}
//查询值
console.log(person.name); //小黄瓜
//设置值
person.name = 'guanguan';
console.log(person.name); //guanguan
复制代码
let person = {
name : 'xiaohuanggua',
age : 22
}
//查询值
console.log(person["name"]); //xiaohuanggua
//设置值
person["name"] = 'guanguan';
console.log(person["name"]); //guanguan
//但方括号语法的主要优势是能够经过变量来访问属性
let newName = "name";
console.log(person[newName]); //guanguan
复制代码
返回一个数组中包含全部属性名(全部的
key
值)。
let person = {
name : 'xiaohuanggua',
age : 22
}
Object.keys(person); //["name", "age"]
复制代码
返回一个数组中包含全部属性值(全部的
value
值)。
let person = {
name : 'xiaohuanggua',
age : 22
}
Object.values(person); //["xiaohuanggua", 22]
复制代码
delete
运算符
能够删除对象的属性。
let person = {
name : 'xiaohuanggua',
age : 22
}
delete person.name;
console.log(person); //{age: 22}
复制代码
delete
运算符只能删除自有属性,不能够删除继承属性(要删除继承属性必须从这个属性的原型对象上删除)。
delete
运算符不能删除可配置项为false
的属性。
用于检测对象成员中的所属关系,判断某个属性是否存在于某个对象中。
in
运算符若是右侧对象的自有属性或者继承属性中包含左侧属性(字符串),则返回true
,不然返回false
。
let person = {
name : 'xiaohuanggua',
age : 22
}
let test ="name" in person;
console.log(test); //true
let test2 ="sex" in person;
console.log(test); //false
复制代码
用于判断属性是否为对象的自有属性,自有属性返回true
,继承属性返回false
。
let person = {
name : 'xiaohuanggua',
age : 22
};
person.hasOwnProperty('name'); //true person对象存在name属性
person.hasOwnProperty("sex"); //false person对象并无这个属性
person.hasOwnProperty("toString"); //false 这个属性是继承自Object对象
复制代码
只有当属性是对象的自有属性,且属性的可枚举性为
true
是才为true
,不然为false
。
let person = {
name : 'xiaohuanggua',
age : 22
};
person.propertyIsEnumerable('name');
//true person对象存在name属性且可枚举
person.propertyIsEnumerable('sex');
//false person对象不存在sex属性
person.propertyIsEnumerable('toString');
//false person对象存在toString属性,可是toString不是person的自有属性,且不可枚举
复制代码
判断属性是否为
undefined
let person = {
name : 'xiaohuanggua',
age : 22
};
person.name !== undefined; //true
person.sex !== undefined; //false
person.toString !== undefined; //true
复制代码
可是 !==
操做符 不能区分不存在的属性和存在可是值为undefined
的属性,而in
能够很好地区分。
let person = {
name : undefined,
};
// !==
person.name !== undefined; //false 属性存在,但值为undefined
person.age !== undefined; //false 属性不存在
// in
'name' in person; //true 属性存在,但值为undefined
'age' in person; //false 属性不存在
复制代码
let person = {
name : "xiaohuanggua",
age : 22,
sex : 'boy',
};
for(item in person){
console.log(item); //name,age,sex
}
复制代码
for in老是获得对象的key值。
得到对象全部可见属性的属性名(key值),不包括原型中定义属性。
let person = {
name : "xiaohuanggua",
age : 22,
sex : 'boy',
};
Object.keys(person); //["name", "age", "sex"]
复制代码
得到对象全部属性,不包括原型中定义属性。
let person = {
name : "xiaohuanggua",
age : 22,
sex : 'boy',
};
Object.getOwnPropertyNames(person); //["name", "age", "sex"]
复制代码
Get
:在读取属性时调用的函数。默认值为 undefined
。
Set
:在写入属性时调用的函数。默认值为 undefined
。
let man = {
name:'小黄瓜',
weibo:'@xiaohuanggua',
get age(){
return new Date().getFullYear()-1997;
},
set age(val){
console.log('我今年'+ val);
}
}
console.log(man.age); //22 读取的时候调用
man.age = 1000; //我今年1000 设置的时候调用
复制代码
数据属性和访问器属性。
数据属性包含一个数据值的位置,在这个位置能够读取和写入值。
数据属性特性:
Configurable
:表示可否修改属性的特性,可否经过 delete
删除属性从新从新定义属性,或者可否把属性修改成访问器属性,这个特性默认值为 true
。
Enumerable
:表示可否经过循环返回属性(可枚举),这个特性默认值为 true
。
Writable
:表示是否能够修改属性的值。默认值为 true
。
Value
:包含这个属性的数据值。读取属性值的时候,从这个位置读;写入属性值的时候, 把新值保存在这个位置。这个特性的默认值为 undefined
。
let person = {
name: "小黄瓜" ;
};
复制代码
直接在对象上定义的属性,它们的Configurable
、Enumerable
和Writable
都被设置为 true
,而value
特性被设置为指定的值。
上面的例子建立了一个名为 name
的属性,为它指定的值是"小黄瓜
"。也就是说,value
特性将 被设置为"小黄瓜
",而对这个值的任何修改都将反映在这个地方。
而若是要修改属性默认的特性,必须使用 Object.defineProperty()
方法。
这个方法接收三个参数: 属性所在的对象、属性的名字和一个对象。
其中,对象的属性必须是:configurable
、enumerable
、writable
和 value
。
let person = {};
Object.defineProperty(person, "name", {
writable: false,
value: "小黄瓜"
});
alert(person.name); //"小黄瓜"
person.name = "小绿瓜";
alert(person.name); //"小黄瓜"
复制代码
咱们建立了一个名为 name
的属性,它的值"小黄瓜
"是只读的。这个属性的值是不可修改 的,若是尝试为它指定新值,那么赋值操做无效。
let person = {};
Object.defineProperty(person, "name", {
configurable: false,
value: "小黄瓜"
});
alert(person.name); //"小黄瓜"
delete person.name;
alert(person.name); //"小黄瓜"
复制代码
由于咱们将 configurable
设置为 false
,表示不能从对象中删除属性,因此删除操做无效。
一旦把属性定义为不可配置的,就不能再把它变回可配置了。那么再调用Object.defineProperty()
方法修改除 writable
以外的特性,都会致使错误:
let person = {};
Object.defineProperty(person, "name", {
configurable: false,
value: "小黄瓜"
});
//报错!!
Object.defineProperty(person, "name", {
configurable: true,
value: "小黄瓜"
});
复制代码
访问器属性 getter
和 setter
函数(这两个函数都不是必需的)。 在读取访问器属性时,会调用 getter
函数,这个函数负责返回有效的值;在写入访问器属性时,会调用 setter
函数并传入新值,这个函数负责如何处理数据。
有以下 四 个特性:
Configurable
:表示可否经过 delete
删除属性从而从新定义属性,可否修改属性的特 性,直接在对象上定义的属性,这个特性的默认值为true
。Enumerable
:表示可否经过循环返回属性。对于直接在对象上定义的属性,这个特性的默认值为 true
。Get
:在读取属性时调用的函数。默认值为 undefined
。Set
:在写入属性时调用的函数。默认值为 undefined
。let person = {
name: '小黄瓜',
edition: 1
};
Object.defineProperty(person, "year", {
get: function(){
return this.name;
},
set: function(newValue){
if (newValue > 2019) {
this.edition = 2;
}
}
});
person.year = 2020;
alert(person.edition); //2
复制代码
不必定非要同时指定 getter
和 setter
。只指定 getter
意味着属性是不可写,写入属性会被忽略。
Object.defineProperties()
方法。利用这个方法能够一次定义多个属性。
这个方法接收两个对象参数:第一个对象是要添加和修改其属性的对象,第二个对象的属性与第一个对象中要添加或修改的属性一一对应。
例如:
let person = {};
Object.defineProperties(person, {
name: {
value: '小黄瓜'
},
edition: {
value: 1
},
year: {
get: function(){
return this.name;
},
set: function(newValue){
if (newValue > 2004) {
this.edition = 1;
}
}
}
});
复制代码
在 person
对象上定义了两个数据属性(name
和 edition
)和一个访问器属性(year
)。 最终的对象与以前中定义的对象相同。惟一的区别是这里的属性都是在同一时间建立的。
Object.getOwnPropertyDescriptor()
方法,能够取得给定属性的描述。
这个方法接收两个参数:属性所在的对象和要读取其描述符的属性名称。返回值是一个对象,若是 是访问器属性,这个对象的属性有 configurable
、enumerable
、get
和 set
;若是是数据属性,这个对象的属性有 configurable
、enumerable
、writable
和 value
。
let person = {};
Object.defineProperties(person, {
name: {
value: '小黄瓜'
},
edition: {
value: 1
},
year: {
get: function(){
return this.name;
},
set: function(newValue){
if (newValue > 2004) {
this.edition = 1;
}
}
}
});
let descriptor = Object.getOwnPropertyDescriptor(person, "name");
alert(descriptor.value); //小黄瓜
alert(descriptor.configurable); //false
alert(typeof descriptor.get); //"undefined"
let descriptor = Object.getOwnPropertyDescriptor(person, "year");
alert(descriptor.value); //undefined
alert(descriptor.enumerable); //false
alert(typeof descriptor.get); //"function"
复制代码
对象有两个方法:stringify()
和 parse()
。这两个方法分别用于把 JavaScript
对象序列化为 JSON
字符串和把 JSON
字符串解析为原生 JavaScript
值。
//对象转字符串
let obj = {x:1,y:true,z:[1,2,3],nullVal:null};
JSON.stringify(obj); //"{"x":1,"y":true,"z":[1,2,3],"nullVal":null}"
//若是存在undefined,则不会出现序列化中
let obj = {val:undefined,a:NaN,b:Infinity,c:new Date()};
JSON.stringify(obj); //"{'a':null,'b':null,'c':2019-06-20T10:32:34}"
//字符串转对象
let obj = JSON.parse('{"x":1}');
obj.x; //1
复制代码
每个对象都有与之相关的原型(proto
)、类(class
)、可扩展性(extensible
)。这就是对象的三个属性。
原型属性
经过对象字面量的方式建立的对象使用Object.prototype
做为它们的原型;
经过new
建立的对象使用构造函数的prototype
属性来做为它们的原型;
经过Object.create()
来建立的对象使用第一个参数做为它们的原型。
//想要检测一个对象是不是另外一个对象的原型(或者处于原型链中),使用isPrototypeOf()方法。
let person = {x:1,y:2};
let newPerson = Object.create(person);
person.isPrototypeOf(newPerson);//true
Object.prototype.isPrototypeOf(newPerson);//true
复制代码
类属性
用于表示信息对象类型。 只能经过toString()
这种方法查询对象的类信息。该方法返回以下格式的字符串: [object class]
。接着提取字符串的第八个到倒数第二个位置之间的字符获得类信息。
经过内置构造函数建立的对象,其类属性与构造函数的名称相匹配。
经过对象字面量和Object.create
建立的对象的类属性是 Object
。
自定义构造函数建立的对象的类属性也是Object
。
可扩展属性
用以表示是否能够向对象添加新属性。
(详情见属性类型)
toString()
方法可用于将当前对象转换为字符串形式,并返回结果。
//Object
let person = {name:'小黄瓜',age:1000};
console.log(person.toString()); //[object Object]
//Array
let array = ["小黄瓜", true, 12, -5];
console.log(array.toString()); //小黄瓜,true,12,-5
复制代码
toLocaleString()
方法返回一个表示这个对象的本地化字符串。可根据本地时间把 Date
对象转换为字符串,并返回结果。
let date = new Date();
console.log(date.toLocaleString()); //2019/8/11 下午11:51:09
复制代码
valueOf()
方法用于返回指定对象的原始值。
// Array:返回数组对象自己
let array = ["小黄瓜", true, 12, -5];
console.log(array.valueOf()); //["小黄瓜", true, 12, -5]
console.log(array.valueOf() === array ); // true
// Object:返回对象自己
let person = {name: "小黄瓜", age: 18};
console.log(person.valueOf()); //{name: "小黄瓜", age: 18}
console.log(person.valueOf() === person ); // true
复制代码
toJSON()
方法返回其自身的 JSON
数据格式。
//原生 Date 对象 toJSON()方法
let d=new Date();
let n=d.toJSON();
console.log(n); //2019-08-11T16:19:52.681Z
//任何对象添加 toJSON()方法
let book = {
"title": "Professional JavaScript",
"authors": [
"Nicholas C. Zakas"
],
edition: 3,
year: 2011,
toJSON: function(){
return this.title;
}
};
let jsonText = JSON.stringify(book);
console.log(jsonText); //"Professional JavaScript"
复制代码
toJSON()
能够做为函数过滤器的补充。假设把一个对象传入JSON.stringify()
,序列化该对象的顺序以下:
1. 若是存在 toJSON()方法并且能经过它取得有效的值,则调用该方法。不然,返回对象自己。
2. 若是提供了第二个参数,应用这个函数过滤器。传入函数过滤器的值是第一步返回的值。
3. 对第二步返回的每一个值进行相应的序列化。
4. 若是提供了第三个参数,执行相应的格式化。
复制代码
关于对象的上半部分已经完结,下一篇还会远吗.....
本文参考: