一、对象成员速写
示例1
const name = "xiaocan";
const age = 23;
const sayHello = function () {
console.log(`my name is ${this.name}`);
};
// 过去的方式
const user = {
name: name,
age: age,
sayHello: sayHello,
};
// 速写
const user = {
name,
age,
sayHello,
};
user.sayHello();
示例2
// 以前的方式
const myMath1 = {
sum: function (a, b) {
//...
},
random: function (min, max) {
//...
},
};
// 速写
const myMath2 = {
sum(a, b) {
//...
},
random(min, max) {
//...
},
};
二、展开运算符
示例1
const arr = [1, 5, 34, 5, 21, 5];
const result = Math.max(1, 5, 34, 5, 21, 5); // Math.max(...arr)
示例2
const o1 = {
a: 1,
b: 2,
};
const o2 = {
c: 3,
d: 4,
};
// 对对象的展开
const o3 = {
...o1,
...o2,
};
console.log(o3); // { a: 1, b: 2, c: 3, d: 4 }
示例3
const arr = [1, 3, 4, 5];
const arr1 = [42, 42, ...arr, 13];
console.log(arr1); //[42,42,1,3,4,5,13]
示例4
const user = {
name: "小灿",
age: 23,
};
const user2 = {
...user,
name: "小灿同学",
};
console.log(user2); // { name: '小灿同学', age: 23 }
三、解构
示例1
const user = {
name: "小灿",
age: 23,
address: {
province: "广东",
city: "深圳",
},
};
const { name, age } = user;
const {
address: { city },
} = user;
console.log(name, age, city); // 小灿 23 深圳
示例2
const arr = [1, 2, 3, 4, 5];
const [a, b, c] = arr;
console.log(a, b, c); // 1 2 3
const [, , d, , e] = arr;
console.log(d, e); // 3 5
const [, , f, ...arr2] = arr;
console.log(f, arr2); // 3 [ 4, 5 ]
示例3
let a = 1,
b = 2;
// 交换两个变量
[b, a] = [a, b];
console.log(b, a); // 1 2
示例4
// 在参数的位置对传入的对象进行解构
function method({ a, b }) {
console.log(a, b); // 1 2
}
const obj = {
a: 1,
b: 2,
c: 3,
};
method(obj);
示例5
const users = [
{ name: "小灿同学", age: 23 },
{ name: "小灿", age: 23 },
];
// 在遍历的时候进行解构
for (const { name, age } of users) {
console.log(name, age);
// 小灿同学 23
// 小灿 23
}
四、属性描述符
对于对象中的每个成员,JS使用属性描述符来描述它们
const users = { name: "小灿同学", age: 23 };
上面的对象,在JS内部被描述为
{
// 属性 name 的描述符
name: {
value: "小灿同学",
configurable: true, // 该属性的描述符是否可以被重新定义
enumerable: true, // 该属性是否允许被這历,会影响for-in循环
writable: true, // 该属性是否允许被修改
},
// 属性 age 的描述符
age: {
value: 23,
configurable: true, // 该属性的描述符是否可以被重新定义
enumerable: true, // 该属性是否允许被這历,会影响for-in循环
writable: true, // 该属性是否允许被修改
},
};
ES5提供了一系列的API,针对属性描述符进行操作
1. Object.getOwnPropertyDescriptor(obj, propertyName)
该方法用于获取一个属性的描述符
const user = { name: "小灿同学", age: 23 };
console.log(Object.getOwnPropertyDescriptor(user, "name"));
/**
{
value: '小灿同学',
writable: true,
enumerable: true,
configurable: true
}
*/
2. Object.defineProperty(obj, propertyName, descriptor)
const user = { name: "小灿同学", age: 23 };
Object.defineProperty(user, "name", {
value: "小灿",
writable: false, // 该属性不允许被修改
enumerable: false, // 该属性是否允许被這历,for-in循环循环不出来,读取user也看不见user.name
configurable: false, // 该属性的描述符不可以被重新定义
});
user.name = "xiaocantongxue";
console.log(user); // { age: 23 }
console.log(user.name); // 小灿
for (const key in user) {
if (Object.hasOwnProperty.call(user, key)) {
console.log(key); // age, 遍历不到name
}
}
3. getter 和 setter
属性描述符中有两个特殊的配置,分别为 get 和 set,通过它们,可以把属性的取值和赋值变为方法调用
const obj = {};
Object.defineProperty(obj, "a", {
get() {
// 读取属性a时,会运行该函数,得到的是该函数返回的值
return 1;
},
set(val) {
// 设置属性a时,会把val传值进去,调用该方法
console.log(`执行了这句话,传进来的值是:${val}`);
},
});
console.log(obj.a); // 1
obj.a = 100; // 执行了这句话,传进来的值是:100
console.log(obj.a); // 1
const obj = {};
let innerValue = 1;
Object.defineProperty(obj, "a", {
get() {
// 读取属性a时,会运行该函数,得到的是该函数返回的值
return innerValue;
},
set(val) {
// 设置属性a时,会把val传值进去,调用该方法
console.log(`将传进来的val值复制给innerValue变量`);
innerValue = val;
},
});
console.log(obj.a); // 1
obj.a = 100; // 将传进来的val值复制给innerValue变量
console.log(obj.a); // 100
五、键值对
Object.keys(obj)
:获取对象的属性名组成的数组
Object.values(obj)
:获取对象的值组成的数组
Object.entries(obj)
:获取对象属性名和属性值组成的数组
Object.fromEntries (entries)
:将属性名和属性值的数组转换为对象
const user = { name: "小灿同学", age: 23 };
console.log(Object.keys(user)); // [ 'name', 'age' ]
console.log(Object.values(user)); // [ '小灿同学', 23 ]
console.log(Object.entries(user)); // [ [ 'name', '小灿同学' ], [ 'age', 23 ] ]
console.log(
Object.fromEntries([
["name", "小灿同学"],
["age", 23],
])
); // { name: '小灿同学', age: 23 }
/**
打印:
name: '小灿同学'
age: 23
*/
for (const [key, value] of Object.entries(user)) {
console.log(`${key}: ${value}`);
/**
name: '小灿同学'
age: 23
*/
}
六、冻结
使用 Object.freeze(obj)
可以冻结一个对象,该对象的所有属性均不可更改
const obj = {
a: 1,
b: 2,
c: {
d: 3,
},
};
Object.freeze(obj); //冻结对象obj
obj.a = "a"; // 不报错,代码无效
obj.b = "b"; // 不报错,代码无效
delete obj.a; // 不报错,代码无效
obj.c = "c"; // 不报错,代码无效
obj.c.d = "d"; // 对象c没有被冻结,有效
console.log(obj); // { a: 1, b: 2, c: { d: 'd' } }
可以使用 Object.isFrozen 来判断一个对象是否被冻结
七、相同性判断
Object.is
方法,可以判断两个值是否相同,它和===
的功能基本一致,区别在于:
- NaN和NaN相等
- +0和-0不相等
console.log(Object.is(1, 2)); // false
console.log(Object.is("1", 1)); // false
console.log(Object.is(NaN, NaN)); // true
console.log(Object.is(+0, -0)); // false
八、Set
set是一种数据集合,用于保存一系列唯一的值
MDN参考
1.数组去重
// Use to remove duplicate elements from the array
const numbers = [2, 3, 4, 4, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 5, 32, 3, 4, 5];
console.log([...new Set(numbers)]); // [2, 3, 4, 5, 6, 7, 32]
八、Map
Map是一种数据集合,用于保存一系列键值对(key-value pair),其中,键(key)可以是任何类型,并且是唯一的
MDN参考
九、练习题
练习题1
const obj = {
a: 1,
b: 2,
c: 3,
};
// 遍历对象的所有属性名
for (const key of Object.keys(obj)) {
console.log(key);
}
// 遍历对象的所有属性值
for (const value of Object.values(obj)) {
console.log(value);
}
// 遍历对象的所有属性名和属性值
for (const [key, value] of Object.entries(obj)) {
console.log(key, value);
}
// 复制obj的所有属性到一个新的对象
const newObj = {
...obj,
};
console.log(newObj);
// 复制obj除a以外的所有属性到一个新的对象
const { a, ...removeAObj } = newObj;
console.log(removeAObj);
练习题2
// 根据下面的调用和注释,完成函数 createOptions
function createOptions(options) {
options = options || {};
const defaultOptions = { time: 1000, speed: 50, text: "" };
return {
...defaultOptions,
...options,
};
}
console.log(createOptions()); // { time: 1000, speed: 50, text: '' }
console.log(
createOptions({
time: 500,
})
); // { time: 500, speed: 50, text: '' }
console.log(
createOptions({
time: 500,
text: "hello world",
})
); // { time: 500, speed: 50, text: 'hello world' }
练习题3
// 遍历对象 user, 将其每一个属性变为 getter 和 setter, 保持读写功能不变
// 读取属性时,输出:正在读取xxx属性,值为xxx
// 给属性赋值时,输出:正在设置xxx属性,新的值为xxx
const user = {
name: "小灿同学",
age: 23,
sex: "male",
};
for (let [key, innerValue] of Object.entries(user)) {
Object.defineProperty(user, key, {
get() {
console.log(`正在读取 ${key} 属性,值为${innerValue}`);
return innerValue;
},
set(val) {
innerValue = val;
console.log(`正在设置 ${key} 属性,设置为${innerValue}`);
},
});
}
user.name; // 正在读取 name 属性,值为小灿同学
user.name = "小灿"; // 正在设置 name 属性,设置为小灿同学
user.name; // 正在读取 name 属性,值为小灿
user.age; // 正在读取 age 属性,值为23
user.age = 22; // 正在设置 age 属性,设置为23
user.age; // 正在读取 age 属性,值为22
user.age += 10; // 正在读取 age 属性,值为22 正在设置 age 属性,设置为32
笔记整理自渡一教育袁老师课堂