阅读 100

class的基本语法

js语言中,生成实例对象的传统方法就是通过构造函数: Es6 通过class (类)这个盖面,作为对象的模板,通过class,可以定义类。 新的class写法是一个语法糖,他绝大部分功能,es5都可以 看到,新的class写法智能让对象原型的写法更加清晰,更像面向对象变成语法而已。

  1. 例子
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);
p.toString();
//"(1,2)"

//改写class
 class Point{
     constructor(x,y){
         this.x=x;
         this.y=y;
     }
      toString () {
        return `( ${this.x}, ${this.y} )`;
       }
       toValue () {
        return this.x+this.y;
       }
 }

 var p = new Point(1,2);
p.toString();
//"(1,2)"
p.toValue();
//3
复制代码

定义了一个Point类,他里面有一个constructor方法,这就是构造方法;而this关键字母代表实例对象,也就是说Es5的构造函数Ponit对应Es6的Point类的构造方法,Point类除了构造方法,还定义了一个toString的方法,定义方法的时候前面不需要加Function这个关键字,直接将函数定义放进去,也不需要都好分隔。 构造函数的prototype属性,在es6的类上继续存在,实际上类的所有方法都定义在类的Prototype属性上面;

  1. 严格模式

在类和模块的内部默认就是严格模式 不需要指定运行模式

constructor 方法

constructor 方法是类的默认方法,通过new 命令生成实例时,自动调用该方法,一个类必须有constructor方法,如果没有显示定义,会被默认添加。

class A{

}
//等于
class A{
    constructor(){

    }
}
//定义一个空的类A JavaScript引擎会自动添加一个空的constructor方法
复制代码

constructor 方法默认的返回实例对象(this);完全可以指定返回另外一个对象。

class A {
    constructor(){
        return Object.create(null)
    }
}
new A() instanceof A

//false

//实例  instanceof 构造函数用来判断是否是构造函数的实例

复制代码
类的实例对象

生成实例对象的写法,与Es一样都是使用New命令,实例属性除非显示定义在其本身(既定义在this对象上),否则都是定义在原型上既:定义在class上。

class A{
    constructor(x,y){
        this.x=x
        this.y =y
    }
    toString(){
          return `( ${this.x}, ${this.y} )`;
    }
}
var B=new A(1,2)
A.toString();
A.hasOwnProperty(x)//true
A.hasOwnProperty(y)//true
A.hasOwnProperty('toString')//true
A.__proto__.hasOwnProperty('toString')//true
复制代码

xy都是实例对象A自身的属性 定义在this上,所以hasOwnProperty都会返回true 而toString是原型对象的属性,所以hasOwnProperty返回false。 和Es5保持一致。

class表达式
 const MyClass =class Me{
    getClassName(){
        return Me.name
    }
}

let inst =new MyClass();
inst .getClassName();
//A
Me.name
//ReferenceError :Me is not defined

复制代码

Me只有在Class 内部有定义, 如果类的内部没有用到的话可以省略Me改写成:

class MyClass =class {
    getClassName(){
        return Me.name
    }
}
复制代码

才有class表达式可以直接写出立即执行函数class

let person =new class{
    constructor 
(name){
        this.name =name;
    }
    sayName(){
        console.log(
        this.name
    )}
}('梅花十三');

person.sayName();
复制代码
不存在变量提升
new Foo();//ReferenceError
class Foo{};
复制代码

foo类的使用在前定义在后, 这样会报错,Es6不会吧类的生命提升到代码头部。这种规定的原因与下文要提到的继承有关,必须保证子类在父类之后定义

this的指向

类的方法内部如果含有this,他默认指向类的实例,但是必须非常小心,一旦单独使用该方法,可能会报错。

class Logger{
    printName(name="three"){
        this.print(`hello${name}`)
    }
    print(text) {
    console.log(text);
  }
}
  

const logger =new Logger()
const {printName} =logger;
printName();// TypeError: Cannot read property 'print' of undefined
复制代码

printName 方法中的this,默认指向Logger类的实例,但是如果将这个方法提取出来单独使用,this会指向该方法运行时所在的环境,因为找不到print方法而导致报错。

#####Class 的取值函数(getter)和存值函数(setter) 在类的内部可以使用get和set关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为

class MyClass1{
    constructor(){
        //...
    }
    get prop(){
        return 'get'
    }
    set prop(value){
        console.log('set'+value)
    }
}

let inst =new MyClass1();
inst.prop=123;
inst.prop
复制代码

prop属性有对应的存值函数和取值函数,因此赋值和读取行为都被自定义了。

class 静态方法

类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果一个方法前面加上static ,就标识该方法不会被实例继承 而是直接通过类来讲。

class Foo {
  static classMethod() {
    return 'hello';
  }
}

Foo.classMethod() // 'hello'
var foo =new Foo();
foo.classMethod()// foo.classMethod is not a function
复制代码

Foo类的classMethod方法前有static关键字,表明该方法是一个静态方法,可以直接在Foo类上调用;而不是在Foo类的实例上调用如果在实例上 调用静态方法,标识不存在。 如果静态方法包含this关键字,这个this指的是类,而不是实例。

class Foo {
  static bar () {
    this.baz();
  }
  static baz () {
    console.log('hello');
  }
  baz () {
    console.log('world');
  }
}

复制代码

静态方法bar调用了this.baz,这里的this指的是Foo类,而不是Foo的实例,等同于调用Foo.baz。另外从这个例子还卡伊看出,静态方法可以于非静态方法重名。 父类静态方法可以被子类继承。

class Foo {
  static classMethod() {
    return 'hello';
  }
}

class Bar extends Foo {
}

Bar.classMethod() // 'hello

复制代码

静态方法也可以从super上调用。

Class 的静态属性和实例属性

静态属性是指class本身的属性,既class.propName,而不是定义在实例this上的属性。

class Foo {

}
Foo.prop=1;
Foo.prop
//Foo类定义了一个静态属性prop只有这种写法可行,因为 ES6 明确规定,Class 内部只有静态方法,没有静态属性。
复制代码
  1. 类的实例属性

类的实例属性可以用等式,写入类的定义之中。

class MyClass1{
    myProp=34;
    constructor(){
        console.log(this.myProp)
    }
}
var myclass= new MyClass1();
myclass
// myProp就是MyClass1的实例属性,在MyClass的实例上可以读取这个属性。
复制代码

基于# 阮一峰的ES6

文章分类
前端
文章标签