0

If I make an object through a new constructor() call, to something like this:

function constructor(){
    function privateFn(){
        console.log('this is private');
    }
    this.publicFn = function(){
        console.log('this is public');
    }
    function doSomething(){
        privateFn();
        publicFn();
    }
    console.log(this.publicFn ? "exists" : "does not exist"); // logs exists
    doSomething(); //throws an error -> publicFn() is not this.publicFn().
}
new constructor();

So the question is, is there any way to make this accessible without the this. part? My IDE (netbeans) appears to recognize it even without the this. though that doesn't necessarily mean anything, but it got me wondering, is it possible to somehow reference publicFn() as a function, rather then as a property of the object? Maybe construct it differently?

EDIT: The goal is to create an object which has both private and public methods, with the new constructor, but simultaneously allow the constructor itself as well as all the object's methods to call the public methods without the this. prefix.

SPECIAL EDIT FOR BEKIM BACAJ

Updated this section specially for you just to show you what I mean. It is not the console.log tricking me, the call to a doSomething or whatever other method comes after the object is indeed created. It is still not accessible though, and now that I've seen the answer as to why, it makes some sense. The contextual this is not the same for the private methods, or rather the functions within the constructor have this set to window, so their contextual this is not the same as that of the public method they are attempting to call. The pattern that Phylogenesis suggested is what I am looking for and it fits the needs.

function constructor(){
    function privateFn(){
        console.log('Call to privateFN succesful');
        console.log('------------------------------------------------------------------------------------');
    }
    function doSomething(){
        console.log('Executing: doSomething;');
        //I want to be able to access both private and public methods here (which i can)
        //I want to be able to access them the same way (which I cannot).
        privateFn(); //works
        publicFn(); //error 
        //Read NOTE1 below.
    }
    this.callDoSomething = function(){
        console.log('Call to callDoSomething succesful');
        console.log('------------------------------------------------------------------------------------');
        //made just so that you can access doSomething from the outside to test.
        doSomething();
    };
    this.publicFn = function(){
        console.log('Call to publicFN succesful');
        console.log('------------------------------------------------------------------------------------');
    };
    //.... many more methods (we are talking hundreds)
    //.... some of them are public, some are private
    //.... some are resutls of calling functions that return functions from other files (collaborative work), 
    //.... these might be public or private, which we achive like so:
    //.... var externalModule = extrenalModuleInitializer(this);
    //.... as you can imagine this externalModuleInitializer function can either:
    //.... A) PRIVATE: return a function, making this externalModule variable a private method
    //.... B) PUBLIC: do stuff with the `this` object that was passed, adding public methods to it
    //.... So since I do not know if certain parts of this object will be private or public, i need
    //.... a way to access them in the same way in order to make the coding easier.
}

console.clear();
var a = new constructor();
a.publicFn();
a.callDoSomething();
Dellirium
  • 1,362
  • 16
  • 30
  • everything is wrong with your approach and therefore the code itself – Bekim Bacaj Oct 19 '17 at 09:39
  • @BekimBacaj then do explain what is the proper way – Dellirium Oct 19 '17 at 09:43
  • It is very unclear what you are trying to do first you are using new fn - there's no such constructor, than you are calling a function which calls a function which is not there yet. – Bekim Bacaj Oct 19 '17 at 09:47
  • methods in constructor without ```this``` can not be publicly available – Aliaksandr Pitkevich Oct 19 '17 at 09:49
  • The `new fn()` in the top of the post is just rethorical, the constructor used is the one displayed bellow in code. The goal is to allow an object constructed with this constructor to have private and public methods, and to simultaneously allow both public and private methodes, as well as the constructor itself to reference all of the other members visible to them without the use of `this.` – Dellirium Oct 19 '17 at 09:49
  • 1
    Why do you want to avoid the use of `this`? – Jonah Oct 19 '17 at 09:50
  • @Jonah it makes it easier for implementation when you do not have to worry if the method which you can access (because you can, its visible) is accessible via `this.name()` or just `name()`. You do not access private and public members of classes in different manner other languages, so I am trying to see if I can make it so that they are accessed in same manner in JS. (we are talking from within the object itself, not the outside world). There will be hundreds of methods, it is tedious to keep track of which is private and which is public, especially once they start going into prototypes. – Dellirium Oct 19 '17 at 09:57
  • no this is still muddy give us a usage example - what and how would you like to use this object after it has been created with clear code declarations even if it doesn't currently work that way. Give us a use case of all these private and own property functions. – Bekim Bacaj Oct 19 '17 at 10:09
  • @BekimBacaj I am not sure what is it that you do not understand? What and how would I use the object? I would call it's public methods from wherever I instantiated it, like any other object. Its a concept that we are talking about here. Being able to call private and public methods from WITHIN the object itself the same way without having to worry weather a `this.` needs to be prefixed to a method. The use case is, everyday usage of any big ass object where you do not necessarily know if certain parts of it are private or public. (Collaborative work might come to mind) – Dellirium Oct 19 '17 at 10:19
  • Still not clear. Give us a user scenario. You probably don't even need a constructor at all for that matter. And as already mentioned, constructor properties will be available to you as soon as you've created its object instance. And you are not being able to access the this property beforehand you are being tricked by the console log because the requests for those properties are being stacked in the order they've been called and only after the function exits they will be printed. – Bekim Bacaj Oct 19 '17 at 11:12
  • @BekimBacaj updated the question with a section meant for you and your comments, though since Phylogenesis gave an answer, I do not think it is of much use. Still if you want to understand the use-case / what I need this for it is there. – Dellirium Oct 19 '17 at 12:04

4 Answers4

3

I think what you are really after is called the module pattern:

function MyConstructor() {
  var publicFn = function () {
    console.log('this is public');
  }

  var privateFn = function () {
    console.log('this is private');
  }

  var doSomething = function () {
    privateFn();
    publicFn();
  }

  doSomething();

  return {
    publicFn: publicFn
  };
}

Note how you return a list of the "publicly" accessible methods, but nothing internally refers to this.

An example of this is here.

Phylogenesis
  • 7,775
  • 19
  • 27
  • Precisely what I needed. Though I'd still just append `this.publicFn = publicFn;` and leave the return of the original this. That way the object truly returns the intended this with constructor, yes? – Dellirium Oct 19 '17 at 11:52
  • Yes, if you want to use the implicit return, that's fine. Bear in mind, however, that this is slightly more memory inefficient than the normal way to handle prototypes (to attach methods to the prototype itself rather than to each instance). – Phylogenesis Oct 19 '17 at 12:04
  • Great. Then this is precisely what is needed. – Dellirium Oct 19 '17 at 12:05
  • @Dellirium as already told you ÿou don't need a constructor at all. And this is no constructor at all this is a plain function as any other. – Bekim Bacaj Oct 19 '17 at 12:28
  • To be fair, all constructors in JavaScript are just plain functions. It is really the `new` operator that does all the work (returns the called function's `this` object). – Phylogenesis Oct 19 '17 at 12:37
0

I'm not sure if it fits what you need, but this (the return statement at the end) exposes the method:

function constructor(){ function privateFn(){ console.log('this is private'); } this.publicFn = function(){ console.log('this is public'); } function doSomething(){ privateFn(); publicFn(); } return{ publicFn: this.publicFn } }

And you can call it like this:

var constr = constructor(); constr.publicFn();

Jorge Guberte
  • 10,464
  • 8
  • 37
  • 56
  • Does not fit what I need, the method is exposed as soon as i call the constructor with `new`, but what i need is to be able to reference the method within the constructor (and other functions inside the constructor's scope) without the usage of `this`, I am not sure if it is possible. – Dellirium Oct 19 '17 at 09:39
0

this is a reference to an object that is gonna be created (but does not exist yet) based on prototype your function describes, so you can't avoid this keyword when declaring public method. Technically you can define this function outside the constructor like this:

function publicFn(){}

function constructor() {
  ....
}

var obj = new constructor();
obj.publicFn = publicFn;

but, I'm afraid, it doesn't make much sense

dr_leevsey
  • 365
  • 4
  • 15
  • But if the object is going to be created and yet does not exist, how am I able to do the following: `console.log(this.publicFn ? "exists" : "doesnt exist");` and it will say "exists" right before calling the `publicFn()` (which happens to throw an error :SSS – Dellirium Oct 19 '17 at 09:41
  • And what happens when you do `console.log(publicFn ? "exists" : "doesn't exist");`? You are comparing different things. – Phylogenesis Oct 19 '17 at 09:52
  • Provide the full code (where did you place console.log) – dr_leevsey Oct 19 '17 at 09:53
  • @dr_leevsey I edited the post to reflect the console.log. I had it in there but deleted it as I think it will just cause additional confusion. The console.log itself notes that `this.publicFn` is indeed present at the time of `doSomething()`'s execution. The thing is, `doSomething` does not have a reference to `this.publicFn()`, it attempts to use `publicFn` and apparently even if the context of `doSomething`'s this is the same object as publicFn's this it doesn't see fit to run it. – Dellirium Oct 19 '17 at 10:08
  • @Phylogenesis it throws an uncought reference error actually, to my surprise o.0? I was certain it would write "doesn't exist", but it does not. – Dellirium Oct 19 '17 at 10:12
0

To devise this response, I relied on the technique of "Using self invoking function and call" offered by Yves M.in this discussion

var Constructor = (function (){

    function Constructor (){}

    function privateFn(){
        console.log('this is private');
    }

    Constructor.prototype.publicFn = function(){
        console.log('this is public');
        
    }
    Constructor.prototype.doSomething = function(){
        return privateFn.call(this);
    }
    
    return Constructor;
})();    

var Constructor = new Constructor();
Constructor.publicFn();
Constructor.doSomething();

Note: even though the empty constructor method seemingly does nothing it is essential to the code running without error. Otherwise, you'll see an error message stating: "Cannot read property 'prototype' of undefined",

What makes the privateFn() method hidden is that it is not part of the prototype for the Constuctor object. Also, I was able to get the privateFn's call method to work without providing a this parameter, however it is part of the signature of the call method. Per the documentation, neglecting to provide this results in a null and undefined parameter being "... replaced with the global object and primitive values will be converted to objects."

slevy1
  • 3,797
  • 2
  • 27
  • 33
  • The goal is to obscure the private and expose the public within an object created when the call is made with `new` whilst still preserving the possibility to reference the public methods internally without the use of `this.` – Dellirium Oct 19 '17 at 09:42
  • @Dellirium see if this helps. [Emulating private methods with closures](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures#Emulating_private_methods_with_closures) – Jorge Guberte Oct 19 '17 at 09:44
  • Yeah i know how closures work, this whole `constructor` is indeed emulating private methods such as the `privateFn` because its a closure. However (edited the post above) I am trying to make it so that both public and private membres are visible to the object itself (which is a standard behaviour) without the usage of `this.` as within the object we shouldn't be forced to differentiate between their calls. If we were to talk other languages, within an object you can call private and public members the same way, just `name()` there is no need for `this.name()` on publics. – Dellirium Oct 19 '17 at 09:52