Bootstrap

JS中ES5和ES6面向对象的不同

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 关键字。

其次是取值函数和设置值函数。

在“类”的内部可以使用getset关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取 行为。

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关键字能调用父类的方法了。

;