第六章 对象 梳理

对象是一种复合值,汇聚多个值并允许按名字存储和获取这些值。

创建对象的几种方式

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个获取属性名数组的函数

  1. Object.keys()返回可枚举自有属性名的数组
  2. Object.getOwnPropertyNames()返回所以是字符串格式的属性名数组
  3. Object.getOwnPropertySymbols()返回所有是符号的属性名数组
  4. Reflect.ownKeys()返回所有属性名

扩展对象assign() ES6

把一个对象复制到另一个对象。
接收两个或多个对象作为参数,其中第一个对象作为目标对象,之后的对象作为源对象。
每个来源对象会把自身的可枚举自有属性复制到目标对象,第一个来源对象的属性会覆盖目标对象的同名属性,第二个来源对象属性会覆盖第一个来源对象的同名属性。

序列化对象

对象序列化是把对象的状态转换为字符串的过程,之后再从中恢复到对象的状态。
JSON.string()用于将对象转为字符串,只序列化对象的可枚举自由属性
JSON.parse()用于恢复字符串为对象格式

对象方法

  1. toString()方法不接收参数,返回调用它的对象的值的字符串。
  2. toLocaleString()方法,返回对象的本地化字符串表示。
  3. valueOf()方法,用于把对象转换为某些非字符串原始值时被调用。
  4. 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

你可能感兴趣的:(第六章 对象 梳理)