黑马程序员技术交流社区

标题: Es6class类 [打印本页]

作者: 小江哥    时间: 2019-6-17 18:33
标题: Es6class类
面向对象思想
什么是面向对象编程(Object Oriented Programming| OOP)?
如何实现对象(类)的定义
JS中并没有类(class)的概念,更多的时候我们称之为对象(function),然后把对象叫做实例(instance)。如下,Person 类型为function
class Person {
    // ...
    sayHi() {
        console.log('Hi')
    }
}
typeof Person // 'function'
Person === Person.prototype.constructor // 'true'
let p1 = new Person();
p1.sayHi()  // Hi
上列代码表明,类的数据类型就是函数,类本身就是指向构造函数。
使用的时候,也是直接对类使用new命令,跟构造函数的用法完全一致。
类的由来
在js里面,我们通常都是通过构造函数来创建对象(class),然后通过new这个关键字来实例化一个对象,如:
ES5中的方法:
上面这种写法跟传统的面向对象语言(比如 C++ 和 Java)差异很大,很容易让新学习这门语言的程序员感到困惑。
ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。
基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。上面的代码用 ES6 的class改写,就是下面这样。
构造函数的prototype属性
        构造函数的prototype属性,在 ES6 的“类”上面继续存在。事实上,类的所有方法都定义在类的prototype属性上面。
ES6中的变形:方法的传值class Person {
    showName(name) {
      return `我的名字为:${name}`
    }
}
let p1 = new Person();
console.log(p1.showName('Jing'))
类的传参实例:  class Person {
    constructor(name,age) {
      this.name = name;
      this.age = age;
    }
    showName() {
      return `我的名字为:${this.name}`
    }
    showAge() {
      return `我的年龄为:${this.age}`
    }
  }
  let p1 = new Person('Jing',18)
   
  console.log(p1.showName()); // 我的名字为:Jing
  console.log(p1.showAge()); // 我的年龄为:18
constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。如下:
class Person {
   
}
// 等同于
class Person {
    constructor () {}
}
表达式形式  let Person = class {
    constructor(name,age) {
      this.name = name;
      this.age = age;
    }
    showName() {
      return `我的名字为:${this.name}`
    }
    showAge() {
      return `我的年龄为:${this.age}`
    }
  }
  let p1 = new Person('Jing',18)
   
  console.log(p1.showName()); // 我的名字为:Jing
  console.log(p1.showAge()); // 我的年龄为:18  let Person = new class {
    constructor(name,age) {
      this.name = name;
      this.age = age;
    }
    showName() {
      return `我的名字为:${this.name}`
    }
  }('Jing')
  console.log(Person.showName())  // Jing属性表达式: 类的属性名可以采用表达式let methodName = 'showName';
  class Person {
    constructor (name) {
      this.name = name;
    }
    [methodName]() {
      return `我的名字为:${this.name}`
    }
  }
  let p1 = new Person('Jing')
  console.log(p1.showName()); // 我的名字为:Jing
上列代码中Person类的方法名showName是从表达式得到的。
  // 字符串拼接形式
    let aa = 'show';
    let bb = 'Name';
    class Person {
      constructor (name) {
        this.name = name;
      }
      [aa+bb]() {
        return `我的名字为:${this.name}`
      }
    }
    let p1 = new Person('Jing')
    console.log(p1.showName()); // 我的名字为:Jingclass取值函数,存值函数  class Person {    constructor() {    }    get aaa() {      return `aaa的属性`    }    set aaa(val) {      console.log(`设置aaa属性,值为:${val}`);     }  }  let p1 = new Person();  p1.aaa = '123'  p1.aaa  //设置aaa属性,值为:123
注意点严格模式
类和模块的内部,默认就是严格模式,所以不需要使用use strict指定运行模式。只要你的代码写在类或模块之中,就只有严格模式可用。考虑到未来所有的代码,其实都是运行在模块之中,所以 ES6 实际上把整个语言升级到了严格模式。
不存在变量提升  let p1 = new Person()  console.log(p1);  class Person {    constructor (){      this.name = 'Jing'    }  }  // 报错显示初始化前无法访问Person(即Person类没有创建)静态方法
静态方法   类身上的方法  在方法名前加上static,可以直接用Person类调用
类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
  class Person {    constructor() {    }    showName() {      return `这是showName方法`    }    static aaa() {      return `这是静态方法`    }  }  let p1 = new Person();  console.log(p1.showName()); //这是showName方法  console.log(Person.aaa());  // 这是静态方法实例属性新写法
实例属性除了定义在constructor()方法里面的this上面,也可以定义在类的最顶层。
class IncreasingCounter {  constructor() {    this._count = 0;  }  get value() {    console.log('Getting the current value!');    return this._count;  }  increment() {    this._count++;  }}
上面代码中,实例属性this._count定义在constructor()方法里面。另一种写法是,这个属性也可以定义在类的最顶层,其他都不变。
class IncreasingCounter {  _count = 0;  get value() {    console.log('Getting the current value!');    return this._count;  }  increment() {    this._count++;  }}
上面代码中,实例属性_count与取值函数value()和increment()方法,处于同一个层级。这时,不需要在实例属性前面加上this。
这种新写法的好处是,所有实例对象自身的属性都定义在类的头部,看上去比较整齐,一眼就能看出这个类有哪些实例属性。
类的继承  class Person {    constructor(name) {      this.name = name;    }    showName() {      return `我的名字为${this.name}`    }  }  // 子类  class Student extends Person{  }  // 调用  let stu1 = new Student('Jing')  console.log(stu1.showName());
super
  class Person {    constructor(name) {      this.name = name;    }    showName() {      return `我的名字为${this.name}`    }  }  // 子类  class Student extends Person{    constructor(name,skill) {      super(name)      this.skill = skill    }  }  // 调用  let stu1 = new Student('Jing','学习')  console.log(stu1.skill);






欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2