第壹章第13节 C#和TS语言对比-原型(仅TS)

24 阅读3分钟

JS/TS中的原型对象和原型链是整个类型系统的底层原理,示例代码为JS,TS和UTS也是一样。实际应用开发中,尽少会碰原型,但听说面试时经常会问,我是纯野生程序员,没有面过,不清楚!

  1. 定义一个类或函数时,JS引擎会自动创建一个对应的原型对象,你把它想象成一个配套设施。
  2. 每个类或函数,都有一个属性prototype,指向自己的原型对象。如下例中的Person.prototype。prototype不是实例属性,也不是静态属性,但它属于类层面,与静态属性比较相似。
  3. 当实例化一个对象时,会自动为对象创建一个__proto__属性,这个属性指向该对象所属类型的原型对象。如下例中,p1.proto==p2.proto==Person.prototype。即某类型的所有实例对象的__proto__属性,都指向该类型的原型对象。
  4. ①构造函数、②类中以"xxx(){}"方式定义的方法、③类中以"xxx(){this.property = "mc"}"方式定义的属性,都会被放到原型对象上,如下例中的sayHi()方法和somePropertyInMethod属性。除此之外,还可以通过p1.__proto__或者Person.prototype,直接定义原型对象里的方法或属性,但JS框架建议通过获取原型对象后,再进行相关操作,获取方式为:Object.getPrototypeOf(p1)。
  5. 类中通过等号方式定义的属性和方法,会被放在实例对象上,如下例中的name、age、jump()、sing()均在实例对象自身上。
  6. 原型对象也是一个对象,每个原型对象上也有一个__proto__属性,该属性指向父类的原型对象,依次类推,形成一个原型对象组成的引用链条,即为原型链。原型链的最后的原型对象是Object的原型对象,而Object的原型对象的__proto__属性,指向了null。
  7. 当实例对象调用一个属性或方法时,会先在自身上找,如果找不到,就到所属类型的原型对象上找,如果还找不到,就延着原型链找,直到Object类型的原型对象为止。所以下例中,如果我们在类中重新定义一个方法"sayHi=()=>{}",这个方法在实例对象本身上,则调用p1.sayHi()时,会优先调用这个sayHi方法,而不是原型对象中的那个。
  8. 由于所有实例对象都可以访问原型对象,所以,它适合放公用的方法或属性,这样就不需要每实例化一个对象,就要创建所有方法或属性。同时,在原型对象的基础上,JS/TS实现了原型链,从而实现了类型的继承。
class Person{
  
  //通过等号定义的属性和方法,在实例对象上
  constructor(name,age){
    this.name = name;
    this.age = age;
    this.jump = ()=>(console.log("跳"););
  }
  sing = ()=>(console.log("唱"););

  
  //xxx(){}方式定义的方法,在类的原型对象上
  sayHi(){
    console.log("我是"+this.name+"今年"+this.age+"岁了");
  }
  //这里定义的属性,在类的原型对象上
  someMethod() {
    this.somePropertyInMethod = 'value';
    
  }
}

const p1 = new Person("zs",18);
const p2 = new Person("ls",28);
console.log(p1, p2, Person.prototype)

//访问原型对象的方式
p1.__proto__
Object.getPrototypeOf(p1)
Person.prototype

image.png

Snipaste_2024-06-09_22-02-37.png