美文网首页前端学习指南饥人谷技术博客让前端飞
《高程第六章---面向对象程序设计》小结---理解对象

《高程第六章---面向对象程序设计》小结---理解对象

作者: 大春春 | 来源:发表于2017-11-26 11:09 被阅读22次

    《JavaScript高级程序设计》这本书比较厚,之前刚学JS的时候挑战过一次,结果止步第三章。现在工作了一段时间想想还是得回过头来补充一下基础知识的。目前刚看完第六章,就从第六章开始总结吧,再逐步补充之前的好了。

    理解对象

    该章节讲解了JS中对象的属性类型以及对象属性间的一些设置。

    JS中的对象是什么

    • JS中的对象只是一堆属性和值的无序集合,值的类型包括基本类型,函数,或者对象。
    • 属性和值之间的关系是映射关系,遵循key: value的规范。

    如何创建对象

    JS中创建对象的方法非常简单,有两种:

    • 使用Object构造函数
    let a = new Object()
    a.name = 'oxc'
    console.log(a) // {name: "oxc"}
    

    当然,你也可以在Object构造函数中传入一个参数,然后创建出来的对象是原始数据类型对象。

    let a = new Object(1) // Number {[[PrimitiveValue]]: 1}
    console.log(a) // 1
    typeof a // 'object'
    
    • 使用对象字面量创建对象
    let a = {
        name: 'oxc'
    }
    console.log(a) // {name: "oxc"}
    

    对象的属性类型

    该章节介绍了JS对象属性的类型及其特点,其中属性类型分为了数据属性访问器属性两种,同时介绍了定义属性特征值的api: defineProperty()defineProperties,以及读取对象属性特征值的api: getOwnerPropertyDescriptor()

    • 对象属性的特征值
      • 介绍:
        对象属性的特征值是对象的属性的一些特性,可以在定义该属性的时候进行设置,但是在JS中是不能直接对其进行访问的。
      • 分类
        • configurable: 表示该属性是否能够被关键词delete删除并进行重新定义,以及该属性的特性和属性类型能否被修改;
        • enumerable: 设置该属性能否被for-in循环遍历到;
        • writable: 设置该属性的值能否被修改;
        • value: 设置该属性的值;
        • get: 访问该属性的时候执行的函数;
        • set: 对该属性的值进行设置的时候执行的函数;
    • 关于Object.definePropertyObject.defineProperties
      这两个api的作用就是用来设置上面的对象属性特征值的
      • Object.defineProperty
        该api用于设置单个对象属性的特征值,接受三个参数,顺序是需要设置属性特征值的对象,需要设置的属性,然后是特征值,使用示例如下
            let a = {}
            Object.defineProperty(a, 'name', {
                configurable: true,
                enumerable: true,
                writable: true,
                value: 'oxc'
            })
            console.log(a)  //  {name: 'oxc'}
    
    • Object.defineProperties
      该api和defineProperty作用一致,但是可以批量设置对象属性特征值,示例如下:
            let a = {}
            Object.defineProperties(a, {
                name: {
                    value: 'oxc',
                    writable: false
                },
                age: {
                    value: 12,
                    writable: false
                }
            })
            console.log(a)  // {name: "oxc", age: 12}
    
    • 对象的属性类型(数据属性和访问器属性)
      • 数据属性
        • 介绍: 对象的数据属性只标明数据值的位置,在该位置可以对值进行访问和写入。
        • 数据属性包含的特征值有:configurable, enumerable, writable, value
        • 如何定义一个数据属性:
            let a = {}
            Object.defineProperty(a, 'name', {
                configurable: false,
                enumerable: false,
                writable: false,
                value: 'oxc'
            })
            console.log(a)  //  {name: 'oxc'}
            // 该例子创建了一个名为name的属性,该属性可以被delete删除,for-in循环无法遍历它,也无法对其值进行修改,他的值为`oxc`,并且也不可以在下面对其属性特征值进行重写,重写特征值不会有任何反应。
           // 该属性就是数据属性,值得一提的是,用对象字面量或者对象构造函数新建的对象属性`configurable`,`writable`,`enumerable`三个值默认都为true
    
    • 访问器属性
      • 介绍: 访问器属性是指通过这个属性去对象的属性;
      • 访问器属性包含的特征值有:configrable,enumerable,get,set;
      • 定义一个访问器属性
            let a = {
                _name: 'oxc'
            }
            Object.defineProperty(a, 'name', {
                configurable: false,
                enumerable: true,
                get() {
                    return this._name
                },
                set(value) {
                    this._name = value
                }
            })
        //  这时候我们可以通过调用a.name来对_name属性进行访问和写入,并且可以在访问和写入的过程中通过get和set做一些手脚,例如我想通过name读取到的是123,可以在get函数中这么写
        get(){ return 123 }
        console.log(a.name)   // 123
    // 又或者我想别人无论怎么设置a.name, a._name都是123,就可以在set函数中这么写
        set(value){ this._name = 123 }
    // 另外值得一提的是,如果enumerable设置为true, 那么访问器属性name也是可以可以被for-in循环遍历到的
    
    • 访问器属性的用途
      访问器属性除了上面所说的功能,在实际中的用途也是很广的,其中用得最多的一条就是用getset函数通过计算对目标对象的其它属性进行修改,如下例子:
            let a = {
                _name: 'oxc',
                age: 10
            }
            Object.defineProperty(a, 'name', {
                configurable: false,
                enumerable: true,
                get() {
                    return this._name
                },
                set(value) {
                    value === '大春春' ? this.age = 80 : this.age = 10
                }
            })
            a.name = '大春春'
            console.log(a)      //  {_name: "oxc", age: 80}
    
    • 值得一提的是,当前Vue的响应式系统的原理就是利用Object.defineProperty进行设置的,关于这点可以查看我的这篇博客关于Vue的MVVM

    • 关于属性特征默认值

      • 如果使用普通的对象创建方法创建的对象,就是不使用Object.definePropertyObject.defineProperties创建的属性,那么默认是数据属性,并且configurable,enumerable,'writable'都是true
      • 但是如果使用的是Object.definePropertyObject.defineProperties创建的数据属性,那么configurable,enumerable,'writable'都是false访问器属性一样默认configurableenumerable都为false
    // 普通创建的对象属性特征值
            let a = {
                name: 'oxc'
            }
            let b = Object.getOwnPropertyDescriptor(a, 'name')
            console.log(b) // {value: "oxc", writable: true, enumerable: true, configurable: true}
    // 使用Object.defineProperty创建的属性
            let a = {}
            Object.defineProperty(a, 'name', {
                value: 'oxc'
            })
            let b = Object.getOwnPropertyDescriptor(a, 'name')
            console.log(b) // {value: "oxc", writable: false, enumerable: false, configurable: false}
    

    读取属性的特性

    读取属性的特征值可以用Object.getOwnPropertyDescriptor, 该方法接受两个参数,第一个参数是需要读取的属性所在的对象,第二个是需要读取的属性,例子如上默认值例子。

    相关文章

      网友评论

        本文标题:《高程第六章---面向对象程序设计》小结---理解对象

        本文链接:https://www.haomeiwen.com/subject/klrkbxtx.html