ES6中的class是一个基于prototype继承的语法糖,它提供了更接近传统语言的写法,引入了class(类)这个概念作为对象的模版。通过class关键字可以定义类,但是通过class做的工作,es5也可以做到,只是通过class,可以使我们的工作更加方便。
在我们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);
但当我们学完ES6class命令后可以把上述代码换成下面这种
class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + this.x + ', ' + this.y + ')'; } }
//等同于,ES5写法
Point。prototype={
constructor(){},
toString(){},
}
//注:类的所有方法都定义在类的prototype
属性上面。
新的class
写法让对象原型的写法更加清晰、更像面向对象编程的语法。另外class的函数声明没有函数声明提升。
一、类的创建与实例化
constructor
方法是类的默认方法,通过new
命令生成对象实例时,自动调用该方法。一个类必须有constructor
方法,如果没有显式定义,一个空的constructor
方法会被默认添加。
class Star{ constructor(uname,age){ this.uname=uname;//this.uname指向创建的实例 this.age=age;
this.btn=document.querySelector('button');
this.btn.onclick=this.say;
// this.btn.onclick=this.say();代表立即调用
}
say(){
console.log(this.uname);//undefined.因为this指向btn
} } var ldh=new Star('刘德华',18); console.log(ldh);
值得注意的几点:
1. 通过class关键字创建类,类名我们还是习惯性定义首字母大写
2. 类里面的constructor函数,可以接受传递过来的参数,同时返回实例对象
3. constructor 函数只要new生成实例时,就会自动调用这个函数,如果不写也会自动调用
4. 创建类,类名后面不加小括号;生成实例,类后面加小括号,构造函数不需要加function
5. 类没有变量提升,所以必须先定义类,才能通过类实例化对象;
6. 类里面的共有的属性和方法一定要加this使用
二、类中添加共有方法
class Polygon { constructor(height, width) { this.height = height; this.width = width; } get area() { return this.calcArea(); } calcArea() { return this.height * this.width; } } const square = new Polygon(20, 20); const sss = new Polygon(10,250); console.log(square._proto_ === sss._proto_); //true console.log(square.area); //400 console.log(sss.area); //2500
值得注意的是:
1. 我们类里面所有的函数不需要写function
2. 多个函数之间不需要添加逗号隔开
3. 实例的属性除非显示定义在其本身(即this对象)上,否则都是定义在原型上的。
三、类的继承
类相当于实例的原型,所有在类中定义的方法,都会被实例继承。通过extends实现。
基本语句格式:
class Father{
//...
}
class Son extends Father{
}
下面用一简单的例子加深了解
//案例一
class Father{ constructor (){ } say(){ return '我是爸爸'; } } class Son extends Father{ say(){
console.log('我是儿子');
} } var son=new Son(); son.say();//我是儿子
//案例二 通过super关键字访问和调用对象父类上的函数,可以调用父类的构造函数,也可以调用父类的普通函数
class Father{
constructor (x,y){
this.x=x;
this.y=y
}
sum(){
console.log(this.x+this.y);
}
}
class Son extends Father{
constructor(x,y){
super (x,y);//调用了父类中构造函数
}
}
var son=new Son(1,2);
son.sum();
//案例三 子类继承父类方法,同时还拓展自己的方法
class Father{
constructor (x,y){
this.x=x;
this.y=y
}
sum(){
console.log(this.x+this.y);
}
}
class Son extends Father{
constructor(x,y){
super (x,y);//调用了父类中构造函数
//super 必须在子类this之前调用
this.x=x;
this.y=y;
}
subtract(){
console.log(this.x - this.y);
}
}
var son=new Son(5,2);
son.subtract();
son.sum();
//son(5,2)先将参数传给子类的构造函数,先弄自身减法,再通过super传给父类的构造函数,实现继承的方法
注:
1.子类必须在constructor方法中调用super方法。否则新建实例时会报错。
2.子类在构造函数中使用super,必须放到this前面
四、类里面this指向问题
1.在constructor 里面的this 指向的是 创建的实例对象
2.函数方法里面的this指向调用者
验证如下
var that;
var that2;
class Star{
constructor(uname){
that=this;
}
dance(){
that2=this;
console.log(this);
}
}
var zxy=new Star('张学友');
console.log(that ===zxy);//true
zxy.dance();
console.log(that2 ===zxy);//true