ES6-终于有了Class

Javascript最开始被设计出来,是为了解决一些Web上的简单交互的,但随着网络的发展,要解决的问题越来越复杂,在JS编程中,代码总是显得怪里怪气,不过好在在ES6中,增加了Class语法,虽然它本质上属于语法糖,但是至少JS像是真正的面向对象语言了。
在阅读本篇之前,希望能先阅读一下关于JS构造函数和继承相关的文章。

Class基础语法

1、通过class关键字,可以定义类。
2、每个类中必须包含构造方法(constructor方法),构造方法对应的就是es5中的构造函数,如果没有显示声明constructor方法,JS会自动添加一个空的constructor方法。
3、类中的this关键字则代表实例对象。
4、同构造函数一样使用new关键字实例化一个对象,且必须使用new关键字
5、类内部定义的方法,前面不用加function,后面不可以加逗号 ,方法会自动定义在类的prototype属性中。

class Spanner {
  constructor(material) {
    this.material = material;
  };
  aboutMaterial() {
    console.log(`这是一个${this.material}${Spanner.name}`);
  };
};
console.log(new Spanner('铁'));

ES6-终于有了Class_第1张图片
Spanner 类翻译成ES5是这样的

var Spanner = function () {
    function Spanner(material) {
      _classCallCheck(this, Spanner);
      this.material = material;
    }
    _createClass(Spanner, [{
      key: 'aboutMaterial',
      value: function aboutMaterial() {
        console.log('这是一个' + this.material + Spanner.name);
      }
    }]);
    return Spanner;
  }();

这里省略了两个函数_classCallCheck和_createClass,

  • _classCallCheck函数是为了防止构造函数被当做普通函数执行,只有对象是类的实例才可以继续执行。
    下面的写法都会抛出错误
Spanner('铁');
Spanner.call({},'铁');
  • _createClass函数用于把类中定义的方法拷贝到构造函数的原型上去,并且设置这些方法的属性为enumerable,不可枚举。

6、类的内部定义的所有方法都是不可枚举的
7、类的内部默认是严谨模式

Class中的属性详解

在Class基本语法中的内容是ES6中比较明确的内容,目前各浏览器对ES6的支持大不相同,而且ES的语法还在不断的变化中,下面的代码是在Chrome浏览器中测试过的,其他浏览器不一定适用。虽然如此,也不用过分担心浏览器的差异问题,以后我们用ES6基本会在框架中使用,相信会有很好的解决方案。

首先,参考class中定义方法的形式来定义一个属性,理所当然我认为该属性会成为一个原型属性

class Spanner {
  constructor(material) {
    this.material = material;
  };
  //定义一个属性
  productName='扳手';
  //定义一个方法
  aboutMaterial() {
    console.log(`这是一个${this.material}${Spanner.name}`);
  };
};
console.log(new Spanner('铁'));

ES6-终于有了Class_第2张图片
结果有点出乎意料,在firefox中根本不支持这种语法,实际上这是ES7的语法,Chrome中,productName成为了自有属性,在代码解析成ES6语法时,可以看到实际上是在构造函数的内部调用了一个函数_defineProperty,作用是将属性添加到对象中。
这样做的效果和在构造函数中用this直接定义是一样的,而效率更低,所以不建议这样做。

静态属性和静态方法

定义类的时候,如果需要静态方法,可以参考构造函数的方法,添加静态属性,这种方式和给函数添加静态属性是一样的。

方法1
class Spanner {
};
Spanner.width='10cm';
Spanner.operation=function () {
  return '静态方法被调用了';
}
console.log(Spanner.width); //10cm
console.log(Spanner.operation()); //静态方法被调用了
方法2

使用static关键字定义静态方法和静态属性,目前大部分浏览器不支持。

class Spanner {
    static width = '10cm';
    static operation = function () {
      return '静态方法被调用了';
    }
  };
  console.dir(Spanner);
  console.log(Spanner.width); //10cm
  console.log(Spanner.operation()); //静态方法被调用了

这个方法只是让class的封装更美好的语法糖,实际上和方法1是一样的,解析成
ES6是这样的:

class Spanner {}
_defineProperty(Spanner, "width", '10xm');
_defineProperty(Spanner, "operation", function () {
  return '静态方法被调用了';
});

私有属性和私有方法

在构造函数中可以定义私有的属性和方法,在class中要怎么处理呢?
答案是ES6中的classES6没有提供私有属性、私有方法的语法。
和从前一样,又要开始模拟了,下面介绍两个封装到class中的方法。
1、用命名方式来区别
用下划线表示私有属性和私有方法,这种写法只是一种约定,约定这种方式定义的是私有属性,不要用常规的方式调用。

class Spanner {
  constructor(material) {
    this.material = material;
    this.productName='扳手';
  };
  _privateV='私有属性';
  _privateF(){
    return '调用了私有方法'
  }
  publicF() {
    return this._privateF();
  };
};
let s=new Spanner('Fe');
console.log(s.publicF());   //调用了私有方法
console.log(s._privateF()); //调用了私有方法

2、在属性名之前,使用#表示

class Spanner {
  constructor(material) {
    this.material = material;
    this.productName='扳手';
  };
  #privateV='私有属性';
  #privateF(){
    return '调用了私有方法'
  }
};
console.log(new Spanner('Fe'));

这种写法目前还是一直提案,Chrome中支持#定义私有属性,不支持私有方法,关于私有属性的用法就先说到这里,等学习框架的时候还会遇到的。

你可能感兴趣的:(前端进阶之路,Javascript)