阅读了两者的介绍后,我很好奇编程社区如何使用它们?在什么情况下会使用哪一个?
传统继承存在许多问题,而原型继承则不存在这些问题,例如:
紧密耦合。继承是面向对象设计中最紧密的耦合方式。派生类对其祖先类有深入的了解。
不灵活的层次结构(也称必要的重复)。单个父类层次结构很少能描述所有可能的用例。最终,所有层次结构都会对新的用例“不太适用”--这是一个需要代码重复的问题。
多继承很复杂。继承多于一个父类通常是可取的。这个过程非常复杂,并且其实现与单一继承的过程不一致,使得阅读和理解更加困难。
脆弱的架构。由于紧密耦合,经常很难重构具有“错误”设计的类,因为许多现有功能依赖于现有设计。
大猩猩/香蕉问题。通常有部分父类属性你不希望继承。子类允许你覆盖来自父类的属性,但它不允许你选择要继承哪些属性。
为了理解原型继承如何解决这些问题,首先应该了解两种不同类型的原型继承。JavaScript支持两种:
委托。如果在实例上找不到一个属性,将在其原型上查找该属性。这使您可以在多个实例之间共享方法,为您提供轻量级模式。
串联。动态添加属性的能力使您可以自由地将任何属性从一个对象复制到另一个对象中,全部或部分地复制。
您可以同时结合这两种形式的原型继承,以实现非常灵活的代码重用系统。 事实上,使用原型很容易实现传统继承。反之不成立。
原型继承允许实现大多数经典语言中的重要特性。在JavaScript中,闭包和工厂函数允许您实现私有状态,而函数式继承可以轻松地与原型相结合,以添加支持数据隐私的混合内容。因为JavaScript不支持大多数人理解的“经典”继承(并且您没有提供任何阅读参考资料),我假设您指的是像这样处理继承:-
function base() {
var myVar;
this.someBaseFunc = function() { }
}
function derived() {
base.call(this);
var someOtherVar;
this.SomeOtherFunc = function() { }
}
我通常的经验法则是:
instanceof
是一种不可靠的检查方式,当对象被扩展或跨执行上下文边界时无法正常工作。即使在TypeScript中,接口也是更可靠的开发工具机制。 - Eric Elliott