js 对象


一、什么是对象

  1. 对象其实就是一个无序集合
  2. 一个属性包含一个名和一个值。一个属性的值可以是原始数据类型也可以是引用数据类型,如果是函数这种情况下属性也被称为方法
  3. 对象的每个属性或方法都由一个名称来标识,由属性名来称映射到一个值

二、创建对象

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

普通函数创建(本文略过工厂模式)和构造函数创建只有以下几点差异

  1. 只不过没有显式地创建对象。
  2. 属性和方法直接赋值给了 this。
  3. 没有 return。

当创建构造函数时要使用new操作符,new操作符执行了以下操作

  1. 在内存中创建一个对象
  2. 设置原型,将构造函数的原型赋值给新对象的[[Prototype]], 说人话就是赋值给对象的__proto__
  3. 将this指向新建对象
  4. 将构造函数中的值,赋值给对象
  5. 如果构造函数, 返回一个引用数据类型,就返回这个引用数据类型;否则,返回第一步创建的新对象。

三、数据属性

数据属性有四个特性可以描述他们的行为,可以通过Object.defineProperty来修改这几个特性

  1. configurable: 是否能通过 delete 删除该属性 默认为true, 严格模式下抛出一个错误,非严格没效果
  2. enumerable: 是否可枚举(是否能通过for in 循环),默认true
  3. writable: 是否能被修改 默认true, 设置fasle尝试修改,严格模式下抛出一个错误,非严格没效果
  4. 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 开始,有三种原生的方法用于列出或枚举对象的属性

  1. for…in 循环,依次访问一个对象及其原型链中所有可枚举的属性
  2. Object.keys(object), 该方法返回对象自身包含(不包括原型中)的所有可枚举属性的名称的数组。
  3. 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)
}
        

参考自:

  1. mdn
  2. 高级程序设计4
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
)">
< <上一篇

)">
下一篇>>