ECMAScript6之Class

1、Class的基本语法

1、1简介

  基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已

1、2静态方法

  类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。

class Foo {
  static classMethod() {
    return 'hello';
  }
}
Foo.classMethod()
// 'hello'
var foo = new Foo(); foo.classMethod() // TypeError: foo.classMethod is not a function

注意,如果静态方法包含this关键字,这个this指的是类,而不是实例

class Foo {
  static bar() {
    this.baz();
  }
  static baz() {
    console.log('hello');
  }
  baz() {
    console.log('world');
  }
}

Foo.bar() // hello

虽然既然类的静态方法不可被实例所继承,但是却可以被子类继承,不赘述。

1、2实例属性

  实例属性除了定义在constructor()方法里面的this上面,也可以定义在类的最顶层。写法对比:

//实例属性this._count定义在constructor()方法里面
class IncreasingCounter {
  constructor() {
    this._count = 0;
  }
  get value() {
    console.log('Getting the current value!');
    return this._count;
  }
  increment() {
    this._count++;
  }
}
//属性定义在类的最顶层,其它不变
class IncreasingCounter {
  _count = 0;
  get value() {
    console.log('Getting the current value!');
    return this._count;
  }
  increment() {
    this._count++;
  }
}

  这种新写法的好处是,所有实例对象自身的属性都定义在类的头部,看上去比较整齐,一眼就能看出这个类有哪些实例属性。

1、3静态属性

  静态属性指的是 Class 本身的属性,即Class.propName,而不是定义在实例对象(this)上的属性。

class Foo {
}

Foo.prop = 1;
Foo.prop // 1

  目前,只有这种写法可行,因为 ES6 明确规定,Class 内部只有静态方法,没有静态属性。现在有一个提案提供了类的静态属性,写法是在实例属性法的前面,加上static关键字。

// 老写法
class Foo {
  // ...
}
Foo.prop = 1;

// 新写法
class Foo {
  static prop = 1;
}

1、4构造方法

  一个类必须要有 constructor 方法,如果没有显示定义,一个空的 constructor 方法会被默认添加

class Animal { }
// 等同于
class Animal {
  constructor() {}
}

上面代码中,定义了一个空的类Animal,JavaScript 引擎会自动为它添加一个空的constructor()方法。

constructor()方法默认返回实例对象(即this),完全可以指定返回另外一个对象。

class Foo {
constructor() {
return Object.create(null);
  }
}
new Foo() instanceof Foo
// false

上面代码中,ES6constructor()方法返回一个全新的对象,结果导致实例对象不是Foo类的实例。

类必须使用new调用,否则会报错。这是它跟普通构造函数的一个主要区别,后者不用new也可以执行。

class Foo {
constructor() {
return Object.create(null);
  }
}
Foo()
// TypeError: Class constructor Foo cannot be invoked without 'new'

2、Class的继承

2、1简介

  Class 可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多。

  • 子类必须在constructor方法中调用super方法,否则新建实例时会报错
class ColorPoint extends Point {
  constructor(x, y, color) {
    super(x, y); // 调用父类的constructor(x, y)
    this.color = color;
  }

  toString() {
    return this.color + ' ' + super.toString(); // 调用父类的toString()
  }
}

  这是因为子类自己的this对象,必须通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后对其加工,加上子类自己的实例属性和方法,如果不调用super方法,子类就得不到this对象。

  • 父类的静态方法,也会被子类继承
class A {
  static hello() {
    console.log('hello world');
  }
}

class B extends A {
}

B.hello()  // hello world

  hello()是A类的静态方法,B继承A,业绩承了A的静态方法。

2、2super关键字

  super这个关键字,既可以当作函数使用,也可以当作对象使用。在这两种情况下,它的用法完全不同.
  1. 当做函数使用
class parent {
    constructor() {
        console.log(11)
    }
}
class child extends parent{
    constructor() {
        super();
    }
}
let c = new child();//打印11

  当做函数使用时,super()调用会生成一个空对象,作为context来调用父类的constructor,返回this对象,作为子类constructor的context继续调用构造函数。

  2.  当做对象使用

const proto = {
  foo: 'hello'
};
const obj = {
  foo: 'world',
  find() {
    return super.foo;
  }
};
Object.setPrototypeOf(obj, proto);
obj.find() // "hello"

  上面代码中,对象obj.find()方法之中,通过super.foo引用了原型对象proto的foo属性。

 

2、3this关键字

JavaScripte中的this可以是全局对象、当前对象或者任意对象,这完全取决于函数的调用方式

  • this关键字最终指向的是调用它的对象
function GetThis(){
    console.log(this);
};
GetThis();//打印出window对象

  最后的调用我们也可以写成window.GetThis();调用他的就是window对象。其实window.可以省略不写。

var getThis={ 
    user:'me',
    fn:function(){
        console.log(this);
    }
}
getThis.fn();//打印的就时getThis对象

 

this含义如此之多的原因


 

    JavaScripte中的函数既可以被当作普通函数执行,也可以作为对象的方法执行。一个函数被执行时,会创建一个执行环境(ExecutionContext),函数的所有的行为均发生在此执行环境中,构建 改执行环境时,JavaScript首先会创建argument变量,其中包含调用函数时传入的参数。接下来创建作用域链。然后初始化变量,首先初始化 函数的形参表,值为argument变量中对应的值,如果argument变量中没有对应值,则该形参初始化为undefined。如果该函数中有内部函数,则初始化这些内部函数。如果没有,继续初始化改函数内定义的局部变量,需要注意的是此时这些变量初始化为undefined,其复制操作在执行环境创建成功后,函数执行时才会执行。最后为this变量赋值,如前所述,会根据函数调用方式的不同,付给this全局对象,当前对象,至此,函数的执行环境创建成功,函数开始执行,所需变量均从之前构建好的执行环境中读取。



posted @ 2019-12-18 19:34  林小冉  阅读(488)  评论(1编辑  收藏  举报