这是一个非常简单的基于原型的对象模型,在解释过程中将其视为示例,但尚无注释:
function Person(name){
this.name = name;
}
Person.prototype.getName = function(){
console.log(this.name);
}
var person = new Person("George");
在通过原型概念之前,我们必须考虑一些关键点。
1- JavaScript函数实际上如何工作:
第一步,我们必须弄清楚JavaScript函数实际上是如何工作的(作为类,类似于使用this
关键字的函数),或者作为带有参数,其作用和返回结果的常规函数。
假设我们要创建一个Person
对象模型。但在这一步中,我将尝试不使用prototype
and new
关键字而做同样的事情。
所以在这一步functions
中objects
和this
关键字就是我们所拥有的。
第一个问题是如何this
不使用new
keyword,关键字有用?
因此,要回答这个问题,假设我们有一个空对象,并且两个函数类似:
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,其值为“乔治”。
b。我们可以将它们附加到对象上,作为其属性
- 最简单的方法是修改空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);
它的作用是创建一个新的JavaScript Object
并将其附加propertiesObject
到__proto__
属性。因此,请确保您可以执行以下操作:
console.log(person.__proto__===propertiesObject); //true
但是,这里的棘手问题是您可以访问__proto__
在第一层定义的所有属性。person
对象(有关详细信息,请阅读摘要部分)。
如您所见,使用这两种方式中的任何一种 this
都会精确地指向person
对象。
C。JavaScript还有另一种向函数提供功能的方式this
,即使用call或apply来调用该函数。
apply()方法使用给定的此值和作为数组(或类似数组的对象)提供的参数调用函数。
和
call()方法使用给定的此值和单独提供的参数来调用函数。
这样,这是我的最爱,我们可以轻松地调用以下函数:
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功能的重要的初始步骤。
2- new
关键字如何运作?
这是了解.prototype
功能的第二步。这是我用来模拟过程的内容:
function Person(name){ this.name = name; }
my_person_prototype = { getName: function(){ console.log(this.name); } };
在这一部分中,我将尝试采取JavaScript所采取的所有步骤,而在使用new
关键字prototype
时不使用关键字and new
。因此,当我们执行时new Person("George")
,Person
函数充当了构造函数,这就是JavaScript所要做的,一个接一个:
一个。首先,它生成一个空对象,基本上是一个空哈希,例如:
var newObject = {};
b。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"]);
然后构造函数可以执行任何所需的操作,因为该构造函数内部的对象是刚刚创建的对象。
现在,在模拟其他步骤之前为最终结果:对象{name:“ George”}
摘要:
基本上,当您在函数上使用new关键字时,您正在调用该函数,并且该函数用作构造函数,因此当您说:
new FunctionName()
JavaScript在内部创建一个对象,一个空散列,然后将其提供给构造函数,然后构造函数可以执行其所需的任何操作,因为该构造函数内部的对象是刚刚创建的对象,然后为您提供了该对象如果您尚未在函数中使用return语句,或者return undefined;
在函数主体的末尾放置了a 。
因此,当JavaScript在对象上查找属性时,它要做的第一件事就是在对象上查找属性。然后是[[prototype]]
我们通常喜欢的一个秘密属性,__proto__
而该属性就是JavaScript接下来要看的内容。并且,当它遍历时__proto__
,就再次成为另一个JavaScript对象,它具有自己的__proto__
属性,它会不断上升直到到达下一个__proto__
为null 的地步。该点是JavaScript中唯一一个其__proto__
属性为null的Object.prototype
对象是object:
console.log(Object.prototype.__proto__===null);//true
这就是继承在JavaScript中的工作方式。
换句话说,当您在函数上具有原型属性并在其上调用一个新属性时,JavaScript完成对新创建的对象的属性查找后,它将去查看该函数的.prototype
对象,并且该对象也可能具有其属性自己的内部原型。等等。