JS数据类型之Object(一)对象知识扫盲

简介

在javascript中,对象被定义为一组属性的无序集合。即对象是一组没有特定顺序的值。
对象的构成为:属性和方法。一个对象可以拥有多个属性和多个方法。

{
  age: 18,
  name: "名字是什么",
  sayName() {
    console.log(this.name);
  }
}

对象的属性

一个JavaScript对象中有很多属性。一个对象的属性可以被解释为一个附加到对象上的变量。
属性由一个字符串类型的名字(name)和一个属性描述符(property descriptor)对象构成。

属性的类型

JavaScript中使用一些内部特性来描述属性的特征。开发者不能在JavaScript中直接访问这些特性。规范中用两个中括号把特性的名称括起来,如[[Enumerable]]

属性分两种:数据属性和访问器属性

数据属性【数据】

数据属性包含一个保存数据值的位置。数据属性有四个特性描述它们的行为。

属性描述符 解释 取值
[[Configurable]] 1、是否可以通过delete删除并重新定义
2、是否可以修改它的特性
3、是否可以把它改为访问器属性
true:默认值
false
[[Enumerable]] 是否可以被for-in循环返回 true:默认值
false
[[Writable]] 是否可以被修改 true:默认值
false
[[Value]] 属性实际值 undefined:默认值
JavaScript中的任意类型

数据属性定义

  • 直接定义:直接定义属性的时候,以上四种属性描述符都是默认值true。
  • 使用Object.defineProperty()方法进行精确定义属性及其属性描述符。
Object.defineProperty(对象名, 属性名, 属性描述符(对象))

属性描述符是必须是一个对象,对象中最多有四个属性:configurableenumerablewritablevalue。如果configurableenumerablewritable没有指定,将被指定为falsevalue指定为undefined

访问器属性【存储】

访问器属性不包含数据值。相反,它们包含一个获取(get)函数和一个设置(set)函数,不过这两个函数不是必须的。

  • 获取函数(get):在读取访问器属性时,被调用;返回一个有效值。
  • 设置函数(set):在设置访问器属性时,被调用;设置为传入的 新值。
    访问器属性有四个特性描述它们的行为。
属性描述符 解释 取值
[[Configurable]] 1、是否可以通过delete删除并重新定义
2、是否可以修改它的特性
3、是否可以把它改为数据属性
true:默认值
false
[[Enumerable]] 是否可以被for-in循环返回 true:默认值
false
[[Get]] 获取函数,在读取属性时调用 undefined:默认值
[[Set]] 设置函数,在设置属性时调用 undefined:默认值

访问器属性常常用来设置一些私有属性,从而达到属性的保护。

访问器属性定义

  • 访问器属性不能直接定义
  • 使用Object.defineProperty()定义访问器属性
Object.defineProperty(对象名, 属性名, 属性描述符(对象))

属性描述符中的获取和设置函数不一定都要定义。只定义设置函数,表示不能读取;只定义获取函数,表示只能读取。

定义多个属性

通过Object.defineProperties()方法定义多个属性及其属性描述符。

Object.defineProperties(对象, {
  数据属性: 数据属性的描述符,
  ...
  访问器属性: 访问器属性的描述符
  ...
})

注意事项
【1】数据属性的configurablewritable为false,可以通过访问器属性的set()方法进行修改。
【2】如果数据属性configurableenumerablewritable没有指定,将被指定为falsevalue指定为undefined

读取属性的描述符
  • 使用Object.getOwnPropertyDescriptor()方法可以取得指定属性的属性描述符。
    语法:Object.getOwnPropertyDescriptor(对象名, 属性名)
    参数:属性所在对象和对应的属性名。
    返回值:一个对象。对于数据属性,返回configuraableenumerablewritablevalue属性;对于访问器属性,返回configurableenumerablegetset属性。

  • 使用Object.getOwnPropertyDescriptors()方法可以取得指定属性的属性描述符。
    语法:Object.getOwnPropertyDescriptors(对象名)
    参数:属性所在对象
    返回值:一个对象。对于数据属性,返回configuraableenumerablewritablevalue属性;对于访问器属性,返回configurableenumerablegetset属性。

访问对象的方式

方式 使用 样例
点符号 属性为有效的JavaScript字符串 objectName.propertyName
方括号 属性为有效/无效的JavaScript字符串
通过for...in循环遍历对象属性
objectName[propertyName变量]
  • 注意事项:
    1、对象的名字和属性的名字是大小写敏感的。
    2、对象中未赋值的属性的值为undefined
    3、对象的属性名可以是有效的JavaScript字符串,也可以被转换为字符串的任何类型。
    4、对象的属性的值可以是普通变量,也可以是函数。

增强的对象语法

属性简写

给对象添加变量时,属性名和变量名一致,我们可以使用属性简写的进行添加变量。

let name = "名字"
// 之前
let person = {
  name: name
}
// 属性简写后
let person = {
  name
}
计算属性

计算属性:在[ ]中放入表达式,计算结果可以当做属性名。
这种用法和用方括号访问属性非常类似。

简写方法名
// 未简写
let person = {
  sayName: function() {
    
  }
}

// 简写后
let person = {
  sayName() {
    
  }
}

注意事项

  • 简写方法名对获取函数(get)和设置函数(set)也是适用的。
  • 简写方法名可以与计算属性相互兼容

对象解构

对象解构就是使用与对象匹配的结构来实现对象属性的赋值。

展开语法(...):三个点,将对象中的属性全部提取出来。【与数组中的展开语法类似,但有区别】
解构语法(...):将对象中的某些属性从中拿出来。【注意:左边的源数据,右边是声明的变量】解构语法可以解构内置对象中的某些属性。



    
        
    
    
        
    

对象合并

合并的方法:

  • 使用展开语法(...)将对象的枚举属性赋值到一个新的对象上。
  • 使用Object.assgin()方法进行对象的赋值。【Object.assign()进行对象复制的时候是浅复制】
Object.assign() 展开语法
使用场景 复制对象
对象拷贝
复制对象
对象拷贝
枚举 可枚举 可枚举
原型链 不触发,即使原型链上是可枚举的属性 不触发,即使原型链上是可枚举的属性
区别 会触发setter 不会触发setter

对象的方法

一个方法是关联到某个对象的函数,或者简单说,一个方法是一个值为某个函数的对象属性。定义方法就像定义普通的函数,然后赋值给对象的某个属性。
方法的定义有两种方式:

// 常规方式
var obj = {
  foo: function() {
    /* code */
  },
  bar: function() {
    /* code */
  }
};
// 方法名简写方式
var obj = {
  foo() {
    /* code */
  },
  bar() {
    /* code */
  }
};

Object中的静态方法

Object.assgin()
  • 作用:进行对象的复制【浅拷贝】
  • 语法:Object.assign(目标对象, 多个源对象)
  • 返回值:返回合并后的对象,与目标对象相等。
  • 底层:使用源对象的[[Get]]取的属性的值,使用目标对象的[[Get]]设置属性的值。
    注意事项
    1、复制以字符串和符号为键的属性。
    2、Object.assgin()该方法是浅拷贝。
    3、如果多个源对象有相同的属性,则使用最后一个复制的值。
Object.is()
  • 作用:进行对象的判断
  • 语法:Object.is(对象1,对象2)
  • 返回值:如果相等,返回true;否则返回false。
    注意事项
    1、该方法与===的作用类型
    2、参数可以是基本数据类型
Object.defineProperty()
  • 作用:给某个对象添加单个属性,同时设置属性的描述符
  • 语法:Object.defineProperty(对象, 属性名, 属性描述符)
    注意事项
    1、属性描述符必须是一个对象
Object.defineProperties()
  • 作用:给某个对象同时添加多个属性,同时设置属性的描述符
  • 语法:Object.defineProperties(对象, 属性名及属性描述符)
    注意事项
    1、第二个参数的形式如下,属性描述符必须是一个对象。
{
  属性一: 属性描述符,
  ...
}
Object.getOwnPropertyDescriptor()
  • 作用:获取某个对象中某个属性的属性描述符
  • 语法:Object.getOwnPropertyDescriptor(对象, 属性名)
  • 返回值:返回一个对象。如果是数据属性,返回configurableenumerablewritablevalue;如果是访问器属性,返回configurableenumerablegetset
Object.getOwnPropertyDescriptors()
  • 作用:获取某个对象中某个属性的属性描述符
  • 语法:Object.getOwnPropertyDescriptor(对象)
  • 返回值:返回一个对象。如果是数据属性,返回configurableenumerablewritablevalue;如果是访问器属性,返回configurableenumerablegetset

对象引用

对象和函数、数组一样是引用类型,即复制只会复制引用地址。
对象作为函数的形参,实际上传递的是对象的地址

this

this关键字表示当前对象

对象的遍历

枚举一个对象的属性

以下方法受到enumerable原型链的影响。

方法 for...in循环 Object.keys(o) Object.getOwnPropertyNames(o) Object.getOwnPropertySymbols(o)
含义 返回对象及原型链上可枚举的属性 返回自身的所有可枚举属性 返回自身所有属性 返回自身所有的Symbols属性
是否可枚举 不关心 Symbol
是否访问原型链 访问 不访问 不访问 不访问
是否访问Symbol 不访问 不访问 不访问 访问

for...in

作用:以任意顺序遍历一个对象的除Symbol以外的可枚举属性【包含原型链上可枚举的属性】

Object.keys()

作用:返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致 。

Object.values()

作用:返回一个给定对象自身的所有可枚举属性值的数组。

Object.entries()

作用:返回一个给定对象自身可枚举属性的键值对数组

Object.getOwnPropertyNames()

作用:返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。

Object.getOwnPropertySymbols()

作用:返回一个给定对象自身的所有 Symbol 属性的数组。

对象的继承

所有的JavScript对象至少继承于一个对象,被继承的对象被称为原型。
每个对象可以通过构造函数的prototype属性找到原型 或 每个实例对象有一个私有属性__proto__指向原型

获取对象原型

方法一:Object.getPrototypeOf()方法返回指定对象的原型。
方法二:实例化对象.__proto__

Object.getPrototypeOf(object)

  • 参数
    obj:要返回其原型的对象
  • 返回值
    给定对象的原型,如果没有继承属性,则返回null

设置或修改对象原型

方法一:Object.create()创建对象的时候指定原型.
方法二:Object.prototype.__proto__
方法三:Objcet.setPrototypeOf()
方法四:Reflect.setPrototypeOf()

Object.create(proto, propertiesObject):

  • 参数:
    proto:新创建对象的原型对象
    propertiesObject:可选
  • 返回值
    一个新对象,带着指定的原型对象的属性。


   
       
   
   

       
   

Objcet.setPrototypeOf(obj, prototype)

  • 参数:
    obj:设置其原型对象
    prototype:对象的新原型(对象或null)
  • 过程:
    如果对象的原型被修改成不可扩展(通过Object.isExtensible())的,则抛出TypeError异常。
    如果prototype新原型参数不是对象或努力了,则什么也不做。
    否则,该方法修改对象的原型。

Reflect.setPrototypeOf(target, prototype)

  • 参数:
    target:设置其原型对象
    prototype:对象的新原型(对象或null)
  • 返回值:
    返回一个boolean类型表明是否原型已经设置成功。
  • 过程:
    如果参数target不是Object,或者prototype既不是对象,也不是null,则抛出TypeError异常。

Object原型与属性相关的方法

方法 作用 参数 返回值
obj.hasOwnProperty() 判断属性是否在某个对象自身上 {不含原型链} prop:要检测的属性 true:有
false:无
prop in obj 判断属性是否在某个对象上 {含原型链} prop:要检测的属性 true:有
false:无
prototypeObj.isPrototypeOf(obj) 测试一个对象是否在另一个对象的原型链上 object:在该对象的原型链上搜寻 true:在
false:不
instanceof操作符 检测构造函数的prototype属性是否会出现在某个实例对象的原型链上 操作符,不是函数 true:在
false:不在
obj.propertyIsEnumerable(prop) 判断属性名是否可枚举 prop需要测试的属性 true:枚举
false:非枚举

你可能感兴趣的:(JS数据类型之Object(一)对象知识扫盲)