我们常说JS类是一种语法糖,那么也就是说在实现同样功能的时候,使用类比使用构造函数等其他方法实现同样的功能会好很多,本质上来说,类就是一种函数,某些情况下它可以当成函数来使用。即如果只是了解其用法,并没有很多新的东西需要我们用大量时间去学习。
我们知道,类可以理解为,将某一类对象所共有的一些属性和方法放在一个类里面,当我们需要调用其共有的属性和方法的时候,我们可以直接在类里面取就可以了,这可以提高代码的复用率,让自己的代码更优雅一点。
接下来会对比说明类在使用的时候会有什么不一样的地方,即它的优点又在哪里。
规范
1. 类是抽象了对象的公共部分,泛指某一大类。对象特指某一个,通过类实例化一个具体的对象。
2. 书写规范
- 通过class关键字创建类,类名定义成首字母大写
- 类里面的函数不需要写function
- 多个函数之间不需要用逗号分割
3. 在ES6中没有变量提升,所以必须先定义类,才能通过类实例化对象。
4. 函数声明和类声明之间的一个重要区别在于,函数声明会提升,类声明不会。下面一段代码就很好的说明了两者的区别。
<script>
//不会报错
fn();
function fn(){
console.log(333);
}
</script>
<!-- 变量提升 -->
<script>
//报错
let obj=new Father('李白',22);
class Father{
constructor(name,age){
this.name=name;
this.age=age;
}
}
5. 类里面共有的属性和方法一定要加this使用。
类必须使用new实例化对象
<button>按钮</button>
<script>
class Father{
constructor(name,age){
this.name=name;
this.age=age;
//不加this会报错
this.btn=document.querySelector('button');
this.btn.onclick=this.sing;
}
sing(){
console.log(3333);
console.log(this);//指向button
}
}
let obj=new Father('杜甫',22);
</script>
类表达式
1.. 类表达式也可以定义类。类表达式可以命名或不命名。命名类表达式的名称是该类体的局部名称。
<script>
let p=class Father{
constructor(name,age){
this.name=name;
this.age=age;
}
sing(){
console.log(111);
}
}
let obj1=new p();
console.log(p.name);//Father
// console.log(p.sing());//报错
obj1.sing();//11
let p1=class {
constructor(name,age){
this.name=name;
this.age=age;
}
sing(){
console.log(111);
}
}
console.log(p1.name);//p1
//console.log(p1.sing());//报错
</script>
2. 如果想在类体内部也能引用这个类本身,那么你就可以使用命名类表达式,并且这个类名只能在类体内部访问。
<script>
let s=class Father{
sing(){
return Father.name;
}
}
let obj=new s();
console.log(obj.sing());//Father
console.log(s.name);//Father
console.log(Father.name);//报错
</script>
严格模式
1. 类声明和类表达式的主体都执行在严格模式下。
1)严格模式会将JavaScript陷阱直接变成明显的错误。
2)严格模式修正了一些引擎难以优化的错误。
3)同样的代码有些时候严格模式会比非严格模式下更快。
4)严格模式禁用了一些有可能在未来版本中定义的语法。
<script>
// class Father{
// constructor(name,age){
// this.name=name;
// this.age=age;
// }
// sing(){
// t=new String();//报错
// console.log(this);
// }
// }
// let obj=new Father('王勃',33);
// obj.sing();//Father {name: '王勃', age: 33}
//不会报错
function Fn(name){
this.name=name;
t=new String();
}
</script>
使用 ‘use strict’; 可以进入严格模式。
constructor
1. constructor()方法是类的构造方法(默认),用于传递参数,返回实例对象。
通过new命令生成对象实例时,自动调用该方法。如果没有显示定义,类的内部会自动为我们创建一个constructor()方法。
<script>
class Father{
constructor(name,age){
this.name=name;
this.age=age;
this.sing();
}
sing(){
console.log(5555);
}
}
let obj=new Father('李白',22);
//控制台会打印555,一旦new,构造函数就会自动执行
// obj.sing();//打印2次
</script>
2. constructor里面的this指向的是创建的实例对象。
3. 一个构造函数可以使用super关键字来调用一个父类的构造函数。
super
1. super关键字用于访问和调用对象父类上的函数。可以调用父类的构造函数,也可以调用父类的普通函数。
2. 就近原则
- 继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的方法。
- 继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法。
<script>
class Father{
sing(){
console.log('唱歌');
}
}
class Son extends Father{
sing(){
return super.sing();
}
}
let obj=new Son();
obj.sing();
3. 子类构造函数中使用super,必须放到this前面,即必须先调用构造方法,再使用子类的构造方法。
<script>
class Father{
constructor(name,age){
this.name=name;
this.age=age;
}
sing(){
console.log('唱歌');
}
}
class Son extends Father{
// constructor(sex){
// this.sex;
// }报错
// constructor(sex){
// super(name,age);
// }报错
constructor(name,age,sex){
super(name,age);
this.sex=sex;
}
sing(){
return super.sing();
}
}
let obj=new Son();
</script>
static
1. static只能通过类来访问。即static只能通过类自身来调用,不能通过类的实例来调用。
<script>
class Father{
constructor(name,age){
this.name=name;
this.age=age;
}
sing(){
console.log(this.name+'唱歌!');
}
static fb(){
console.log(this.name);
}
}
Father.song=function (){
console.log(this.name);
}
Father.prototype.fa=function (){
console.log(this.age);
}
console.log(typeof Father);//fucntion
let obj1=new Father('李白',33);
let obj2=new Father('杜甫',32);
obj1.sing();
obj2.sing();
console.log(obj1.sing===obj2.sing);//true
//obj1.song();//报错
obj2.fa();//32
// obj1.fb();//报错
Father.fb();//Father
Father.song();//Father
</script>
2. 静态方法调用同一个类中的其他静态方法,可使用 this 关键字。
3. 非静态方法中,不能直接使用 this 关键字来访问静态方法。而是要用类名来调用;或者用构造函数的属性来调用该方法。
<script>
class Father{
sing(){
return this.fa();
}报错
// sing(){
// return Father.fa();
// }
static fa(){
console.log(22);
}
}
let obj=new Father();
obj.sing();//22
</script>
extends
1. extends 关键字在 类声明 或 类表达式 中用于创建一个类作为另一个类的一个子类.
2. 子类中定义了构造函数,那么它必须先调用 super() 才能使用 this。
继承前面已有简单说明,这里我们看一下构造函数里面是怎样实现继承的,通过下面代码会发现使用类实现继承要好很多。
<script>
function Star(name,age){
this.name=name;
this.age=age;
}
Star.prototype.sing=function (){
console.log('唱歌');
}
function Son(name,age,sex){
Star.call(this,name,age);
this.sex=sex;
}
//属性的继承
let obj1=new Son('杜甫',22,'男');
console.log(obj1);
//方法的继承
Son.prototype=new Star();
let obj=new Son('李白',52,'男');
console.log(obj);
obj.sing();
</script>