js 对象
一、什么是对象
- 对象其实就是一个无序集合
- 一个属性包含一个名和一个值。一个属性的值可以是原始数据类型也可以是引用数据类型,如果是函数这种情况下属性也被称为方法
- 对象的每个属性或方法都由一个名称来标识,由属性名来称映射到一个值
二、创建对象
1.1 通过new创建
1.2 字面量创建对象,两种写法是等价的
// new 运算符是创建一个自定义对象
const obj = new Object()
// 字面量定义对象
const obj2 = {
name: 'name'
}
// 修改
obj2.name = 1
obj2[name] = 2
1.3 通过构造函数创建
// 通过构造函数创建对象
// 普通函数名小写,构造函数名首字母大写,主要是为了要区分普通函数和构造函数,毕竟构造函数就是能够创建对象的函数
function CreatePerson (a, b, c) {
this.a = a
this.b = b
this.c = c,
this.init = function () {
console.log(a)
}
}
// 如果不传参数,调用时可以不写小括号
// const createPerson = new CreatePerson
const createPerson = new CreatePerson(1, 2, 3)
console.log(createPerson) //CreatePerson {a: 1, b: 2, c: 3}
//构造函数被识别为特定类型(对象),因为自定义对象它继承的是object
console.log(createPerson instanceof Object); // true
console.log(createPerson instanceof CreatePerson); // true
普通函数创建(本文略过工厂模式)和构造函数创建只有以下几点差异
- 只不过没有显式地创建对象。
- 属性和方法直接赋值给了 this。
- 没有 return。
当创建构造函数时要使用new操作符,new操作符执行了以下操作
- 在内存中创建一个对象
- 设置原型,将构造函数的原型赋值给新对象的[[Prototype]], 说人话就是赋值给对象的__proto__
- 将this指向新建对象
- 将构造函数中的值,赋值给对象
- 如果构造函数, 返回一个引用数据类型,就返回这个引用数据类型;否则,返回第一步创建的新对象。
三、数据属性
数据属性有四个特性可以描述他们的行为,可以通过Object.defineProperty来修改这几个特性
- configurable: 是否能通过 delete 删除该属性 默认为true, 严格模式下抛出一个错误,非严格没效果
- enumerable: 是否可枚举(是否能通过for in 循环),默认true
- writable: 是否能被修改 默认true, 设置fasle尝试修改,严格模式下抛出一个错误,非严格没效果
- value: 设置初始值 默认undefined
const obj = {}
Object.defineProperty(obj, 'name', {
configurable: false,
enumerable: false,
writable: false,
value: 321
})
四、操作对象
4.1 合并对象
es6提供合并对象Object.assign(),接收一个目标对象和多个源对象,而源对象会将自有的属性复制到目标对象上,并且返回一个新的对象
let obj = {a: 1}
Object.assign(obj, {b: 2}) // { a: 1, b: 2 }
console.log(obj) // { a: 1, b: 2 }
// 多个源对象, 合并的极限是几个没试出来
Object.assign(obj, {b: 2}, {c: 3}, {d: 4}, {e: 4}, {f: 4}, {g: 1})
// 如果目标对象和源对象的属性相同,那么会覆盖重复的属性
Object.assign(obj, {b: 2})
console.log(obj) // {a: 1, b: 2, c: 3, d: 4, e: 4, f: 4, g: 1}
// Object.assign实际上是一个浅拷贝, 如果赋值期间出错,那么它只会复制部分属性
obj = {}
let obj2 = {
a: 321,
get b () {
throw new Error()
},
c: 123
}
try {
Object.assign(obj, obj2)
} catch {}
console.log(obj) // {a: 321}
4.2 可计算属性
const nameKey = 'name'
const ageKey = function () { return 666 }
const brKey = nameKey === 'name' ? '123' : '321'
// 动态添加属性名
const obj = {
[nameKey]: 123,
[ageKey()]: 3,
[brKey]: 321,
obj: 10
}
4.3 对象解构, 使用与对象匹配的结构来实现对象属性赋值
const { name } = obj
const { length } = Object.keys(obj)
console.log(name, length)
// 如果要取的值不存在,可以给一个默认值
const { age = 1 } = obj
// 嵌套解构
const objCopy = {}
const obj2 = {
name: 'Matt',
age: 27,
job: {
title: '对象'
}
};
// 将obj2的属性复制给objCopy, obj2的属性改变objCopy跟着改变, 可以浅拷贝,不能深拷贝
({ age: objCopy.age, job: objCopy.job } = obj2)
// 解构参数
const objData = {a: 1, b: 2}
const fn = function ({ a, b }) {
console.log(a, b) // 1, 2
}
fn(objData)
五、对象迭代
从 ECMAScript 5 开始,有三种原生的方法用于列出或枚举对象的属性
- for…in 循环,依次访问一个对象及其原型链中所有可枚举的属性
- Object.keys(object), 该方法返回对象自身包含(不包括原型中)的所有可枚举属性的名称的数组。
- Object.getOwnPropertyNames(object),返回对象自身包含(不包括原型中)的所有属性(无论是否可枚举)的名称的数组。
let key1 = Symbol('key1')
let key2 = Symbol('key2')
const o = {
[key1]: 1,
[key2]: 2,
key3: 3,
key4: 4,
5: 5
}
console.log(Object.keys(o))
console.log(Object.getOwnPropertyNames(o))
console.log(Object.getOwnPropertySymbols(o))
// ['5', 'key3', 'key4'] Symbol会被忽略
// ['5', 'key3', 'key4'] Symbol会被忽略
// [Symbol(key1), Symbol(key2)]
对象的迭代, es8新增 Object.values()和 Object.entries() 参数是对象,Symbol会被忽略
console.log(Object.values(o))
console.log(Object.entries(o))
// [5, 3, 4] 返回对象的值
// [['5', 5], ['key3', 3], ['key4', 4]] 值对的数组, 原对象键名不是字符串也会变成字符串
for (const [ key, value ] of Object.entries(o)) {
console.log(key, value)
}
参考自:
- mdn
- 高级程序设计4
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
二维码