在以前JS传统做法是当生成一个对象实例,需要先定义构造函数,然后通过prototype的方式来添加方法,在生成实例:
function Person(){
this.name = "测试";
this.age = 26;
}
Person.prototype.getName = function (){
console.log("name:"+this.name);
}
//得到一个学员信息对象
var p = new Person()
然而现在用ES6:
class Person{
constructor(name,age){
this.name = name;
this.age = age;
}
getName(){
return this.name;
}
}
var p=new Person("luoqiang",26)
其实class 说到底也是一种语法糖 比如在typeof Person //function 还是function 而不是class 还有Person === Person.prototype.constructor //true 也是相等的 在ES5中原本的构造函数被constructor替代了,本来需要定义在prototype上面的 方法直接定义在class里面即可,如果有接触过JAVA 或者Asp.NET 对于这种语法理解很有帮助.
class 继承
以前的继承方式其中一种:
function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype.getName = function (){
console.log("name:"+this.name);
}
function Student(stu_class,name,age){
Person.call(this,name,age);
this.stu_class=stu_class;
}
Student.prototype=new Person;
Student.prototype.constructor=Student;
Student.prototype.getClass=function(){
console.log("班级:"+this.stu_class)
}
//得到一个学员信息对象
var s = new Student()
采用class继承:
class Person{
constructor(name,age){
this.name = name;
this.age = age;
}
getName(){
return this.name;
}
}
class Student extends Person{
constructor(stu_class,name,age){
//需注意这个地方 如果一个子类继承了父类,那么必须在这个地方调用super 才能再constructor 使用this 否则会报 this is not defined
//但是在类其他方法定义里面还是会指向实例本身的
super(name,age);
}
getClass(){
console.log("班级:"+this.stu_class)
}
}
var p=new Person("luoqiang",26)
同时也可以也可以扩展传统的基于函数的“类”
function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype.getName = function (){
console.log("name:"+this.name);
}
class Student extends Person{
constructor(stu_class,name,age){
super(name,age);
}
getClass(){
console.log("班级:"+this.stu_class)
}
}
var p=new Person("luoqiang",26)
p.getName();
请注意,类不能继承
非可构造对象。如果要继承常规对象,可以改用Object.setPrototypeOf();
Class Getter/Setter
class Student {
constructor(){
this.linguistic=98;
this.math=84;
}
getClass(){
console.log("班级:"+this.stu_class)
}
get TotalPoints(){
return this.linguistic+this.math;
}
}
var p=new Student()
p.TotalPoints //182
Class 静态方法
static 关键字用来定义一个类的一个静态方法。调用静态方法不需要实例化该类,但不能通过一个类实例调用静态方法。静态方法通常用于为一个应用程序创建工具函数
在大多数情况下,只需要关心类的实例方法,但是同样也需要为类对象本身定义一些方法来满足一些特殊的需求.比如Array.isArray(),Object.key,Object.creatae 等
class Person{
constructor(name,age){
this.name = name;
this.age = age;
}
getName(){
return this.name;
}
static getEat(){
console.log(["香蕉","苹果"])
}
}
Person.getEat() //["香蕉","苹果"]
使用Class 需要注意些什么:
Class 定义方法是不能使用箭头函数
Class 也可以使用表达式方式声明
let Person=class{
constructor(name,age){
this.name = name;
this.age = age;
}
getName(){
return this.name;
}
}
//也可像方法一样有立即执行
const p = new class {
constructor(name,age){
console.log(name,age);
}
}("luoqiang",26) //p 获得一个实例对象
//注意: 类表达式也同样受到类声明中提到的提升问题的困扰。
//但是 定义类本身时不存在声明的提升 如:
new Person(); //错误,Person is not defined
class Person{...}
严格模式
类声明和类里定义的方法都执行在严格模式下。比如,构造函数,静态方法,原型方法,getter和setter都在严格模式下执行。
构造函数
constructor方法是一个特殊的方法,其用于创建和初始化使用class创建的一个对象。一个类只能拥有一个名为 “constructor”的特殊方法。如果类包含多个constructor的方法,则将抛出 一个SyntaxError 。
this的不确定性
当一个对象调用静态或原型方法时,如果该对象没有“this”值,那么“this”值在被调用的函数内部将为 undefined
而不是window 因为是在严格模式下执行
class Animal {
speak() {
return this;
}
static eat() {
return this;
}
}
let obj = new Animal();
obj.speak(); // Animal {}
let speak = obj.speak;
speak(); // undefined
Animal.eat() // class Animal
let eat = Animal.eat;
eat(); // undefined
使用 super 调用超类
可使用super 在子类直接调用父类方法,如在子类调用super.getName()
兼容性
参考:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes
《实战ES2015》