I have two codes of JavaScript,they are the same result of executing,so i am confused and wonder why we use call function.
Not use function call:
<script language="javascript">
function ClassA(obj, sColor) {
obj.color = sColor;
obj.sayColor = function() {
alert(obj.color);
};
}
function ClassB(sColor, sName) {
ClassA(this, sColor);
this.name = sName;
this.sayName = function () {
alert(this.name);
};
}
var objB = new ClassB("red", "Luke");
objB.sayColor();
objB.sayName();
use function call:
<script language="javascript">
function ClassA(sColor) {
this.color = sColor;
this.sayColor = function() {
alert(this.color);
};
}
function ClassB(sColor, sName) {
ClassA.call(this,sColor);
this.name = sName;
this.sayName = function () {
alert(this.name);
};
}
var objB = new ClassB("red", "Luke");
objB.sayColor();
objB.sayName();
In this instance, the outcome is the same, but these two code snippets are very different. In the first, ClassA
is not following the pattern of an object constructor. Instead, it takes as its argument an object, and it modifies that object (by adding a property and method to it). While the syntax is valid, I would argue that this is poor practice, because naming a function that starts with an uppercase letter usually indicates it is an object constructor, and therefore it should use this
, not modify one of its arguments. It also exhibits inconsistent behavior:
var objA = new ClassA(); // will throw error
var objB = new ClassB(); // valid object constructor
The second example is a more standard example of object construction in JavaScript. You can create an instance of ClassA
by saying new ClassA
and you can create an instance of ClassB
by calling new ClassB
. Nice and consistent.
I would go with the second example. I would also read up on object models in JavaScript to get a better understanding of what's going on here. A good place to start is Douglas Crockford's essay on object-oriented programming in JavaScript .
I totally agree with what @EthanBrown has said. If you have a function which its responsibility is to modify an object, don't start your function's name with an uppercase letter.
Other than this, the whole idea behind your code is to add the color
and sayColor
to the ClassB, which is kind of inheriting.
The point here is, the second snippet is the way we usually implement inheritance
in JavaScript. it doesn't mean that your code has completely implemented inheritance
, but the idea of using call
in a constructor
to invoke another constructor is mostly used in inheritance. if you want to completely inherit the ClassB
from ClassA
, the only missing parts is to copy the prototypes, and set the constructor, like this:
ClassB.prototype = Object.create(ClassA.prototype);
ClassB.constructor = ClassA;
the only drawback in your second snippet is not using prototype
, you better use it to create the sayColor
and sayName
function, and if you completely implement the inheritance in your code, using the 2 lines above, then you can easily do this:
ClassA.prototype.sayColor = function() {
alert(this.color);
};
ClassB.prototype.sayName = function() {
alert(this.color);
};
then you can create you ClassB
instance:
var objB = new ClassB("red", "Luke");
objB.sayColor();
objB.sayName();
and the most important point here is:
objB instanceof ClassA;
objB instanceof ClassB;
both are true.
you can create a simple inherit method like:
function inherit(class, baseClass){
class.prototype = Object.create(baseClass.prototype);
class.constructor = baseClass;
}
then use it like:
function ClassA(sColor) {
this.color = sColor;
}
ClassA.prototype.sayColor = function() {
alert(this.color);
};
function ClassB(sColor, sName) {
ClassA.call(this, sColor);
this.name = sName;
}
ClassB.prototype.sayName = function() {
alert(this.color);
};
inherit(ClassB, ClassA);
call is used when you want to control the scope that will be used in the function called(we inject the scope inside the function). You might want the this keyword to be something else than the scope you assigned the function to, in those cases you need to use call or apply to bring the right scope into the function.
Some example:
function ClassA(sColor) {
// if we say ClassA.call(window), **this** will be window (inject)
this.color = sColor;
this.sayColor = function() {
alert(this.color);
};
}
// use call method
ClassA.call(window, "red");
ClassA.call(document, "blue"); // after this document will have sayColor method
After calling ClassA function we extend WINDOW object, and now you call window.sayColor method.
So we use call method in your example to extend ClassB object
function ClassB(sColor, sName) {
ClassA.call(this,sColor);
this.name = sName;
this.sayName = function () {
alert(this.name);
};
}
Now when you write next code:
var b = new ClassB("Color", "Name");
// b will have sayName method, sayColor method
the non-call way is just like this, in the constructor of ClassB, the function ClassA is called to add a property and method to current ClassB instance. in this case, obj in ClassA points to current ClassB's object.
in the call way, in the constructor of ClassB, call function ClassA but change its execution context to current ClassB object. in this case, the 'this' points to ClassB's object.
so in the above two cases, obj and this in ClassA both point to ClassB objects.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.