class是es6引入的最重要特性之一。在没有class之前,我们只能通过原型链来模拟类。

基本用法

如果你用过java这样的纯面向对象语言,那么你会对class的语法非常熟悉。

  1. class People {
  2. constructor(name) { //构造函数
  3. this.name = name;
  4. }
  5. sayName() {
  6. console.log(this.name);
  7. }
  8. }

上面定义了一个People类,他有一个属性 name 和一个方法 sayName(),还有一个构造函数; 
你可以这样使用这个类:

  1. var p = new People("Tom");
  2. p.sayName();

就像函数有函数声明和函数表达式两种定义方式,类也可以通过类表达式来定义:

  1. let People = class {
  2. constructor(name) { //构造函数
  3. this.name = name;
  4. }
  5. sayName() {
  6. console.log(this.name);
  7. }
  8. }

你可能以为类声明和类表达式的区别在于变量提升的不同。但是事实是无论是类声明还是类表达式的方式来定义,都不会有变量提升。所以下面的写法是错的:

  1. var p = new People("Tom"); //错误,People 未定义
  2. class People {
  3. //...
  4. };

类中的所有方法默认都是 strict mode,所以不用再次声明了。

继承

通过关键字 extends 来继承一个类,并且,可以通过 super 关键字来引用父类。

  1. class People {
  2. constructor(name) { //构造函数
  3. this.name = name;
  4. }
  5. sayName() {
  6. console.log(this.name);
  7. }
  8. }
  9.  
  10. class Student extends People {
  11. constructor(name, grade) { //构造函数
  12. super(name); //调用父类构造函数
  13. this.grade = grade;
  14. }
  15. sayGrade() {
  16. console.log(this.grade);
  17. }
  18. }

上面的例子中我们定义了一个 Student ,他是 People 的子类。

注意我们在 constructor 中是如何通过 super 调用父类的构造函数的。

getters & setters

现在我们可以通过 get 和 set 关键字来定义 getters 和 setters 了。

下面我们给 name 属性定义 getter 和 setter

  1. class People {
  2. constructor(name) { //构造函数
  3. this.name = name;
  4. }
  5. get name() {
  6. return this._name.toUpperCase();
  7. }
  8. set name(name) {
  9. this._name = name;
  10. }
  11. sayName() {
  12. console.log(this.name);
  13. }
  14. }
  15. var p = new People("tom");
  16. console.log(p.name); //TOM
  17. console.log(p._name); //tom
  18. p.sayName(); //TOM

仔细看上面的例子,搞清楚最后三行分别会输出什么,就明白getter 和 setter该怎么用了。

主要是要区分 this._name 和 this.name 的区别。因为我们定义了 name 的读写器,而没有定义 _name 的读写器,所以访问这两个属性的结果是不同的。

但是要注意一点,不要这样写:

  1. set name(name) {
  2. this.name = name;
  3. }

因为给 this.name 赋值的时候会调用 set name ,这样会导致无限递归直到栈溢出。

静态方法

通过 static 关键字定义静态方法:

  1. class People {
  2. constructor(name) { //构造函数
  3. this.name = name;
  4. }
  5. sayName() {
  6. console.log(this.name);
  7. }
  8. static formatName(name) {
  9. return name[0].toUpperCase() + name.sustr(1).toLowerCase();
  10. }
  11. }
  12.  
  13. console.log(People.formatName("tom"));

静态方法一般用来提供一些工具方法。

私有属性

很不幸的时ES6并没有提供对私有属性的语法支持,但是我们可以通过闭包来实现私有属性。

  1. var People = (function() {
  2. var p = new WeakMap();
  3. class People {
  4. constructor(name) { //构造函数
  5. var privateProperties = {
  6. name: name
  7. };
  8. p.set(this, privateProperties);
  9. }
  10. sayName() {
  11. console.log(this.name);
  12. }
  13.  
  14. get name() {
  15. return p.get(this).name;
  16. }
  17. }
  18. return People;
  19. })();
  20.  
  21. var p = new People("tom");
  22. console.log(p.name);
  23. p.sayName();
  24.  
  25. var p2 = new People("bob");
  26. console.log(p2.name);
  27. p2.sayName();
 

【es6】class的更多相关文章

  1. 【ES6】改变 JS 内置行为的代理与反射

    代理(Proxy)可以拦截并改变 JS 引擎的底层操作,如数据读取.属性定义.函数构造等一系列操作.ES6 通过对这些底层内置对象的代理陷阱和反射函数,让开发者能进一步接近 JS 引擎的能力. 一.代 ...

  2. 【ES6】更易于继承的类语法

    和其它面向对象编程语言一样,ES6 正式定义了 class 类以及 extend 继承语法糖,并且支持静态.派生.抽象.迭代.单例等,而且根据 ES6 的新特性衍生出很多有趣的用法. 一.类的基本定义 ...

  3. 【ES6】迭代器与可迭代对象

    ES6 新的数组方法.集合.for-of 循环.展开运算符(...)甚至异步编程都依赖于迭代器(Iterator )实现.本文会详解 ES6 的迭代器与生成器,并进一步挖掘可迭代对象的内部原理与使用方 ...

  4. 【ES6】数组的扩展——扩展运算符

    1.扩展运算符[三个点(...)将一个数组转为用逗号分隔的参数序列] 作用:用于函数调用 function add(x, y) { return x + y; } const numbers = [2 ...

  5. 【ES6】函数的扩展

    1.函数参数默认值[详情例子参照ESMAScript 6入门 (阮一峰)] 允许为函数的参数设置默认值,即直接写在参数定义的后面.[例子1] 参数变量是默认声明的,所以不能用let或const再次声明 ...

  6. 【ES6】数值的扩展

    1.Number.isFinite()和Number.isNaN()[只对数值有效] (1)Number.isFinite()用来检查一个数值是否为有限的(finite),即不是Infinity. [ ...

  7. 【ES6】Generator+Promise异步编程

    一.概念 首先我们要理解Generator和Promise的概念. Generator:意思是生成器,可以在函数内部通过yeild来控制语句的执行或暂停状态. *Foo(){ yeild consol ...

  8. 【ES6】import, require,export

    node编程中最重要的思想就是模块化,import和require都是被模块化所使用. 遵循规范 require 是 AMD规范引入方式 import是es6的一个语法标准,如果要兼容浏览器的话必须转 ...

  9. 【ES6】函数

    函数默认值问题 在ES6之前,不能直接为函数指定默认值,但是ES6允许为函数的参数设置默认值 之前实现方式 function log(x, y) { y = y || 'World'; console ...

  10. 【ES6】let 命令

    let命令 为es6新增命令,用来声明变量,类似于var,但是let所声明的变量,只在let命令所在的块级作用域内有效 块级作用域写法(ES6块级作用域允许任意嵌套): // 块级作用域写法 { le ...

随机推荐

  1. Proxy Hosted Virtual

    http://books.sonatype.com/nexus-book/reference/confignx-sect-manage-repo.html Public Repositories 对外 ...

  2. web service 架构

                                        Web services architecture The service provider sends a WSDL file ...

  3. noip第9课作业

    1.    打印乘法表 [问题描述] 用for循环实现输出1至9的乘法表 [样例输出] 1*1=1 1*2=2 2*2=4 1*3=3 2*3=6 3*3=9 1*4=4 2*4=8 3*4=12 4 ...

  4. 破解Oracle ERP密码

    前提:你有apps的数据库账户,想知道某个用户的密码,因为fnd_user中的密码为加密的,所以无法看懂,你可以尝试用下边的方式来查看用户密码. SQL> desc fnd_user; Name ...

  5. Toad 实现 SQL 优化

    It is very easy for us to implement sql tuning by toad.  We need to do is just give complex sql stat ...

  6. python 应用 base64、hmac、hashlib包实现:MD5编码 base64编码解码、SHA256编码、urlsafe_b64encode编码等等基本所有的加密签名的方法

    用python做HTTP接口自动化测试的时候,接口的很多参数是经过各种编码加密处理后在传到后台的,这里列举出python实现 应用 base64.hmac.hashlib包实现:md5编码 sha1编 ...

  7. Android实现带下划线的EditText(BUG修正)

    之前写了一个关于实现EditText显示下划线的例子,发现仍然存在一些问题,在此继续探索,原文链接:http://www.cnblogs.com/ayqy/p/3599414.html (零)另一个b ...

  8. LINQ to objects遇到的小坑

    1.C#中LINQ to Objects中延迟查询的陷阱(其他类型的LINQ也基本一致) 之前在不了解LINQ延迟查询的时候,我使用下面的这种方式,将where语句的结果直接as为List<T& ...

  9. ODP.NET 之 ExecuteNoQuery 执行 Merge into 返回值

    当执行Oracle.ManagedDataAccess.Client.OracleCommand.ExecuteNonQuery时,如果sql语句是 merge into ...,则返回值表现不稳定, ...

  10. 【UVA11107 训练指南】Life Forms【后缀数组】

    题意 输入n(n<=100)个字符串,每个字符串长度<=1000,你的任务是找出一个最长的字符串使得超过一半的字符串都包含这个字符串. 分析 训练指南上后缀数组的一道例题,据说很经典(估计 ...