ES6 Class基本语法

1.类的声明

最早期的JavaScript中没有类的概念,最相近的思路是创建一个自定义的类型:首先创建一个构造函数,然后定义另一个方法并赋值给构造函数的原型。

<script>
	function Person(name){
      this.name = name;
    }
    Person.prototype.sayName = function(){
      console.log(this.name);
    }
    var person = new Person('galaxy');
    person.sayName()
	</script>

这段代码中Person是一个构造函数,其执行后创建一个名为name的属性,给Person的原型添加了一个sayName的方法,所以Person对象的所有实例都将共享这个方法。
以上这种写法跟面向对象语言差异比较大,ES6提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES6的class可以看作只是一个语法糖,它的绝大部分功能,ES5都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。

<script>
    class Person{
      constructor(name){
        // 等价于Person构造函数
        this.name = name;
      }
      // 等价于Person.prototype.sayName
      sayName(){
        console.log(this.name);
      }
    }
    let person = new Person('galaxy');
    person.sayName();
    console.log(typeof Person);
</script>

这里通过 constructor方法名来定义构造函数,这里typeof Person最终返回的结果是‘function’,所以Person声明实际上创建了一个具有构造函数方法行为的函数。实例中的sayName方法实际上是Person.prototype上的一个方法。

2.类与自定义类型

差异

  1. 函数声明可以提升,而类声明与let声明类似,不能被提升
  2. 在自定义类型中,需要通过Object.defineProperty()方法手工指定某个方法不可枚举,但是在类中,所有的方法都是不可以枚举的。
  3. 每个类都有一个名为[[Construct]]的内部方法,通过关键字new调用那些不含[[Construct]]的方法会导致程序抛出错误
3.常量类名

类的名称只在类中为常量,所以不能在类的方法中修改类名,但是可以在外部修改

	<script>
		class Foo{
      constructor(){
        Foo = 'bar'  //执行报错
      }
    }
    Foo = 'bar'; //修改成功
	</script>
4.类表达式

类和函数都存在两种形式,声明形式和表达式形式。

<script>
		let Person = class{
      //等价于Person构造函数
      constructor(name){
        this.name = name;
      }
      sayName(){
        console.log(this.name);
      }
    }
    let person = new Person('galaxy');
    person.sayName();
	</script>
5.命名类表达式

类和函数一样都可以定义为命名表达式

	<script>
		let Person = class Person1{
      //等价于Person构造函数
      constructor(name){
        this.name = name;
      }
      sayName(){
        console.log(this.name);
      }
    }
   	console.log(typeof Person)  //function
   	console.log(typeof Person1) // undefined
	</script>

类表达式被命名为Person1,由于标识符Person1只存在于类定义中,因此只能被用在类内部,比如sayName这样的方法中。这个类的名字是Person而不是Person1,Person1只在Class的内部代码可用,指代当前类。

6.静态成员

在ECMAScript5中,直接将方法添加到构造函数中来模拟静态成员

<script>
		function Person(name){
      this.name = name;
    }
    // 静态方法
    Person.create = function(name){
      return new Person(name);
    }
    // 实例方法
    Person.prototype.sayName = function(){
      console.log(this.name);
    }
    var person = Person.create('galaxy');
    person.sayName();
	</script>

ES6中

	<script>
		class Person{
      constructor(name){
        this.name = name;
      }
      static sayName(){
        console.log(this.name);
      }
    }
    let person = new Person()
    person.sayName(); //typeError: person.sayName is not a function
	</script>

类的sayName方法前有static关键字,表明该方法是一个静态方法,可以直接在Person类上调用(Person.sayName()),而不是在Person类的实例上调用。如果在实例上调用静态方法,会抛出一个错误,表示不存在该方法。
不可在实例中访问静态成员,必须要直接在类中访问静态成员

7.类的继承

ECMAScript5中中实现继承

	<script>
    function Rectangle(length,width){
      this.length = length;
      this.width = width;
    }
    Rectangle.prototype.getArea = function(){
      return this.length * this.width
    }
    function Square(length){
      Rectangle.call(this,length,length);
    }
    Square.prototype = new Rectangle();
    Square.prototype.constructor = Square;
    const square = new Square(3);
    
    console.log(square.getArea(3))
	</script>

ES6中 Class之间可以通过extends关键字实现继承

	<script>
		class Rectangle{
	      constructor(length,width){
	        this.length = length;
	        this.width = width;
	      }
	      getArea(){
	        return this.length * this.width
	      }
	    }
	    class Square extends Rectangle{
	      constructor(length){
	      // 等价于Rectangle.call(this,length,length)
	        super(length,length);
	      }
	    }
	    var square = new Square(3);
	    console.log(square.getArea())
	</script>

实质是先创造父类的实例对象this(所以必须先调用super方法),然后再用子类的构造函数修改this。
在子类的构造函数中,只有调用super之后,才可以使用this关键字。这是因为子类实例的构建,是基于对父类实例加工,只有super方法才能返回父类实例。

8.子类对父类方法的重写
<script>
    class Phone{
      // 构造方法
      constructor(brand,price){
        this.brand = brand;
        this.price = price;
      }
      // 父类的成员属性
      call(){
        console.log('我可以打电话')
      }
    }
    class SmartPhone extends Phone{
      // 构造方法
      constructor(brand,price,color,size){
        super(brand,price);  // Phone.call
        this.color = color;
        this.size =size;
      }
      photo(){
        console.log('拍照')
      }
      playGame(){
        console.log('玩游戏')
      }
      call(){
        console.log('wokeyishi')
      }
    }
    const xiaomi = new SmartPhone('xiaomi',7999,'red','4.7');
    console.log(xiaomi);
    xiaomi.call();
  </script>
9.Class的取值函数(getter)和存值函数(setter)

Class内部可以使用get和set关键字,对某个属性设置存值函数和取值函数.

<script>
    // get set
    class Phone{
      // 获取属性
      get price(){
        console.log('价格属性被读取了');
        return 'ilive'
      }
      // 设置属性
      set price(newVal){
        console.log('价格属性被修改了')
      }
    }
    let s = new Phone();
    // console.log(s.price)
    s.price = 'free';
    console.log(s.price)
  </script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值