Javascript面向对象(八)——Class

Javascript面向对象(八)——Class

类结构允许使用简洁、漂亮的方式定义基于原型的类模式。

class语法

类的语法有多种形式,我们从简单的开始。
这里是基于原型的类User:

function User(name) {
  this.name = name;
}

User.prototype.sayHi = function() {
  alert(this.name);
}

let user = new User("John");
user.sayHi();

然后,我们同样使用类的语法:

class User {

  constructor(name) {
    this.name = name;
  }

  sayHi() {
    alert(this.name);
  }

}

let user = new User("John");
user.sayHi();

很容易看到两个示例相似。那么class到底做了什么?我们可能认为这定义了新语言级的实体,但并非如此。
class User {…}确切地说做了两件事:
1、声明了变量User,其引用constructor函数。
2、把定义的方法放入User.prototype,这里包括sayHi和constructor。

下面这段代码进行检测:
class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}

// proof: User is the "constructor" function
alert(User == User.prototype.constructor); // true

// proof: there are two methods in its "prototype"
alert(Object.getOwnPropertyNames(User.prototype)); // constructor, sayHi

User类的图示如下:

所以class是定义构造函数和原型方法的特定语法。但不仅如此,有一些差别用来确保用法正确。
举例,constructor不能不使用new调用:

class User {
  constructor() {}
}

alert(typeof User); // function
User(); // Error: Class constructor User cannot be invoked without 'new'

输出类
如果输出类,如alert(User),一些引擎显示”class User”,而另一些显示”function User…”。
这里不要困惑,字符串显示可能不同,其实仍然是函数,在javascript语言中没有单独class实体。

类方法是非枚举的
类定义对所有原型中的方法设置enumerable标志为false,这时好事,因为如果我们使用for…in遍历对象,我们通常不想得到class方法。

如果没有构造函数怎么样?
如果在class结构没有构造函数,那么一个空的构造函数自动生成,写法如:constructor(){}。

class总是使用严格模式
所有在class结构的代码自动使用严格模式。

getter/setter

类也可以包括getter/setter,这里示例使用user.name,实现代码:

class User {

  constructor(name) {
    // invokes the setter
    this.name = name;
  }

  get name() {
    return this._name;
  }

  set name(value) {
    if (value.length < 4) {
      alert("Name too short.");
      return;
    }
    this._name = value;
  }

}

let user = new User("John");
alert(user.name); // John

user = new User(""); // Name too short.

只有方法

与对象定义不同,类定义代码不能有属性:值方式赋值。只能有方法(方法间没有逗号分割)和getter/setter。

根据这个思想:类中定义的所有内容都是在原型中定义,因为原型应该只存储方法,其在对象之间共享。数据是描述具体对象的状态,应该存储在各自对象中。

如果我们真坚持方非函数值至原型中,那么class无法做到。只能手工修改原型,如下:

class User { }

User.prototype.test = 5;

alert( new User().test ); // 5

虽然技术上可行,但我们应该知道我们为什么要做。使用getter的替代方式:

class User {
  get test() {
    return 5;
  }
}

alert( new User().test ); // 5

从外部代码看是一样的,但通过getter方式应该慢点。

Class 表达式

和函数一样,类能够定义在另一个表达式内部,用于传递、返回等。这里是一个返回类的函数(类工厂):

function getClass(phrase) {
  return class {
    sayHi() {
      alert(phrase);
    };
  };
}

let User = getClass("Hello");

new User().sayHi(); // Hello

如果还记得class就是函数原型模式定义的特殊形式,就会觉得这很正常。
如命名函数表达式一样,class也可以有一个名称,只能在class定义内部可见。

let User = class MyClass {
  sayHi() {
    alert(MyClass);
  }
};

new User().sayHi(); // works, shows MyClass definition

alert(MyClass); // error, MyClass is only visible in methods of the class

静态方法

静态方法与类函数绑定,而不是原型。且可以使用this关键字(this代表类,java是不能使用的),示例:

class User {
  static staticMethod() {
    alert(this == User);
  }
}

User.staticMethod(); // true

在User.staticMethod()方法内部的this值为类User的构造器自身(点前面对象的规则)。
通常static方法用来表达与类相关的功能,不是类的特定对象。
举例,我们有Article对象,并需要一个比较函数,那自然的选择应该是Article.compare,如下:

class Article {
  constructor(title, date) {
    this.title = title;
    this.date = date;
  }

  static compare(articleA, articleB) {
    return articleA.date - articleB.date;
  }
}

// usage
let articles = [
  new Article("Mind", new Date(2016, 1, 1)),
  new Article("Body", new Date(2016, 0, 1)),
  new Article("JavaScript", new Date(2016, 11, 1))
];

articles.sort(Article.compare);

alert( articles[0].title ); // Body

这里的Article.compare是在所有articles对象之上的,意味这比较他们。

另一个示例被称为工厂方法,使用特定的参数创建一个对象,如Article.createTodays():

class Article {
  constructor(title, date) {
    this.title = title;
    this.date = date;
  }

  static createTodays() {
    // remember, this = Article
    return new this("Todays digest", new Date());
  }
}

let article = article.createTodays();

alert( articles.title ); // Todays digest

现在,我们每次需要一个“当天摘要”对象,我们直接调用Article.createTodays()
静态方法用于数据库相关的类,用于从数据库中查询/保存/删除实体,代码示例:
// assuming Article is a special class for managing articles
// static method to remove the article:
Article.remove({id: 12345});

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值