这是一个非常简单的基于原型的对象模型,在解释过程中将被视为示例,尚无评论:
function Person(name){
this.name = name;
}
Person.prototype.getName = function(){
console.log(this.name);
}
var person = new Person("George");
在了解原型概念之前,我们必须考虑一些关键点。
1- JavaScript 函数的实际工作原理:
为了迈出第一步,我们必须弄清楚 JavaScript 函数实际上是如何工作的,作为一个使用this
关键字的类之类的函数,或者只是作为一个带有参数的常规函数,它做什么以及它返回什么。
假设我们要创建一个Person
对象模型。但在这一步中,我将尝试在不使用and关键字的情况下做同样的事情prototype
new
。
所以在这一步functions
中,objects
和this
关键字,是我们所拥有的。
第一个问题是在不使用关键字的情况下如何this
使用new
关键字。
因此,要回答这个问题,假设我们有一个空对象,以及两个函数,例如:
var person = {};
function Person(name){ this.name = name; }
function getName(){
console.log(this.name);
}
现在不使用new
关键字我们如何使用这些功能。所以 JavaScript 有 3 种不同的方法来做到这一点:
一种。第一种方法是将函数作为常规函数调用:
Person("George");
getName();//would print the "George" in the console
在这种情况下,这将是当前上下文对象,通常是 浏览器window
或GLOBAL
. Node.js
这意味着我们将拥有浏览器中的 window.name 或 Node.js 中的 GLOBAL.name,其值为“George”。
湾。我们可以将它们附加到一个对象上,作为它的属性
-最简单的方法是修改空person
对象,例如:
person.Person = Person;
person.getName = getName;
这样我们就可以这样称呼它们:
person.Person("George");
person.getName();// -->"George"
现在person
对象是这样的:
Object {Person: function, getName: function, name: "George"}
-将属性附加到对象的另一种方法是使用该对象的prototype
,该对象可以在任何 JavaScript 对象中找到,名称为__proto__
,我试图在摘要部分解释一下。所以我们可以通过这样做得到类似的结果:
person.__proto__.Person = Person;
person.__proto__.getName = getName;
但是这种方式我们实际上正在做的是修改Object.prototype
,因为每当我们使用字面量 ( ) 创建一个 JavaScript 对象时{ ... }
,它都是基于创建的,这意味着它Object.prototype
作为一个名为__proto__
,正如我们在之前的代码片段中所做的那样,所有的 JavaScript 对象都会被更改,这不是一个好的做法。那么现在更好的做法是什么:
person.__proto__ = {
Person: Person,
getName: getName
};
而现在其他的对象都安然无恙,但似乎还是不是一个好的做法。所以我们还有一个解决方案,但是要使用这个解决方案,我们应该回到person
创建对象的那一行代码(var person = {};
),然后将其更改为:
var propertiesObject = {
Person: Person,
getName: getName
};
var person = Object.create(propertiesObject);
它所做的是创建一个新的 JavaScriptObject
并将 附加propertiesObject
到__proto__
属性。所以要确保你能做到:
console.log(person.__proto__===propertiesObject); //true
但是这里的棘手点是您可以访问对象__proto__
第一级中定义的所有属性person
(阅读摘要部分以获取更多详细信息)。
正如您所看到的,使用这两种方式中的任何一种this
都会准确地指向person
对象。
C。JavaScript 有另一种方式为函数提供this
,即使用call或apply来调用函数。
apply() 方法使用给定的 this 值和作为数组(或类似数组的对象)提供的参数调用函数。
和
call() 方法使用给定的 this 值和单独提供的参数调用函数。
这种我最喜欢的方式,我们可以轻松地调用我们的函数,例如:
Person.call(person, "George");
或者
//apply is more useful when params count is not fixed
Person.apply(person, ["George"]);
getName.call(person);
getName.apply(person);
这 3 种方法是找出 .prototype 功能的重要初始步骤。
new
2-关键字如何工作?
这是了解功能的第二步。这是.prototype
我用来模拟该过程的:
function Person(name){ this.name = name; }
my_person_prototype = { getName: function(){ console.log(this.name); } };
在这一部分中,我将尝试执行 JavaScript 所采取的所有步骤,而不使用new
关键字 and prototype
,当您使用new
关键字时。因此,当我们这样做时new Person("George")
,Person
函数充当构造函数,这些是 JavaScript 所做的,一一对应:
一种。首先,它创建一个空对象,基本上是一个空哈希,例如:
var newObject = {};
湾。JavaScript 的下一步是将所有原型对象附加到新创建的对象
我们my_person_prototype
这里有类似原型的对象。
for(var key in my_person_prototype){
newObject[key] = my_person_prototype[key];
}
这不是 JavaScript 实际附加原型中定义的属性的方式。实际方式与原型链概念有关。
一种。& b。而不是这两个步骤,您可以通过执行以下操作获得完全相同的结果:
var newObject = Object.create(my_person_prototype);
//here you can check out the __proto__ attribute
console.log(newObject.__proto__ === my_person_prototype); //true
//and also check if you have access to your desired properties
console.log(typeof newObject.getName);//"function"
现在我们可以调用我们的getName
函数my_person_prototype
:
newObject.getName();
C。然后它将该对象提供给构造函数,
我们可以用我们的样本来做到这一点,比如:
Person.call(newObject, "George");
或者
Person.apply(newObject, ["George"]);
然后构造函数可以做它想做的任何事情,因为构造函数内部的this是刚刚创建的对象。
现在是模拟其他步骤之前的最终结果: Object {name: "George"}
概括:
基本上,当您在函数上使用new关键字时,您正在调用该函数并且该函数用作构造函数,所以当您说:
new FunctionName()
JavaScript 在内部创建一个对象,一个空的哈希,然后将该对象提供给构造函数,然后构造函数可以为所欲为,因为该构造函数内部的 this 是刚刚创建的对象,然后它当然会为您提供该对象如果您没有在函数中使用 return 语句,或者如果您在return undefined;
函数体的末尾放置了 a。
所以当 JavaScript 在一个对象上查找一个属性时,它做的第一件事就是在那个对象上查找它。然后有一个[[prototype]]
我们通常拥有的秘密属性,__proto__
该属性是 JavaScript 接下来要研究的。当它查看 时__proto__
,只要它又是另一个 JavaScript 对象,它就有自己的__proto__
属性,它会不断上升,直到到达下一个__proto__
为空的点。要点是 JavaScript 中唯一一个__proto__
属性为 null 的对象是Object.prototype
object:
console.log(Object.prototype.__proto__===null);//true
这就是 JavaScript 中继承的工作原理。

换句话说,当你在一个函数上有一个原型属性并且你在它上面调用了一个 new 时,在 JavaScript 完成了对新创建的属性对象的查看之后,它会去查看函数的.prototype
,并且这个对象也可能有它的自己的内部原型。等等。