Javascript chapter9 classes

9.1 class 和prototype
自己定义函数并使用Object.create()函数就相当于定义了一个javascript类。

*[Symbol.iterator](){
  for(let x=Math.ceil(this.from);x<=this.to;x++)yield x;
}

上述代码实现了迭代器,类可以迭代可以使用for/of循环和...操作符

ES6之前的类实现如下

function Range(from,to){
  this.from=from;
  this.to=to;
}//构造函数

Range.prototype={
  includes:function(x){return this.from<=x&&x<=this.to},//return x
  //迭代器实现
  [symbol.iterator]:function*(){
    let x=Math.ceil(this.from);x<=this.to;x++)yield x;
},
  toString:function(){return "("+this.from+"..."+this.to+")";}
};

//调用:
  let r=new Range(1,3);
  r.includes(2);//true
  r.toString();//(1,2,3)
  [...r]//[1,2,3]

9.2.1
instanceof
r instance of Range;//判断r是不是Range类的对象。左操作数是被检测的对象,右操作数是构造函数名
o instanceof C 实际检查的是o是否继承于C.prototype,下例说明问题。

function Strange(){};
Strange.prototype=Range.prototype;
new Strange() instanceof Range;//true

isPrototypeOf()方法。也是用来检测对象是否是某类的对象
range.methods.isPrototypeOf(r);//range.methods is the prototype object.

9.2.2

let F=function(){};//函数对象
let p=F.prototype;//p是F的原型
let c=p.constructor;//c是p的构造函数
c===F;//true  F.protype.constructor===F

9.3类

class Range{
  constructor(from,to){
    this.from=from;
    this.to=to;
  }
  //return true if x in the range,false otherwise;
  includes(x){return this.from<=x && x<=this.to;}

  //class迭代器
  *[symbol.iterator](){
    for(let x=Math.ceil(this.from);x<=this.to;x++)yield x;
  }

  //toString方法实现。
  toString(){return `(${this.from}...${this.to})`;}
}

使用extends关键字实现继承。

class Span extends Range{
    constructor(start,length){
        super(start,length);
  }
}

两点:1.在class类定义的代码是严格模式
2.必须先定义后使用类代码。

9.3.1静态方法
使用static 关键字定义静态方法。
注意:static方法是类方法,不存在实例,所以不要使用this关键字。
9.3.3私有变量

代表私有变量。外部不可见,不可直接访问,是Immutable的变量。

class Buffer{
  #size=0;
  get size(){return this.#size;}
}

例:复数类

class Complex{
  #r=0;
  #i=0;

constructor(real,imaginary){
  this.r=real;
  this.i=imaginary;
}

  plus(that){
      return new Complex(this.r+that.r,this.i+that.i);
}
  times(that){
    return new Complex(this.r*that.r-this.i*that.i,this.r*that.i+this.i*that.r);
  }

  static sum(c,d){return c.plus(d);}
  static product(c,d){return c.times(d);}

  get real(){return this.r;}
  get imaginary(){return this.i;}
  get magnitude(){return Math.hypot(this.r,this.i);}

  toString(){return `{${this.r},${this.i}}`};

  equals(that){
      return that instanceof Complex &&
        this.r===that.r&&this.i===that.i;
  }
}

9.4给类添加方法。
给原型添加方法。
Complex.prototype.conj=function(){return new Complex(this.r,-this.i);};

9.5子类
ES6之前子类的定义 ,下例span类继承于range类

//span的构造函数
 function Span(start,span){
    if(span>=0){
        this.from=start;
        this.to=start+span;
  }else{
        this.to=start;
        this.from=start+span;
    }
}
//保证span类继承于Range类
Span.prototype = Object.create(Range.prototype);
//构造函数不是Range的构造函数,把它设定为Span的构造函数。
Span.prototype.constructor=Span;
//覆盖父类的对应函数
Span.prototype.toString=function{
      ....
}

ES6之后的继承

class EZArray extends Array{
    get first(){return this[0];}
    get last(){return this[this.length-1];}
}

子类调用父类的函数使用super关键字。

1.如果你使用了extends表示继承,构造函数中必须调用父类的构造函数
2.如果你没有对子类设定构造函数,那么会生成默认的构造函数
3.你也许不能使用this关键字在你的构造函数中,直到你调用了父类的构造函数。

posted @ 2024-12-23 14:37  zhongta  阅读(12)  评论(0)    收藏  举报