Putting methods on Object.getPrototypeOf(this) - javascript

See this class definition:
function MyClass (property) {
// Private
var privateVariable;
var privateMethod = function () {};
// Public
this.publicProperty = property;
this.publicPrivilegedMethodOnInstance = function () {};
Object.getPrototypeOf(this).publicPrivilegedMethodOnPrototype = function () {};
}
MyClass.prototype.publicMethod = function () {};
var myMyClass = new MyClass('foo');
The method publicPrivilegedMethodOnPrototype is public, yet can access private variables (which publicMethod) can’t. It’s also shared on the prototype, which publicPrivilegedMethodOnInstance is not.
Any downsides of defining publicPrivilegedMethodOnPrototype like this? I guess ECMAScript 5 is a requirement, and that the method is redefined every time MyClass is instantiated.

It's a very bad idea.
So you create many objects but as you're assigning the property to the prototype of all of them, at some point even functions which weren't meant to access certain values will do it... This is very odd.
A given prototype function is meant to access properties from the object whose own the prototype using this:
function X() {
this.text = "hello world";
}
X.prototype.doStuff() {
console.log(this.text);
};
Thus, avoid that anti-pattern. It makes no sense. My advise is that you need to deal with the absense of access modifiers in JavaScript instead of blindly looking for a workaround.

Related

How can I pass 'this' object to lower function in javascript? [duplicate]

In C++, the language I'm most comfortable with, usually one declares an object like this:
class foo
{
public:
int bar;
int getBar() { return bar; }
}
Calling getBar() works fine (ignoring the fact that bar might be uninitialized). The variable bar within getBar() is in the scope of class foo, so I don't need to say this->bar unless I really need to make it clear that I'm referring to the class' bar instead of, say, a parameter.
Now, I'm trying to get started with OOP in Javascript. So, I look up how to define classes and try the same sort of thing:
function foo()
{
this.bar = 0;
this.getBar = function() { return bar; }
}
And it gives me bar is undefined. Changing the bar to this.bar fixes the issue, but doing that for every variable clutters up my code quite a bit. Is this necessary for every variable? Since I can't find any questions relating to this, it makes me feel like I'm doing something fundamentally wrong.
EDIT: Right, so, from the comments what I'm getting is that this.bar, a property of an object, references something different than bar, a local variable. Can someone say why exactly this is, in terms of scoping and objects, and if there's another way to define an object where this isn't necessary?
JavaScript has no classes class-based object model. It uses the mightier prototypical inheritance, which can mimic classes, but is not suited well for it. Everything is an object, and objects [can] inherit from other objects.
A constructor is just a function that assigns properties to newly created objects. The object (created by a call with the new keyword) can be referenced trough the this keyword (which is local to the function).
A method also is just a function which is called on an object - again with this pointing to the object. At least when that function is invoked as a property of the object, using a member operator (dot, brackets). This causes lots of confusion to newbies, because if you pass around that function (e.g. to an event listener) it is "detached" from the object it was accessed on.
Now where is the inheritance? Instances of a "class" inherit from the same prototype object. Methods are defined as function properties on that object (instead of one function for each instance), the instance on which you call them just inherits that property.
Example:
function Foo() {
this.bar = "foo"; // creating a property on the instance
}
Foo.prototype.foo = 0; // of course you also can define other values to inherit
Foo.prototype.getBar = function() {
// quite useless
return this.bar;
}
var foo = new Foo; // creates an object which inherits from Foo.prototype,
// applies the Foo constructor on it and assigns it to the var
foo.getBar(); // "foo" - the inherited function is applied on the object and
// returns its "bar" property
foo.bar; // "foo" - we could have done this easier.
foo[foo.bar]; // 0 - access the "foo" property, which is inherited
foo.foo = 1; // and now overwrite it by creating an own property of foo
foo[foo.getBar()]; // 1 - gets the overwritten property value. Notice that
(new Foo).foo; // is still 0
So, we did only use properties of that object and are happy with it. But all of them are "public", and can be overwritten/changed/deleted! If that doesn't matter you, you're lucky. You can indicate "privateness" of properties by prefixing their names with underscores, but that's only a hint to other developers and may not be obeyed (especially in error).
So, clever minds have found a solution that uses the constructor function as a closure, allowing the creating of private "attributes". Every execution of a javascript function creates a new variable environment for local variables, which may get garbage collected once the execution has finished. Every function that is declared inside that scope also has access to these variables, and as long as those functions could be called (e.g. by an event listener) the environment must persist. So, by exporting locally defined functions from your constructor you preserve that variable environment with local variables that can only be accessed by these functions.
Let's see it in action:
function Foo() {
var bar = "foo"; // a local variable
this.getBar = function getter() {
return bar; // accesses the local variable
}; // the assignment to a property makes it available to outside
}
var foo = new Foo; // an object with one method, inheriting from a [currently] empty prototype
foo.getBar(); // "foo" - receives us the value of the "bar" variable in the constructor
This getter function, which is defined inside the constructor, is now called a "privileged method" as it has access to the "private" (local) "attributes" (variables). The value of bar will never change. You also could declare a setter function for it, of course, and with that you might add some validation etc.
Notice that the methods on the prototype object do not have access to the local variables of the constructor, yet they might use the privileged methods. Let's add one:
Foo.prototype.getFooBar = function() {
return this.getBar() + "bar"; // access the "getBar" function on "this" instance
}
// the inheritance is dynamic, so we can use it on our existing foo object
foo.getFooBar(); // "foobar" - concatenated the "bar" value with a custom suffix
So, you can combine both approaches. Notice that the privileged methods need more memory, as you create distinct function objects with different scope chains (yet the same code). If you are going to create incredibly huge amounts of instances, you should define methods only on the prototype.
It gets even a little more complicated when you are setting up inheritance from one "class" to another - basically you have to make the child prototype object inherit from the parent one, and apply the parent constructor on child instances to create the "private attributes". Have a look at Correct javascript inheritance, Private variables in inherited prototypes, Define Private field Members and Inheritance in JAVASCRIPT module pattern and How to implement inheritance in JS Revealing prototype pattern?
Explicitly saying this.foo means (as you've understood well) that you're interested about the property foo of the current object referenced by this. So if you use: this.foo = 'bar'; you're going to set the property foo of the current object referenced by this equals to bar.
The this keyword in JavaScript doesn't always mean the same thing like in C++. Here I can give you an example:
function Person(name) {
this.name = name;
console.log(this); //Developer {language: "js", name: "foo"} if called by Developer
}
function Developer(name, language) {
this.language = language;
Person.call(this, name);
}
var dev = new Developer('foo', 'js');
In the example above we're calling the function Person with the context of the function Developer so this is referencing to the object which will be created by Developer. As you might see from the console.log result this is comes from Developer. With the first argument of the method call we specify the context with which the function will be called.
If you don't use this simply the property you've created will be a local variable. As you might know JavaScript have functional scope so that's why the variable will be local, visible only for the function where it's declared (and of course all it's child functions which are declared inside the parent). Here is an example:
function foo() {
var bar = 'foobar';
this.getBar = function () {
return bar;
}
}
var f = new foo();
console.log(f.getBar()); //'foobar'
This is true when you use the var keyword. This means that you're defining bar as local variable if you forget var unfortunately bar will became global.
function foo() {
bar = 'foobar';
this.getBar = function () {
return bar;
}
}
var f = new foo();
console.log(window.bar); //'foobar'
Exactly the local scope can help you to achieve privacy and encapsulation which are one of the greatest benefits of OOP.
Real world example:
function ShoppingCart() {
var items = [];
this.getPrice = function () {
var total = 0;
for (var i = 0; i < items.length; i += 1) {
total += items[i].price;
}
return total;
}
this.addItem = function (item) {
items.push(item);
}
this.checkOut = function () {
var serializedItems = JSON.strigify(items);
//send request to the server...
}
}
var cart = new ShoppingCart();
cart.addItem({ price: 10, type: 'T-shirt' });
cart.addItem({ price: 20, type: 'Pants' });
console.log(cart.getPrice()); //30
One more example of the benefits of the JavaScript scope is the Module Pattern.
In Module Pattern you can simulate privacy using the local functional scope of JavaScript. With this approach you can have both private properties and methods. Here is an example:
var module = (function {
var privateProperty = 42;
function privateMethod() {
console.log('I\'m private');
}
return {
publicMethod: function () {
console.log('I\'m public!');
console.log('I\'ll call a private method!');
privateMethod();
},
publicProperty: 1.68,
getPrivateProperty: function () {
return privateProperty;
},
usePublicProperty: function () {
console.log('I\'ll get a public property...' + this.publicProperty);
}
}
}());
module.privateMethod(); //TypeError
module.publicProperty(); //1.68
module.usePublicProperty(); //I'll get a public property...1.68
module.getPrivateProperty(); //42
module.publicMethod();
/*
* I'm public!
* I'll call a private method!
* I'm private
*/
There's a little strange syntax with the parentless wrapping the anonymous functions but forget it for the moment (it's just executing the function after it's being initialized). The functionality can be saw from the example of usage but the benefits are connected mainly of providing a simple public interface which does not engages you with all implementation details. For more detailed explanation of the pattern you can see the link I've put above.
I hope that with this :-) information I helped you to understand few basic topics of JavaScript.
function Foo() {
this.bar = 0;
this.getBar = function () { return this.bar };
}
When you call the function above with the new keyword - like this...
var foo = new Foo();
... - a few things happen:
1) an object is created
2) the function is executed with the this keyword referencing that object.
3) that object is returned.
foo, then, becomes this object:
{
bar: 0,
getBar: function () { return this.bar; }
};
Why not, then, just do this:
var foo = {
bar: 0,
getBar: function () { return this.bar; }
};
You would, if it's just that one simple object.
But creating an object with a constructor (that's how it's called) gives us a big advantage in creating multiple of the "same" objects.
See, in javascript, all functions are created with a prototype property [an object], and all objects created with that function (by calling it with the new keyword) are linked to that prototype object. This is why it's so cool - you can store all common methods (and properties, if you wanted to) in the prototype object, and save a lot of memory. This is how it works:
function Foo( bar, bob ) {
this.bar = bar;
this.bob = bob;
}
Foo.prototype.calculate = function () {
// 'this' points not to the 'prototype' object
// as you could've expect, but to the objects
// created by calling Foo with the new keyword.
// This is what makes it work.
return this.bar - this.bob;
};
var foo1 = new Foo(9, 5);
var foo2 = new Foo(13, 3);
var result1 = foo1.calculate();
var result2 = foo2.calculate();
console.log(result1); //logs 4
console.log(result2); //logs 10
That's it!
To get closer to OOP in JavaScript, you might want to take a look into a Module design pattern (for instance, described here).
Based on the closure effect, this pattern allows emulating private properties in your objects.
With 'private' properties you can reference them directly by its identifier (i.e., no this keyword as in constructors).
But anyway, closures and design patterns in JS - an advanced topic. So, get familiar with basics (also explained in the book mentioned before).
In javascript this always refers to the owner object of the function. For example, if you define your function foo() in a page, then owner is the javascript object windows; or if you define the foo() on html element <body>, then the owner is the html element body; and likewise if you define the function onclick of element <a>, then the owner is the anchor.
In your case, you are assigning a property bar to the 'owner' object at the begining and trying to return the local variable bar.
Since you never defined any local varialbe bar, it is giving you as bar is undefined.
Ideally your code should have defined the variable as var bar; if you want to return the value zero.
this is like a public access modifier of objects(variables or functions), while var is the private access modifier
Example
var x = {};
x.hello = function(){
var k = 'Hello World';
this.m = 'Hello JavaScript';
}
var t = new x.hello();
console.log(t.k); //undefined
console.log(t.m); //Hello JavaScript

Call ES5 class method from static method

I want to call an inner function from a static function that was called without an instance, like so:
Foo.Bar = function (options) {
Autodesk.Viewing.Extension.call(this, options);
...
this.innerFunc = function innerFunc(){
...
}
};
Foo.Bar.prototype.constructor =
Foo.Bar;
Foo.Bar.SomeStaticFunc = function () {
innerFunc();
}
Use: Foo.Bar.SomeStaticFunc();.
But I get SomeStaticFunc is not a function.
The example here uses a variable for the class, like var Foo.Bar = function (options) {... but isn't that the same as making an instance of the class like so and calling an inner function?
let x= new Foo.Bar(options);
x.innerFunc();
Is there another way to do this?
PS: I know about ES6 classes but I prefer not to migrate this class to ES6 for now because it isn't totally straight forward.
Well... It seems that you do not know how JavaScript works internally, so here is a quick recap. :)
JavaScript IS an object-oriented language. Object literals are objects, arrays are objects, functions are objects, etc.
JavaScript IS NOT a class-based language. You could say: "Hey, I've seen class and extends keywords in ES6!". Yes, but this is just syntactic sugar. JavaScript is not based on classes like Java, it is based on prototypes.
With ES5 syntax, there are two ways to create what you call a "class":
An object literal
A constructor function
When you use an object literal, your class looks like this:
var myClass = {
myAttribute: "foo",
myMethod: function () {
return "bar";
}
};
When you use a constructor function, your class looks like this:
function MyClass() {
this.myAttribute = "foo";
this.myMethod = function () {
return "bar";
};
}
There are of course differences between these two approaches. With the object literal, you have a sort of Singleton where properties are all static to some extent. With the constructor function, you can produce instances whose properties will be introduced by the this keyword. Example:
var myInstance = new MyClass();
console.log(myInstance);
This instance will have "myAttribute" and "myMethod" in its own properties. This means that these properties are tied to the instance. If you want to call this method, you must do this:
myInstance.myMethod();
So far so good... But there is something wrong with what we did previously. this.myMethod will be created again and again for each instance of MyClass and it is always the same. A better way to handle this is to put it in the prototype so that it can be shared by all instances:
function MyClass() {
this.myAttribute = "foo";
}
MyClass.prototype.myMethod = function () {
return "bar";
};
This is much better, but myMethod is still tied to MyClass instances...
Now I want to create a static method. By definition, our static method will be tied to the class, not to its instances:
MyClass.myStaticMethod = function () {
return "baz";
};
Nice. Here, for the sake of experimentation, I want to do something like this:
MyClass.myStaticMethod = function () {
myMethod();
};
This does not work. Why? In fact, myMethod does not exist in the given scope nor in the outer scope. myMethod has been declared inside another function (the constructor function) and it is not returned, so it is invisible from the outside. Moreover, this function has been put in the prototype of MyClass. This means that it is not available globally, but only on instances of MyClass. When you think about it, it is pretty logical. For instance, when you want to call array methods (methods in Array.prototype), it does not make sense to do that:
push('test');
reverse();
includes('a');
You must call these methods on an array (instance of Array).
[].push('test');
['foo', 'bar', 'baz'].reverse();
['a', 'b'].includes('a');

Difference between using a module pattern and instantiating new objects

I'm trying to restructure some javascript and I'm confused about the module pattern.
One way I have now is to simply declare a class containing all the functionality for a component like so
var Foo = function(){
this.Bar = {};
...
}
and create a new instance for use in the component. But I've also read about the module pattern and I can't see what the benefit would be compared to what I have since it appears to do about the same, just in a more complicated way. Maybe I just haven't encountered the case that makes it a better choice.
For example, a pattern like this:
var module = (function () {
// private variables and functions
var foo = 'bar';
// constructor
var module = function () {
};
// prototype
module.prototype = {
constructor: module,
something: function () {
}
};
// return module
return module;
})();
var my_module = new module();
doesn't appear significantly different from what I already had. What does this pattern let me do that I can't do the other way?
The key difference between the two is in the first example, you can't have private variables and functions if you want to work with the prototype. You can have private variables and functions, but only if your public properties and methods are created in the constructor by attaching them to this.
Example 1 with a private variable and function:
var Foo = function(){
var privateVar = "priv";
function privateFunction(){
console.log(privateVar);
}
this.publicProperty = 1;
this.publicFunction = function(){
console.log(privateVar);
}
}
The above is no problem if you don't want to use the prototype. However, if you do then there is no way to have private variables, without the new scope that your second example benefits from.
As you can see, you have to include everything within the constructor, whereas the second example you can leave the constructor just for initialising variables.
Conversely, the prototype methods in the second example are out of scope of the constructor, so they can't use any variables of functions within the constructor. All functions and variables that the prototype methods need must be declared in the outer closure scope.

Can you name an instance the same as its constructor name?

Can you name an instance the same as its constructor name?
var myFunc = new function myFunc(){};
?
As it seems, this replaces the Function Object with the new instance... which means this is a good Singleton.
I haven't seen anyone using this, so I guess, there are downsides to this that I am unaware of...
Any thoughts?
YES...
However, it does look weird that you're creating a named function but never refer to it by name.
The more common pattern(s) I've seen are
function MyClass(){
this.val = 5;
};
MyClass.prototype.getValue = function() {
return this.val;
}
MyClass = new MyClass();
But when people do that I wonder why they don't just use a literal object
var MyClass = {
val: 5,
getValue: function() {
return this.val;
}
}
And I would even prefer to use the module pattern here
var MyClass = (function(){
var val = 5;
return {
getValue: function() {
return val;
}
};
})();
Disclaimer
Now whether the singleton pattern should be used, that's another question (to which the answer is NO if you care about testing, dependency management, maintainability, readability)
http://accu.org/index.php/journals/337
Why implementing a Singleton pattern in Java code is (sometimes) considered an anti-pattern in Java world?
As it seems, this replaces the Function Object with the new instance
No, it does not replace anything. The name of a function expression (that's what you have) is only accessible inside the function itself, not outside of it. It would be exactly the same as if you omit the name:
var myFunc = new function(){};
In general, if you don't want certain symbols accessible, just don't make them global. Define those symbols inside a function and just return whatever you want to make accessible, e.g:
var myobj = (function() {
function Foo() {};
// do whatever
return new Foo();
}());
However, if you just want to create a single object, it is often easier to use an object literal:
var myobj = {};
There is no reason to use a constructor function if you only want to create a single instance from it. If you want to establish inheritance, you can use Object.create [MDN]

Creating functions for an object in javascript

As far as I can tell, there are two main ways of creating functions for an object in javascript. They are:
Method A, make it in the constructor:
function MyObject() {
this.myFunc1 = function() {
...
}
this.myFunc2 = function() {
...
}
...
}
Method B, add it to the prototype:
function MyObject() {
...
}
MyObject.prototype.myFunc1 = function() {
...
}
MyObject.prototype.myFunc2 = function() {
....
}
Obviously if you did:
MyObject.myFunc3 = function() {
....
}
then myFunc3 would become associated with MyObject itself, and not any new objects created with the new keyword. For clarity, we'll call it method C, even though it doesn't work for creating new objects with the new keyword.
So, I would like to know what the differences between the two are. As far as I can tell they have the same effect logically, even if what's happening on the machine is different.
If I were to guess I would say that the only real difference is when you're defining them in the constructor like in method A, it creates a whole new function object for each object that's created, and Method B only keeps one copy of it (in MyObject), that it refers to any time it's called. if this is the case, why would you do it one way over the other. Otherwise, what is the difference between method A and method B.
The advantage of giving a separate function to each object is that you can close over variables in the constructor, essentially allowing for "private data".
function MyObject(a,b) {
var n = a + b; //private variable
this.myFunc1 = function() {
console.log(n);
}
};
vs
function MyObject(a,b) {
this.n = a + b; //public variable
}
MyObject.prototype.myFunc1 = function() {
console.log(this.n);
}
Whether this is a good idea or not depends on who you ask. My personal stance is reserving constructor functions for when I actually use the prototype, as in option #2 and using plain functions (say, make_my_object(a,b)) when using closures, as in option #1.
The idea is that you can modify the prototype at any time and all objects of the type (even those created before the modification) will inherit the changes. This is because, as you mentioned, the prototype is not copied with every new instance.
The MyObject in method A is an instance for inner functions.
You cannot call its functions explicitly outside of it unless object (you can call it a class) was instantiated.
Assume this:
MyObject.MyFunc1(); // will not work
var obj = new MyObject();
obj.MyFunc1(); // will work
so this is the same as any class in other languages. Describing usefulness of classes and their usages goes beyond that question though.
Also to notice:
function MyObject() {
var privateVar = "foo";
this.publicProperty = "bar";
// public function
this.publicFunc = function() {
...
}
// private function
function privateFunc () {
...
}
}
For method B it's same as with method A, the only difference is prototyping is a style of creating object. Some use prototypes for readability or out of preference.
The main advantage in prototypes is that you can extend existing object without touching the original source. You need to be careful with that though.
(as example Prototype framework)
For method C you can call them a static functions. As you said they can be called explicitly by referring through object like:
MyObject.MyFunc1();
So which one to use depends on situation you're handling.

Categories

Resources