[英]Javascript Difference between prototype and call
I am learning javascript and got puzzled. 我正在学习javascript并感到困惑。 An example over here which has example as below:-
这里有一个例子如下: -
// define the Person Class
function Person() {}
Person.prototype.walk = function(){
alert ('I am walking!');
};
Person.prototype.sayHello = function(){
alert ('hello');
};
// define the Student class
function Student() {
// Call the parent constructor
Person.call(this);// <---- Confusion
}
// inherit Person
Student.prototype = new Person(); //<---- Confusion
// correct the constructor pointer because it points to Person
Student.prototype.constructor = Student;
// replace the sayHello method
Student.prototype.sayHello = function(){
alert('hi, I am a student');
}
// add sayGoodBye method
Student.prototype.sayGoodBye = function(){
alert('goodBye');
}
var student1 = new Student();
student1.sayHello();
student1.walk();
student1.sayGoodBye();
// check inheritance
alert(student1 instanceof Person); // true
alert(student1 instanceof Student); // true
Now, I am confused ( <----
) in these two lines. 现在,我在这两行中感到困惑(
<----
)。 When I say Person.call(this);
当我说
Person.call(this);
, this is simply stating to Inherit properties of Person class... Right? ,这只是说明继承Person类的属性......对吗?
Then what is this doing? 那是做什么的?
// inherit Person
Student.prototype = new Person(); //<---- Confusion
As per my knowledge, .prototype
also inherits all properties? 据我所知,
.prototype
还继承了所有属性?
To explain it, first let's remember how constructor functions work in JavaScript: 为了解释它,首先让我们记住构造函数在JavaScript中是如何工作的:
function Guide(a) {
this.a = a;
}
Guide.prototype.q = "Life, the Universe, and Everything";
var g = new Guide(42);
console.log(g.q); // "Life, the Universe, and Everything"
console.log(g.a); // 42
When we do new Guide(42)
, the new
operator creates a new object and assigns it a prototype using the Guide.prototype
property. 当我们执行
new Guide(42)
, new
运算符会创建一个新对象,并使用Guide.prototype
属性为其分配原型 。 Then new
calls Guide
, passing in that new object as this
. 然后,
new
电话Guide
,传递新的对象作为this
。 Guide
uses this
to add properties to the new object that aren't on its prototype. Guide
使用this
将属性添加到新的对象,不在它的原型。 Then the new
expression completes and its result is the new object that it created. 然后
new
表达式完成,其结果是它创建的新对象。
When we look at gq
, since the g
object doesn't have its own property called q
, the JavaScript engine looks at g
's prototype, which (again) it got assigned when it was created. 当我们查看
gq
,由于g
对象没有自己的属性q
,JavaScript引擎会查看g
的原型,它(再次)在创建时分配了它。 That prototype has a q
property, and so the engine uses its value. 该原型具有
q
属性,因此引擎使用其值。
In contrast, when we look at ga
, the g
object has its own property called a
, and so the value is used directly. 相反,当我们查看
ga
, g
对象有自己的属性a
,因此直接使用该值。
With that foundation in place, let's look at Student
and Parent
: 有了这个基础,让我们来看看
Student
和Parent
:
function Student() {
// Call the parent constructor
Person.call(this);// <---- Confusion
}
When we call new Student()
, within the call to Student
, this
is (again) the new object created by the new
operator, which has Student.prototype
as its underlying prototype. 当我们调用
new Student()
,在对Student
的调用中, this
是(再次)由new
运算符创建的新对象,它具有Student.prototype
作为其底层原型。 But the Parent
function hasn't had a chance to do anything with this new object. 但是
Parent
函数没有机会对这个新对象做任何事情。 So what that line does is give Parent
a chance to do whatever it needs to do to new objects that it can't do via the prototype, like our Guide
function earlier assigning to this.a
. 那么该行的作用是让
Parent
有机会对它不能通过原型做的新对象做任何事情,就像之前指定给this.a
Guide
函数一样。 In technical terms, Parent.call(this);
在技术方面,
Parent.call(this);
calls the Parent
function, ensuring that this
within the call to Parent
is the value passed into call
(which is, in this case, the this
of the call to Student
— eg, the new object). 调用
Parent
功能,确保this
调用中Parent
是传递到值call
(这是在这种情况下, this
调用的Student
-例如,新的对象)。 If you're familiar with class-based languages, this is like doing super();
如果你熟悉基于类的语言,这就像做
super();
(that's Java, but you get the idea) in a derived constructor: It gives the base constructor a chance to initialize the object. (这是Java,但你明白了)在派生的构造函数中:它为基础构造函数提供了初始化对象的机会。
// inherit Person
Student.prototype = new Person(); //<---- Confusion
Since Student
is supposed to inherit from Person
, what that code is doing is creating the prototype that will be assigned to objects created via new Student
. 由于
Student
应该从Person
继承,因此该代码正在创建的原型将分配给通过new Student
创建的对象。 The object it's creating is a Person
object. 它创建的对象是
Person
对象。
FWIW, that code isn't quite implementing the construction chain correctly (it's calling Person
more often than it should [both when creating Student.prototype
and when Student
is called], and failing to set constructor
). FWIW,该代码并没有完全正确地实现构造链(它更频繁地调用
Person
[创建Student.prototype
和调用Student
时],并且没有设置constructor
)。
The more correct way to create Student
's prototype
property, if we're going to call Parent
from within Student
, looks like this: 创建
Student
的prototype
属性的更正确的方法,如果我们要从Student
调用Parent
,看起来像这样:
function derive(child, parent) {
function ctor() { this.constructor = child; }
ctor.prototype = parent.prototype;
child.prototype = new ctor();
}
derive(Student, Parent);
That way, we get a prototype based on Parent.prototype
but without calling Parent
. 这样,我们得到一个基于
Parent.prototype
的原型,但没有调用Parent
。 It's an either-or: Either call Parent
to create Student.prototype
, or call Parent
within Student
, but don't do both. 它是一个 - 或者: 要么调用
Parent
来创建Student.prototype
, 要么在Student
调用Parent
,但不要同时执行这两个操作。 When building hierarchies with constructor functions, typically you want to call the parent from the child constructor, rather than when creating the child prototype. 使用构造函数构建层次结构时,通常需要从子构造函数调用父级,而不是在创建子级原型时。 When using direct object inheritance (without constructor functions), of course you do it the other way.
当使用直接对象继承(没有构造函数)时,你当然是以另一种方式做到这一点。
If you're interested in inheritance in JavaScript, I've written a helper script called Lineage
you might want to look at, and in particular even if you don't use Lineage
, this discussion on its wiki page may be useful for understanding inheritance hierarchies. 如果您对JavaScript中的继承感兴趣,我编写了一个名为
Lineage
的帮助脚本,您可能希望查看,特别是即使您不使用Lineage
,在其Wiki页面上进行此讨论可能对理解继承有用层次结构。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.