作者回复: 是句口误,原话: “类成员的属性”都是实例属性,而不是原型属性;“类成员的方法”都是“实例”方法。 纠正为: “类的成员属性”都是实例属性,而不是原型属性,“类的成员方法”都是“原型”方法。
作者回复: Husky 中的 this.color=color 可以删掉,参数加上public 相当于做了这个赋值。
作者回复: JS 的继承方式是原型式继承,原型上的属性和方法是所有实例共享的,不需要共享的就放在构造函数中(也就是实例自己的属性和方法)。当调用实例的属性或方法时,先看实例自身有没有,如果没有就会沿着原型链查找。
作者回复: 类中如果有太多的方法,首先就要考虑这个设计是否合理。有几点建议: 1)按功能拆分成多个类 2)通过继承基类,减少子类的方法 3)看方法中是否存在能够拆分出来的独立逻辑,每个函数的职责尽量要单一 装饰器适用的场景是动态地为类添加新的能力,用在一个基础工具类中不是一个好的模式。
作者回复: 构造函数中定义的是参数的类型,而不是类成员的类型,要区分开,下面这个定义更方便理解: class A { constructor(x: string) { this.name = x } name: string; }
作者回复: 举个例子来说明: 传统 JavaScript 的继承: function Animal(name) { this.name = name; } function Dog(name) { Animal.call(this, name); } ES6的继承: class Animal { constructor(name) { this.name = name; } } class Dog extends Animal { constructor(name) { super(name); } } 这里 super 的作用是调用父类 Animal 的构造函数来初始化子类 Dog,等价于 Animal.call(this, ...)。也就是说,只有相关的实例属性被绑定到 this 上后,才能调用 this.xxx。
作者回复: function readFile(file: Blob, callback?: (result: string) => void) { let fsReader: (FileReader | null) = new FileReader(); fsReader.readAsDataURL(file); fsReader.onload = function(e) { let result = <string>(<FileReader>fsReader).result callback && callback(result); fsReader = null; } }
作者回复: 父类的实例
作者回复: 你的意思是类B“实现”了这个接口吧?看下面的例子: class A { method() {} } interface I extends A {} // B必须实现method class B implements I { method() {} } // C是A的子类,就不用实现method class C extends A implements I {} 接口可以继承类,是为了从已知的类中直接抽离出成员结构,用作它用,比如去约束其他的变量。
作者回复: 你要分清两条原型链: 1)构造函数的原型链:Dog -> Anima -> Function Dog.__proto__ === Animal // true Animal.__proto__ === Function.prototype // true Animal.isPrototypeOf(Dog) // true,表示 Dog 在 Animal 的原型链上 2)原型的原型链:Dog.prototype -> Animal.prototype -> Object.prototype Dog.prototype.__proto__ === Animal.prototype // true Animal.prototype.__proto__ === Object.prototype // true Animal.prototype.isPrototypeOf(Dog.prototype) // true, 表示 Dog.prototype 在 Animal.prototype 的原型链上