JavaScript高级(七)--对象【包含vue2响应式原理】

 对象

对象是JavaScript中一个非常重要的概念,这是因为对象可以将多个相关联的数据封装到一起,更好的描述一个事物,JavaScript其实支持多种编程范式的,包括函数式编程面向对象编程

创建对象的方式
  • 早期使用创建对象的方式最多的是使用Object类,并且使用new关键字来创建一个对象。
    var person = new Object();
    person.name = "malong";
    person.age = 22
    person.study = function() {
        console.log(this.name)
    }
  • 后来很多开发者为了方便起见,都是直接通过字面量的形式来创建对象,这种方式看起来更简洁内聚性也更强。
        var person1 = {
            name: "malong",
            age: 22,
            study: function() {
                console.log(this.name)
            }
        }
    
    对象属性操作的控制
    对象属性获取
  •     var obj = {
            name: "zhangsan",
            age: 18
        }
        console.log(obj.name)
对象属性修改

    var obj = {
        name: "zhangsan",
        age: 18
    }
    
    obj.name = "malong"


对象属性删除

    var obj = {
        name: "zhangsan",
        age: 18
    }
    delete obj.age
    console.log(obj)


对象遍历

    Object.prototype.gender = "男"
    var obj = {
        name: "zhangsan",
        age: 18
    }
    obj.__proto__.avator = "我的头像"
    // for in 用来遍历对象
    // 要注意 for in 会遍历原型链上的属性
    for(var key in obj){
        // 使用for in 会遍历到原型链上的属性 这里要进行一下过滤才可以
        if( obj.hasOwnProperty(key) ) {
            console.log(obj[key])
        }
    }

// 顺带提一下for of(用来遍历数组)
//for (var item of arr)
//arr 不能是对象,因为对象是不可迭代的
//但可以遍历数组,并且item已经是值了,而不是属性名
//for of 和for in的另外一点不同是:for of 不会遍历目标原型链上的属性
 

对象属性描述符

如果我们想要对一个属性进行比较精准的操作控制,那么我们就可以使用属性描述符。 通过属性描述符可以精准的添加或修改对象的属性,属性描述符需要使用 Object.defineProperty 来对属性进行添加或者修改。

  • Object.defineProperty(obj,prop,descriptor) 功能:方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。如果不指定configurable, writable, enumerable ,则这些属性默认值为false,如果不指定value, get, set,则这些属性默认值为undefined。 obj要定义属性的对象

prop 要定义或修改属性的名称 或 Symbol

descriptor 要定义或修改的属性描述符

返回值 被传递给函数的对象

数据属性描述符

数据属性描述符四个配置

  • 【configurable】表示属性是否可以通过delete删除,是否可以重新定义属性描述符,或者是否可以将它修改为存取属性描述符;
    • 当我们直接在一个对象上定义某个属性时,这个属性的configurable为true
    • 当我们通过属性描述符定义某个属性时,这个属性的configurable为false
  • 【enumerable】 表示是否可以通过for-in和Object.keys()返回该属性
    • 当我们直接在一个对象上定义某个属性时,这个属性的enumerable为true
    • 当我们通过属性描述符定义某个属性时,这个属性的enumerable为false
  • 【writable】 表示是否可以修改属性的值
    • 当我们直接在一个对象定义某个属时,这个属性的writable为true
    • 当我们通过属性描述符定义某个属性时,这个属性的writable为false
  • 【vaule】 属性的value值,读取属性时返回该值,修改属性时会对其修改
    • 默认都是undefined
var obj = {
    name: "malong",
    age: 18
};
// 如果使用数据属性描述符 用了value,  不能使用get/set
Object.defineProperty(obj,"address",{
    // 是否可以删除、是否可以重新定义属性描述符、是否可以修改为存取属性描述符 默认值 false
    configurable: true,
    // 可枚举的 (能被遍历)  默认值 false
    enumerable: true, 
    // 可以写入 (能修改属性) 默认值 false
    writable: true,
    // 设置值 默认值 undefined
    value: "深圳"  
})

存取属性描述符:

定义多个属性描述符

  • Object.defineProperties(obj, props) 功能: 方法直接在一个对象上定义一个或多个新的属性或修改现有属性,并返回该对象。

obj:  将要被添加属性或修改属性的对象

props:  该对象的一个或多个键值对定义了将要为对象添加或修改的属性的具体配置

返回值 被传递给函数的对象

    var obj = {
      _address:''
    };

    Object.defineProperties(obj, {
      age: {
        // 是否可以删除、是否可以重新定义描述符
        configurable: true,
        enumerable: true,
        writable: true,
        value: 18
      },
      address: {
        // 是否可以删除、是否可以重新定义描述符
        configurable: true,
        enumerable: true,

        get() {
          return _address;
        },
        set(value) {
          // 设置address 的时候赋值给_address
          this._address = value;
        }
      }
    })
获取对象属性描述符
var obj = {
      _address:''
    };

    Object.defineProperties(obj, {
      age: {
        // 是否可以删除、是否可以重新定义描述符
        configurable: true,
        enumerable: true,
        writable: true,
        value: 18
      },
      address: {
        // 是否可以删除、是否可以重新定义描述符
        configurable: true,
        enumerable: true,

        get() {
          return _address;
        },
        set(value) {
          // 设置address 的时候赋值给_address
          this._address = value;
        }
      }
    })
   //获取单个 属性描述符
   console.log( Object.getOwnPropertyDescriptor(obj,"age"))
   // 获取整个对象的属性描述符
   console.log( Object.getOwnPropertyDescriptors(obj))
Object其他的一些方法
    var obj = {
      name: 'malong',
      age: 18
    }

    // 1.禁止对象继续添加新的属性
    Object.preventExtensions(obj)
    obj.xxx = 'xxx' //无法添加 

    // 2.用for fo遍历对象的key 和 value
    // Object.entries(obj)
    // 返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for...in 循环遍历该对象时返回的顺序一致(区别在于 for-in 循环还会枚举原型链中的属性)
    for (var [key, value] of Object.entries(obj)) {
      console.log(key, value)
    }

    // 3.禁止对象配置/删除里面的属性 for of
    // for (var [key, value] of Object.entries(obj)) {
    //   Object.defineProperty(obj, key, {
    //     configurable: false,
    //     enumerable: true,
    //     writable: true,
    //     value: obj[key]
    //   })
    // }

    // 4.禁止对象配置/删除里面的属性 for in
    // for (var key in obj) {
    //   if (obj.hasOwnProperty(key)) {
    //     Object.defineProperty(obj, key, {
    //       configurable: false,
    //       enumerable: true,
    //       writable: true,
    //       value: obj[key]
    //     })
    //   }
    // }


    // 5.让属性不可配置 configurable 都为 false
    Object.seal(obj)
    // 6.让属性不可以修改 writable 都为 false
    Object.freeze(obj)
    // 7.获取对象的长度 keys()方法只能遍历自己的对象上的可枚举的属性,不能遍历自己原型上可枚举的属性:
    console.log(Object.keys(obj).length)

    // 获取一个对象的所有自身属性的描述符。
    console.log(Object.getOwnPropertyDescriptors(obj))
    
    //更多API请参考MDN:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

vue2响应式原理:

    var obj = {
      name: "malong",
      age: 18,
      _address:'不希望被暴露的属性' 
    }
    // 如果使用存取属性描述符 用了get/set, 不能使用writable/value
    // 有人读取address会触发get 有人写入address会触发set
    Object.defineProperty(obj, "address", {
      // 可配置的 (能删除属性) 默认值 false
      configurable: true,
      // 可枚举的 (能被遍历)  默认值 false
      enumerable: true,
      get() {
        // 获取属性的时候会自动调用get
        console.log('get')
        return this._address
      },
      set(value) {
        // 设置属性的时候会自动调用set
        this._address = value
      }
    })

  • 24
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值