重寻JS之路-对象篇-理解对象

大家好,我是练习时长两年半的JS练习生。

你真的理解对象吗?

带着这个问题,我决定以红宝书为基石,进行一场JS回访之旅,第一站,来拜访对象

1.属性的类型

属性也有类型? 不就键和值吗? 非也!属性分为两种:数据属性访问器属性

1.1数据属性

数据属性,通俗一点就是所谓的键(key)。但是我们今天关注它的四个特性,这四个特性描述了四种行为。我们想探索这四种特性,就得使用Object.defineProperty()来验证。这个方法接收3个参数:要给其添加属性的对象、属性的名称和一个描述符对象(我们的四个特性就写在这里面)

const oldOBj = {
    name:'gjh'
}
console.log(oldOBj.name) // gjh 
// 上面的这段代码可以用下面的代码来描述
let newOBj = {}
Object.defineProperty(newOBj,'name',{
    configurable:true,// 允许对象里的name属性  可以被删除
    enumerable:true, // 允许对象里的name属性   可以被遍历返回
    writable:true, // 允许对象里的namne属性   可以被修改
    value:'gjh'   // 这里就是name属性对应的值
})
console.log(newOBj.name) // gjh 

那么我们可以逆向思维来测试它的这个特性。

Object.defineProperty(newOBj,'name',{
    configurable:false,// 不允许对象里的name属性被删除
    enumerable:false, // 不允许对象里的name属性被遍历返回
    writable:false, // 不允许对象里的namne属性被修改
    value:'gjh'   // 这里就是name属性对应的值
})
console.log(newOBj.name) // gjh
delete newOBj.name  // 因为我们的configurable的特性是false 所以你删除不掉它
console.log(newOBj.name) // gjh
newOBj.name = 'zh'  // 我们将writable设置为false  所以也无法去修改它的value
console.log(newOBj.name) // gjh

通过上面的例子,我们重新认识了对象。原来它也是有生命的,也是有增删改查特性。 

1.2访问器属性

访问器属性我理解为是查。接下来我会用一个例子,来定义一个私有属性,并且用访问器get和set来实现改变一个属性如何去影响另一个属性。


let book = {
    year_:24, // 属性加下划线  表示它是私有的
    edition:1 
}
Object.defineProperty(book,'year',{
    get:() =>this.year_, //这是es6的写法
    set(newValue) {
        if(newValue > 24) {
            this.edition += newValue - this.year_
            this.year_ = newValue;
        }
    }
})
book.year = 23
console.log(book.edition) // 1 条件没有被满足 因此输出1
book.year = 25 
console.log(book.edition) // 2 满足条件  因此输出2

我们将上面的代码更加原始化的体现一下 

let newbook = {}
Object.defineProperty(newbook,
{
    year_:{
        value:24
    },
    edition:{
        value:1
    },
   year:{
    get:() =>this.year_, //这是es6的写法
    set(newValue) {
        if(newValue > 24) {
            this.edition += newValue - this.year_
            this.year_ = newValue;
        }
    }
   }
   
})

ok,到目前为止,我们才终于初步理解了对象。

1.3 获取对象属性的描述特征

上面我们用代码去体验了属性的特征。 那么我们拿到别人设计的对象,如何去知道它有哪些特征呢? 使用getOwnPropertyDescriptor().

let book = {};
Object.defineProperties(book, {
  year_: {
    value: 2017
  },
  edition: {
    value: 1
  },
  year: {
    get: function() {
      return this.year_;
    },
    set: function(newValue){
      if (newValue > 2017) {
        this.year_ = newValue;
        this.edition += newValue -2017;
      }
    }
  }
});
console.log(Object.getOwnPropertyDescriptors(book));
// {
//    edition: {
//      configurable: false,
//      enumerable: false,
//      value: 1,
//      writable: false
//    },
//    year: {
//      configurable: false,
//      enumerable: false,
//      get: f(),
//      set: f(newValue),
//    },
//    year_: {
//      configurable: false,
//      enumerable: false,
//      value: 2017,
//      writable: false
//    }
// }

 1.4 对象合并方法Object.assign() 与 ES6的{...obja,...objb} 的不同之处

        1.4.1:大家观察dest 和 src 。在经过了assign 合并后 dest对象竟然也被改变了 。我之前以为它两合并成一个新的对象。没成想  首位对象本身也会被改变。

        1.4.2:合并后dest和result 是不是用的一个引用地址? 

        1.4.3: ES6的合并 并不会去改变首位对象

let dest, src, result;
/**简单复制 */
dest = {name:'gjh'};
src = { id: 'src' };
result = Object.assign(dest, src);
// Object.assign修改目标对象
// 也会返回修改后的目标对象
console.log(dest === result); // true
console.log(dest === src);     // false
console.log(result);   // { name: 'gjh', id: 'src' }
console.log(dest);    // { name: 'gjh', id: 'src' }
console.log(src)

/**
 * ES6的写法
 */
let a,b,c;
    a = {a_name:'a'};
    b = {b_name:'b'};
    c = {...a,...b};
    console.log(a) // { a_name: 'a'}
    console.log(b) // { b_name: 'b' }
    console.log(c)  // { a_name: 'a', b_name: 'b' }

1.5 可计算属性

        换句话来说 就是属性名字也是可以通过值传进去的,在某些场景下,比如你去写自定义组件的或者去vue的mixins复用方法时,这个知识点就很用的上,下面我用ES6的语法给大家介绍一下如何实现

const keyList = ['name','age']
const valueList = ['gjh',24]
const my_obj =  keyList.reduce((pre,keyName,inx) => {
    let newObj =  {[keyName]:valueList[inx]}
    return {...newObj,...pre}
},{})
console.log(my_obj) // { age: 24, name: 'gjh' }

1.6 对象解构

结构运算符 比较牛逼的地方在于。如果你结构出来的值,不存在的话 它并不会报错

const keyList = ['name','age']
const valueList = ['gjh',24]
const my_obj =  keyList.reduce((pre,keyName,inx) => {
    let newObj =  {[keyName]:valueList[inx]}
    return {...newObj,...pre}
},{})
const tarObj = {son:{niubiname:'niubi'}}
const niubiObj = {...my_obj,...tarObj}
console.log(niubiObj) // { age: 24, name: 'gjh', son: { niubiname: 'niubi' } }
// 结构从这里开始
const {
    age,
    name,
    son:{
        niubiname //  这里是多层结构
    },
    gjh // 注意看  这个属性并不存在于我们的对象中
} = niubiObj
console.log(niubiname) // 这里是多层结构
console.log(gjh) // 不存在的属性 并不会报错 它会报undefined

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值