原型继承的概念对于许多开发人员来说是最复杂的概念之一。让我们试着理解问题的根源,以便更好地理解原型继承。让我们从一个简单的函数开始。
如果我们在Tree函数上使用一个新运算符,我们将其作为构造函数调用。
每个JavaScript函数都有一个原型。当你记录Tree.prototype时,你会。。。
如果查看上面的console.log()输出,您可以看到Tree.prototype上的构造函数属性和__proto__属性。__proto__表示这个函数所基于的原型,由于这只是一个普通的JavaScript函数,还没有设置继承,所以它引用的是Object原型,它是JavaScript中刚刚内置的东西。。。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype
这包括.toString、.toValue、.hasOwnProperty等。。。
__我的mozilla带来的proto__已被弃用,取而代之的是Object.getPrototypeOf方法来获取对象的原型。
Object.getPrototypeOf(Tree.prototype); // Object {}
让我们向Tree原型添加一个方法。
我们修改了Root并向其添加了一个函数分支。
这意味着当您创建Tree实例时,可以调用它的分支方法。
我们还可以向原型中添加原语或对象。
让我们在树中添加一个子树。
在这里,Child从Tree继承了它的原型,我们在这里做的是使用Object.create()方法根据您传递的内容创建一个新对象,这里是Tree.prototype。在这种情况下,我们正在做的是将Child的原型设置为一个看起来与Tree原型相同的新对象。接下来,我们将Child的构造函数设置为Child,如果不设置,它将指向Tree()。
孩子现在有了自己的原型,它的__proto__指向Tree,Tree的原型指向base Object。
Child
|
\
\
Tree.prototype
- branch
|
|
\
\
Object.prototype
-toString
-valueOf
-etc., etc.
现在您创建了一个最初在Tree中可用的Child和call分支的实例。我们还没有在Child原型上定义分支。但是,在Child继承的Root原型中。
在JS中,一切都不是对象,一切都可以像对象一样。
Javascript有字符串、数字、布尔值、未定义、null等原语。它们不是对象(即引用类型),但肯定可以充当对象。让我们看一个例子。
在该列表的第一行中,为name指定了一个基本字符串值。第二行将名称视为对象,并使用点表示法调用charAt(0)。
这是幕后发生的事情://JavaScript引擎的作用
String对象在被销毁之前只存在一个语句(一个称为自动装箱的过程)。让我们再次回到我们的原型继承。
Javascript支持基于原型。每个函数都有一个原型属性,该属性引用另一个对象财产/函数是从对象本身或通过原型链(如果不存在)
JS中的原型是一个对象,它使您成为另一个对象的父对象。授权意味着如果你不能做某事,你会告诉别人帮你做。
https://jsfiddle.net/say0tzpL/1/
如果您查找上面的fiddle,dog可以访问toString方法,但它在其中不可用,但可以通过委托给Object.prototype的原型链使用
如果您查看下面的一个,我们正在尝试访问每个函数中可用的调用方法。
https://jsfiddle.net/rknffckc/
如果您查找上面的fiddle,Profile Function可以访问调用方法,但它在其中不可用,但可以通过委托给Function.prototype的原型链使用
注意:prototype是函数构造函数的属性,而__proto__是从函数构造函数构造的对象的属性。每个函数都有一个原型属性,其值为空对象。当我们创建函数的实例时,我们得到一个内部属性[[Prototype]]或__proto__,其引用是function构造函数的原型。
上图看起来有点复杂,但展示了原型链接工作原理的全貌。让我们慢慢来:
有两个实例b1和b2,其构造函数是Bar,父实例是Foo,并且有两个来自原型链的方法通过Bar和Foo识别和说话
https://jsfiddle.net/kbp7jr7n/
如果你查阅上面的代码,我们有Foo构造函数,它有方法identify(),Bar构造函数有speak方法。我们创建了两个Bar实例b1和b2,它们的父类型是Foo。现在,在调用Bar的speak方法时,我们能够通过原型链识别谁在调用speak。
Bar现在拥有Foo的所有方法,这些方法都在其原型中定义。让我们进一步了解Object.prototype和Function.prototype以及它们之间的关系。如果您查找Foo的构造函数,Bar和Object是Function构造函数。
Bar的原型是Foo,Foo的原型是Object,如果仔细观察,Foo原型与Object.prototype相关。
在结束之前,让我们在这里用一小段代码来总结上面的内容。我们在这里使用instanceof运算符来检查对象的原型链中是否包含构造函数的prototype属性,该属性在下面概括了整个大型图。
我希望这是一些信息,我知道这类信息可能很难掌握。。。简单地说,它只是链接到对象的对象!!!!