Object

211 阅读3分钟

创建对象不继承任何属性的方法

var obj = Object.create(null)

Set

Set存储的成员是不能重复的

  1. 创建

参数为可遍历的对象

let s = new Set()
let s1 = new Set([1,3,4])
  1. 增加add
s.add('hello')
s.add(9).add(10)
  1. 删除
s.delete('hello')
  1. 清空
s.clear()
  1. 查找
s.has('hello')
  1. 长度
s.size()
  1. 读取
s.keys()
s.values()
s.entries()
s.forEach(item =>{
  console.log(item)
})
for (let item of s ){
  console.log(item)
}

Set Map Object的区别

  1. 所以对象的属性名必须是字符串类型,如果属性名不是字符串也会转换成字符串,并且属性名在对象中是唯一的。
var obj = Object.create(null)
map[5] = 5
map['5'] // 5
var obj = Object.create(null)
var key1 = {}
var key2 = {}
map[key1] = 100
mapp[key2] // 100 原因:Object->String的类型转换中被转换成了"[object,Object]"

Object.getOwnPropertyDescriptor()

var obj = {
    name:'luoyi'
}
Object.getOwnPropertyDescriptor(obj,'name')

Object.defineProperty()

Object.defineProperty(obj,'sex',{
  value:'girl',
  writable:true, //是否可以修改属性的值
  configurable:true, //是否可以使用defineProperty来修改属性的描述
  enumerable:true //是否会出现在对象的枚举中
})

writable

决定是否可以修改属性的值

configurable

是否可以通过defineProperty配置对象的属性

  1. configurable设置为false之后,可以将writable设置为false之外,但是不能再将writable设置为false。
  2. configurable设置为false之后,用delete删除属性也会失败。

enumerable

设置对象的属性是否可枚举

writable:false和configurable:false配合使用可以创建一个常量属性。

var obj = {}
Object.defineProperty(obj,'CONSTVALUE',{
    value:40,
    writable:false,
    configurable:false
})

Object.defineProperties()

Object.preventExtensions()

禁止对象扩展属性,但是可以修改属性的值

var obj = {
    name:'luoyi'
}
Object.preventExtensions(obj)
obj.sex = 'girl'
obj.sex // undefined
obj.name = 'luoyi3'
obj.name // 'luoyi3'
delete obj.name 
obj.name // undefined

Object.seal() :Object.preventExtensions() + 所有属性的configurable设置为false

不能添加新属性,不能重新配置属性的描述,不能删除属性,但是可以修改属性的值

Object.freeze():Object.preventExtensions() + 所有属性的configurable设置为false + 所有属性的writable设置为flase

hasOwnProperty()

只会检查对象本身,不会检查原型链

var obj = {
    a : 1,
    b : 2
}
obj.hasOwnProperty(a) // true
obj.hasOwnProperty(c) // false

propertyIsEnumerable()

检查给定属性是否直接存在于对象中,并且满足enumerable:true

var obj = {a : 1}
obj.propertyIsEnumerable('a') //true

Object.keys()

返回对象本身可枚举属性组成的数组,不包括Symbol类型

var obj = {a : 1}
Object.keys(obj) // ["a"]

Object.getOwnPropertyNames()

返回对象本身所有属性的组成的数组包括可枚举和不可枚举 不包括Symbol类型

Object.getPrototypeOf()

获取实例对象的原型

Object.getOwePropertySymbols()

返回包含所有Symbol自有属性的数组。

Reflect.onKeys(obj)

获取对象的所有类型的key值包括Symbol类型

如何实现对象的浅拷贝和深拷贝

浅拷贝

  1. Object.assing()
var obj = {
    name :'luoyi',
    age:3
}
var obj1 = Object.assign({},obj)

2. 扩展运算符

var obj3 = {...obj}
  1. for-in循环
    let obj = {
      a: 100,
      b: [10, 20, 20],
      c: {
        x: 10
      },
      d: /^\d+$/
    }
    let obj2 = {}

    for (let key in obj) {
      if (!obj.hasOwnProperty(key)) break;
      obj2[key] = obj[key]
    }

深拷贝

  1. 对于JSON安全的对象(可以被序列化为JSON字符串并且可以根据这个字符串解析出一个结构和值完全一样的对象)
var someObj = {
    name:'luoyi',
    age: 3
}
var newObj = JSON.parse(JSON.stringify(someObj))

问题

  • 不能正确处理Data类型和RegExp类型的数据。
  • 会忽略symbol和undefined。
  1. 实现一个深拷贝的函数
  • 原则
  • 如果是基本数据类型直接返回。
  • 如果是 RegExp 或者 Date 类型,返回对应的类型。
  • 如果是复杂数据类型,进行递归。
  • 考虑循环引用的问题。
function deepClone(obj,hash=new WeakMap(){
    // 判断循环引用
    if(hash.has(obj)){
        return hash.get(obj)
    }
    if(obj instanceof Date){
        return new Date(obj)
    }
    if(obj instanceof RegExp){
        return new RegExp(obj)
    }
    var t = new obj.constructor()
    hash.set(obj,t)
    for(var key in obj){
        if(obj.hasOwnProperty(key)){
            t[key] = deepClone(obj[key],hash)
        }
    }
    return t
}

为对象增加一个遍历器的方法