JavaScript中的原型对于每个人都很困惑
任何类型(Object、String、Array等)上的构造函数最初都与创建它们的Function Object
相关联。一旦对象类型的值/对象被创建,它们才会被分配自己的原型,这是一个唯一的属性和对象,当每个值被创建时,函数构造函数创建它们。但是,JavaScript中所有对象/类型(Object、String、Array等)的原型起始都是Function.prototype
。它们都源自函数及其构造函数,用于在内存中创建对象和基本值的实例!只有在它们的值由它们的函数构造函数创建后,它们才会被分配自己的独特原型,包括它们继承的"prototype"属性和Object原型。
这就是99%的互联网网页没有告诉你的内容!
例如,
Number
(或String Array、Boolean等)类型始终具有构造函数,即
Number.constructor
,它派生自分配给“Number”类型的“Function Object”。这就是为什么“Number”被称为“构造函数”的原因。因此,在检查时,它的原型是
Function.prototype
。一旦它的函数或构造函数构建了一个真正的
Number
原始值或类型,它就会分配自己独特的原型
Number.prototype
。让我们在下面证明这一点!
以下是更简单的解释。下面是JavaScript中大多数对象从null开始继承到对象类型的方式:
String < Function < Object < null
Array < Function < Object < null
Object < Function < Object < null
Function < Function < Object < null
这里有证据!
下面我只是在询问每个对象找到的原型。注意:Object.prototype.toString.call()
只告诉我们原型的字符串名称:
Object.prototype.toString.call(String)
Object.prototype.toString.call(Array)
Object.prototype.toString.call(Object)
Object.prototype.toString.call(Function)
Object.prototype.toString.call(String.__proto__)
Object.prototype.toString.call(Array.__proto__)
Object.prototype.toString.call(Object.__proto__)
Object.prototype.toString.call(Function.__proto__)
Object.prototype.toString.call(String.__proto__.__proto__)
Object.prototype.toString.call(Array.__proto__.__proto__)
Object.prototype.toString.call(Object.__proto__.__proto__)
Object.prototype.toString.call(Function.__proto__.__proto__)
Object.prototype.toString.call(String.__proto__.__proto__.__proto__)
Object.prototype.toString.call(Array.__proto__.__proto__.__proto__)
Object.prototype.toString.call(Object.__proto__.__proto__.__proto__)
Object.prototype.toString.call(Function.__proto__.__proto__.__proto__)
请注意,字符串“[object Function]”表示类型的“prototype”或父对象为“Function.prototype”。因此,它是在每个级别分配的基础原型父对象的表示。现在让我们更深入地解释一下...
JavaScript中的
原型是一个词,意思如下:
- JavaScript中的所有对象最终都从一系列原型或“基类”继承其各种属性和特性。这沿着树向下级联到底部的子级。在JavaScript中,所有对象最终都从接近该继承树顶部的Object.prototype继承。
- 术语“原型”表示具有由子对象继承的属性和方法的特殊对象
- “原型”也是JavaScript中赋予所有对象的特殊属性,将给定对象分配为父原型到子级,但还授予访问更改原型的权限。它控制分配给子对象的实际原型,但也像真正的类属性一样运作,因为您可以使用它来操作子对象的原型。我不建议您这样做,但您可以通过简单的属性添加或通过包含属性的对象文字添加属性来修改所有对象继承的原始Object.prototype:
Object.prototype.myproperty = "Hello World"
Object.prototype.myobjectproperties = {text1: "Hello", text2: "World"}
"prototype"属性与子对象名称组合表示为"MyObjectType.prototype"。这个新名称现在既是父原型的标识符,也是改变它的工具。但它不是指向实际原型对象的引用!(使用__proto__进行下面的操作)。当创建该类型的所有新对象时,它被分配给它们。它首先分配给构建对象的函数构造器,然后传递给函数构造器创建的对象。
"__proto__"是分配给子对象的实际原型对象的引用。它也是一个属性,但它是一个引用。因此,它用于沿着子对象继承的原型对象树向上移动并访问它们及其属性。下面的示例从创建的对象文字向上遍历树,并以"null"为顶部结束:
alert({}.__proto__.__proto__);// null
原型中的怪异现象
在JavaScript继承中,一切都始于函数类型!为什么呢?因为你不能创建任何对象“类型”(Object、Array、Function、String等)而没有一个函数。当你这样做时,它们仍然会从某个函数中调用的“构造函数”中构建。函数及其构造函数不仅可以从类型创建新对象,还可以分配“prototype”属性、“__proto__”属性和实际继承的原型树或子对象将使用的对象。
在JavaScript中,有两种对象状态,即“类型”和实际实例化的对象。这就是为什么“Object”与“const x = {}”创建的对象不同的原因。这也是为什么“类型”从其最终继承或原型开始时具有不同的继承或原型的原因。
看看这个!
// The Array type has a prototype of "Function.prototype"
alert(Object.prototype.toString.call(Array))
// But an instance of an Array object has a NEW prototype of "Array.prototype" that the function prototype's constructor created for the object!
const myarray = []
alert(Object.prototype.toString.call(myarray))
发生了什么事?
事实证明,当对象被创建时,FUNCTION CONSTRUCTOR
创建并分配最终的prototype
。但是,在使用许多其他属性、对象等在数组对象创建之前和之后,可以修改自定义原型。因此,由Function对象的构造函数设置了最终的分配的原型,如上所示,这是Array类型的初始原型。
因此,请注意,Function.prototype
是JavaScript中所有Object类型的主要原型!它位于所有对象下面,但是是创建分配其自己的原型的最终实例化对象的工具。请注意,“Array.prototype”具有父原型Object.prototype
,其父原型为“null”。因此,Object.prototype
仍然是所有这些对象继承的顶级父级,但在创建它们时,构造函数会更改所有子对象的直接父级,当新对象被创建时。
请注意,
Function.prototype
从其自身的
Object.prototype
中继承了许多功能。它为您创建的对象构建的原型也是从此父原型中制作的。因此,最终,
Object.prototype
提供了创建和管理分配给它们的原型所需的好东西,无论是
Function 还是
Object 都是具有特殊工具和功能的特殊预构建类型,用于创建所有类型的对象!请记住这一点。
最后一个测试... 让我们看看我们创建的自定义对象如何使用原型。下面的示例证明函数构造器(
Function.prototype 的一部分)将
"prototype"属性分配给创建的对象,但可以在分配给对象的
MyCustomObject.prototype
原型之前或之后使用各种属性和方法进行自定义。这表明,您的对象的最终原型不必是
Object.prototype
继承属性的静态副本,而可以是您创建的全新内容!
let newPet;
function Pet() {
this.fourlegs = true;
}
var Cat = {
type : "cat"
}
var Dog = {
type : "dog"
}
Pet.prototype = Cat;
newPet = new Pet();
alert(newPet.type);
Pet.prototype = Dog;
newPet = new Pet();
alert(newPet.type);
alert(newPet.fourlegs);
Pet.prototype.furcolor = "white";
newPet = new Pet();
alert(newPet.furcolor);
__proto__
与prototype
在 JavaScript 中的区别 和 JavaScript 的.prototype
如何工作? - Bergi