-
属性特性(property attribute):每个属性与之相关的值:
可写(writable attribute);
可枚举(enumerable attribute);
可配置(configurable attribute);
-
对象特性(object attribute):
原型(prototype);
类(class);
扩展标记(extensible flag);
-
三类js对象:
内置对象(native object):由ECMAScript规范定义的对象或类;
宿主对象(host object):由js解释器所嵌入的宿主环境定义的;
自定义对象(user-defined object):由运行中的js代码创建的对象
-
两类属性:
自有属性(own property):直接在对象中定义的属性;
继承属性(inherited property):在对象的原型对象中定义的属性;
1 创建对象
三种方法:直接量;new
和Object.create()
函数;
1.1 对象直接量
语法:
var o = {};
1.2 通过new创建对象
语法:
var o = new Object();
1.3 原型
通过Object.prototype
获得对原型对象的引用
1.4 Object.create()
第一个参数是这个对象的原型;第二个可选参数是对对象的属性进行进一步描述
//创建一个普通的空对象
var o = Object.create(Object.prototype);
2 属性的查询和设置
[]
和.
2.1 作为关联数组的对象
JavaScript对象都是关联数组(字典、映射、散列等)
2.2 继承
[暂跳]
2.3 属性访问错误
当访问不存在的对象的属性就会报错,可以通过下面方法避免出错:
var book = {};
var len;
if (book.subtitle) {
len = book.subtitle.length;
}
console.log(len); //undefined
//或者
var book = {subtitle:"toJSON"};
var len;
len = book && book.subtitle && book.subtitle.length; //&&运算符的短路行为
console.log(len); //6
//当左操作数是真值时,“&&”运算符将计算右操作数的值并将其返回作为整个表达式的计算结果
2.4 删除属性
delete运算符不能删除继承属性
3 检测属性
5种方法:
in运算符,检测自有属性和继承属性
var o = {name:"Oliver",age:18,nothing:undefined};
console.log("name" in o); //True
console.log("toString" in o); //True
console.log("nothing" in o); //True
hasOwnProperty方法,检测自有属性
var o = {name:"Oliver",age:18,nothing:undefined};
console.log(o.hasOwnProperty("toString")); //False
console.log(o.hasOwnProperty("name")); //True
propertyIsEnumerable方法,检测自有可枚举的属性
var o = {name:"Oliver",age:18,nothing:undefined};
console.log(o.propertyIsEnumerable("toString")); //False
console.log(o.propertyIsEnumerable("name")); //True
"!=="方法,检测属性是否为undefined
var o = {name:"Oliver",age:18,nothing:undefined};
console.log(o.name !== undefined); //True
console.log(o.nothing !== undefined); //False
有一种场景只能使用in运算符。in可以区分不存在的属性和存在但是值为undefined的属性:
var o = {name:"Oliver",age:18,nothing:undefined};
console.log("nothing" in o); //True
console.log(o.nothing !== undefined); //False
delete o.nothing;
console.log("nothing" in o); //False
console.log(o.nothing !== undefined); //False
需要注意的是,"!=="可以区分undefined和null
4 枚举属性
把p中的可枚举属性赋值到o中,并返回o,如果有同名属性则覆盖o中的属性
function extend (o, p) {
for (var prop in p) {
o[prop] = p[prop];
}
return o;
}
如:
var p = {name:"Oliver",age:18,nothing:undefined};
var o = {};
function extend (o, p) {
for (var prop in p) {
o[prop] = p[prop];
}
return o;
}
console.log(extend(o,p));
将p中的可枚举属性复制到o中,并返回o,如果有同名属性则不覆盖o中的属性
function merge (o, p) {
for (var prop in p) {
if (o.hasOwnProperty(prop)) {
continue;
o[prop] = p[prop];
}
}
return o;
}
如:
var p = {name:"Oliver",age:18,nothing:undefined};
var o = {name:"Oli"};
function merge (o, p) {
for (var prop in p) {
if (o.hasOwnProperty(prop)) {
continue;
o[prop] = p[prop];
}
}
return o;
}
console.log(merge(o,p).name); //Oli
如果o中的属性在p中没有同名属性,则从o中删除这个属性
function restrict (o, p) {
for (var prop in o) {
if (!(prop in p)) {
delete o[prop];
}
}
return o;
}
如:
var p = {age:18,nothing:undefined};
var o = {name:"Oli"};
function restrict (o, p) {
for (var prop in o) {
if (!(prop in p)) {
delete o[prop];
}
}
return o;
}
console.log(merge(o, p).name); //undefined
如果o中的属性在p中存在同名属性,则从o中删除这个属性
function subtract (o, p) {
for (var prop in o) {
if (prop in p) {
delete o[prop];
}
}
return o;
}
如:
var p = {name:"Oliver",age:18,nothing:undefined};
var o = {name:"Oli"};
function subtract (o, p) {
for (var prop in o) {
if (prop in p) {
delete o[prop];
}
}
return o;
}
console.log(subtract(o, p).name); //undefined
返回一个新对象,这个对象同时拥有o的属性和p的属性,如果有重名属性,使用p中的属性值
function union (o, p) {
for (var prop in o) {
if (prop in p) {
o[prop] = p[prop]
}
}
return o;
}
如:
var p = {name:"Oliver",age:18,nothing:undefined};
var o = {name:"Oli"};
function union (o, p) {
for (var prop in o) {
if (prop in p) {
o[prop] = p[prop]
}
}
return o;
}
console.log(union(o, p).name); //Oliver
返回一个新对象,这个对象同时拥有o的属性和p的属性,如果重名,使用o的值
function intersection (o, p) {
for (var prop in o) {
if (prop in p) {
delete p[prop];
}
}
return o;
}
如:
var p = {name:"Oliver",age:18,nothing:undefined};
var o = {name:"Oli"};
function intersection (o, p) {
for (var prop in o) {
if (prop in p) {
delete p[prop];
}
}
return o;
}
console.log(intersection(o, p).name); //Oliver
返回一个数组,这个数组包含的是o中可枚举的自有属性的名字
5 属性getter和setter
存取器属性(accessor property):由getter和setter定义的属性;它不同于数据属性(data property),数据属性只有一个简单的值;
语法:
var o = {
data_prop: value,/*这是普通数据属性*/
get accessor_prop(){/*这里是函数体*/},
set accessor_prop(value){/*这里是函数体*/}
};
这个定义没有使用function关键字,而是使用get和(或)set
存取器属性是可以继承的
var o = {
n: 0,/*这是普通数据属性*/
get next(){return this.n++},
set next(n){this.n = n}
};
o.next = 10; //setter
console.log(o.next) //getter
6 属性的特性
存取器属性的四个特性:读取(get)、写入(set)、可枚举性(enumerable)和可配置性(configurable)
数据属性的四个特性:值(value)、可写性(writable)、可枚举性(enumerable)和可配置性(configurable)
获得某个对象特定属性的属性描述符
Object.getOwnPropertyDescriptor()
方法:
//name数据属性
let o = {
name: "Oliver",
get transferName(){return this.name},
set transferName(value){this.name = name}
};
let result = Object.getOwnPropertyDescriptor(o, "name");
console.log(result); //Object
for (let name in result) {
console.log(name, result[name]);
}
//value Oliver
//writable True
//enumerable True
//configurable True
//transferName存取器属性
let o = {
name: "Oliver",
get transferName(){return this.name},
set transferName(value){this.name = name}
};
let result = Object.getOwnPropertyDescriptor(o, "transferName");
console.log(result); //Object
for (let name in result) {
console.log(name, result[name]);
}
//get function transferName(){return this.name}
//set function transferName(value){this.name = name}
//enumerable True
//configurable True
设置属性的特性
Object.defineProperty()
方法:
let o = {
name: "Oliver",
get transferName(){return this.name},
set transferName(value){this.name = name}
};
let result = Object.getOwnPropertyDescriptor(o, "name");
console.log(result); //Object
for (let name in result) {
console.log(name, result[name]);
}
//value Oliver
//writable True
//enumerable True
//configurable True
Object.defineProperty(o, "name", {
value: "Oli",
writable: false,
enumerable: false,
configurable: false
});
let result1 = Object.getOwnPropertyDescriptor(o, "name");
console.log(result1); //Object
for (let name in result1) {
console.log(name, result1[name]);
}
//value Oli
//writable False
//enumerable False
//configurable False
该方法不能修改继承属性
设置多个属性特性
Object.defineProperties()
方法:
语法:Object.defineProperties(Object, props)
var obj = {};
Object.defineProperties(obj, {
x: {value: 1, writable: false, enumerable: true, configurable: false},
y: {get: function(){return this.x}, enumerable: true, configurable: false}
});
console.log(obj.y); //1
console.log(obj.x); //1
obj.x = 2;
console.log(obj.x); //严格模式下报错
老式API
在ES5之前,需要用到
__lookupGetter()__
__lookupSetter()__
__defineGetter()__
__defineSetter()__
7 对象的三个属性
原型(prototype)
类(class)
可扩展性(extensible)
7.1 原型属性
对象的原型属性是用来继承属性的
var obj = {};
console.log(obj.constructor); //function Object(){ [native code] }
console.log(obj.__proto__); //Object
console.log(Object); //function Object(){ [native code] }
console.log(Object.prototype); //Object
console.log(Object.prototype.isPrototypeOf(obj)); //True
检测一个对象是否是另一个对象的原型
isPrototypeOf()
方法
var obj = {};
var anotherObj = Object.create(obj);
console.log(Object.prototype.isPrototypeOf(obj)); //True
console.log(obj.isPrototypeOf(anotherObj)); //True
7.2 类属性
是一个字符串,用以表示对象的类型信息,默认的toString()方法很有可能被修改,所以应该使用下面的classof函数:
查询类
使用classof()
函数:
function classof (o) {
if (o === null) {
return "Null";
}
if (o === undefined) {
return "Undefined";
}
return Object.prototype.toString.call(o).slice(8, -1);
}
例如:
console.log(classof(obj)); //Object
console.log(classof(Number)); //Function
console.log(classof(123)); //Number
7.3 可扩展性
可扩展性表示是否可以给对象添加新属性
设置为不可扩展,检测是否不可扩展
Object.preventExtensions()
设置为对象不可扩展Object.isExtensible()
检测是否可扩展
var obj = {
name: "Oliver"
};
Object.preventExtensions(obj);
obj.name = "Oli"; //可修改属性的值
delete obj.name; //可配置属性
obj.age = 18; //不可扩展 严格模式下报错
设置为不可扩展且不可配置,检测是否不可扩展且不可配置
Object.seal()
Object.isSealed()
var obj = {
name: "Oliver"
};
Object.seal(obj);
obj.name = "Oli"; //可修改属性的值
delete obj.name; //不可配置属性 严格模式下报错
obj.age = 18; //不可扩展 严格模式下报错
设置为不可扩展、不可配置且所有数据属性设置为只读(setter不受影响),以及检测方法
Object.freeze()
Object.isFrozen()
var obj = {
name: "Oliver",
anotherObj: {
name: "Oliver"
},
set setName (value) {
this.name = value;
}
};
Object.freeze(obj);
obj.anotherObj.name = "Oli"; //可以修改属性值为对象的子对象的属性
obj.setName = "Oli"; //不可修改setter属性的值
obj.name = "Oli"; //不可修改属性的值
delete obj.name; //不可配置属性 严格模式下报错
obj.age = 18; //不可扩展 严格模式下报错
8 序列化对象
-
对象序列化(serialization):将对象的状态转换为字符串,或将字符串还原成对象;
JSON.stringify()
JSON.parse()
JSON(JavaScript Object Notation):JavaScript对象表示法;
var date = new Date();
console.log(date.toString()); //与JSON.stringify()的返回值不同
console.log(date.toJSON()); //与JSON.stringify()的返回值一样
9 对象方法
toString方法
toLocaleString方法
toJSON方法(严格意义上不算对象原型的方法)
valueOf方法(用在需要将它转换成某种原始值而非字符串的时候)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。