class

作者: keknei | 来源:发表于2017-12-25 02:18 被阅读18次

在原先的js上生成实例是通过构造函数和原型结合,一个简单的例子

function Person(name,age){
    this.name=name;
    this.age=age;
};
Person.prototype.getName=function (){
    return this.name;
};
Person.prototype.getAge=function (){
    return this.age;
};
var p=new Person("张三",15);
console.log(p.getName());//张三
console.log(p.constructor === Person);//true
console.log(p instanceof Person);//true

es6的class生成的实例对象

class Person{
  constructor(name,age){
    this.name=name;
    this.age=age;
  }
  getName(){
    return this.name;
  }
  getAge(){
    return this.age;
  }
}
let p1=new Person("张三",15);
let p2=new Person("李四",17);
console.log(p1.getName());//张三
console.log(p1.constructor === Person);//true 类本身就指向构造函数。
console.log(p1 instanceof Person);//true
console.log(p1.prototype===p2.prototype);//true 因为原型相等,所以可以为其中一个实例添加方法,另外的实例也就有了这个方法
上面的例子中注意一下几个点
  1. 如果不写constructor,class会默认加个constructor
  2. class里函数与函数之间不用写逗号
  3. 类里面的所有函数都定义在类的prototype上

class表达式

let Person=class Bodys{
  constructor(name,age){
    this.name=name;
    this.age=age;
  }
  getClassName(){
    return Bodys.name;
  }
  getAge(){
    return Bodys.age;
  }
  getName(){
    return this.name;
  }
}
let p=new Person("王五",13);
console.log(p.getClassName());//Bodys
console.log(p.getName());//王五
  1. 注意上面的bodys只是个class名字而已,只能在class内部用,真正的构造函数名字还是Person
  2. class和let一样,不存在变量提升

如果用不到这个bodys,是可以不写的

{
   let Person=class{
       /*..... */
   }
}

用表达式可以立即执行,如下

{
  let Person=new class{
    /*..... */
  }
}

class里的this指向 类内部的this默认指向类的实例

let Person=class{
  getThis(){
    console.log(this);
  }
}
let p=new Person();
p.getThis();//this 就是Person这个实例
let {getThis}=p;
getThis.call(this);//window
getThis();//undefinde

上面三种调用方法有三种结果,不稳定,如果我们就想要这个this指向类的实例,一个简单的方法,就是在constructor绑定this,或者用箭头函数

let Person=class{
  constructor (){
    this.getThis=this.getThis.bind(this);
  }
  getThis(){
    console.log(this);
  }
}
let p=new Person();
p.getThis();//this 就是Person这个实例
let {getThis}=p;
getThis.call(this);//this 就是Person这个实例
getThis();//this 就是Person这个实例

箭头函数,因为箭头函数里面的this永远都是外层的this,没有自己的this,可以很好的利用这个特性

let Person=class{
  constructor (){
    this.getThis=()=>{
      console.log(this);
    };
  }
}
let p=new Person();
p.getThis();//this 就是Person这个实例
let {getThis}=p;
getThis.call(this);//this 就是Person这个实例
getThis();//this 就是Person这个实例

class的取值函数和设置函数,可以用来在class的属性设置或者取值的过程中做一些处理

class Person{
  set prop(val){
    console.log("处理一下"+val+"逻辑");
  }
  get prop(){
    console.log("处理一下逻辑");
    return "getVal";
  }
}

let p=new Person();
p.prop="张三";//处理一下张三逻辑
console.log(p.prop);//getVal

class的静态方法

  1. 静态方法就是在class里的方法前加上“static”关键字就行了
  2. 静态方法只能通过类来调用,而且可以跟class实例的方法重名,并不影响.而且static里面的this指的是class,并不是实例
let Person=class{
  static getName(){
    this.getAge();//classAge
    console.log("ClassName");
  }
  static getAge(){
    console.log("classAge");
    return "Person:classAge";
  }
  getName(){
    console.log("name");
  }
  getAge(){
    console.log("age");
  }
}
const p=new Person();
p.getName();//name
Person.getName();//ClassName

//继承
//子类可以继承父类的静态方法,也可以在super上调用
class Son extends Person{
  static superAge(){
    console.log("super+"+super.getAge());
  }
}
Son.getName();//className
Son.superAge();//super+Person:classAge

class的静态属性和实例属性

类的静态属性是直接在class身上加的,目前而言,es6规定,class内部只有静态方法,没有静态属性,实例属性只能定义在constructor里

let Person = class{
  constructor(){
    this.y=0;
  }
}
Person.x=12;
console.log(Person.x);//12
console.log(new Person().y);//0

现在有个提案,就是直接在class里定义静态属性,和属性

let Myclass=class{
  x=12;
  static y=0;
}
console.log(new Myclass().x);
console.log(Myclass.y);

class 的new.target的属性

new.target这个属性一般在构造函数里,这个值就是当前的class,不过子类继承的时候值是子类的class,可以利用这个特性来写一个只有被子类继承的时候才能用的class

class Person{
  constructor(name,age){
    if (new.target===Person){
      throw new Error("必须子类继承才能实例");
    }else{
      this.name=name;
      this.age=age;
    }
  }
}

class Son extends Person{
  constructor(name,age,job){
    super(name,age);
    this.job=job;
  }
}
//let p=new Person("张三",18);//报错 必须子类继承才能实例
let s=new Son("李四",12,"IT");
console.log(s.name);//李四

class的继承

class Person{
  constructor(name,age){
    this.name=name;
    this.age=age;
    this.x=1;
  }
  getName(){
    console.log(this.name);
    return this.name;
  }
  static getName(){
    return "static+"+this.name;
  }
}

class Son extends Person{
  constructor(name,age,job){
    super(name,age);
    this.job=job;

    this.x=2;
    super.x=3;
    console.log(super.x);//undefined
    console.log(this.x);//3
  }
  getName(){
    console.log(this.job+"--"+super.getName());//IT--李四
  }
  getAge(){
    console.log(super.age);//undefined
  }
  static getName(){
    console.log(super.getName());//static+Son
  }
}
let p=new Person("张三",18);
let s=new Son("李四",12,"IT");
console.log(s.name);//李四
console.log(s instanceof Person);//true
console.log(s instanceof Son);//true
s.getName();
s.getAge();
Son.getName();

类的继承super关键字的几个注意点

  1. super函数只能在constructor里用,并且必须写在第一句,否则会报错
  2. 如果继承后不写constructor,会自动加上constructor并且加上super(...args)这句代码
  3. super函数相当于是Person.prototype.constructor.call(this),虽然代表的是父类,但是返回是子类,new.target可以证明
  4. super作为对象时,是指向父类的原型对象,是拿不到父类构造函数里的属性或者方法,只能取原型上的 Son里的getAge可以说明
  5. es6规定,通过super调用父类的方法时,方法内部的this指向子类 Son通过调用父类的getName可以说明
  6. 如果通过super对某个属性赋值,这时的this就是super,指向子类,赋值的属性就变成子类实例的属性。如果通过super对某个属性取值时,super代表的是父类的原型对象 Son实例的this.x可以证明
  7. super在static静态方法中指向父类,而不是父类的原型对象

Object.getPrototypeOf(子类)可以查找父类

类的prototype和proto属性

  1. 子类的proto属性,表示构造函数的继承,总是指向父类。
  2. 子类prototype属性的proto属性,表示方法的继承,总是指向父类的prototype属性。
class A{

}
class B extends A{

}
console.log(A.prototype);
console.log(A===B.__proto__);//true
console.log(A.prototype===B.prototype.__proto__);//true
//内部就是子类继承父类的实例和属性
Object.setPrototypeOf(B,A);
Object.setPrototypeOf(B.prototype,A.prototype);

setPrototypeOf的实现

Object.setPrototype=(obj,proto)=>{
  obj.__proto__=proto;
  return obj;
}

原生构造函数的继承,大概有这些Boolean()、Number()、String()、Array()、Date()、Function()、RegExp()、Error()、Object()
es6以前是无法继承原声构造函数的,因为拿不到父类的属性,但是es6是可以的

class newArr extends Array{

}
let arr=new newArr;
arr.push(12);
console.log(arr[0]);//12
console.log(arr.length);//1

关于class就介绍这么多,希望对你有所帮助,如果想看更详细的资料,请狠狠的点击我

相关文章

网友评论

      本文标题:class

      本文链接:https://www.haomeiwen.com/subject/swmdwxtx.html