1.ES5中创建类
1.1 封装
ES5创建对象主要是利用函数里面的this,谁调用就指向谁的特点。和函数的prototype属性,构造原型链。
例子:
function person(name,age){
this.name=name;
this.age=age;
// 函数是每个对象内部独有的,没有进行共享
// this.show=function (){
// console.log(this.name+':'+this.age);
// }
}
person.prototype.show=function(){
console.log(this.name+':'+this.age);
}
let p=new person("p",10)
p.show()
对于可以共享的属性(函数)可以动态添加到函数的prototype属性。而创建对象之后,对象内部的__proto__属性实际上就是指向函数的prototype属性,所以可以把对象的方法添加到这个属性中进行所有对象共享。
1.2 继承
在这里只写了一种
function person2(sex,name,age){
person.call(this,name,age)
this.sex=sex
}
person2.prototype=person.prototype
person2.prototype.ToString=function (){
console.log(this.name+this.age+this.sex);
}
let p2=new person2("男","p2",12)
p2.show()
p2.ToString()
person2.prototype=person.prototype 必须写在创建对象之前。
function person2(sex,name,age){
person.call(this,name,age)
this.sex=sex
}
person2.prototype=person.prototype
person2.prototype.ToString=function (){
console.log(this.name+this.age+this.sex);
}
let p2=new person2("男","p2",12)
p2.show()
p2.ToString()
2.ES6中创建类
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
这里也是用了语法糖,其实方法也是放在Point的原型对象上的。
所以由这个类创建的所有对象,都是共享一个原型对象,这里和ES5 一样。
注意:在class 里面创建方法不需要再方法前面添加function 关键字。
其次是取值函数和设置值函数。
在“类”的内部可以使用get
和set
关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取 行为。
class Point {
// 可以在这里声明对象
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
static show(){
console.log("-shwo-");
}
get prop() {
return 'getter';
}
set prop(value) {
console.log('setter: '+value);
}
}
let p = new Point(1,2)
p.prop="xx"
静态
静态方法:所有在方法前面加上Static 的方法都是静态方法。
注意:父类的静态方法,也可以被子类继承。 (但是不是被实例所有)
还有静态属性,也和静态方法的继承一样。
为了可以在创建类的时候对静态属性初始化,引入了静态代码块。
继承
Class 可以通过extends
关键字实现继承,让子类继承父类的属性和方法。
class Person{
name;
age;
constructor(name, age) {
this.name=name
this.age=age
console.log("父类的构造方法");
}
show(){
console.log("this is Person");
}
}
class Human extends Person{
constructor(name, age,sex) {
super(name,age)
this.sex=sex;
console.log("子类构造方法");
}
show(){
console.log('获取父类的属性'+`${this.name} ${this.age}`);
super.show()
}
}
1. extends 继承,是ES6 添加的语法糖,本质上还是原型继承的写法(没必要纠结这个)
2.super 关键值,代表父类的原型对象,所以可以在子类中通过这个关键值调用父类的方法(方法在父类的原型对象上)。
const proto = {
foo: 'hello'
};
const obj = {
foo: 'world',
find() {
return super.foo;
}
};
Object.setPrototypeOf(obj, proto);
obj.find() // "hello"
注意,super
关键字表示原型对象时,只能用在对象的方法之中,用在其他地方都会报错。
原型链
本质上ES6 的继承也是通过原型实现的。
(1)子类的__proto__
属性,表示构造函数的继承,总是指向父类。
(2)子类prototype
属性的__proto__
属性,表示方法的继承,总是指向父类的prototype
属性。
class A {
}
class B extends A {
}
B.__proto__ === A // true
B.prototype.__proto__ === A.prototype // true
通过这也就能解释的通,前面的继承,super关键字能调用父类的方法了。