美文网首页
JS创建对象方案(一)

JS创建对象方案(一)

作者: 未路过 | 来源:发表于2022-09-03 14:29 被阅读0次

    5.1 JavaScript的面向对象

    JavaScript其实支持多种编程范式的,包括函数式编程和面向对象编程

    1. JavaScript中的对象被设计成一组属性的无序集合,像是一个哈希表,有key和value组成;
    2. key是一个标识符名称,value可以是任意类型,也可以是其他对象或者函数类型;
    3. 如果值是一个函数,那么我们可以称之为是对象的方法;

    如何创建一个对象呢?

    1. 早期使用创建对象的方式最多的是使用Object类,并且使用new关键字来创建一个对象:
    2. 这是因为早期很多JavaScript开发者是从Java过来的,它们也更习惯于Java中通过new的方式创建一个对象;
    3. 后来很多开发者为了方便起见,都是直接通过字面量的形式来创建对象: 这种形式看起来更加的简洁,并且对象和属性之间的内聚性也更强,所以这种方式后来就流行了起来;

    5.2 创建对象的两种方式

    41.png

    5.3 对对象属性进行操作

    43.PNG
    var obj = {
      name: "why",
      age: 18
    }
    
    // 获取属性
    console.log(obj.name)
    
    // 给属性赋值
    obj.name = "kobe"
    console.log(obj.name)
    
    // 删除属性
    // delete obj.name
    // console.log(obj)
    
    // 需求: 对属性进行操作时, 进行一些限制
    // 限制: 不允许某一个属性被赋值/不允许某个属性被删除/不允许某些属性在遍历时被遍历出来
    
    // 遍历属性
    for (var key in obj) {
      console.log(key)
    }
    

    5.4 Object.defineProperty

    42.png
    
    var obj = {
      name: "why",
      age: 18
    }
    
    // 属性描述符是一个对象
    Object.defineProperty(obj, "height", {
      // 很多的配置
      value: 1.88
    })
    
    console.log(obj)
    console.log(obj.height)
    

    1.属性描述符

    属性描述符的类型有两种:

    1. 数据属性(Data Properties)描述符(Descriptor);
    2. 存取属性(Accessor访问器 Properties)描述符(Descriptor);
    44.PNG

    2.数据属性描述符

    45.PNG
    1. configurable
        const obj = {
            name:"why",
            age:18,
            friends:{
              name:"kobe"
            },
            hobbies:["篮球","足球"]
          }
    
    
     //Object.defineProperty()//
          /* 直接在对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象 */
          
          let res = Object.defineProperty(obj, "name", {
            value:"new setting value",
           //第一种:当我们直接在一个对象上定义某个属性的时候,这个属性的configurable为true
           //第二种:当我们通过属性表舒服定义一个属性的时候,这个属性的configurable默认为false
           //configurable:false
            
          })
    
        //  delete obj.name
          
          console.log(obj)
          //{age: 18, friends: {…}, hobbies: Array(2)} 
          //不写/configurable:false的话,name能删除是因为这个obj是属于第一种,configurable的默认值是true
          //如果在里面设置configurable为flase之后,就不能删除了
          ////设置了configuratble为false之后,就不能删除address和改变它的definProperty里面的configurable属性。
    
          console.log(res === obj)//true
    
    
           Object.defineProperty(obj, "name", {
            value:"new setting value2",
           //第一种:当我们直接在一个对象上定义某个属性的时候,这个属性的configurable为true
           //第二种:当我们通过属性表舒服定义一个属性的时候,这个属性的configurable默认为false
           configurable:true//如果上一个definProerty的时候设置了configurableweifalse,第二次就不能再次把他它变成了false
            
          })
    
    

    2.enumrable
    第一种:当我们直接在一个对象上定义某个属性时,这个属性的[[Enumerable]]为true;
    第二种:当我们通过属性描述符定义一个属性时,这个属性的[[Enumerable]]默认为false;

          const obj = {
            name:"why",
            age:18,
            friends:{
              name:"kobe"
            },
            hobbies:["篮球","足球"]
          }
    
     
    
         console.log(Object.keys(obj));//返回一个数组,里面是对象里面的所有可以遍历的属性的key名字
         //(3) ['age', 'friends', 'hobbies']
          Object.keys(obj).map((currentValue,index, arr) => {
            console.log(obj[currentValue])
          })
    
         //Enumerable:表示属性是否可以通过for-in或者Object.keys()返回该属性
         for(let key in obj) {
          console.log(key, obj[key])
         }
         /* 
         name why
        test.html:31 age 18
        test.html:31 friends {name: 'kobe'}
        test.html:31 hobbies (2) ['篮球', '足球']
         */
    
    
          var obj = {
      name: "why",
      age: 18
    }
    
    //数据属性描述符
    Object.defineProperty(obj, "address", {
      value:"北京市",// 默认值undefined
      configuratble:false,// 默认值false
      //该特殊是配置对应的属性(address)是否是可以枚举
      enumerable:false,//默认值false
    })
    console.log(obj)//{name: 'why', age: 18, address: '北京市'}
    for (var key in obj) {
      console.log(key)//name //age//address
    }
    console.log(Object.keys(obj))//) ['name', 'age', 'address']
    
    
    //设置enumerable为false的时候,是不可被枚举,输出为下
    
    //{name: 'why', age: 18, address: '北京市'}
    //name age 
    //['name', 'age']
    
    

    3.writable
    [[Writable]]:表示是否可以修改属性的值;
    p 当我们直接在一个对象上定义某个属性时,这个属性的[[Writable]]为true;
    p 当我们通过属性描述符定义一个属性时,这个属性的[[Writable]]默认为false;

    const obj = {
      name:"my",
      age:18,
      address:"none"
    }
    //数据属性描述符
    Object.defineProperty(obj, "address", {
      value:"北京市",// 默认值undefined
      configuratble:false,// 默认值false
      //该特殊是配置对应的属性(address)是否是可以枚举
      enumerable:true,//默认值false
      //该特性是属性是否是可以赋值(写入值) 
      writable: true// 默认值false
    
    })
    //当设置为writable为false的时候
    obj.address = "上海市"
    console.log(obj.address)//"北京市"
    //当设置为ture的时候
    //上海市
    

    4.value
    n [[value]]:属性的value值,读取属性时会返回该值,修改属性时,会对其进行修改;
    p 默认情况下这个值是undefined;

    3.存取属性描述符

    46.PNG
     var obj = {
      name: "why",
      _address: "北京市"
    }
    /*,1.,第一个场景的话就是我们隐藏某一个私有属性,不希望直接被外界使用和赋值
    
    我不希望address这个属性随随便便被暴露出去,我们比如说给他来了一个下划线,
    
    因为一般下划线开头的话,我们会表示他是一个私有的,然后呢使用了address这个属性名字,
    来获取或者设置_address, 这个样子的化我们就不知道这个对象还有_address这个属性名
    
    2.如果我们希望截获某一个属性它访问和设置值的过程时, 也会使用存储属性描述符
    
    */
     
     Object.defineProperty(obj, "address", {
      enumerable: true,
      configurable: true,
      get: function() {
        foo()
        return this._address //这个this值得是obj,因为是obj.address调用
      },
      set: function(value) {
        bar()
        this._address = value
      }
    })
    
    console.log(obj.address)
    
    obj.address = "上海市"
    console.log(obj.address)
    
    function foo() {
      console.log("获取了一次address的值")
    }
    
    function bar() {
      console.log("设置了addres的值")
    }
          
    console.log(obj)
    
    /* 
    
    获取了一次address的值
    北京市
    设置了addres的值
    获取了一次address的值
    上海市
    
    {name: 'why', _address: '上海市'}
    address
    : 
    (...)
    name
    : 
    "why"
    _address
    : 
    "上海市"
    */
    

    5.5 同时定义多个属性

    image.png
    var obj = {
      // 私有属性(js里面是没有严格意义的私有属性) 就是别人不知道这个属性的名字,不能访问这个属性
      /* 在整个JS社区里面,一般情况下,我们以下划线开头的某一个属性,
      我们就认为我们就认为他是一个私有属性 */
      _age: 18,
      _eating: function() {},
    }
    
    Object.defineProperties(obj, {
      name: {
        configurable: true,
        enumerable: true,
        writable: true,
        value: "why"
      },
       age: {
        configurable: true,
        enumerable: false,
        get: function() {
          return this._age
        },
        set: function(value) {
          this._age = value
        }
      } 
    })
    
    obj.age = 19
    console.log(obj.age)
    
    console.log(obj)
    

    如果设置age的enumerable为false,打印obj的话


    image.png

    如果设置address的enumerable为true,打印obj的话


    image.png
    可以发现age一个是虚的一个是实的。代表能不能列举。

    另外,在js中还有另一种写法

    /* var obj = {
      _age: 18,
      _eating: function() {},
    }
     */
    
     var obj = {
     
      _age: 18,
      _eating: function() {},
      set age(value) {
        this._age = value
      },
      get age() {
        return this._age
      } 
    }
    
    /* ,在我们开发里面,如果我们想要给我们的某一个某一个对象的某一个属性,给它定义对应的get和set,
    而且另外它的这个值和这个值,我们想要使用默认的时候,其实我们这里可以这样来做 
    
    如果age的configurable为true,enumerable为true,那我们可以把definproperties里面的age这个代码给注释掉,
    可以在obj里面直接定义set和get
    例如obj.age = 19, console.log(obj.age)
    
    */
    
    obj.age = 19
    console.log(obj.age)
    console.log(obj)
    
    
    /* 
    在obj里面直接写set和get何用definProperty有一些差异,就是直接在obj中写就是直接设置了enumerable的值为true和configurable为true。
    ,这个时候和definProperty中的enumerble为true和configurable为true的结果一样。只不过如果我们用definProperty来写的话,你可以更加精准的去控制我们这个属性。
    */
    
    
    
    Object.defineProperties(obj, {
      name: {
        configurable: true,
        enumerable: true,
        writable: true,
        value: "why"
      },
    /*   age: {
        configurable: true,
        enumerable: true,
        get: function() {
          return this._age
        },
        set: function(value) {
          this._age = value
        }
      } */
    })
    

    5.6 获取属性描述符Object.getOwnPropertyDescriptor

    image.png
    var obj = {
      _age: 18,
      _eating: function() {}
    }
    
    Object.defineProperties(obj, {
      name: {
        configurable: true,
        enumerable: true,
        writable: true,
        value: "why"
      },
      age: {
        configurable: true,
        enumerable: true,
        get: function() {
          return this._age
        },
        set: function(value) {
          this._age = value
        }
      }
    })
    
    // 获取某一个特性属性的属性描述符
    console.log(Object.getOwnPropertyDescriptor(obj, "name"))
    //{value: 'why', writable: true, enumerable: true, configurable: true}
    console.log(Object.getOwnPropertyDescriptor(obj, "age"))
    //{enumerable: true, configurable: true, get: ƒ, set: ƒ}
    
    // 获取对象的所有属性描述符
    console.log(Object.getOwnPropertyDescriptors(obj))
    
    image.png
         var obj = {
            name: "why",
            age: 18,
          };
    
          // 1.禁止对象继续添加新的属性
          Object.preventExtensions(obj);
    
          obj.height = 1.88;
          obj.address = "广州市";
    
          console.log(obj); //{name: 'why', age: 18}
    
          // 2.禁止对象配置/删除里面的属性
          // for (var key in obj) {
          //   Object.defineProperty(obj, key, {
          //     configurable: false,
          //     enumerable: true,
          //     writable: true,
          //     value: obj[key]
          //   })
          // }
    
    
          /* 
          可以不用像上面那么写,因为js给我们提供了方法
          密封对象,不允许配置,不可配置就是不可以删除属性:seal
          实际是调用preventExtensions
          并且将现有属性的configurable:false
          */
          Object.seal(obj);
    
          delete obj.name;
          console.log(obj.name);//why
    
          // 3.让属性不可以修改(writable: false)
          Object.freeze(obj);
    
          obj.name = "kobe";
          console.log(obj.name);//why
    

    相关文章

      网友评论

          本文标题:JS创建对象方案(一)

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