一、访问器属性
1、对象字面量声明的2种方法
- 一次性添加全部成员:属性、方法
let obj = {
//用一个data属性包裹,便于分类管理
data: {
name: "Tom",
email: "123@qq.com",
},
//方法:读
getinfo() {
return this.data.name + ":" + this.data.email;
},
//方法:写
setinfo(value) {
this.data.email = value;
},
};
obj.data.email = "234@qq.com";
console.log(obj.getinfo()); //打印:Tom:234@qq.com
- 逐个添加成员:属性、方法
let obj = {}; //首先要创建空对象
obj.data = {}; //创建一个分类管理的对象
obj.data.name = "zhangsan"; //属性初始化(赋值),挂在到分类管理的对象data上
obj.data.age = 18;
obj.data.sex = "male";
//方法:读
obj.getinfo = function () {
return this.data.name + ":" + this.data.age + ":" + this.data.sex;
};
//方法:写
obj.setinfo = function (value1, value2) {
obj.data.age = value1;
obj.data.sex = value2;
};
obj.data.age = 20;
obj.data.sex = "female";
console.log(obj.getinfo()); //打印:zhangsan:20:female
console.log(obj.data.name); //分别打印属性,造成了代码冗余,用下述的访问接口操作
console.log(obj.data.age);
console.log(obj.data.sex);
2、属性访问接口
let obj = {
data: {
name: "zhangsan",
age: 20,
},
// 属性访问接口
// 这是"访问器属性",实际上就是方法,只不过伪装成了属性,套了一个属性的马甲
get name() {
return this.data.name;
},
set name(value) {
this.data.name = value;
},
};
obj.name = "lisi";
console.log(obj.name); //打印:lisi
二、构造函数
专门用于创建对象(实例)的函数就是构造函数
1、原生(常规)的书写方式
// 构造函数:在函数里创建一个对象,3个步骤
let User1 = function (name, age) {
// 步骤1:创建一个空对象
let obj = {};
// 步骤2:创建对象属性
obj.name = name;
obj.age = age;
//步骤3:返回对象
return obj;
};
let user2 = User1("Tom", 29);
console.log(user2); //{name: 'Tom', age: 29}
let user3 = User1("Jerry", 31);
console.log(user3); //{name: 'Jerry', age: 31}
2、简化的书写方式
// 默认创建了空对象,所以不用再创建了,只需要在函数中使用this引用对象即可
let User2 = function (name, age) {
//console.log(this) 去掉第9行的new,然后打印该行,查看this的指向为window,并未指向默认创建的新对象,所以应该用 new 来调用修正
this.name = name;
this.age = age;
};
//默认返回当前对象,所以不需要返回对象return
let user3 = new User2("Tom", 21);
console.log(user3); //{name: 'Tom', age: 21}
注意:
- this默认指向window,查看上述代码第3行
let user3 = new User2("Tom", 21);
使用了new来调用指向创建的新对象,如果不使用new则返回undefined- 即:构造函数必须使用 new 来调用,修正this指向新对象而非window
3、“类”的创建
JS中没有“类”,所谓“类”其实就是函数
class User1 {
// 公共成员
name = "Tom";
// 构造方法/创建实例
constructor(name, age) {
// 自有属性
this.name = name;
this.age = age;
}
// 共享成员
getinfo() {
return `${this.name}:${this.age}`;
}
// 静态成员
static status = "enable";
}
const user = new User1("Jerry", 24);
console.log(user.getInfo());
class User2 extends User1 {
constructor(name, age,sex) {
super(name,age)
this.sex = sex;
}
getinfo() {
return `${super.getinfo()},${this.age}`;
}
}
const user2 = new User2("Jerry", 24,'male');
console.log(user2.getInfo());
注意:
- 继承: extends,来集成父级属性
- super()会自动的调用父类的构造器来初始化该实例
三、解构赋值
1、数组的解构赋值
//赋值
let [name, email] = ['Tom', '123@qq.com'];
//更新
[name, email] = ['Jerry', '456@qq.com'];
//参数不足
let [name, email, age=18] = ['Jerry', '456@qq.com'];
//参数过多
let [num_a, num_b,...rest] = [1,2,3,4,5,6,7,8,9];
2、对象的解构赋值
- 对象解构1:
// 赋值
let obj = ({ id, name, age } = { id: 1, name: "Tom", age: 21 });
// 更新
obj = { id, name, age } = { id: 2, name: "Jerry", age: 31 };
console.log(obj);
- 对象解构2:
// 赋值
let { id, price, num } = { id: 100, price: 200, num: 300 };
// 更新
({ id, price, num } = { id: 102, price: 203, num: 304 });
console.log({ id, price, num });
注意:
在更新的时候需要在两侧加上中括号()
({ id, price, num } = { id: 102, price: 203, num: 304 });
如果左边模板中的变量存在命名冲突怎么办? 起一个别名
let { id: itemId, num, price } = { id: 123, num: 10, price: 1234 };
console.log(itemId, num, price);