Class 集中保存一个类型的构造函数和原型对象的程序结构
- class语法结构
- 在class中保护对象 (开关 / 访问器)
- 两种类型之间的继承
- class语法结构:
class 类型名{
constructor(属性1,属性2,...){
this.属性1=属性1;
this.属性2=属性2;
... = ...
}
方法名(){
... ...
}
}
//创建该类型的子对象
var 子对象 = new 类型名(属性值列表)
子对象自动继承该类型的原型对象
强调: class中每个成员结尾不要加任何分割(, 或 ; 都不要加)
原型对象:创建构造函数时自动创建了原型对象
举例:
class Student{
constructor(sname,sage){
this.sname = sname;
this.sage = sage;
}
intr(){
console.log(`我是${this.sname},${this.sage}岁`);
}
}
var Hanmeimei = new Student("Hanmeimei",15);
console.log(Hanmeimei);
Hanmeimei.intr();
共有属性:保存在原型对象中,由该类型所有子对象共有的属性值
注意:直接放在class下的属性不会成为共有属性,而会成为每个子对象内的自有属性
-
将class下的属性变为共有属性,提供给所有子对象使用
两种方法:旧js/变通做法
//旧js 在class外
类型名.prototype.共有属性名 = 共有属性值
//变通后 在class构造函数末尾 加
if(类型名.prototype.共有属性名 == undefined){
类型名.prototype.共有属性名 == 属性值;
}
举例:
class Student{
constructor(ename,eage){
this.ename = ename;
this.eage = eage;
if(Student.prototype.className === undefined){
Student.prototype.className = "7年8班";
}
}
intr(){
console.log(`我是${this.ename},今年${this.eage},来自${this.className}`);
}
}
var Hanmei = new Student("韩莓",16);
console.log(Hanmei);
Hanmei.intr();
console.log(Hanmei.className);
-
class中保护对象
(1)用开关保护 (保护对象的代码要写在构造函数中,且要保护的对象用this代替)
举例://保护过程写在构造函数中,对象用this代替
class User{
constructor(eid,ename,eage){
this.eid = eid;
this.ename = ename;
this.eage = eage;
Object.defineProperties(this,{
eid:{
writable:false,
configurable:false
},
ename:{
configurable:false
},
eage:{
enumerable:false,
configurable:false
}
});
//保护属性结束
}
}
//创建两个子对象用户
var Hanmei = new User(1,"韩莓",22);
var Wanwan = new User(2,"绾绾",20);
//尝试修改eid
Hanmei.eid = 3;
//尝试删除ename属性
delete Hanmei.ename;
//尝试遍历所有属性
for(var key in Hanmei){
console.log(`韩莓的属性名:${key},属性值:${Hanmei[key]}`);
}
console.log(Hanmei);
结果://在严格模式下,会静默升级,报错
正常模式下,不会报错,开关生效,eid修改失败 韩莓的ename未修改
????for in 没防住
因为我的enumerable写错了~ 呜呜呜~
(2)用访问器属性保护 在class中定义访问器属性get() set()
在构造函数中手动创建半隐藏的受保护的属性,并修改访问器属性的enumerable为true
class 类名{
constructor(...){
... = ...
this.访问器属性 = 属性值;
}
get(){
return this._受保护的属性
}
set(value){
if(){
this._受保护属性 = value;
}else{
throw error("Error")
}
}
}
举例:
class Emp{
constructor(eid,ename,eage){
this.eid = eid;
this.ename = ename;
//创建一个新的半隐藏属性
Object.defineProperty(this,"_eage",{
writable:true,
enumerable:false,
configurable:false
});
//修改Emp中的eage属性的enumerable为true
Object.defineProperty(Emp.prototype,"eage",{
enumerable:true
});
this.eage = eage;
}
//构造函数结束
get eage(){
return this._eage;
}
set eage(value){
if(value >= 18 && value <=50 ){
this._eage = value;
}else{
throw Error(`年龄不符合`)
}
}
}
//
//创建类的子对象
var Hanmei = new Emp(1,"韩莓",26);
console.log(Hanmei);
-
两种类型之间的继承
当2个class拥有部分相同的树形结构和方法时,定义一个父类型,集中保存相同部分的属性和功能
class 子类型 extends 父类型{
constructor(...){
super(...);
this.子类型属性 = ...
}
}
举例:使用两种类型间继承描述飞机大战游戏的数据结构
class Flyer{
constructor(x,y){
this.x = x;
this.y = y;
}
fly(){
console.log(`当前位置(${this.x},${this.y})`);
}
}
//开始继承
class Plane extends Flyer{
constructor(x,y,score){
//调用super()来请父类型构造函数帮忙补齐类型缺少的属性
super(x,y);
this.score = score;
}
getScore(){
console.log(`掉落一架敌机,得分${this.score}分`);
}
}
//创建飞机
var f1 = new Plane(50,100,5);
console.log(f1);
f1.getScore();
//plane继承了flyer的x,y属性