早上岁月静好,炎热的夏天,早上七点的成都还算凉爽,妈妈在厨房煮着早餐,女儿还在床上熟睡,我在床边看着书,一切很美好。
ES6对于对象的扩展
属性简写
- 可以直接在对象中写入变量
- key相当于变量名,value相当于变量值,可以省略value,只通过key表示对象的完整属性
const name = 'yangf';
const people = {name,age};
console.log(people); // {name:'yangf',age:''}
属性遍历
-
for...in
- 包含可枚举的自身属性、继承属性
- 不包含不可枚举属性、Symbol属性
-
Object.keys(obj)
- 返回的是一个数组
- 包含可枚举的自身属性
- 不包含继承属性、不可枚举属性、Symbol属性
-
Object.getOwnPropertyNames(obj)
- 返回的是数组
- 包含所有的自身属性
- 不包含继承属性、Symbol属性
-
Object.getOwnPropertySymbols(obj)
- 返回数组
- 只包含Symbol属性
-
Refect.ownKeys(obj)
- 返回数组
- 包含自身所有属性(可枚举、不可枚举、Symbol)
- 不包含继承属性
根据需要获取对象的key值再获取相应的value值
// 定义一个拥有实例属性、继承属性的对象,其中包含Symbol属性、可枚举属性、不可枚举属性,覆盖全部的场景
// 父类
function People(name,age){
this.name = name;
this.age = age;
}
// 子类(成绩和年纪)
function Student(achievement,grade) {
this.achievement = achievement;
this.grade = grade;
this[Symbol('school')] = '成都小学'
}
// 继承
Student.prototype = new People();
// 生成子类的实例
let student = new Student('85','三年级');
// 在实例上增加可枚举属性和不可枚举属性
Object.defineProperty(student,'sex',{
configurable:true,
enumerable:true,
writable:true,
value:'女'
});
Object.defineProperty(student,'class',{
configurable:true,
enumerable:false,
writable:true,
value:'二班'
});
/**
*描述属性是否可删除
*以及除value和writable特性外的其他特性是否可以被修改
*例外:可以把writable的状态由true改为false,但是无法由false改为true
*在writable: true的情况下,可以改变value的值
*默认false
*configurable:true
*描述属性是否可枚举,默认false
*enumerable:true
*描述属性是否可写,默认false
*writable:true
*value:'女'
**/
- 实例属性:achievement、grade、Symbol('school')、sex
- 继承属性:name、age
- 可枚举属性:achievement、grade、sex
- 不可枚举属性:class
- Symbol属性:Symbol('school')
题外话Object.defineProperty()
- 作用:在一个对象上定义一个新属性或者修改一个已经存在的属性
- 语法:Object.defineProperty(obj,prop,desc)
- obj:需要操作的对象
- prop:需要修改或者新增的属性名
- desc:一些描述
- desc描述:通过对象属性赋值的情况下,对象的属性可以修改、删除等操作;但是通过Object.defineProperty()定义属性,通过描述符的设置可以进行精准的控制对象属性
- 通过Object.defineProperty()定义对象属性有两种形式(数据描述符、存取描述符)
- 数据描述符:特有的两个属性:writable、value
- 存取描述符:是由一对getter、setter函数功能来描述的属性
- get:给属性提供getter方法,方法返回值被用作属性值,默认undefined
- set:给属性提供setter方法,方法接受唯一参数,将该参数的新值分配给该属性,默认undefined www.jianshu.com/p/8fe1382ba… blog.csdn.net/getTheChees…
for(let key in student){
console.log(key);
}
// achievement grade sex name age
Object.keys(student);
// ["achievement", "grade", "sex"]
Object.getOwnPropertyNames(student)
// ["achievement", "grade", "sex", "class"]
Object.getOwnPropertySymbols(student)
// [Symbol(school)]
Reflect.ownKeys(student)
// ["achievement", "grade", "sex", "class", Symbol(school)]
Object.assign()函数
-
特点及作用
- 用于将一个或者多个对象的可枚举属性赋值给目标对象,然后返回目标对象
- 当多个源对象具有相同的属性时,后者的属性值会覆盖前面的属性值
- 无法复制对象的不可枚举属性和继承属性,可以复制可枚举的Symbol属性
let obja = {a:1}; // 目标对象
let objb = {b:2}; // 源对象1
let objc = {c:3}; // 源对象2
let objd = {c:4}; // 源对象3
console.log(Object.assign(obja,objb,objc,objd));
// {a:1,b:2,c:4}
-
常见用途
- 对象复制
- 不是严格意义上的深拷贝
- 如果属性是基本数据类型,则会复制它的值
- 如果属性是引用数据类型,则会复制它的引用
- 对象复制
const obja = {
a:1
}
const objb = Object.assign({},obja);
objb.a = 2;
console.log(obja.a);// 1
- 给对象添加属性
- 给对象添加函数
- 合并对象
// 传统写法
function People(name,age,sex){
this.name = name;
this.age = age;
this.sex = sex;
};
People.prototype.getName = function() {
return this.name;
}
// new
function People(name,age,sex){
Object.assign(this,name,age,sex);
};
Object.assign(People.prototype,{
getName() {
retun this.name;
}
});
// 合并对象
let obja = {a:1};
let objb = {b:2};
const merge = (obja, ...objb)=>Object.assign({}, obja, ...objb);
console.log(merge(obja,objb));// {a: 1, b: 2}
- 题外话:js深拷贝的方法
- JSON.parse(JSON.stringify())
- 非安全的JSON值会被丢弃,如undefined、function、symbol
- set、map这种数据格式的对象,也不会被正确处理,而是处理成一个空对象
- 递归
- 安全可靠
- JSON.parse(JSON.stringify())
Symbol类型
-
ES6之前,对象的属性名都是由字符串构成的
- 假如一个对象继承了另一个对象的属性,我们又需要定义新的属性时,很容易造成属性名的冲突
- 为此ES6引入了一种新的基本数据类型Symbol,它表示的是一个独一无二的值
- 至此JavaScript中就一共存在6种基本数据类型
- Undefined类型、Null类型、Boolean类型、String类型、Number类型、Symbol类型
- 假如一个对象继承了另一个对象的属性,我们又需要定义新的属性时,很容易造成属性名的冲突
-
特性
- 唯一性
- 似于一种唯一标识性的ID,通过Symbol()函数来创建一个Symbol值
- 任何通过Symbol()函数创建的Symbol值都是不相同的
- 是一个新增的基本数据类型,所以通过typeof运算符得到的结果是“symbol”
- 函数中可以传递一个字符串参数,表示对Symbol值的描述,主要是方便对不同Symbol值的区分
- 似于一种唯一标识性的ID,通过Symbol()函数来创建一个Symbol值
- 唯一性
let a = Symbol();
let b = Symbol();
let c = Symbol('one');
let d = Symbol('one');
console.log(type of a); // symbol
console.log(a === b); // false
console.log(c === d); // false
- 不能使用new操作符
- Symbol函数并不是一个构造函数
- 不能参与类型运算
- 可以通过toString()函数显示地转换为字符串
- 本身不能参与其他类型的运算
- 可以创建同一个Symbol值
- 使用Symbol.for()函数,函数接收一个字符串作为参数
- 功能:
- 先搜索有没有以该参数作为名称的Symbol值
- 如果有,就返回这个Symbol值
- 否则就新建并返回一个以该字符串为名称的Symbol值
- 特点:
- 使用Symbol.for()函数创建的变量会被登记在全家作用域中以便搜索
- 函数调用不会立即返回一个新的值,而是先搜索该值是否存在
let symbol = Symbol('string');
symbol.toString();// Symbol(string)
symbol + '';
// Uncaught TypeError: Cannot convert a Symbol value to a string
let s1 = Symbol.for('string');
let s2 = Symbol.for('string');
s1 === s2; // true
-
常见用途
- 在对象中不需要对外访问的变量可以使用symbol
- 因为Object.keys()函数或者for...in遍历不出来symbol属性
- 在对象中不需要对外访问的变量可以使用symbol
let people = {
name:'yangf',
age:18,
[Symbol('card')]:'XXXX'
};
console.log(Object.keys(people)); // ['name', 'age']
因为Symbol属性不会出现在属性遍历的过程中,所以在使用JSON.stringify()函数将对象转换为JSON字符串时,Symbol值也不会出现在结果中