Javascript Namespace: local variable has been updated but not the public one - javascript

I have a namespace MyNameSpace which has a public variable Name and public methods SayName and ChangeName
var MyNameSpace = MyNameSpace|| function () {
var _name = "John";
function _SayMyName() {
return _name;
}
function _changeMyName(newName) {
_name = newName;
}
return {
SayName: _SayMyName,
ChangeName : _changeMyName,
Name:_name
}
}();
alert(MyNameSpace.SayName()) // John
MyNameSpace.ChangeName("Paul")
alert(MyNameSpace.SayName()) // Paul
alert(MyNameSpace.Name) // John
jsfiddle
MyNameSpace.Name will always return John even if _Name has been changed. Why?
MyNameSpace.Name doesn't hold a reference to _Name?
What to do so MyNameSpace.Name returns the same value as _Name?

You are creating a Object which Name property holds a copy of _name. The value of _nameis copied by value, not by reference, that's why it does not change.
You could write this, to mimic your desired behaviour:
return {
get Name () { return _name; },
//if you like to have a setter, than:
set Name (n) { _name = n; }
//the other properties go here...
}

Related

Call a getter function with its name in JavaScript?

When I create a class in JavaScript like this one:
class Person {
_firstName = "";
_lastName = "";
constructor(firstName, lastName) {
this._firstName = firstName;
this._lastName = lastName;
}
get firstName() {
return this._firstName;
}
get lastName() {
return this._lastName;
}
fullName() {
return `${this.firstName} ${this.lastName}`;
}
}
let me = new Person("John", "Doe");
It creates a variable me that is an instance of Person. Its prototype has some functions whose names are “fullName” and “get firstName” (plus other functions)
I can call the function fullName by its name using:
me[“fullName”]();
John Doe
However, calling the getter function by its name throws an error:
me[“get firstName”]();
Uncaught TypeError: me.get firstName is not a function
Why does this behavior happen?
EDIT: Thanks for the replies. I know I can and should access it as a property. But I'd like to understand why accessing it by its name with the brackets notation does not work. Does that mean JavaScript has different kinds of functions since a behavior that works for one function does not work for another function (when it has a space in its name / is a getter or setter)?
When a function is assigned to a variable or as a property value (maybe a getter), there are two names involved:
The name of the function
The name of the variable/property
These names are different entities and don't necessarily have to be the same.
Here is a simple object with property "a" that has as value a function whose name is "b":
let obj = {
a: function b() { }
};
console.log("property: ", Object.keys(obj)[0]); // "a"
console.log("function: ", obj.a.name); // "b"
Now when the function does not get an explicit name, it is given one:
let obj = {
a() { }
};
console.log("property: ", Object.keys(obj)[0]); // "a"
console.log("function: ", obj.a.name); // "a"
This may give the false impression that both names are one and the same string, but this cannot be true as the same function object might be assigned to different properties:
let obj = {
a() { }
};
obj.c = obj.a;
console.log("property: ", Object.keys(obj)[1]); // "c"
console.log("function: ", obj.c.name); // "a"
Getters
The situation with a getter can be confusing, because the expression obj.a.name will not retrieve the name of the function, but will invoke the getter and then try to access the name property of the returned value.
To still get the name of the getter function, you can use Object.getOwnPropertyDescriptor as follows:
let obj = {
get a() { }
};
console.log("property: ", Object.keys(obj)[0]); // "a"
console.log("function: ", Object.getOwnPropertyDescriptor(obj, "a").get.name); // "get a"
This is how a getter's function name is set by default. You can however set it explicitly to your desire using Object.defineProperty as follows:
let obj = {};
Object.defineProperty(obj, "a", {
get: function b() {},
enumerable: true
});
console.log("property: ", Object.keys(obj)[0]); // "a"
console.log("function: ", Object.getOwnPropertyDescriptor(obj, "a").get.name); // "b"
Conclusions
A property name does not necessarily match with the name of the function that might be the property's value.
A property is identified by property name, not by the name of the function that might be associated with it.
The function object, that serves as a getter property, can be accessed with Object.getOwnPropertyDescriptor(object, propertyName).get
You should access it as a normal property like this:
me["firstName"];
But, if you know already the name, you could access the firstName value like this:
me.firstName
Typically, you use the first form if you want to access a property of an object using a variable like this:
const person = new Person("John", "Doe");
const propertyName = "firstName";
const firstName = person[propertyName];
If you want to know more about getter and setters check out this and this.
Follows a fully working example:
class Person {
_firstName = "";
_lastName = "";
constructor(firstName, lastName) {
this._firstName = firstName;
this._lastName = lastName;
}
get firstName() {
return this._firstName;
}
get lastName() {
return this._lastName;
}
fullName() {
return `${this.firstName} ${this.lastName}`;
}
}
const me = new Person("John", "Doe");
const propertyName = "firstName";
console.log(me["firstName"])
console.log(me.firstName)
console.log(me[propertyName])
When doing this:
get firstName() {
return this._firstName;
}
it´s defining a property and the you have to call it over:
me.firstName;
doing it like this:
getFirstName() {
return this._firstName;
}
is really defining a getter function and you can call it like this:
me.getFirstName();
Maybe this is helpfull: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Functions/get

create setter in Javascript

I want to create a setter in JS. But there is something wrong with my code, and this is my code:
class test {
constructor(str) {
this.name = str;
}
set name(str) {
this.sayHi();
}
sayHi() {
let temp = this.name;
console.log(`My name is ${temp}`)
}
}
let a = new test('bill') //My name is undefined
a.sayHi() //My name is undefined
why does it console undefined in this example?how to make it work?
Your setter needs to store the value somewhere; you'll also need a getter to get the value from that place.
Here's a simple example storing the value in another property:
class Test {
constructor(str) {
this._name = str; // ***
// (You might use `this.name = str` here, setters are sometimes
// considered an exception to the "don't call methods in the
// constructor" rule)
}
set name(str) {
this._name = str; // ***
}
get name() { // ***
return this._name; // ***
} // ***
sayHi() {
let temp = this.name;
console.log(`My name is ${temp}`)
}
}
let a = new Test('bill') //My name is undefined
a.sayHi() //My name is undefined
Of course, if you're going to do that, it doesn't make a lot of sense to have a setter, but that's getting a bit afield of the question...
Note: I changed the name of your class to Test (instead of test). The overwhelming convention in JavaScript is that class names (really constructor function names) are initially-capitalized.
Try this instead:
class test {
constructor(str) {
this.name = str;
}
set name(str) {
this._name = str
}
sayHi() {
let temp = this.name;
console.log(`My name is ${temp}`)
}
get name() {
return this._name
}
}

JavaScript Self Invoking function properties

Trying to understand JS better, have a couple of clarifications. Lets suppose we have the following method
var customer = function(){
var name = "Contoso";
return {
getName : function(){
return this.name;
},
setName : function(newName){
this.name = newName;
}
}
}();
why is name not visible outside ?, when we log (customer.name) its undefined, however if we remove the self initializing parenthesis on function and change the variable declaration to (this.name) & again when we log the same we are able to see the value. what am i missing in here.
You need to take in consideration that JavaScript doesn't really have native classes. With this said, the way you can create constructors in order to "mimic" a class and be able to use this you need to create something like so:
function fnc (string) {
this.string = string;
}
fnc.prototype.getString = function() {
return this.string;
}
var x = new fnc('bar');
console.log(x.getString()); //bar
This is called the Constructor Pattern.
What you're trying to do is use something called the Module Pattern which works something like so:
var fn = (function() {
var string = 'foo';
return {
getString() {
return string;
}
}
})();
console.log(fn.getString()); //foo
Here is a working example: https://repl.it/FCn7
Also, a good read: https://addyosmani.com/resources/essentialjsdesignpatterns/book/
Edit
Example using getString and setString with the Module Pattern
var fn = (function() {
var string = 'foo';
return {
getString() {
return string;
},
setString(str){
string = str;
}
}
})();
fn.setString('xyz');
console.log(fn.getString()); // xyz
var is creating variable inside function scope which is not available outside as function property. If you want to access properties like customer.name you need to initialize it as this.name as you noticed.
var in this example is like creating private variable which can be modified by functions, but not directly.
SO this will work:
var customer = function(){
var name = "Contoso";
return {
getName : function(){
return name;
},
setName : function(newName){
name = newName;
}
}
}();

JS getters and setters inside a class?

I'd like to create a class in JS that uses native getters and setters. I know I can create getters/setters for objects, like so:
var obj = {
get value(){
return this._value;
},
set value(val){
this._value = val;
}
}
I also know that I can use this.__defineGetter__ inside a class/function, but MDN says that using __defineGetter__() etc is discauraged.
Is there any better way to add getters and setters to js class than:
function class(){
};
class.prototype = {
get value(){
//....
}
?
2019: Hooray for ES6!
class Person {
get name() {
return this._name + '!!!'
}
set name(newValue) {
this._name = newValue
}
constructor(name) {
this._name = name
}
}
const me = new Person('Zach')
console.log(me.name) // Zach!!!
me.name = 'Jacob'
console.log(me.name) // Jacob!!!
// Of course, _name is not actually private.
console.log(me._name) // Jacob
The cleanest way to define properties on a class is via Object.defineProperties. This allows you to define all of your properties in a single, easily readable block. Here's an example:
var MyClass = function() {
this._a = undefined;
this._b = undefined;
};
Object.defineProperties(MyClass.prototype, {
//Create a read-only property
a : {
get : function() {
return this._a;
}
},
//Create a simple read-write property
b : {
get : function() {
return this._b;
},
set : function(value) {
this._b = value;
}
}
});
There are a plethora of other options when defining properties, so be sure to check out the link I posted for more information. It's also important to keep in mind that even the most basic getter/setter property is only as fast as a method call in current browsers, so they can become a bottleneck in performance-intensive situation.
How about this implementation:
function makeObject(obj, name) {
// The property
var value;
// The setter
obj["get" + name] = function() {return value;};
// The getter
obj["set" + name] = function(v) {
value = v;
};
}
To experiment:
var obj = {};
makeObject(obj, "Name");
obj.setName("Lolo");
print(obj.getName());
Of course, you can test name for validity before storing it in value. The test can be supplied as an additional argument to the makeObject function.

JS: OOP private functions / private fields [duplicate]

This question already has answers here:
A way to encapsulte ( add privacy ) to models in the MVC?
(2 answers)
JavaScript private methods
(34 answers)
Closed 8 years ago.
Systemname =
{
Question :
{
send: function()
{
console.log("send");
},
read: function()
{
console.log("read");
},
delete: function()
{
console.log("delete");
}
},
Answer :
{
send: function()
{
console.log("Answer sent");
}
},
Person :
{
foo: 'foo',
bar: 'bar',
add: function(name)
{
console.log('person "' + name + '" added');
},
remove: function(id)
{
console.log('person with id "' + id + '" removed');
}
}
}
i'm learning how oop works in js and i'm a bit confused now about private methods and fields. i'd like to have some private member in the person section such as 'personCount' or 'lastAddedPerson'. if i add them like this:
Person:
{
personCount: 0,
lastAddedPerson: '',
...
}
at the beginning of the person section, the fields are public and can be called with Systemane.Person.Field.... how can i set them private? and the same for a method.
thx for your help.
Here is one way.
function Person(n) {
var name = n;
this.getName = function() {
return name;
}
this.setName = function(newName) {
name = newName;
}
}
var person = new Person('roman');
You can't have private properties or methods when you create objects using literals. In fact, there are no private properties in JavaScript, but you can achieve that in practice by using a constructor function, and declaring the private properties and methods as variables:
function Person() {
var privteProperty = 1;
var privateMethod = function(){}
this.publicProperty = 2;
this.publicMethod = function(){}
}
Then you can create an instance with:
var john = new Person();
I like using a sort of factory pattern instead of new:
var Person = (function() {
return {
create: function(name) {
return (function(n) {
var name = n;
function getName() {
return name;
}
function setName(newName) {
name = newName;
}
return {
getName: getName,
setName: setName
};
}(name));
}
};
})();
Then:
var person = Person.create("Bob");
person.getName(); //returns Bob
person.setName("Jimbo");
person.getName(); //returns Jimo
Seems complex, but is pretty simple.
Person is essentially assigned the return value of an anonymous self-invoked function. This return value has a single property called create, which is a reference to another function, which more-or-less acts like a constructor. This function also returns the return value of another anonymous self-invoked function. However, this return value is the actual instance of the object that you want. Inside this anonymous self-invoked function, you can see that I have a variable called name. This variable is private to that anonymous self-invoked function and lexically bound to the scope in which it is defined. What this means is that the value of name is preserved inside that function. Basically it hangs around even after the function is done executing. The only way you can access or modify that variable is through the getName and setName functions.

Categories

Resources