ES6学习第七篇--类(class)

ES5的类原理

1.首先看下面实例

function Father(name,age) {
	this.name = name;
	this.age = age;
	this.getName = function(){
		console.log("name:"+this.name);
	}
}
Father.prototype.getAge = function() {
	console.log("age:"+this.age);
}
var father = new Father("testFather", 30);//new出新的对象
console.log(father);

运行结果图:
在这里插入图片描述

实例分析:
1 创建了一个构造函数Father,此构造函数相当于"类",并定义了类的两个属性(name和age)和一个方法(getName)。
2 Father.prototype对象定义了一个方法(getAge)。
3 用new关键字实例化一个对象father。
4 对象直接访问getAge访问不到时,会访问Father.prototype的getAge方法。(_proto_原型链)
下面将对father对象结构进行分析,如果对js的原型链不太熟悉的朋友可以先学习深入理解javascript原型和闭包(3)——prototype原型
father对象的结构分析:
1 new关键字在创建对象时,会先创建一个father的简单对象,构造函数的this会指向这个对象;构造函数执行完毕后,father对象会有两个属性和一个方法;
2 father对象是由Father构造函数创建出来的,所以它的_proto_属性指向
Father.prototype对象;
3 Father.prototype._proto_是由Object创建出来的,所以Father.prototype._proto_属性指向Object.prototype对象;
4 当访问father.constructor访问不到时,会访问Father.prototype.constructor。

console.log(father.__proto__ ==== Father.prototype);//true
console.log((Father.prototype.__proto__) === Object.prototype);//true
console.log(father.constructor=== Father);//true
console.log(father.constructor=== Father.prototype.constructor);//true

原型链图:
在这里插入图片描述

ES6的类(Class)原理

1.首先看下面实例

class Father {
    constructor(name, age){
		this.name = name;
		this.age = age;
		this.getName = function(){
			console.log("name:"+this.name);
		}
	}
	getAge(){
		console.log("age:"+this.age);
	}
}
var father = new Father("testFather", 30);//new出新的对象
console.log(father);

运行结果图:
在这里插入图片描述

对比上面两张程序运行结果图发现,ES5和ES6的类实现都是建立在原型链的基础之上,他们的原型链结构几乎完全一样。

ES6的类(Class)继承

类继承原理:
ES6中提供了extends关键字实现类的继承,相比较ES5的原型继承,更方便易懂,extends在实现继承方面,本质上也是原型链继承,该方法实现了两步原型链继承。
大多数浏览器的 ES5 实现之中,每一个对象都有__proto__属性,指向对应的构造函数的prototype属性(father.proto === Father.prototype)。
Class 作为构造函数的语法糖,同时有prototype属性和__proto__属性,因此同时存在两条继承链

  • (1)子类的__proto__属性,表示构造函数的继承,总是指向父类,子类构造函数(Child)的原型(Child.proto)指向了父类构造函数(Father)。
  • (2)子类prototype属性的__proto__属性(Child.prototype.proto),表示方法的继承,总是指向父类的prototype属性(Father.prototype)。

实现原理代码:

Child.prototype = Object.create(Father.prototype, {constructor:{value: Child}})
即将Child.prototype.__proto__ = Father.prototype

类继承实例:

class Father {
    constructor(name, age){
		this.name = name;
		this.age = age;
		this.getName = function(){
			console.log("name:"+this.name);
		}
	}
    getAge(){
		console.log("age:"+this.age);
	}
}
class Child extends Father {
    constructor(name, age, sex){
        super(name, age);
		this.sex = sex;
    }
}
 
var child = new Child("xiaoming", 10, "男");
console.log(child);

运行结果图:
在这里插入图片描述

ES6的类(Class)静态方法和方法的区别

ES6 中规定,Class 内部只有静态方法,没有静态属性。静态方法用static关键字修饰,用static关键字定义的方法属于类的方法,不属于对象的方法。

class Father {
    constructor(name, age){
		this.name = name;
		this.age = age;
		this.getName = function(){
			console.log("name:"+this.name);
		}
	}
	//方法加入了satic修饰
    static getAge(){
		console.log("age:"+this.age);
	}
}
class Child extends Father {
    constructor(name, age, sex){
        super(name, age);
		this.sex = sex;
    }
}
 
var child = new Child("xiaoming", 10, "男");
console.log(child);
console.log(child.getAge);
console.log(Child.getAge);
console.log(Father.getAge);

运行结果图:
在这里插入图片描述
分析上面运行结果,得出结论:
1 静态方法是属于类级别的方法,只能被类直接访问。
2 父类的静态方法能够被子类直接继承。原因是上面说的两条继承链中的第一条(Child.proto === Father)。

ES6类的getter / setter方法

getter 不可单独出现,getter 与 setter 必须同级出现

class Father {
    constructor(name, age){
		this.name = name;
		this.age = age;
	}
	//方法加入了satic修饰
    get name(){
        console.log('getter name');
        return this._name;
    }
    set name(_name){
        console.log('setter name');
        this._name = _name;
    }
	get age(){
        console.log('getter age');
        return this._age;
    }
    set age(_age){
        console.log('setter age');
        this._age = _age;
    }
}
class Child extends Father {
    constructor(name, age, sex){
        super(name, age);
		this.sex = sex;
    }
	get sex(){
        console.log('getter sex');
        return this._sex;
    }
    set sex(_sex){
        console.log('setter sex');
        this._sex = _sex;
    }
}
 
var child = new Child("xiaoming", 10, "男");
console.log(child);

运行结果图:
在这里插入图片描述
分析例子运行结果可以发现:
1 构造函数给属性赋值时,会调用属性的set函数;运行结果中起始三行打印了set函数调用的日志;
2 对象可以通过_name、_age和_sex间接访问对象属性;
3 对象直接访问name、age和sex属性时,会调用get函数;运行解脱最后面四行打印了get函数调用日志;

ES6类的super关键字

子类的构造函数constructor中super方法实现对父类构造函数的调用
注意事项:
1 子类 constructor 方法中必须有 super ,且必须出现在 this 之前。

class Father {
    constructor() {}
}
class Child extends Father {
    constructor() {}
    // or 
    // constructor(a) {
        // this.a = a;
        // super();
    // }
}
let test = new Child(); // Uncaught ReferenceError: Must call super 
// constructor in derived class before accessing 'this' or returning 
// from derived constructor

2 调用父类构造函数,必须出现在子类的构造函数。

class Father {
    test(){
        return 0;
    }
    static test1(){
        return 1;
    }
}
class Child extends Father {
    constructor(){
        super();
    }
}
class Child1 extends Father {
    test2() {
        super(); // Uncaught SyntaxError: 'super' keyword unexpected     
        // here
    }
}

3 子类方法(非静态的方法)中可以通过super调用父类的方法(非静态方法)

class Father {
    constructor(name, age){
		this.name = name;
		this.age = age;
		this.getName = function(){
			console.log("name:"+this.name);
		}
	}
	//方法加入了非satic修饰
    getAge(){
		console.log("Father getAge");
		console.log("age:"+this.age);
	}
}
class Child extends Father {
    constructor(name, age, sex){
        super(name, age);
		this.sex = sex;
    }
	getAge(){
		console.log("child getAge");
		super.getAge();
	}
}
 
var child = new Child("xiaoming", 10, "男");
console.log(child);
child.getAge();

运行结果图:
在这里插入图片描述
分析运行结果发现:
    super其实等价于Father.prototype即Father.prototype.call(this),所以通过super调用getAge方法时,方法中的this执行了child对象,返回对象的age属性;
4 子类静态方法中可以通过super调用父类静态方法
此时super等价于Father,而不是Father.prototype

class Father {
    constructor(name, age){
		this.name = name;
		this.age = age;
		this.getName = function(){
			console.log("name:"+this.name);
		}
	}
	//方法加入了satic修饰
    static getAge(){
		console.log("Father getAge");
		console.log("age:"+this.age);
	}
}
class Child extends Father {
    constructor(name, age, sex){
        super(name, age);
		this.sex = sex;
    }
	static getAge(){
		console.log("child getAge");
		super.getAge();
	}
}
 
var child = new Child("xiaoming", 10, "男");
console.log(child);
Child.getAge();
console.log("给Father类赋值");
Father.age = 20;
Child.getAge();

运行结果图:
在这里插入图片描述
分析例子运行结果发现:
Father静态方法中的this,指向的是Father。

上一篇:ES6学习第六篇–生成器(Generator)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值