Javascript Object

1.对象含义和创建

  • 含义:对象是拥有属性和方法的数据
  • 创建方式一:字面量声明
var person = {}
  • 创建方式二:使用关键字new
var person = new Object()

2.增(添加属性)

  • 通过点语法添加属性
var person = {}
person.name = "kyo"
  • 通过api添加:Object.defineProperty(obj, key,options),默认只读且不可被枚举,如果属性已经存在,则相当于更新该属性的属性描述对象
属性名 默认值 说明
value 属性值
writable false 值是否可被修改,默认只读
configurable false 属性是否可被重新配置
enumerable false 是否可被枚举,默认false,不可被for in 和Object.keys() 遍历到
get function 属性被读取时执行
set function 属性被赋值时执行
//默认效果
var person = {
    name:'key',
    age:20
}
//基本使用
Object.defineProperty(person,'brithday',{
    value:"2020-12-28",//默认值
})
  • 获取属性描述对象:Object.getOwnPropertyDescriptor(obj,key)
<script>
    //默认效果
    var person = {
        name:'key',
        age:20
    }
    //基本使用
    Object.defineProperty(person,'brithday',{
        value:"2020-12-28",//默认值
    })

    console.log(Object.getOwnPropertyDescriptor(person, 'name'))
    //{value: 'key', writable: true, enumerable: true, configurable:true}

    console.log(Object.getOwnPropertyDescriptor(person, 'brithday'))
    //{value: '2020-12-28', writable: false, enumerable: false, configurable: false}

</script>

3.删(删除属性)

  • 通过运算符 delete 进行删除, 删除成功返回true,删除失败返回false
  • 属性是只读时,会触发删除失败
<script>
    var person = {}
    person.name = 'kyo'
    person.age = 20
    //添加只读属性
    Object.defineProperty(person,'id',{
        value: 1,
        writable: false
    })
    console.log(delete person.age) //true
    console.log(delete person.friend) //true
    console.log(delete person.id) //false
    console.log(person) //{name: 'kyo', id: 1}
</script>

3.改(修改字段值)

  • 字面量修改
<script>
    var person = {
        name: 'kyo',
        age: 20
    }
    person.age = 21
    console.log(person) //{name: 'kyo', age: 21}
</script>

4.查

  • 可枚举:通过字面量方式添加的属性都是可枚举的,只有Object.defineProperty()方式添加的才有不可枚举的可能性,涉及遍历的方法,都只能遍历可枚举的属性,后面不再标注
  • 属性遍历:使用 for in 对属性名称进行遍历
<script>
    var person = {}
    person.name = 'kyo'
    person.age = 20
    //添加属性(默认不可枚举)
    Object.defineProperty(person,'id',{
        value: 1,
    })
    //遍历(id属性不可枚举,遍历时会被忽略)
    for(var key in person){
        console.log(key)
        //name
        //age
    }
</script>
  • 获取属性名列表:Object.keys() - 将对象属性组合成数组返回
<script>
    var person = {}
    person.name = 'kyo'
    person.age = 20
    //添加属性(默认不可枚举)
    Object.defineProperty(person,'id',{
        value: 1,
    })
    //属性名列表
    var keys = Object.keys(person)
    console.log(keys) // ['name', 'age']
</script>
  • 获取属性值列表:Object.values() - 将对象属性值组合成数组返回
<script>
    var person = {}
    person.name = 'kyo'
    person.age = 20
    //添加属性(默认不可枚举)
    Object.defineProperty(person,'id',{
        value: 1,
    })
    //属性名列表
    var keys = Object.values(person)
    console.log(keys) // ['kyo', 20]
</script>
  • 获取属性和属性值列表:Object.entries() - 将对象转换成二维数组返回,及 [[key1,value1],[key2,value2]]
<script>
    var person = {}
    person.name = 'kyo'
    person.age = 20
    //添加属性(默认不可枚举)
    Object.defineProperty(person,'id',{
        value: 1,
    })
    //
    var result = Object.entries(person)
    console.log(result) // [['name', 'kyo'],['age', 20]]
</script>
  • 判断自身属性:hasOwnProperty(key) / in 运算符 原型链上的不算
<script>
    var person = {}
    person.name = 'kyo'
    person.age = 20
    //添加属性(默认不可枚举)
    Object.defineProperty(person,'id',{
        value: 1,
    })
    //枚举与非枚举属性都支持
    console.log(person.hasOwnProperty('name')) //true
    console.log(person.hasOwnProperty('id')) //true
    //原型链属性不支持
    console.log(person.hasOwnProperty) //hasOwnProperty() { [native code] }
    console.log(person.hasOwnProperty('hasOwnProperty')) //false

    'name' in person //true
</script>
  • 获取属性名列表2:Object.getOwnPropertyNames - 相当于Object.keys()的加强版,能遍历不可枚举属性
<script>
    var person = {}
    person.name = 'kyo'
    person.age = 20
    //添加属性(默认不可枚举)
    Object.defineProperty(person,'id',{
        value: 1,
    })
    var keys = Object.getOwnPropertyNames(person)
    console.log(keys) //['name', 'age', 'id']
</script>

5.对象属性值合并

  • 将一个或多个对象的键值对合并到目标对象中并将目标对象返回:Object.assign(target, ...sources) 执行完毕后,target会被改变
  • 注意:操作完成后,target会被改变,如果有同名字段,则会被后面的对象覆盖
<script>
    //人员1
    var person = {
        name: 'key',
        age: 20
    }
    //技能1
    var skill_1 = {
        html: "熟练",
        js: "熟练"
    }
    //技能2
    var skill_2 = {
        php: "空白",
        database: "空白",
        //有冲突的字段
        age: 25
    }
    //合并
    console.log(Object.assign(person,skill_1,skill_2)) //{name: 'key', age: 25, html: '熟练', js: '熟练', php: '空白', …}
    //原对象
    console.log(person) //{name: 'key', age: 25, html: '熟练', js: '熟练', php: '空白', …}
    console.log(skill_1) //{html: '熟练', js: '熟练'}
    console.log(skill_2) //{php: '空白', database: '空白'}
</script>

6.空对象

  • 对象的非空验证思路很简单,遍历其属性名即可,存在一个或者一个以上的属性名,就表示不为空
<script>
    function ObjIsEmpty(obj){
        var isEmpty = true
        //如果存在任何一个属性,则将isEmpty赋值为false
        for(key in obj){
            isEmpty = false
        }
        return isEmpty
    }

    var obj = {}
    var obj2 = {a:1, b:2}
    console.log(ObjIsEmpty(obj)) //true
    console.log(ObjIsEmpty(obj2)) //false
</script>

7.转换成JSON字符串

  • 通过JSON.stringify()可将对象转换成JSON字符串
<script>
    var obj = {}
    var obj2 = {a:1, b:2}
    console.log(JSON.stringify(obj)) //{}
    console.log(JSON.stringify(obj2)) //{a:1, b:2}
</script>
  • 通过JSON.parse()可将JSON字符串转换成对象
<script>
    var objStr = '{"a":1, "b":2}'
    var obj = JSON.parse(objStr)
    console.log(obj.a,obj.b) //1 2
</script>

8.数据代理与数据劫持

  • 数据劫持:通过Object.defineProperty()方法给对象添加字段,就可以监听字段的读取与修改
  • 数据代理:数据劫持过程中的set方法不能操作自身的字段值,会造成死循环,所以数据劫持时只能操作第三方的数据,称之为 数据代理
<script>
    //数据代理源
    var vm = {}
    //原始数据(用作缓存)
    var data = {
        name: "张飒",
        age: 20
    }
    //给代理源添加字段并监听
    Object.defineProperty(vm,'name',{
        configurable: false, // 不可重定义
        enumerable: true, // 可枚举 该属性名能被Object.keys()获取
        get(){
            return data.name
        },
        set(newVal){
            console.log('name 值发生变动,请修改页面对应的元素',)
            data.name = newVal
        }
    })
    //给代理源添加字段并监听
    Object.defineProperty(vm,'age',{
        configurable: false, // 不可重定义
        enumerable: true, // 可枚举 该属性名能被Object.keys()获取
        get(){
            return data.age
        },
        set(newVal){
            console.log('age 值发生变动,请修改页面对应的元素',)
            data.age = newVal
        }
    })
    console.log(vm.name,vm.age)
    vm.name = "李四" //打印 name 值发生变动,请修改页面对应的元素
    console.log(vm.name,vm.age)
</script>

9.对象拷贝

  • 通过实例化的对象,拷贝其实例属性和原型
<script>
    //构造函数
    function Person(name,age){
        this.name = name
        this.age = age
    }
    //原型链方法
    Person.prototype.sayHello = function(){
        console.log(`我的名字是${this.name},今年${this.age}岁`)
    }


    //以下代码,你只能操作p1,不能操作Person
    //创建实例
    var p1 = new Person("张三",20)
    //拷贝这个对象(这个方式只能拷贝属性,无法拷贝不可枚举属性和原型)
    var p2 = JSON.parse(JSON.stringify(p1))


    //拷贝实例的属性和原型
    function copyObject(obj){
        //获取传入实例的原型
        var orig_Prototype = Object.getPrototypeOf(obj)
        //创建一个指向实例原型的对象(传入实例的原型)
        var new_obj = Object.create(orig_Prototype)
        //遍历自身属性(包括不可枚举属性),循环挂载
        Object.getOwnPropertyNames(obj).forEach((propKey)=>{
            //获取属性描述
            var desc = Object.getOwnPropertyDescriptor(obj, propKey)
            //挂载属性
            Object.defineProperty(new_obj, propKey, desc)
        })

        //返回结果
        return new_obj
    }

    //调用
    var p3 = copyObject(p1)
    //成功调用原型链方法
    p3.sayHello() //我的名字是张三,今年20岁
    //构造函数一致
    console.log(p3.constructor) //=> Person
</script>
posted @ 2020-11-15 15:14  ---空白---  阅读(107)  评论(0编辑  收藏  举报