ES6总结(四)

对象的扩展

属性的简洁表示法
  • ES6允许直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
  • ES6允许在对象之中,只写属性名,不写属性值。这时,属性值等于属性名所代表的变量。除了属性简写,方法也可以简写。
  • 用处
    • 用于函数的返回值,会非常方便。
    • CommonJS模块输出变量,就非常合适使用简洁写法。
    • 属性的赋值器(setter)和取值器(getter),也是采用这种写法。
  • 注意:简洁写法的属性名总是字符串,这会导致一些看上去比较奇怪的结果。如果某个方法的值是一个Generator函数,前面需要加上星号。
属性名表达式
  • 用表达式作为属性名,要将表达式放在方括号之内。例如:obj[‘a’+‘bc’]=123
  • 如果使用字面量方式定义对象(使用大括号),在ES5中只能使用标识符定义属性。ES6允许字面量定义对象时,用方法二表达式作为对象的属性名,即把表达式放在方括号内。
  • 表达式还可以用于定义方法名。
  • 注意:属性名表达式与简洁表示法,不能同时使用,会报错。
方法的name属性
  • 函数的 name属性,返回函数名。对象方法也是函数,因此也有 name 属性
  • 方法的 name 属性返回函数名(即方法名)。如果使用了取值函数,则会在方法名前加上 get 。如果是存值函数,方法名的前面会加上 set 。
  • 有两种特殊情况:bind 方法创造的函数,name 属性返回“bound”加上原函数的名字;Function 构造函数创造的函数,name 属性返回“anonymous”。
  • 如果对象的方法是一个Symbol值,那么 name 属性返回的是这个Symbol值的描述
Object.is()
  • Object.is() 用来比较两个值是否严格相等,他与严格比较运算符(===)的行为基本一致
  • 不同之处有两个:
    • Object.is()中,+0不等于-0, (===)中相等
    • Object.is()中, NaN等于自身, (===)中不相等
Object.assign()
  • Object.assign 方法用来将源对象(source)的所有可枚举属性,复制到目标对象(target)。它至少需要两 个对象作为参数,第一个参数是目标对象,后面的参数都是源对象。只要有一个参数不是对象,就会抛出 TypeError错误。
  • 注意:如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。
  • Object.assign 只拷贝自身属性,不可枚举的属性(enumerable为false)和继承的属性不会被拷贝。例子如下,该对象只有一个不可枚举的属性invisible
    Object.defineProperty({}, 'invisible', {
    	enumerable:false,
    	value:'hello'
    })
    
  • 属性名为Symbol值的属性,也会被拷贝
  • 对于嵌套对象,Object.assign的处理方法是替换,而不是添加,这点需要特别小心
  • 注意:Object.assign可以用来处理数组,但是会把数组视为对象
  • Object.assign的用法
    • 为对象添加属性
    • 为对象添加方法
    • 克隆对象:采用这种方法克隆,只能克隆原始对象自身的值,不能克隆它继承的值。如果想要保持继承链,可以采 用下面的代码。
    function clone(origin){
    	let originProto = Object.getPrototypeOf(origin);
    	return Object.assign(Object.create(originProto), origin);
    }
    
    • 合并多个对象
    • 为属性指定默认值
属性的可枚举性
  • 对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行为。Object.getOwnpropertyDescriptor 方法可以获取该属性的描述对象
  • 描述对象的 enumerable属性,称为”可枚举性“,如果该属性为 false ,就表示某些操作会忽略当前属性。
  • ES5有三个操作会忽略 enumerable 为 false 的属性。
    • for…in 循环:只遍历对象自身的和继承的可枚举的属性
    • Object.keys():返回对象自身的所有可枚举的属性的键名
    • JSON.stringify():只串行化对象自身的可枚举的属性
  • ES6新增了两个操作,会忽略enumerable 为 false 的属性。
    • Object.assign():只拷贝对象自身的可枚举的属性
    • Reflect.enumerate():返回所有 for…in 循环会遍历的属性
  • 这五个操作之中,只有 for…in 和 Reflect.enumerate()会返回继承的属性
  • 实际上,引入enumerable 的最初目的,就是让某些属性可以规避掉 for…in 操作。比如,对象原型的 toString方法,以及数组的 length 属
    性,就通过这种手段,不会被 for…in 遍历到
  • ES6规定,所有Class的原型的方法都是不可枚举的。
  • 总的来说,操作中引入继承的属性会让问题复杂化,大多数时候,我们只关心对象自身的属性。所以,尽量不 要用 for…in 循环,而用 Object.keys() 代替
属性的遍历

ES6一共有6种方法可以遍历对象的属性。

  • for…in : 循环遍历对象自身的和继承的可枚举属性(不含Symbol属性)。
  • Object.keys(obj):返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含Symbol属性)。
  • Object.getOwnPropertyNames(obj):返回一个数组,包含对象自身的所有属性(不含Symbol属性,但是包括不可枚举属性)。
  • Object.getOwnPropertySymbols(obj):返回一个数组,包含对象自身的所有Symbol属性。
  • Reflect.ownKeys(obj):返回一个数组,包含对象自身的所有属性,不管是属性名是Symbol或字符串,也不管是否可枚举。
  • Reflect.enumerate(obj):返回一个Iterator对象,遍历对象自身的和继承的所有可枚举属性(不含Symbol属性), 与 for…in 循环相同。
  • 以上的6种方法遍历对象的属性,都遵守同样的属性遍历的次序规则。首先遍历所有属性名为数值的属性,按照数字排序。 其次遍历所有属性名为字符串的属性,按照生成时间排序。 后遍历所有属性名为Symbol值的属性,按照生成时间排序。
__proto__属性
  • __proto__属性(前后各两个下划线)用来读取或设置当前对象的prototype对象
  • 无论从语义的角度,还是从兼容性的角度,都不要使用这个属性,而是使用下面的 Object.setPrototypeOf() (写 操作)、Object.getPrototypeOf(读操作)、Object.create(生成操作)代替。
  • 在实现上,__proto__调用的是Object.prototype.proto
  • 如果一个对象本身部署了__proto__ 属性,则该属性的值就是对象的原型。
Object.setPrototypeOf()
  • 该方法的作用与__proto__相同,用拉力设置一个对象的prototype对象,它是ES6正式推荐的设置原型对象的方法
Object.getPrototypeOf()

该方法与setPrototypeOf方法配套,用于读取一个对象的prototype对象。

对象的扩展运算符
  • Rest 参数
    - Rest参数用于从一个对象取值,相当于将所有可遍历的、但尚未被读取的属性,分配到指定的对象上面。所有的键和它们的值,都会拷贝到新对象上面。
  • 扩展运算符
    • 扩展运算符用于取出参数对象的所有可遍历属性,拷贝到当前对象之中。这等同于Object.assign方法
    • 扩展运算符可以用于合并两个对象。
    • 扩展运算符还可以用自定义属性,会在新对象之中,覆盖掉原有参数。
    • 扩展运算符的参数对象之中,如果有取值函数 get ,这个函数是会执行的。
    • 如果扩展运算符的参数是null或undefined,这个两个值会被忽略,不会报错。

Symbol

概述
  • ES6引入Symbol的原因:保证每个属性的名字都是独一无二,这样就从根本上防止属性名的冲突。
  • ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。它是JavaScript语言的第七种数据类型
  • Symbol值通过 Symbol 函数生成。这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串, 另一种就是新增的Symbol类型。凡是属性名属于Symbol类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。
  • 注意: Symbol 函数前不能使用 new 命令,否则会报错。这是因为生成的Symbol是一个原始类型的值,不是对 象。也就是说,由于Symbol值不是对象,所以不能添加属性。基本上,它是一种类似于字符串的数据类型。
  • Symbol 函数可以接受一个字符串作为参数,表示对Symbol实例的描述,主要是为了在控制台显示,或者转为 字符串时,比较容易区分。
  • 注意: Symbol 函数的参数只是表示对当前Symbol值的描述,因此相同参数的›„‘Ž 函数的返回值是不相等 的。
  • Symbol值不能与其他类型的值进行运算,会报错。
  • Symbol值可以显式转为字符串。
  • Symbol值也可以转为布尔值,但是不能转为数值。
作为属性名的Symbol
  • 由于每一个Symbol值都是不相等的,这意味着Symbol值可以作为标识符,用于对象的属性名,就能保证不会 出现同名的属性。这对于一个对象由多个模块构成的情况非常有用,能防止某一个键被不小心改写或覆盖。
  • Symbol值作为对象属性名时,不能用点运算符。
  • 在对象的内部,使用Symbol值定义属性时,Symbol值必须放在方括号之中
  • Symbol类型还可以用于定义一组常量,保证这组常量的值都是不相等的。
  • 常量使用Symbol值大的好处,就是其他任何值都不可能有相同的值了,因此可以保证上面的 switch 语句会 按设计的方式工作
  • Symbol值作为属性名时,该属性还是公开属性,不是私有属性
属性名的遍历
  • Symbol作为属性名,该属性不会出现在 for…in 、for…of 循环中,也不会被 Object.keys() 、Object.getOwnPropertyNames() 返回。但是,它也不是私有属性,有一 个Object.getOwnPropertySymbols 方法,可以获取指定对象的所有Symbol属性名。
  • Object.getOwnPropertySymbols方法返回一个数组,成员是当前对象的所有用作属性名的Symbol值。
  • 使用Object.getOwnPropertyNames 方法得不到Symbol属性名,需要使用Object.getOwnPropertySymbols 方法
  • Reflect.ownKeys方法可以返回所有类型的键名,包括常规键名和Symbol键名
Symbol.for(),Symbol.keyFor()
  • 有时,我们希望重新使用同一个Symbol值,Symbol.for() 方法可以做到这一点。它接受一个字符串作为参数, 然后搜索有没有以该参数作为名称的Symbol值。如果有,就返回这个Symbol值,否则就新建并返回一个以该字符串为名称的Symbol值。
  • Symbol.for() 与Symbol() 这两种写法,都会生成新的Symbol。它们的区别是,前者会被登记在全局环境中供 搜索,后者不会。Symbol.for() 不会每次调用就返回一个新的Symbol类型的值,而是会先检查给定的key是 否已经存在,如果不存在才会新建一个值
  • Symbol.keyFor方法返回一个已登记的Symbol类型值的key
  • Symbol.for() 为Symbol值登记的名字,是全局环境的,可以在不同的iframe或service worker中取到同一个值。
内置的Symbol值

除了定义自己使用的Symbol值以外,ES6还提供了11个内置的Symbol值,指向语言内部使用的方法。

  • Symbol.hasInstance:对象的该属性指向一个内部方法。该对象使用 instanceof 运算符时,会调用这个方法, 判断该对象是否为某个构造函数的实例。
  • Symbol.isConcatSpreadable:对象的该属性等于一个布尔值,表示该对象使用Array.prototype.concat()时,是否可以展开
    • 数组该属性默认为true,表示可以展开
    • 类似数组的对象也可以展开,但它的该属性默认为false,必须手动打开
    • 对一个类来说,该属性必须写成一个返回布尔值的方法
  • Symbol.species:对象的该属性,指向一个方法,该对象作为构造函数创造实例时,会调用这个方法,即如果 this.constructor[Symbol.species] 存在,就会使用这个属性作为构造函数,来创造新的实例对象
  • Symbol.match:对象的该属性,指向一个函数,当执行str.match(myObject) 时,如果该属性存在,会调用它,返 回该方法的返回值。
  • Symbol.replace:对象的该属性,指向一个方法,当该对象被String.prototype.replace 方法调用时,会返回该方法的返回值。
  • Symbol.search:对象的该属性,指向一个方法,当该对象被String.prototype.search 方法调用时,会返回该方法的返回值。
  • Symbol.split:对象的该属性,指向一个方法,当该对象被String.prototype.split 方法调用时,会返回该方法的返回值。
  • Symbol.iterator:对象的Symbol.iterator属性,指向该对象的默认遍历器方法,即该对象进行for…of循环时,会调用这个方 法,返回该对象的默认遍历器
  • Symbol.toPrimitive:对象的该属性,指向一个方法,该对象被转为原始类型的值时,会调用这个方法,返回该对 象对应的原始类型值。
    • 该属性被调用时,会接受一个字符串参数,表示当前运算的模式,一共有三种模式。
      • Number:该场合需要转成数值
      • String:该场合需要转成字符串
      • Default:该场合可以转成数值,也可以转成字符串
  • Symbol.toStringTag:对象的该属性,指向一个方法。在该对象上面调用 Object.prototype.toString 方法时,如 果这个属性存在,它的返回值会出现在 toString 方法返回的字符串之中,表示对象的类型。也就是说,这个属 性可以用来定制 [object Object] 或 [object Array] 中object后面的那个字符串。
  • Symbol.unscopables:对象的该属性,指向一个对象。该对象指定了使用 with 关键字时,哪些属性会被 with环境 排除。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值