not able to acces private method through privilaged methods in javascript - javascript

Error : undefined error in console, while trying to print age function
var Person = function( myName, myProfession, myage ){
this.name = myName; // Public Variable
this.profession = myProfession;
var age = myage; // Private Variable
this.myAge = function(){ // Privilaged Method
return this.age;
};
};
var syed = new Person('syed azam','developer',20);
console.log(syed + "works fine");
console.log(syed.myAge());
<script src="https://getfirebug.com/firebug-lite-debug.js"></script>

What is this.age? You did not encapsulate it correctly:
this.myAge = function(){
return myage;
};
Note that you don't have to use var age = myage;. DEMO.

Related

JavaScript beginner: why does this not work?

My html page is not responding to this code I wrote in JS, i'm a total beginner, and just started learning JS, can somebody tell me why this doesn't work?
/* this is a practice file that'll play with js
nothing strange to look at here folks! */
var firstName = 'Steven';
var lastName = 'Curry';
var fullName = firstName + ' ' + lastName;
function Hotel(HotelName){
this.HotelName = HotelName;
this.numRooms = 20;
this.numGuests;
this.checkAvailability {
if(numRooms != 20 ){
return true;
}
else{
return false;
}
}
this.getHotelName = function(){
//can it work with this dot operator?
return this.HotelName;
}
}
var HiltonHotel = new Hotel('Hilton');
var hName = document.getElementById('hotelName');
hName.textContent = getHotelName();
var el = document.getElementById('name');
el.textContent = fullName;
<!DOCTYPE html>
<html>
<body>
<div id = 'greeting'> Hello
<span id="name">friend</span>!
<h1>Welcome To the <span id = 'hotelName'>Hyatt</span>
</div>
<script
src = "https://stacksnippets.net/js">
</script>
</body>
</html
I'm pretty sure it's ordering and my syntax i need to work on, any advice is greatly appreciated thank you!
Few misunderstandings:
checkAvailability is a function, you are missing parens.
while accessing the getHotelName function, you have to refer to the HiltonHotel variable, to be able to access and call that function.
few minor errors in your html code, while operating in code snippet, you don't have to add a separate script, it's connected together by default.
var firstName = 'Steven';
var lastName = 'Curry';
var fullName = firstName + ' ' + lastName;
function Hotel(HotelName) {
this.HotelName = HotelName;
this.numRooms = 20;
this.numGuests;
this.checkAvailability = function() { // it's a function (missing parens)
if (numRooms != 20) {
return true;
} else {
return false;
}
}
this.getHotelName = function() {
return this.HotelName;
}
}
var WeiHotel = new Hotel('Hilton');
var hName = document.getElementById('hotelName');
hName.textContent = WeiHotel.getHotelName(); // refer to the `WeiHotel` variable
var el = document.getElementById('name');
el.textContent = fullName;
<div id='greeting'> Hello
<span id="name">friend</span>!
<h1>Welcome To the <span id='hotelName'>Hyatt</span></h1>
</div>
An extension to the answer of #KindUser:
You're not using closures anywhere in this class to store some private state. Therefore you should attach the methods to the prototype and not to the instance itself. It's more economic, because now all instances share one function, not one per instance. And the JS engine can optimize that better.
Then, you have another error in checkAvailability: numRooms needs to be addressed as this.numRooms because it is a property of this instance, and there is no variable with this name.
And one about style. If you have something like
if(condition){
return true;
}else{
return false;
}
you can simplify this to:
return condition;
//or if you want to enforce a Boolean value,
//but your condition may return only a truthy/falsy value:
return Boolean(condition);
//sometimes also written as:
return !!(condition);
Next. Stick to the coding standards. In JS a variable/property starting with an uppercase letter would indicate a class/constructor, therefore HotelName, HiltonHotel, WeiHotel are misleading.
And I find the property name hotelName redundant and counter-intuitive. Imo you have a Hotel, it has a name, but that's just an opinion.
var firstName = 'Steven';
var lastName = 'Curry';
var fullName = firstName + ' ' + lastName;
function Hotel(name) {
this.name = name;
this.numRooms = 20;
this.numGuests;
}
Hotel.prototype.checkAvailability = function() {
return this.numRooms !== 20;
}
Hotel.prototype.getHotelName = function() {
return this.name;
}
var hotel = new Hotel('Hilton');
var hName = document.getElementById('hotelName');
hName.textContent = hotel.getHotelName(); // refer to the `weiHotel` variable
var el = document.getElementById('name');
el.textContent = fullName;
<div id='greeting'> Hello
<span id="name">friend</span>!
<h1>Welcome To the <span id='hotelName'>Hyatt</span></h1>
</div>
or as an ES6 class (and some playin around):
class Person{
constructor(firstName, lastName){
this.firstName = firstName;
this.lastName = lastName;
}
//this is a getter, you can read it like a property
get fullName(){
return this.firstName + " " + this.lastName;
}
//this function is implicitely called whenever you try to convert
//an instance of `Person` into a string.
toString(){
return this.fullName;
}
}
class Hotel{
constructor(name) {
this.name = name;
this.numRooms = 20;
this.numGuests;
}
checkAvailability() {
return this.numRooms !== 20;
}
getHotelName() {
return this.name;
}
}
var steve = new Person('Steven', 'Curry');
var hotel = new Hotel('Hilton');
var hName = document.getElementById('hotelName');
hName.textContent = hotel.getHotelName(); // refer to the `weiHotel` variable
var el = document.getElementById('name');
el.textContent = steve.fullName;
//this uses the `toString()` method to convert the `Person` steve into a string
//for people, this makes sense, for the Hotel you'd want to think:
// - where do I want to use this?
// - and what should this string contain?
console.log("Hello, I'm " + steve + " and I'm at the "+ hotel.name);
<div id='greeting'> Hello
<span id="name">friend</span>!
<h1>Welcome To the <span id='hotelName'>Hyatt</span></h1>
</div>

Javascript: Calling private in a outside javascript file with JSON data

I am trying to call the method getTitulo, getDuracion and getLink inside the cancion.js file but when i call the function it returns the following error: "listaCanciones_Lcl[i].getTitulo is not a function". I have searched in different websites but i didnt got lucky with finding an answer. Hopefully someone here can give me some help, i will gladly appreciate it!
//Logic.js file
var listaCanciones = [],
ejecuTitulo = '',
ejecuDuracion = '',
ejecuLink = '';
var btnGenerarLista = document.getElementById("addList").addEventListener("click", agregarCanc);
var btnAgregarLista = document.getElementById("gnrList").addEventListener("click", llenarTabla);
function agregarCanc (){
var nameSong = document.querySelector('#nameSong').value;
var duraSong = document.querySelector('#duraSong').value;
var linkSong = document.querySelector('#linkSong').value;
var objCancion = new Cancion(nameSong, duraSong, linkSong);
listaCanciones.push(objCancion);
var listaCancionesJson = JSON.stringify(listaCanciones);
localStorage.setItem('json_canciones', listaCancionesJson);
}
function llenarTabla (titulo){
var celdaTitulo = document.querySelector('#tituloList'),
celdaDuracion = document.querySelector('#duracionList'),
celdaLink = document.querySelector('#linkList'),
listaCanciones_Lcl = JSON.parse(localStorage.getItem('json_canciones'));
for(var i=0; i<listaCanciones_Lcl.length;i++){
// Acceder a lista canciones
I am getting an error in this line, where is says "getTitulo" is not a function but i dont really know why?
var nodoTextoTitulo = document.createTextNode(listaCanciones_Lcl[i].getTitulo()),
nodoTextoDuracion = document.createTextNode(listaCanciones_Lcl[i].getDuracion()),
nodoTextoLink = document.createTextNode(listaCanciones_Lcl[i].getLink());
// Create td
var elementoTdTitulo = document.createElement('td'),
elementoTdDuracion = document.createElement('td'),
elementoTdLink = document.createElement('td');
// Celda Id Append Child
elementoTdTitulo.appendChild(nodoTextoTitulo);
elementoTdDuracion.appendChild(nodoTextoDuracion);
elementoTdLink.appendChild(nodoTextoLink);
// Fila Append Child
celdaTitulo.appendChild(elementoTdTitulo);
celdaDuracion.appendChild(elementoTdDuracion);
celdaLink.appendChild(elementoTdLink);
}
}
//Cancion.js File
var Cancion = function(pTitulo, pDuracion, pLink){
var id = 0;
var titulo = pTitulo;
var duracion = pDuracion;
var link = pLink;
this.getId = function (){
return id;
};
this.setTitulo = function (pTitulo){
titulo = pTitulo;
};
this.getTitulo = function(){
return titulo;
};
this.setDuracion = function(pDuracion){
duracion = pDuracion;
};
this.getDuracion = function(){
return duracion;
};
this.setLink = function (pLink){
link = pLink;
};
this.getLink = function(){
return link;
};
};
First, make sure you are loading the Cancion.js file before the others in your HTML. Your problem is that when you parse the JSON back out of local storage, Cancion is not a known object, so getTitulo is undefined. You'll have to do listaCanciones_Lcl[i].titulo; instead.
And another change you'll need is to loosen the scope of your variables. The reason you need this.x = pX is because before JSON.stringify(new Cancion(1, 2, 3)) just returned "{}". With this code it returns "{"id":0,"titulo":1,"duracion":2,"link":3}", which I think is what you were after.
function Cancion(pTitulo, pDuracion, pLink){
this.id = 0;
this.titulo = pTitulo;
this.duracion = pDuracion;
this.link = pLink;
this.getId = function (){
return this.id;
};
this.setTitulo = function (pTitulo){
this.titulo = pTitulo;
};
this.getTitulo = function(){
return this.titulo;
};
this.setDuracion = function(pDuracion){
this.duracion = pDuracion;
};
this.getDuracion = function(){
return this.duracion;
};
this.setLink = function (pLink){
this.link = pLink;
};
this.getLink = function(){
return this.link;
};
};
var objWithFunction = {
name: 'Object with Function',
getName: function() { return this.name }
};
undefined
objWithFunction.getName() // --> "Object with Function"
var string = JSON.stringify(objWithFunction)
string // -=> "{"name":"Object with Function"}"
JSON is for data only..
Better you create a model, and fill it with data.. but this model has to exist in your application.. or you load the model parallel to your data..
function SomeThing() {};
SomeThing.prototype.getName = function() { return this.name };
var Thing1 = new SomeThing(JSON.parse("{name:'ThingOne'}"));
Thing1.getName(); // ThingOne

multi inherit or access the property and method outside the object

var ob = function(){
};
ob.prototype.func = function(){
};
var t = function(){
this.p=0;
this.function1(){
}
var a=new ob();
a.func=function(){//overrides the func
//hope to access this.p this.function1
}
};
is it possible to make a can access this.p this.function1 ?
Your comment welcome
You need to keep a reference to this from inside t if you want to access it within a.func. Try the following:
var t = function(){
var this_t = this; // Use this_t to access this.p and this.function1 inside a
this.p=0;
this.function1 = function(){
}
var a=new ob();
a.func = function(){//overrides the func
this_t.p = 1;
this_t.function1();
}
};

How to declare a dynamic local variable in Javascript

I want to create a local variable dynamically. JavaScript: Dynamically Creating Variables for Loops is not exactly what I am looking for. I dont want an array. I want to access it like a local variable.
Something like:
<script type="text/javascript">
var properties = new Object();
properties["var1"] = "value1";
properties["var2"] = "value2";
createVariables(properties);
function createVariables(properties)
{
// This function should somehow create variables in the calling function. Is there a way to do that?
}
document.write("Outside the function : " + var1 + "<br>");
document.write("Outside the function : " + var2 + "<br>");
</script>
I tried the following code.
<script type="text/javascript">
var properties = new Object();
properties["var1"] = "value1";
properties["var2"] = "value2";
createVariables(properties);
function createVariables(properties)
{
for( var variable in properties)
{
try
{
eval(variable);
eval(variable + " = " + properties[variable] + ";");
}
catch(e)
{
eval("var " + variable + " = '" + properties[variable] + "';");
}
}
document.write("Inside the function : " + var1 + "<br>");
document.write("Inside the function : " + var2 + "<br>");
}
document.write("Outside the function : " + var1 + "<br>");
document.write("Outside the function : " + var2 + "<br>");
</script>
But the generated variables are not accessible outside the createVariables().
Now, I have this solution.
<script type="text/javascript">
var properties = new Object();
properties["var1"] = "value1";
properties["var2"] = "value2";
function createVariables(properties)
{
var str = "";
for( var variable in properties)
{
str += "try{";
str += "eval('" + variable + "');";
str += "eval(\"" + variable + " = properties['" + variable + "'];\");";
str += "}";
str += "catch(e){";
str += "eval(\"var " + variable + " = properties['" + variable + "'];\");";
str += "}";
}
return str;
}
eval(createVariables(properties));
document.write("Outside the function : " + var1 + "<br>");
document.write("Outside the function : " + var2 + "<br>");
</script>
This works. But I am looking for an alternative/better solution. Is it possible to do it without eval?
EDIT: 04-July
Hi,
I tried a solution similar to what #Jonathan suggested.
<script type="text/javascript">
var startFunc = function(){
var self = this;
self.innerFunc = function innerFunc(){
var properties = new Object();
properties["var1"] = "value1";
properties["var2"] = "value2";
properties["var3"] = "value3";
function createVariables(caller, props) {
for(i in props) {
caller[i] = props[i];
}
caller.func1();
}
createVariables(self, properties);
console.log( var1 );
}
self.func1 = function func1(){
console.log( "In func 1" );
console.log( var2 );
}
innerFunc();
console.log( var3 );
}
startFunc();
</script>
This all works fine. But it is actually creating global variables instead of creating the variables in the function.
The "self" passed to the createVariables() function is window. I am not sure why it is happening. I am assigning the function scope to the self. I am not sure what is happening here. It is anyway creating global variables in this case.
If my question is not clear,
What I am after is creating local variables in the caller. The scenario is like
1) I am inside a function.
2) I invoke another function which returns me a map[This map contains name and value of a variable].
3) I want to dynamically create all the variables, if they are not already defined. If they are already defined [global/local], I want to update them.
4) Once these variables are created, I should be able to access them without any context.[Just the variable name]
<script type="text/javascript">
function mainFunc()
{
var varibalesToBeCreated = getVariables();
createVariables(varibalesToBeCreated);
alert(var1);
alert(var2);
}
function createVariables(varibalesToBeCreated)
{
// How can I implement this function,
// such that the variables are created in the caller?
// I don't want these variables this function.
}
function getVariables()
{
var properties = new Object();
properties["var1"] = "value1";
properties["var2"] = "value2";
}
mainFunc();
</script>
Depending on the scope you'd like the variables to have, this could be accomplished in a few different ways.
Global scope
To place the variables in the global scope, you could use window[varName]:
function createVariables(variables) {
for (var varName in variables) {
window[varName ] = variables[varName ];
}
}
createVariables({
'foo':'bar'
});
console.log(foo); // output: bar
Try it: http://jsfiddle.net/nLt5r/
Be advised, the global scope is a dirty, public place. Any script may read, write, or delete variables in this scope. Because of this fact, you run the risk of breaking a different script that uses the same variable names as yours, or another script breaking yours.
Function scope (using this)
To create variables in a function's scope (this.varName), you can use bind:
var variables = {
'foo':'bar'
};
var func = function () {
console.log(this.foo);
};
var boundFunc = func.bind(variables);
boundFunc(); // output: bar
Try it: http://jsfiddle.net/L4LbK/
Depending on what you do with the bound function reference, this method is slightly vulnerable to outside modification of the variables. Anything that can access boundFunc can change or refer to the value of the values by using boundFunc.varName = 'new value'; This may be to your advantage, depending on use case.
Function scope (using arguments)
You can use apply to pass an array of values as arguments:
var variables = [
'bar'
];
var func = function (foo) {
console.log('foo=', foo);
};
func.apply(null, variables);
Try it: http://jsfiddle.net/LKNqd/
As arguments are ephemeral in nature, nothing "outside" could interfere with or refer back to the values, except by modifying the variable array and re-calling the function.
Global scope as temporary
And here's a small utility function that will make temporary use of the global scope. This function is dangerous to code that also uses the global scope -- this could blast over variables that other scripts have created, use at your own risk:
var withVariables = function(func, vars) {
for (var v in vars){
this[v] = vars[v];
}
func();
for (var v in vars){
delete this[v];
}
};
// using an anonymous function
withVariables(
function () {
console.log('anonymous: ', foo);
},
{
'foo':'bar'
}
); // output: bar
// using a function reference
var myFunction =function () {
console.log('myFunction: ', foo);
};
withVariables(myFunction, {
'foo':'bar'
}); // output: bar
console.log(foo); // output: undefined
Try it: http://jsfiddle.net/X3p6k/3/
Documentation
bind on MDN - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
apply on MDN - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
window on MDN - https://developer.mozilla.org/en-US/docs/Web/API/Window
Here is working sample based on Chris Baker answer: Function scope (using arguments)
function myFn() {
function keyList(params) {
var str = '';
for (var key in params) {
if (params.hasOwnProperty(key)) {
str += ',' + key;
}
}
return str.length ? str.substring(1) : str;
}
function valueList(params) {
var list = [];
for (var key in params) {
if (params.hasOwnProperty(key)) {
list.push(params[key]);
}
}
return list;
}
var params = {
'var1': 'value1',
'var2': 'value2'
};
var expr = 'document.write("Inside the function : " + var1 + "<br>")'
var fn;
eval('var fn = function(' + keyList(params) + '){' + expr + '};');
fn(valueList(params));
}
myFn();
I have written short code snippet which will create both local and global variable dynamically
function createVar(name,dft){
this[name] = (typeof dft !== 'undefined')?dft:"";
}
createVar("name1","gaurav"); // it will create global variable
createVar("id");// it will create global variable
alert(name1);
alert(id);
function outer(){
var self = this;
alert(self.name1 + " inside");
}
createVar.call(outer,"name1","saurav"); // it will create local variable
outer.call(outer); // to point to local variable.
outer(); // to point to global variable
alert(name1);
hope this helps
Regards
Gaurav Khurana
The example below demonstrates how with gets a value from the object.
var obj = { a : "Hello" }
with(obj) {
alert(a) // Hello
}
But I want to notice: with is deprecated!
This answer is more or less the same as several answers above but here with a simplified sample, with and without using eval. First using eval (not recommended):
var varname = 'foo'; // pretend a user input that
var value = 42;
eval('var ' + varname + '=' + value);
And alternatively, without using eval:
var varname = prompt('Variable name:');
var value = 42;
this[varname] = value;
I hope this helps.
Source: https://www.rosettacode.org/wiki/Dynamic_variable_names#JavaScript
since you are wanting the scope of where the function is being called pass this to the function
var properties = new Object();
properties["var1"] = "value1";
properties["var2"] = "value2";
function createVariables(context) {
for(i in properties) {
context[i] = properties[i];
}
}
createVariables(this);
console.log( var1 );
Do you need something like this?
function createVariables(properties, context){
for( var variable in properties){
context[variable] = properties[variable ];
}
}
So, calling as createVariables(properties, this) will fill the current scope with values from properties.
<script type="text/javascript">
var properties = new Object();
properties["var1"] = "value1";
properties["var2"] = "value2";
createVariables(properties, this);
document.write("Outside the function : " + var1 + "<br>");
document.write("Outside the function : " + var2 + "<br>");
</script>

Javascript "private" vs. instance properties

I'm doing some Javascript R&D and, while I've read Javascript: The Definitive Guide and Javascript Object Oriented Programming, I'm still having minor issues getting my head out of class based OOP and into lexical, object based OOP.
I love modules. Namespaces, subclasses and interfaces. w00t. Here's what I'm playing with:
var Classes = {
_proto : {
whatAreYou : function(){
return this.name;
}
},
Globe : function(){
this.name = "Globe"
},
Umbrella : new function(){
this.name = "Umbrella"
}(),
Igloo : function(){
function Igloo(madeOf){
this.name = "Igloo"
_material = madeOf;
}
// Igloo specific
Igloo.prototype = {
getMaterial : function(){
return _material;
}
}
// the rest
for(var p in Classes._proto){
Igloo.prototype[p] = Classes._proto[p]
}
return new Igloo(arguments[0]);
},
House : function(){
function House(){
this.name = "My House"
}
House.prototype = Classes._proto
return new House()
}
}
Classes.Globe.prototype = Classes._proto
Classes.Umbrella.prototype = Classes._proto
$(document).ready(function(){
var globe, umb, igloo, house;
globe = new Classes.Globe();
umb = Classes.Umbrella;
igloo = new Classes.Igloo("Ice");
house = new Classes.House();
var objects = [globe, umb, igloo, house]
for(var i = 0, len = objects.length; i < len; i++){
var me = objects[i];
if("whatAreYou" in me){
console.log(me.whatAreYou())
}else{
console.warn("unavailable")
}
}
})
Im trying to find the best way to modularize my code (and understand prototyping) and separate everything out. Notice Globe is a function that needs to be instantiated with new, Umbrella is a singleton and already declared, Igloo uses something I thought about at work today, and seems to be working as well as I'd hoped, and House is another Iglooesque function for testing.
The output of this is:
Globe
unavailable
Igloo
My House
So far so good. The Globe prototype has to be declared outside the Classes object for syntax reasons, Umbrella can't accept due to it already existing (or instantiated or... dunno the "right" term for this one), and Igloo has some closure that declares it for you.
HOWEVER...
If I were to change it to:
var Classes = {
_proto : {
whatAreYou : function(){
return _name;
}
},
Globe : function(){
_name = "Globe"
},
Umbrella : new function(){
_name = "Umbrella"
}(),
Igloo : function(){
function Igloo(madeOf){
_name = "Igloo"
_material = madeOf;
}
// Igloo specific
Igloo.prototype = {
getMaterial : function(){
return _material;
}
}
// the rest
for(var p in Classes._proto){
Igloo.prototype[p] = Classes._proto[p]
}
return new Igloo(arguments[0]);
},
House : function(){
function House(){
_name = "My House"
}
House.prototype = Classes._proto
return new House()
}
}
Classes.Globe.prototype = Classes._proto
Classes.Umbrella.prototype = Classes._proto
$(document).ready(function(){
var globe, umb, igloo, house;
globe = new Classes.Globe();
umb = Classes.Umbrella;
igloo = new Classes.Igloo("Ice");
house = new Classes.House();
var objects = [globe, umb, igloo, house]
for(var i = 0, len = objects.length; i < len; i++){
var me = objects[i];
if("whatAreYou" in me){
console.log(me.whatAreYou())
}else{
console.warn("unavailable")
}
}
})
and make this.name into _name (the "private" property), it doesn't work, and instead outputs:
My House
unavailable
My House
My House
Would someone be kind enough to explain this one? Obviously _name is being overwritted upon each iteration and not reading the object's property of which it's attached.
This all seems a little too verbose needing this and kinda weird IMO.
Thanks :)
You declare a global variable. It is available from anywhere in your code after declaration of this. Wherever you request to _name(more closely window._name) you will receive every time a global. In your case was replaced _name in each function. Last function is House and there has been set to "My House"
Declaration of "private" (local) variables must be with var statement.
Check this out:
var foo = function( a ) {
_bar = a;
this.showBar = function() {
console.log( _bar );
}
};
var a = new foo(4); // _bar ( ie window._bar) is set to 4
a.showBar(); //4
var b = new foo(1); // _bar is set to 1
a.showBar(); //1
b.showBar(); //1
_bar = 5; // window._bar = 5;
a.showBar();// 5
Should be:
var foo = function( a ) {
var _bar = a;
// _bar is now visibled only from both that function
// and functions that will create or delegate from this function,
this.showBar = function() {
console.log( _bar );
};
this.setBar = function( val ) {
_bar = val;
};
this.delegateShowBar = function() {
return function( ) {
console.log( _bar );
}
}
};
foo.prototype.whatever = function( ){
//Remember - here don't have access to _bar
};
var a = new foo(4);
a.showBar(); //4
_bar // ReferenceError: _bar is not defined :)
var b = new foo(1);
a.showBar(); //4
b.showBar(); //1
delegatedShowBar = a.delegateShowBar();
a.setBar(6);
a.showBar();//6
delegatedShowBar(); // 6
If you remove the key word "this", then the _name is in the "Globe" scope.
Looking at your code.
var globe, umb, igloo, house;
globe = new Classes.Globe();
umb = Classes.Umbrella;
igloo = new Classes.Igloo("Ice");
house = new Classes.House();
At last the house will override the "_name" value in globe scope with the name of "My House".

Categories