对象是一种复合值,汇聚多个值并允许按名字存储和获取这些值。
创建对象的几种方式
1.对象字面量
创建对象最简单的方式。
let empty ={} // 创建空对象
let point ={x:0,y:1} //创建包含两个数值属性
let p2 = {x:point.x,y:point.y} //创建包含两个复杂值的对象
let book ={
"main title":"JavaScript",
"sub-title":"The Definitive Guide",
for:"all audiences",
author:{
firstname:"David",
surname:"Flanagan"
}
}
2.使用new创建对象
new操作符用于创建和初始化一个对象
let o = new Object()
let a = new Array()
let d = new Date()
let r = new Map() //创建一个映射对象,用于存储键/值映射
原型prototype
原型:每个js对象都有另一个与之关联的对象,该对象被称为原型
通过对象字面量创建的所有对象都有相同的原型。使用new关键字创建的对象,它们的原型为objectName.prototype。
3.Object.create()
Object.create()用于创建新对象,能以任意原型创建新对象。使用第一个参数作为新对象的原型:
let o1 = Object.create({x:0,y:1})
创建一个没有原型的对象,只需要传入null。
let o2 = Object.create(null)
创建一个普通空对象,有原型
let o3 = Object.create(Object.prototype)
查询和设置属性
1.使用点操作符
let author = book.author; //获取book.author属性
book.author = "greace"; //修改book.author属性
2.使用[]操作符
let title = book["main title"] //获取book."main title"属性
book["main title"] = "ECMAScript"; //修改"main title"属性
作为关联数组的对象
关联数组是使用object.[字符串]形式,看起来像访问数组,不过是以字符串而不是数值作为索引的数组,这种形式被称为关联数组(或散列、映射、字典)
function addStock(protfolio, stockName, shares) {
protfolio[stockName] = shares;
}
let protfolio ={}
addStock(protfolio,"stock1",1.2)
addStock(protfolio,"stock2",1.3)
console.log(protfolio)
此案例演示了使用数组表示法灵活的为对象添加属性。
继承
js对象有一组自有属性,同时也从它们的原型对象继承一组属性。
let o ={} //o从Obejct.prototype继承对象方法
o.x = 1 //现在它有自有属性x
let p = Object.create(o) //p从o和Obejct.prototype继承属性
p.y = 2 //p有一个自有属性y
let q = Object.create(p) //q从p、o、Obejct.prototype继承属性
q.z = 3 //q有一个自有属性z
let f = q.toString() //toString继承自Object.prototype
console.log(q.x+q.y) //3 x和y分别继承自o和p
属性赋值查询原型链只是为了确定是否允许赋值。如果允许赋值,则只会在原始对象上创建或设置属性,而不会修改原型链中的对象。
属性访问错误
查询不存在的属性不是错误,表达式的求值结果是undefined。
查询不存在对象的属性则是错误。
let len = book.surtitle.length //TypeError,book.surtitle本身不存在为undefined,undefined没有length
还有一种错误是,尝试设置只读属性时也会报错
删除属性
delete操作符用于移除对象中的属性。
delete只删除自有属性,不删除继承属性。
测试属性
检查对象是否有一个给定名字的属性
1.in操作符
自有属性和继承属性都返回true
let o = [x:1}
"x" in o //true
"y" in o //false
"toString" in o //true
2.hasOwnProperty()
对继承属性都返回false
let o = [x:1}
o.hasOwnProperty("x") //true
o.hasOwnProperty("y") //false
o.hasOwnProperty("toString") //false
3.propertyIsEnumerable()
自有属性且该属性为可枚举都返回true
4.使用!==
let o = [x:1}
o.x !== undefined //true
o.y !== undefined //false
o.toString !== undefined //true
可枚举属性
for/in
用于遍历对象的每个可枚举属性。将属性名赋值给循环变量。对象的继承的内置方法不会被遍历。
还可以先获取对象所有属性名的数组,然后在通过for/of循环遍历数组
4个获取属性名数组的函数
- Object.keys()返回可枚举自有属性名的数组
- Object.getOwnPropertyNames()返回所以是字符串格式的属性名数组
- Object.getOwnPropertySymbols()返回所有是符号的属性名数组
- Reflect.ownKeys()返回所有属性名
扩展对象assign() ES6
把一个对象复制到另一个对象。
接收两个或多个对象作为参数,其中第一个对象作为目标对象,之后的对象作为源对象。
每个来源对象会把自身的可枚举自有属性复制到目标对象,第一个来源对象的属性会覆盖目标对象的同名属性,第二个来源对象属性会覆盖第一个来源对象的同名属性。
序列化对象
对象序列化是把对象的状态转换为字符串的过程,之后再从中恢复到对象的状态。
JSON.string()用于将对象转为字符串,只序列化对象的可枚举自由属性
JSON.parse()用于恢复字符串为对象格式
对象方法
- toString()方法不接收参数,返回调用它的对象的值的字符串。
- toLocaleString()方法,返回对象的本地化字符串表示。
- valueOf()方法,用于把对象转换为某些非字符串原始值时被调用。
- toJSON()
对象字面量扩展语法
简写属性
ES6同名属性可以简写
let x = 1, y =2;
let o ={x,y};
o.x+o.y; //3
计算的属性名(ES6)
使用如下:
const PROPERTY_NAME = "p1";
function computedPropertyName(){return "p"+2;};
let o = {};
o[PROPERTY_NAME] = 1;
o[computedPropertyName()] = 2;
//或使用对象字面量的写法
let p ={
[PROPERTY_NAME]: 1,
[computedPropertyName()]: 2
这种语法可以在方括号中加入任何js表达式,这个表达式求值得到的结果会作为属性的名字。
可能需要计算属性的场景是,一个js代码库,需要给这个库传入一个包含一组特定属性的对象,而这组属性的名字在该库中是以常量定义的。
符号作为属性名
const extension = Symbol('my extension symbol');
let o ={
[extension]:{}
}
o[extension].x = 0
使用符号是为了js对象定义安全的扩展机制。符号非常适合用于创建唯一的属性名。
扩展操作符...
扩展运算符只能扩展对象的自有属性,可用于将已有的对象扩展到其他对象上
let o = {x:1}
let p ={x:0,...o} //对象o的值覆盖了初始值
简写方法
把函数定义为对象属性时,称为该函数为方法
// ES6之前的写法
let square ={
area: function(){return this.side * this.side;},
side:10
}
square.area() //100
// ES6之后的写法
let square ={
area (){return this.side * this.side;},
side:10
}
square.area() //100