zoukankan      html  css  js  c++  java
  • Object 重识(一)

    内容有点儿多,将分为两篇内容与大家分享。有的地方确实难以理解,可以多动手实现一下,看看效果。

    一直听说有这么一句话,在JavaScript中,一切皆为对象。

    经本人慎重研究之后发现,此言的确不虚。(这不废话么,虚不虚的还用你说。)

    今天斗胆跟大家一起讨论一下JavaScript重的Object。了解Object背后的 -- 生活

    阅读间隙,还得多注意休息哟~

    1. 对象的创建

    开始第一个小问题,看一下如何创建一个对象。创建对象有四(shi)种方式。以下几种方式都可创建一个对象,只不过创建之后的表现稍有不同。具体表现为原型和this的指向问题。有兴趣的读者可点击查看相关文章。在这里我们就不详细介绍了。(偷个懒)

    彻底弄懂JavaScript原型问题

    深入理解JavaScript的 this 指针

    注意点:

    四种方式创建对象,除了原型this指针表现不同,构造函数指向也有不同。(此时说明的是不手动指定构造函数的情况下)

    • 字面量方式创建的对象。构造函数为 function Object() {}
    • 构造函数创建。构造函数为函数本身
    • Object.create创建的对象,构造函数为入参origin的构造函数
    • class 方式创建,会将本身也作为构造函数。

    1.1 字面量方式创建

    const obj = {} // 构造函数为 [Function: Object]
    

    1.2 构造函数创建

    function Obj() {}
    
    const obj = new Obj() // 构造函数为 [Function: origin]
    

    1.3 Object.create 创建

    const origin = {a: 1, b: 2}
    
    const target = Object.create(origin) // 构造函数为 origin 的构造函数
    

    1.4 class方式创建

    class Origin {}
    
    const target = new Origin() // 构造函数 [Function: Origin]
    

    2. 属性和方法

    注:

    • 官方版

      • 属性是这个对象的属性,方法是这个对象所拥有的功能
    • 通俗版

      • 属性是一个值,不可执行。
      • 方法为一个函数,可执行。

    2.1 属性和方法获取

    1.获取确定的key属性,使用 . 运算符 或 中括号
    const obj = {
      a: 1,
      b: 2,
      c: 3,
      d: function () {}
    }
    
    obj.a === obj['a']// 1
    obj.b === obj['b'] // 2
    obj.c === obj['c'] // 3
    obj.d === obj['d'] // function (){}
    
    2.获取需要计算的kay值,只能使用中括号方式
    const obj = {
      a1: 1,
      a2: 2,
      a3: 3,
      a4: function (){}
    }
    
    for(let i = 1;i < 5;i ++) {
      obj['a' + i]
    }
    // 1,2,3,function (){}
    

    注意:

    如果对象中不含有某个key,获取到的为 undefined

    例如:

    const obj = {}
    
    obj.c() // TypeError: obj.c is not a function
    

    由于obj中不含有c这个方法,所以获取到的是undefined。此值不是函数,执行报错

    可修改为以下写法

    const obj = {}
    
    typeof obj.c === 'function' && obj.c()
    

    这里有的读者可能会说这样也可以 obj.c && obj.c()。这种写法在下面这种情况下依然会报错

    const obj = {
      c: 1
    }
    
    obj.c()
    

    所以,还是要清楚的判断我们要获取的key是一个函数,才能执行。

    2.2 如何判断对象中含有某个值

    在此段内容开始之前,先说一个小问题,如何判断对象中是否含有某个key值?

    1. 使用 2.1中的属性获取
    • 只需判断是否为 undefined 即可。
    • 此方法有一个缺陷,如果此值确实为 undefined,则会出现判断失误的情况
    const obj = {
      c: undefined
    }
    
    console.log(obj.c === 'undefined') // 判断为true,但是obj中确实含有c这个key
    
    2. in
    • 包含某个key
    // 包含某个key
    function A () {
      this.b = 1
    }
    const a = new A()
    console.log('b' in a) // true
    
    • 不包含某个 key
    // 不包含某个key
    function A () {
    }
    const a = new A()
    console.log('b' in a) // false
    
    • 查询的key,值为 undefined 的情况
    // 不包含某个key
    function A () {
      this.b = undefined
    }
    const a = new A()
    console.log('b' in a) // true
    
    • 查询的key存在于原型链上
    function A () {
    }
    
    Object.prototype.b = 1
    const a = new A()
    
    console.log('b' in a) // true
    

    注意点:

    缺点:in方法无法判断当前key是存在于对象本身还是在原型链上。此情况,我们需要用到下面这种方法。

    3. hasOwnProperty 查询属性是否存在于自身
    • 存在于原型链上
    function A () {}
    
    Object.prototype.b = 1
    const a = new A()
    
    console.log(a.hasOwnProperty('b')) // false
    
    • 存在于自身
    function A () {
      this.b = 1
    }
    
    const a = new A()
    
    console.log(a.hasOwnProperty('b')) // true
    
    • 属性值为undefined
    function A () {
      this.b = undefined
    }
    
    const a = new A()
    
    console.log(a.hasOwnProperty('b')) // true
    

    总结:

    • 属性获取不能判断属性值为undefined的情况
    • in 方法不能判断属性是在对象本身还是在原型链上
    • hasOwnProperty可以判断属性是否存在于自身,同时也可判断属性值为undefined的情况

    2.3 删除对象的属性

    删除对象的属性可以使用delete方法,只不过此方法的性能并不算太优越

    const obj = {
      b: 1,
      c: 2
    }
    
    delete obj.b
    console.log(obj) // {c: 2}
    

    休息会儿,这篇文章可长哈,循序渐进的来。

    2.4 属性分类

    JavaScript中将属性分为两种:数据属性和访问器属性

    数据属性包括:ConfigurableEnumerableWritableValue 四个属性描述符

    访问器属性包括:ConfigurableEnumerableSetGet 四个属性描述符

    通过对比我们可以发现,属性描述有六类:

    Configurable、Enumerable、Writeable、Value、Set、Get

    注意:

    修改描述符,只可以通过Object.defineProperty(obj, key, config)修改一个 || Object.defineProperties(obj,config)修改多个 方法来修改。

    例如:

    const obj = {
      a: 1,
      b: 2,
      c: 3
    }
    // 修改一个
    Object.defineProperty(obj, 'a', {
      enumerable: true,
      writable: true,
      configurable: true
    })
    
    // 修改多个
    
    Object.defineProperties(person, {
      a: {
        enumerable: true,
        writable: true,
        configurable: true
      },
      b: {
        enumerable: true,
        writable: true,
        configurable: true
      }
    }
    
    1. 描述符介绍

    Configurable:是否可通过delete删除属性、是否可重新定义属性、是否可修改描述符、是否可进行属性互换。

    • true 上述操作都可进行
    const obj = {
      a: 1,
      b: 2,
      c: 3
    }
    Object.defineProperty(obj, 'a', {
      configurable: true
    })
    
    delete obj.a
    Object.defineProperty(obj, 'a', {
      value: 11
    })
    Object.defineProperty(obj, 'a', {
      enumerable: true
    })
    Object.defineProperty(obj, 'a', {
      set() {}
    })
    
    • false 严格模式下报错,普通模式下过滤操作
    const obj = {
      a: 1,
      b: 2,
      c: 3
    }
    Object.defineProperty(obj, 'a', {
      configurable: false
    })
    
    delete obj.a
    Object.defineProperty(obj, 'a', {
      value: 11
    })
    Object.defineProperty(obj, 'a', {
      enumerable: true
    })
    Object.defineProperty(obj, 'a', {
      set() {}
    })
    

    Enumerable:是否可枚举

    const obj = {
      a: 1,
      b: 2,
      c: 3
    }
    
    // 为 true 的情况,可遍历
    Object.defineProperty(obj, 'a', {
      enumerable: true
    })
    
    for(let item in obj) {
      console.log(item) // a, b, c  可遍历到 a
    }
    
    // 为false的情况,不可遍历
    Object.defineProperty(obj, 'a', {
      enumerable: false
    })
    
    for(let item in obj) {
      console.log(item) // b, c  遍历不到 a
    }
    

    Writable:是否可修改属性的值,加上它,将变为数据属性

    const obj = {
      a: 1,
      b: 2,
      c: 3
    }
    
    // 为 true 可修改属性值
    Object.defineProperty(obj, 'a', {
      writable: true
    })
    obj.a = 2
    console.log(obj.a) // 2
    
    // 为false 不可修改属性值 严格模式下会报错
    Object.defineProperty(obj, 'a', {
      writable: false
    })
    obj.a = 2
    console.log(obj.a) // 1
    

    Value:属性的数据值,加上它,将变为数据属性

    const obj = {
      a: 1,
      b: 2,
      c: 3
    }
    Object.defineProperty(obj, 'a', {
      value: 11
    })
    console.log(obj.a) // 11
    

    Set:写入属性时调用,加上它,将变为访问器属性

    const obj = {
      a: 1,
      b: 2,
      c: 3
    }
    Object.defineProperty(obj, 'a', {
      set() {
        console.log('a的值改变了')
      }
    })
    
    obj.a = 2 // a的值改变了
    

    Get:读取属性时调用,加上它,将变为访问器属性

    const obj = {
      a: 1,
      b: 2,
      c: 3
    }
    Object.defineProperty(obj, 'a', {
      get() {
        console.log('获取a的值')
      }
    })
    
    obj.a // 获取a的值
    
    2. 属性互换:

    数据属性 --> 访问器属性

    Writable、Value 中的任意一个替换为 Set、Get 中的任意一个。

    访问器属性 --> 数据属性

    Set、Get 中的任意一个替换为 Writable、Value 中的任意一个。

    示例可接着往下看

    3. 获取某个属性的描述(查看此属性是数据属性还是访问器属性)

    想要查看某个属性的描述,可以使用Object.getOwnPropertyDescriptor(obj, key) 来查看

    const obj = {
      a: 1
    }
    console.log(Object.getOwnPropertyDescriptor(obj, 'a'))
    // { value: 1, writable: true, enumerable: true, configurable: true }
    
    Object.defineProperty(obj, 'a', {
      get() {
        console.log('获取a的值')
      }
    })
    console.log(Object.getOwnPropertyDescriptor(obj, 'a'))
    /*
    {
      get: [Function: get],
      set: undefined,
      enumerable: true,
      configurable: true
    }
    */
    

    此例我们可以验证 属性互换 的正确性,当我们将get设置为 a 的描述符时,a 会变为访问器属性

    接下文:Object 重识(二)

  • 相关阅读:
    javascript如何处理字符串中的u
    查看postgresql的日志show queries log in PostgreSQL?
    angular7 promiss
    解决echarts的叠堆折线图数据出现坐标和值对不上的问题
    微信小程序将图片数据流添加到image标签中
    深入理解flex布局的flex-grow、flex-shrink、flex-basis
    优先级:content –> width –> flex-basis (limted by max|min-width)
    ubuntu17.10 python3.6 install plugins for AI
    tensorflow import 没找到cudnn库问题解决
    ubuntu17.10 安装ssh
  • 原文地址:https://www.cnblogs.com/yancyCathy/p/13466917.html
Copyright © 2011-2022 走看看