class 语法
JS语言的传统方法是通过构造函数,定义并生成新对象,是一种基于原型的面向对象系统。
首先我们回顾一下ES5中的面向对象系统
// 现在我们声明一个构造函数,函数里面传入两个参数a和b,
const Miaov = function (a, b){
this.a = a;
this.b = b;
return this;
};
// 给这个函数指定一个prototype,也就是它的原型等于一个对象,
Miaov.prototype = {
// 在对象当中写一个constructor属性来修正一下指向
constructor: Miaov,
// 写一个方法对应一个函数,
print: function (){
// 在函数内我们打印出this.a和this.b
console.log(this.a + ' ' + this.b);
}
};
const miaov = new Miaov('hello', 'world').print();
这样我们一个构造函数就写完了
// 接下来我们再来声明一个常量,在实例化的时候我们指定两个参数
// 由于这个返回值就是实例化的对象,所以可以.print(),找到它原型上的print()方法.
const miaov = new Miaov('hello', 'world').print(); //这个时候控制台就打印出了hello world。
以上就是ES5中基于原型的面向对象系统。
这种写法跟传统的面向对象语言(比如C++和Java)差异很大,很容易让新学习这门语言的人感到困惑。
所以,在ES6中新增加了类的概念,可以使用 class 关键字声明一个类,之后以这个类来实例化对象。
那么接下来我们就使用class来改写一下上面的类’
class Miaov {
// 需要通过constructor来指定构造函数
// 在这里构造函数不使用function,而使用constrution(){}
// 小括号中写出构造函数的参数
constructor(a, b){
this.a = a;
this.b = b;
return this;
}
// 当指定原型上的方法时,不在需要在原型prototype上指定了.而是直接在下面写就可以了.
// 这里我们写一个print()方法,
// 这里的方法依然和构造函数是一样的不用写function
// 后面写上一个小括号和大括号
print(){
console.log(this.a + ' ' + this.b);
}
};
这样就定义好了一个类
// 接下来我们声明一个Miaov这个类,在实例化对象的时候,
// 依然可以直接指定其参数
const miaov = new Miaov('hello', 'world').print();打印出来依然是hello world
console.log(typeof Miaov);//function 我们发现它的类型依然是函数,只是换了种写法
下面我们详细的聊一下class的相关语法
1 Miaov中的constructor方法是构造方法,this关键字则代表实例对象。也就是说,ES5的构造函数Miaov,对应ES6的Miaov这个类的构造方法。
2 Miaov这个类除了构造方法,还定义了一个print方法。注意,定义“类”的方法的时候,前面不需要加上function这个关键字,直接把函数定义放进去了就可以了。另外,方法之间不需要逗号分隔,加了会报错。
3 构造函数的prototype属性,在ES6的“类”上面继续存在。而且类的所有方法都定义在类的prototype属性上面。
console.log(Miaov.prototype);
4 定义在类中的方法都是不可以枚举的。
// 我们尝试遍历一下Miaov.prototype下的所有的key
console.log(Object.keys(Miaov.prototype));
// 我们发现打印出来是一个空数组,而Miaov这个类上面明明有print()这个方法,但是并没有被打印出来,这就很好的说明了定义在类中的方法都是不可以被枚举的
5 constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。
举个例子
// 我们声明一个类,叫做P,里面什么都不写
class P {};
// 声明一个常量p
const p = new P();
// 接着我们打印一下这个p
console.log(p); // 可以发现p这个对象依然可以被正确的创建出来
原因就是constructor方法被默认添加到类当中了
6 生成类的实例对象的写法,与ES5完全一样,也是使用new命令。如果忘记加上new,像函数那样调用Class,将会报错。
P(); //报错
但是如果是ES5的构造函数,可以像普通函数一样调用,就不会报错了.