Private variables are variables that are visible only to the class to which they belong. It is a common opinion that there are no strict private variables in JS (except for the new fields like this.#property).
Can anyone kindly explain why the variable 'boy' bellow cannot be considered to be a private one?
class Forrest {
constructor() {
let boy = "Bobby"
this.getBoy = function() {
console.log(boy)
}
}
}
const f = new Forrest()
f.getBoy() // Bobby
I haven't heard people claim that boy in your example isn't private. Quite the opposite, it's private to the constructor and getBoy. Nothing else (including nothing else in that class) can access it. But either way, I suppose that might be in the "opinion-based" realm.
Stepping out of that realm: Regardless of someone may feel about the closure approach shown in the question, JavaScript will have true private fields very, very soon. It's implemented in most major engines and likely to hit the spec this year. Your example with private fields looks like this:
class Forrest {
#boy = "Bobby";
getBoy() {
console.log(this.#boy);
}
}
const f = new Forrest();
f.getBoy() // Bobby
Or if we set it from a constructor parameter:
class Forrest {
#boy;
constructor(boy) {
this.#boy = boy;
}
getBoy() {
console.log(this.#boy);
}
}
const f = new Forrest("Bobby");
f.getBoy() // Bobby
Those will run on up-to-date versions of Chromium-based browsers. Safari and Firefox won't be much longer.
Related
I have built a javascript class that does things to the dom. To simplify the use from outside as much as possible I now have methods like these:
hello.add(id);
hello.delete(id);
hello.select(id);
To make the above work, I have setup a static class that uses the non static class like this:
Static class
class hello {
static add(id) {
let hello = new HelloCore();
hello.add(id);
}
static delete(id) {
let hello = new HelloCore();
hello.delete(id);
}
static select(id) {
let hello = new HelloCore();
hello.select(id);
}
}
Non static class
The real code is 500 lines with a constructor and so on.
class helloCore() {
add() {
// Do something
}
delete() {
// Do something
}
select() {
// Do something
}
}
It's now super simple but I wonder if there is a performance issue with this approach. My guess is that it store a new javascript object on every static call into memory?
Do I need to worry about it?
If yes, what would be a better approach, but still super simple?
What I want to stay away from
From the start I had always needed to pass the object around to the functions where it's going to be used. See below.
let hello = new HelloCore();
function my_function(hello) {
let id = 2;
hello.add(id);
}
my_function(hello);
With the static approach I don't need to pass the object around everywhere. I can just trigger the function from anywhere.
I could use a global var hello = new Hello(); but then I need to make sure it's loaded first, that I don't forget about it and it means extra code for the user.
You may want to take a look at Singleton.
It does exactly what you are trying to achieve.
However, I must admit that I (and a lot of other developers) frown upon singletons, globals and static classes, not because of performance, but as a general pattern.
This SO question tells a bit about why singletons are bad.
#mareful commented this helpful information:
With the static class approach the hello instance is not available after function call any more...
It means that the static class will self clean after each call.
Then I got a comment from #Bergi with an idea to use a const including functions with the same result. This approach works really well.
Before - with static class
class hello {
static add(id) {
let hello = new HelloCore();
hello.add(id);
}
static delete(id) {
let hello = new HelloCore();
hello.delete(id);
}
static select(id) {
let hello = new HelloCore();
hello.select(id);
}
}
After - with const
const hello = {
add(id) {
new HelloCore().add(id);
},
delete(id) {
new HelloCore().delete(id);
},
select(id) {
new HelloCore().select(id);
}
};
In both cases I can call it like hello.add(id);. The const version is shorter and has some other advantages in this case as well.
it doesn't create a constructor function and prototype object that are never needed (and might even be abused, or at least will confuse the reader).
i've got a basic question about instancing of an object in NodeJS and different ways to declare classes.
I've saw few tutorials but no tutorial has descriped, when i should use which way or why there are different ways.
I want to create a instance of an object and have created two code-snippets which does exactly the same but with a completly different code.
My question: Do i get the same result or is there something special i cannot see that it is different and moreover, which way should i use?
ExampleA:
class ExampleA {
constructor () { }
method() {
console.log("Hello world");
}
}
module.exports.ExampleA = ExampleA;
ExampleB:
function ExampleB() {
}
NoSQL1.prototype.method = function() {
console.log("Hello world");
}
module.exports.ExampleB = ExampleB;
If i got it right, in ExampleB i just add a new function to a existing class within the "Classname.prototype.Method"
Maybe there are even more ways to go? As a C# developer i prefer the ExampleA, currently...
There's not a major difference. Javascript doesn't have traditional Classes. Everything is just an Object and the syntax of example A is basically just around because of convention and Javascript trying to cater to both OOP and functional programming.
But only the first pattern allows you to make private variables, through the use of a closure.
You get the same result.
Class is a syntactic sugar in latest version of ECMAScript(ES).
JavaScript is still prototype based, so you should be carefull about refrence on sepcial word this because for example:
class ExampleA {
constructor() {
this.text = 'Hello World!'
}
method() {
console.log(this.text);
}
}
let a = new EampleA()
a.method() // will print 'Hello World'
let m = a.method;
m() // will throw exception "Cannot read property 'text' of undefined
let b = {text: 'Hi'};
m.call(b) // will print 'Hi'
I'm new at JS programming. I have to write a php webapplication which uses ajax calls for every action (can't reload the page). So I have the php code done, and the JS as well, but I don't know what does JS OOP mean. I did google search for hours, and all I could figure out was "JS has no classm but there are tricks". So I would like to ask you to lead me to the right way and show me how to make it right.
I have four js files:
content.js, function.js, onload.js and validate.js
For now, I only do care about the function.js. It has code only for the ajax calls. Their names are:
NewMember(), SearchMembers(), ShowDetails(), DeleteMembers() and EditMember()
I'm going to show you only the first function (I don't want to waste your time by duplicating since each function is totally similar)
function NewMember() {
if (checkFields() == true) {
Loading("start");
var dataArray = {
first_name : $('#first_name').val(),
last_name : $('#last_name').val(),
birth_date : $('#birth_date').val(),
home_phone : $('#home_phone').val(),
work_phone : $('#work_phone').val(),
email : $('#email').val(),
email_again : $('#email_again').val(),
country : $('#country').val(),
city : $('#city').val(),
address : $('#address').val(),
comment : $('#comment').val()
};
var JSONString = JSON.stringify(dataArray);
$.ajax({
type: 'POST',
url : 'adapter.php',
data: {
data : JSONString,
action : 'create' },
success: function(msg) {
alert(msg);
resetFieldValues();
SearchMembers();
},
error: function() {
alert("Oops! Something went wrong, please reload the page!");
}
});
}
}
My question is, how would you re-write this by using the JS OOP? Full code is not neccessary, but please give me "easy" answers since I'm really a newbie. I'm really confused :/ Thanks for your help!
JavaScript is a completely object-oriented language.
Instead of the Classical Inheritance model that programmers are usually familiar with, JavaScript has a unique take on things with its model of Prototypical Inheritance.
Consider classical inheritance in PHP:
<?php
class Arachnid {
public $legs = 8;
function crawl(){ /***/ }
}
class Spider extends Arachnid {
function creep(){ /***/ }
}
class OrbSpider extends Spider {
function buildBeautifulWeb(){ /***/ }
}
?>
This is arguably the simplest methodology in JavaScript for the same faculty:
function Arachnid () {}
Arachnid.prototype.legs = 8;
Arachnid.prototype.crawl = function () { return "crawling" };
function Spider () { /* this is a constructor, so don't define spider's methods in here -- they'd be redefined for every constructor call (each instance) */ }
Spider.prototype = new Arachnid(); // Spider inherits from a new basic Arachnid
Spider.prototype.constructor = Spider;
Spider.prototype.creep = function () { return "creeping" }; // Attach Spider's methods to its prototype for best performance
function OrbSpider () {}
OrbSpider.prototype = new Spider(); // we wholly overwrite the natural prototype to a basic arachnid
OrbSpider.prototype.constructor = OrbSpider; // so we must replace the constructor for instanceof to work
OrbSpider.prototype.buildBeautifulWeb = function () { return "webbing" };
// Testing
var orb = new OrbSpider();
console.log( orb.buildBeautifulWeb() ); //>> webbing
console.log( orb.creep() ); //>> creeping
console.log( orb.crawl() ); //>> crawling
console.log( orb.legs ); //>> 8
console.log( orb instanceof OrbSpider ); //>> true
console.log( orb instanceof Spider); //>> true
console.log( orb instanceof Arachnid); //>> true
In JavaScript, you create Prototype Chains. When you ask an object for a property, JavaScript will first check the object itself for that property -- if it isn't found, JavaScript will check the object's prototype object. If the property isn't there either, JavaScript will check that prototype object's own prototype -- and so on, and so forth, bubbling up the Prototype Chain until the property is found (or not).
JS means JavaScript. OOP means Object Oriented Programming. This is programming JavaScript in an OOP manner. It doesn't have a formal definition of classes in the programming language per say, it has functions, variables and objects (yes, objects, even if it does not have classes). Basically your JavaScript acts as part of your controller and should call PHP functions to carry out requests on the server. Remember OOP usually takes the MVC (Model View Controller) methodology.
So this code should fire when a message is received from an action. Pass the information to the PHP on the server and the PHP should save the information (as a JSON file or in a SQL database for example).
It's important to note that "object-oriented programming" doesn't necessarily mean "class-based programming", so looking online for "how to write a class in JavaScript" will lead you up a blind alley. (JavaScript instead implements prototype-based programming which should be viewed as a different way to do OOP.)
In a lot of the simple cases you'll have in client-side scripts, you don't need to worry about inheritance, you just want to expose an object which has public methods and private state. So instead of diving right into prototypal inheritance (which takes a bit of getting used to), start by learning how to implement encapsulation, and privately scoped variables.
Here's a succinct introduction to basic public and private members, and below (and in this demo) is a quick abstract example of encapsulation (but no inheritance) using JavaScript's object model:
var my_object = function(start_value) {
/* private variables */
var some_number;
/* private methods */
function garble() {
some_number = 42;
}
/* public methods and properties */
var inst = {
'set_number': function(new_value) {
if ( new_value < 0 ) {
garble();
}
else {
some_number = new_value;
}
},
'get_number': function() {
return some_number;
},
'increment_number': function() {
some_number++;
}
}
// Initialisation
inst.set_number(start_value);
return inst;
}
var foo = new my_object(1);
foo.increment_number();
var bar = new my_object(-20);
bar.increment_number();
document.getElementById('foo').innerHTML = foo.get_number();
document.getElementById('bar').innerHTML = bar.get_number();
Note: I'm not an expert on JS OOP, and there may be gotchas or bad practices in my example above; if anyone more experienced spots one, please let me know in a comment.
I have done a lot of reading. I have written a lot of dummy code. I am still as confused as I when I set out to once and for all conquer JavaScript inheritance. Maybe more so.
I am quite in admiration of Backbone.js and I liked its use of collections. So I read the source and felt inspired. But I keep tripping up over inheritance vs extending an object.
Here is, as best as I can deduce a Javascript class with inheritance, for this use purpose I cannot see the benfit in using extend:
function Collection(){
this._models = [];
}
Collection.prototype = {
models: function() {
return this._models;
},
fetch: function() {
console.log("TODO Override fetch method");
},
add: function(model){
this._models.push(model);
$(this).triggerHandler("add", model);
},
}
function Employees(){}
Employees.prototype = new Collection();
Employees.prototype.fetch = function(){
this._models = [new Person("Ron", "male"), new Person("Stevie", "female"), new Person("David Blunkett", "female")];
}
It feels a little strange accessing the super classes(Collection) _models property directly in Employees but it works. Is there anything wrong with this approach? Any gottchas or caveats? I don't want to build an application off of this to find out its a bit... naff.
Edit
its probably worth noting a Person is a Model too...
function Model(){}
Model.prototype = {
get: function(attr){
return this.attr;
},
set: function(attr, value){
return this[attr] = value;
}
}
function Person(name, gender){
this.name = name;
this.gender = gender;
}
Person.prototype = new Model();
Your approach of making a new instance of the parent class and assigning that as the prototype of the child class is what Douglas Crockford calls the "Pseudoclassical" approach to inheritance in JavaScript. Check out this in-depth video where he covers in detail pseudoclassical, prototypal, and parasitic inheritance approaches as well as several variants. (Pseudoclassical is around 12 minutes in).
Your approach works fine with the one (potentially large) limitation in that you cannot share constructor code in this pattern (at least not without some extra fanciness). So if you do:
var e = new Employees();
console.log(e.constructor);
You will see the Collection function instead of the more intuitive Employees function. Again, watch that video, it really covers this entire topic very clearly.
Hullo! This is my first question!
I am experimenting with the module pattern promoted by Doug Crockford and others. Mostly very happy with it so far, but I am a little unsure about the best way of handling a certain inheritance pattern.
I have it boiled down to a bare bones case using cat and mammal, although my actual intention is to make objects for a tile based game in canvas.
But here is my bare bones 'animals' case using a browser alert:
var ZOO = ZOO || {};
//
ZOO.mammal = function () {
"use strict";
var voice = "squeak.mp3", // default mammal sound
utter = function () {
window.alert(this.voice);
};
//
// public interface
return {
utter: utter,
voice: voice
};
};
//
ZOO.cat = function () {
"use strict";
// hook up ancestor
var thisCat = ZOO.mammal();
thisCat.voice = "miaw.mp3";
return thisCat;
};
//
var felix = ZOO.cat();
felix.utter();
What bothers me about this approach is that I have had to make voice a public property so that cat can modify it.
What I really want is something like 'protected' visibility (from Java, ActionScript etc.), so that cat can modify voice without anyone with access to felix being able to modify it.
Is there a solution?
You can simulate protected visibility (visible to yourself, and child objects) by passing a blank object to your base "class" to serve as the repository for your protected properties. This will allow you to share properties through your inheritance chain, without making them public.
var ZOO = ZOO || {};
ZOO.mammal = function (protectedInfo) {
"use strict";
protectedInfo = protectedInfo || {};
protectedInfo.voice = "squeak.mp3";
// public interface
return {
utter: function () {
alert(protectedInfo.voice);
}
};
};
ZOO.cat = function () {
"use strict";
var protectedInfo = {};
// hook up ancestor
var thisCat = ZOO.mammal(protectedInfo);
protectedInfo.voice = "miaw.mp3";
return thisCat;
};
Here's a live demo
Sidesteping non-answer:
There are some ways to kind of get protected properties in Javascript but they aren't necessarily very idiomatic. If I were you I would first strongly consider either
Using the convention of public properties prefaced with an underscore (ex.: _voice) to denote privacy. Its very simple and is something of a standard among dynamic languages.
Seek an alternate solution without inheritance. Inheritance often complicates and couples stuff to much, hence the old "prefer composition over inheritance" mantra. Javascript has many features, like duck typing and higher order functions, that often let you avoid using inheritance in situations where you would normaly need it in Java
There is a workaround to simulate protected members, where you make public those members for a while, and then you privatise them again. I'm not a big fan of this, but it's a "solution".
I'm just quoting from this SitePoint article:
Adding Protected Members
Splitting a script into multiple modules is a common and convenient
practice. It makes a large codebase much easier to manage, and allows
for bandwidth savings to be made when modules aren’t always required.
But what if we want to share data between different modules? If we
make that data public then we’ll lose the benefits of privacy, but if
we make it private it will only be available to one module. What we
really need are shared private members, and these are known as
protected.
JavaScript doesn’t have protected members as such, but we can
effectively create them by making data temporarily public. To achieve
this, let me first introduce you to two key functions — extend and
privatise — which we’ll define as part of a utility-functions object:
var utils = {
extend : function(root, props) {
for(var key in props) {
if(props.hasOwnProperty(key)) {
root[key] = props[key];
}
} return root;
},
privatise : function(root, prop) {
var data = root[prop];
try { delete root[prop]; } catch(ex) { root[prop] = null; }
return data;
}
};
The extend function simply adds new properties to an object, while the
privatise function copies a property and then deletes the original. We
can use extend in one module to create a public reference to a private
variable, and then use privatise in another module to copy it back to
a private variable and delete the public reference.
So here’s an example of the first module which has two protected
members (including the utils object itself), and one public member. To
keep the code example short, the utility functions are just empty
shells, but they would be identical to the functions I showed you a
moment ago:
var MyModule = (function() {
var myProtectedData = 909;
var utils = {
extend : function(root, props) { },
privatise : function(root, prop) { }
};
this.myPublicData = 42;
return utils.extend(this, { myProtectedData : myProtectedData, utils : utils });
})();
You can see how we’re using a variant of the revealing module pattern,
to return not just the public members, but the protected members as
well. So at this point we have three public members:
MyModule.myProtectedData, MyModule.utils and MyModule.myPublicData.
Now here’s an example of the last module which uses the privatise
function to copy the specified public members back to private
variables, and then delete their public references:
var MyModule = (function() {
var myProtectedData = this.utils.privatise(this, 'myProtectedData');
var utils = this.utils.privatise(this, 'utils');
return this;
}).apply(MyModule);
And once that’s done the protected members are locked inside their
objects, privately available to both the modules, but no longer
available from outside them.
Note that the privatise function relies on having separate arguments
for the object and the property-key, because objects in JavaScript are
passed by reference. So root is a reference to MyModule, and when we
delete a property from it that’s specified by key, we’re deleting that
property from the referenced object.
But if it was like this:
privatise : function(root) {
var data = root;
try { delete root; } catch(ex) { root = null; } return data;
}
And called like this:
var myProtectedData = this.utils.privatise(this.myProtectedData);
Then the public members would not be deleted — the function would
simply delete the reference, not the property it refers to.
The try ... catch construct is also necessary for older IE versions,
in which delete is not supported. In that case we nullify the public
property rather than deleting it, which is obviously not the same, but
has an equivalent end result of negating the member’s public
reference.