您的位置:首页 > 其它

ES6 —(Class 的基本语法)

2017-08-23 20:39 204 查看

1、简介

  JavaScript 生成实例对象的传统方法是通过构造函数。

function Point(x, y){
this.x = x;
this.y = y;
}
Point.prototype.toString = function(){
return '(' + this.x + ', ' + this.y + ')';
}
var p = new Point(1, 2);


  ES6 引入了 Class(类)这个概念,作为对象的模板。通过
class
关键字,可以定义类。

class PointClass{
constructor(x, y){
this.x = x;
this.y = y;
}
toString(){
return '(' + this.x + ', ' + this.y + ')';
}
}
var pc = new PointClass(1, 2);


  上述代码,可以看出,ES5 的构造函数
Point
,对应 ES6 的
Point
类的构造方法。 ES6 的
class
可以看做是一个语法糖,新的
class
写法只是让对象原型的写法更加清晰,更像面向对象编程的语法而已。

注意:

  (1)class 中定义方法的时候,前面不需要加
function
这个关键字。并且方法之间不需要逗号分隔,加了会报错。

  (2)类的数据类型是函数,函数本身就指向构造函数,即 ES6 的类,完全可以看做是构造函数的另一种写法。

typeof PointClass => function
PointClass === PointClass.prototype.constructor => true


  (3)类的所有方法都定义在类的
prototype
属性上面。(构造函数的
prototype
)。

  (4)类的实例上面调用方法,其实就是调用原型上的方法。

pc.constructor === PointClass.prototype.constructor => true


  (5)类的内部所有定义的方法,都是不可枚举。这一点与 ES5 不一致。

Object.keys(PointClass.prototype);  => [] // 空
Object.getOwnPropertyNames(PointClass.prototype);
=> ["constructor", "toString"]

Object.keys(Point.prototype); => ["toString"]
Object.getOwnPropertyName(Point.prototype);
=> ["constructor", "toString"]


  (6)类的属性名,可以采用表达式。使用表达式时要用中括号(
[]
)括起来。

  (7)类和模块的内部,默认就是严格模式,所以不需要使用
use strict
指定运行模式。 只要你的代码写在类或模块中,就只有严格模式可用。

  (8)类必须使用
new
调用,否则会报错。

  (9)与 ES5 一样,实例的属性除非显式定义在其本身(即定义在
this
对象上),否则都定义在原型上(即定义在 class 上)。

  (10)与函数一样,类也可以使用表达式的形式定义。采用 Class 表达式,可以写出立即执行的 Class 。

const Myclass = class Me{} // 这个类的名字是 MyClass 而不是 Me,
// Me 只在 Class 的内部代码可用,指代当前类
const Myclass = class {}() // 立即执行的 Class


  (11)类不存在变量提升,所以必须先定义,后使用。

2、constructor 方法

  constructor 方法是类的默认方法,通过
new
命令生成对象实例时,自动调用该方法。一个类必须有
constructor
方法,如果没有显示定义,一个空的
constructor
方法会被默认添加。

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

3、私有方法

  私有方法是常见需求,但 ES6 不提供,只能通过变量方法模拟实现。

  一种做法是在命名上加以区别,在私有方法前加下划线(如
_foo(){}
)。但是这种方法不保险,在类的外部还是可以调用到这个方法。

  另一种方法就是将私有方法移除模块,因为模块内部的所有方法都是对外可见的。

class Myclass {
foo(baz){
bar.call(this, baz);
}
}
function bar(baz){
return this.snaf = baz;
}


上述方法, foo 是共有方法,内部调用了 bar, 这使得 bar 实际上成为了当前模块的私有方法。

  还有一种方法是利用
Symbol
值的唯一特性,将私有方法的名字命名为一个 Symbol 值。

4、私有属性

  与私有方法一样, ES6 不支持私有属性。目前,有一个提案,为 class 加了私有属性。方法是在属性名之前,使用 # 表示。

5、this 的指向

  类的方法内部如果含有
this
,它默认指向类的实例。

  需要注意的是,一旦单独使用了含有
this
的方法很可能会报错,因为单独使用时,
this
会指向该方法的运行时所在的环境,这将导致属性或方法不存在而导致报错。

解决单独使用含有
this
的方法报错的方式


  (1)在构造函数中绑定
this
, 这样就不会找不到属性或方法。

constructor(){
this.foo = this.foo.bind(this);
}


  (2)使用箭头函数

constructor(){
this.foo = (x) => {this.x = x};
}


  (3)使用 Poxy , 获取方法的时候,自动绑定
this


6、Class 的取值函数(getter)和存值函数(setter)

  与 ES5 一样,在类的内部可以使用 get 和 set 关键字,对某个属性设置存值和取值函数,拦截该属性的存取行为。存值函数和取值函数是设置在属性的 Descriptor 对象上。

class MyClass {
get prop(){}
set prop(value){}
}
let my = new MyClass();
my.prop = 123; => 执行 setter 方法
my.prop; => 执行 getter 方法
var descriptor = Object.getOwnProperDescriptor(MyClass, "prop");
"get" in descriptor; => true
"set" in descriptor; => true


7、Class 的静态方法和 Class 的静态属性

(1)Class 的静态方法

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

注意:

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

  2)父类的静态方法,可以被子类继承。

  3)静态方法可以使用 super 对象调用。

(2)Class 的静态属性

  类的静态属性指的是 Class 本身的属性,即 Class.propName ,而不是在实例对象(this)上的属性。目前只有一种定义静态属性的方法:

class Foo{}
Foo.prop = 1;
Foo.prop;


8、new.target 属性

  new 是从构造函数生成实例的命令。 ES6 为 new 命令引入了一个 new.target 属性,该属性一般用在构造函数之中,返回 new 命令作用于那个构造函数。如果构造函数不是通过 new 命令调用的, new.target 会返回 undefined ,因此可以用这个属性来确定构造函数是怎么调用的。

注意:

  1)Class 内部调用 new.target, 返回当前 Class。

  2)ES5 的构造函数中调用 new.target 返回当前构造函数

  3)子类继承父类时,通过子类调用父类,父类中的 new.target 会返回子类。

class Shape {
constructor() {
if (new.target === Shape) { // (1)
throw new Error('本类不能实例化');
}
}
}

class Rectangle extends Shape {
constructor(length, width) {
super();
// ...
}
}

var x = new Shape();  // (1)处为 true 所以报错
var y = new Rectangle(3, 4);  // (1)处为 false 不报错 因为此时new.target === Rectangle


  4)在函数外部,使用 new.target 会报错。

用途 通过该属性可以定义构造函数或者类只能通过 new 来实例,或者可以写出不能独立使用,必须继承后才能使用的类。 参照注意(3)。

阮一峰:ECMAScript 6入门
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: