0

How does one call another object's method in the current method?

Example:

function OjbectA() {}

ObjectA.prototype.doWork = function () {
  alert('do work');
}

var objectA = new ObjectA();

function ObjectB() {}

ObjectB.prototype.method = function() {

   // How to call Object A's doWork() method
}

Current attempt:

// Call doWork
ObjectA.doWork();

Error: "Type Error: doWork() function is not defined.

Question:

What is the correct way to call the method of another object WITHIN the method. What about scoping?

Does ObjectA have to instantiated to call it's methods?

What about the apply() or call() method? I am confused how they apply in this situation.

Final remarks

I want to thank everyone's input in advance. I have only recently made the dive into javascript's OOP. This seemingly simple question is something that I have been struggling all day and I came on here as a final resort.

ProfileTwist
  • 1,524
  • 1
  • 13
  • 18
  • You assigned the object to `objectA`, so you have to use `objectA.doWork()`. `ObjectA` refers to the constructor function. – Felix Kling Aug 07 '14 at 04:02
  • I think `ObjectA.prototype.doWork.call(this)` is one of the best answers if you were looking to extend the function. Like you'd want to re use the code in ObjectA.prototype.doWork but then do something extra in ObjectB.prototype.doWork before or after A is done. More info on this can be found here: http://stackoverflow.com/a/16063711/1641941 – HMR Aug 07 '14 at 13:43

5 Answers5

1

There is a typo, not ObjectA.doWork(); use objectA.doWork();

user626818
  • 1,338
  • 1
  • 11
  • 12
  • Is there a way to call the method without instantiating the object? – ProfileTwist Aug 07 '14 at 04:02
  • 1
    @ProfileTwist: Not if you define the method as an instance method. I mean, the whole point of assigning something to the prototype is so that instances of the constructor function share those properties. If you don't need an object at all, why do you even use constructor + prototype instead of just defining a function? – Felix Kling Aug 07 '14 at 04:02
  • @ProfileTwist ``ObjectA.prototype.doWork();`` – user626818 Aug 07 '14 at 04:04
1

What is the correct way to call the method of another object WITHIN the method. What about scoping?

There is no one "correct" way. Presumably you want to be able to call a method of ObjectA instances (i.e. a method of ObjectA.prototype) but have an instance of ObjectB as this, so:

ObjectB.prototype.method = function() {

    // How to call Object A's doWork() method
    ObjectA.prototype.doWork.call(this);
}

That will call the method and set the instance of ObjectB as this.

Does ObjectA have to instantiated to call it's methods?

If you mean "does and instance of ObjectA have to instantiated to call its methods" then no, as shown above. You can call the method on the constructor's prototype directly.

What about the apply() or call() method? I am confused how they apply in this situation.

See the answer to the first question. Whether to use call or apply depends on the arguments that need to be passed and whether you intend do to any processing on them first.

Additional answers

Could you explain the mechanics of ObjectA.prototype.doWork.call(this) a little more?

It calls the method and sets its this to the supplied object. The rules for how a value is assigned to this are explained in EMCA–2626 §10.4.3.

Would ObjectA.prototype.doWork(this) work just the same way?

No. That calls the function, sets its this to ObjectA.prototype and supplies the value of this from the calling execution context as the first parameter. e.g. if it's global code in a browser, effectively:

ObjectA.prototype.doWork(window);
RobG
  • 142,382
  • 31
  • 172
  • 209
  • Fantastic explanation! Could you explain the mechanics of `ObjectA.prototype.doWork.call(this)` a little more? Would `ObjectA.prototype.doWork(this)` work just the same way? – ProfileTwist Aug 07 '14 at 04:21
1

It's possible to call it from the prototype directly.

Using apply changes the value of this in the execution of the function to the supplied value, so its essentially forwarding this to be itself in the call. You could also use call, the difference is just in how it takes its arguments, apply takes an array whereas call takes an argument list.

ObjectB.prototype.method = function() {
  ObjectA.prototype.doWork.apply(this);
}

However of course an ObjectB does not necessarily have same properties as an ObjectA so make sure you write the method as generic as possible. In order words use a documented concept rather than internal implementation details.

Example again lies with how Array, it's generically applicable methods are documented as such and states what is required for it to work.

In the case you just want to expose a 'utility function', just put it on the object itself. e.g

ObjectA.doWork = function(obj) {
};
Casper Beyer
  • 2,203
  • 2
  • 22
  • 35
  • Good point. The main purpose of object A vs. object B is to keep the methods organized (encapsulated?). Would you recommend this practice or should I just keep it with global functions `objectAFunction1()`, `objectBFunction1()`. Feedback is appreciated! – ProfileTwist Aug 07 '14 at 04:25
  • @ProfileTwist hard to determine by arbitrary means, functions are either properties of an object or utility functions, e.g an object can do something. Such as an array can be sliced, so its a prototype method. Now calculating the intersection between two rectangles is a utility function and would be more appropriately put on the constructor, e.g `Rectangle.intersect(a, b)`. So if i'd condense that to one sentence i suppose it would be 'Is it a property of the object or utility functionality?'. – Casper Beyer Aug 07 '14 at 04:41
  • 1
    @ProfileTwist: In that case, don't use constructor functions. Just create an object with methods, e.g. `var Rectangle = {intersect: function() { ... }};`. – Felix Kling Aug 07 '14 at 18:26
1

There really seems to be some confusion with JavaScript's general OOP model.

Every function has an underlying prototype, which is just an object. You may or may not add anything to it, but if you do, you probably plan to use that function as a constructor. That's what you see happening here:

function ObjectA() {}

ObjectA.prototype.doWork = function () {
  alert('do work');
}

var objectA = new ObjectA();

objectA.doWork();

However, in some instances, it might be more appealing to just create a function with some methods directly attached to it, rather than creating instances of it. Generally, these would be static methods as in other languages, or perhaps your function is really just a singleton object. In this case, you would omit the prototype, and just attach directly, like so:

function ObjectA() {}

ObjectA.doWork = function () {
  alert('do work');
}

ObjectA.doWork()

Going back to the first example, if you define your function and add methods to its prototype, occasionally you may wish to actually call a function that you have defined in a different function's prototype. call and apply can be used to call any function with the value of this changing to the object which you pass into apply or call.

Remember that you are attaching methods to the prototype, so it may look a little funky, but here's an example:

function ObjectA() {}

ObjectA.prototype.doWork = function () {
    console.log(this)
}

var objectA = new ObjectA();

function ObjectB() {}

ObjectB.prototype.method = function() {

   ObjectA.prototype.doWork.call(this);
}

var objectB = new ObjectB();

objectB.method() 

// -> objectB will be logged to your console, bc 
// it became the value of this in ObjectA's doWork method.
ncksllvn
  • 5,699
  • 2
  • 21
  • 28
0

After all I found your typo:

function OjbectA() {}

Should be function ObjectA() {}

That's why you were facing error.


function ObjectA() {}

ObjectA.prototype.doWork = function () {
  alert('do work');
}

var objectA = new ObjectA();

function ObjectB() {}

ObjectB.prototype.method = function() {

   objectA.doWork()
}
Bhojendra Rauniyar
  • 83,432
  • 35
  • 168
  • 231