I am getting an issue in the below code:
let a = 13;
function printA() {
let a = 19;
console.log(this.a);
}
let obj = {
a: 10,
fun: function() {
console.log(this.a);
}
};
let obj2 = {
a: 20
};
let x = obj.fun;
x();
can anybody tell why it is printing undefined ?
It prints 13 when we remove let from let a = 13
There is no a for your x to fetch, that is why you get undefined.
let obj = {
a: 10,
fun: function () {
console.log(this.a);
}
};
let x = obj.fun;
x();
Your x is pointing to a function as obj.fun. But there is no obj.fun.x exist, so it will result undefined.
Try the following:
let obj = {
a: 10,
fun: function () {
console.log(this.a);
}
};
let x = obj;
x.fun();
or
let obj = {
fun: function () {
this.a = 10;
console.log(this.a);
}
};
let x = obj.fun;
x();
They both will result 10 as output.
These two example both have an x property under the x.
NOTE: By making a let a = 10 under the fun function will not give you result of this.a is because such declaration works like a private parameter declaration in C/JAVA etc.
Related
var obj = {
a: 2,
}
var a = 3;
const func = () => {
console.log(this.a);
}
function test() {
setTimeout(func, 100);
}
function test2() {
setTimeout(() => {
console.log(this.a);
}, 100);
}
test.call(obj); //3
test2.call(obj); //2
It seemed that the test and test2 are the same, but the returned result is different, what's the problem with 'this'?
with test arrow function, this will refer to the window object, and as var a = 3, the a will be assigned as a property to the window, it will be like
window.a
But in test2 this will refer to the obj object.
Why the arrow function returned in the following example doesn't prints undefined
let obj = {
a: "88",
c: () => {
console.log(this.a);
},
d: function() {
return () => {
console.log(this.a);
}
}
}
let ob = {
a: 99
}
let t = obj.d()
t(); // its printing 88 not undefined why
d was created with a function expression
Therefore when you call obj.d() the value of this is the same as the value of obj.
d returns an arrow function.
Arrow functions have lexical this so it uses this from d which was the same as obj
this.a is therefore the same as obj.a which is "88"
Because when you do let t = obj.d(), it will return you a function that will be saved in t
t = () => {
console.log(this.a);
}
Now talking about this.a, here this will the obj and value of a in obj is 88 do that is the reason 88 is printed
I come across singleton pattern, it's quite tricky to understand how to implement it, and I know some people would suggest to avoid it most of the time, so below is specific singleton variation that I find it easy to understand, but somehow I feel that this is not the best implementation of this pattern, can you guys suggest better form of this pattern.
var Foo = (function () {
var instance;
var _priVar = 2;
var log = function() {
console.log("Hello");
};
function Singleton(x, y) {
if (instance) {
return instance;
}
this.name = x;
this.age = y + _priVar;
this.log = log;
instance = this;
}
Singleton.getInstance = function () {
return instance || new Singleton();
}
return Singleton;
}());
and my goal is that when we do following
var a = new Foo("Bob", 24);
var b = new Foo();
var c = Foo();
var d = Foo.getInstance();
we will still get
a == b // true
a == c // true
a == d // true
a.name // 'Bob'
b.age // 26
c.log // 'Hello'
d.name // 'Bob'
The simplest singleton, also known as module pattern, consists of an object literal:
var foo = (function () {
var x = "Bob",
y = 24,
_priVar = 2;
function log() {
console.log("Hello");
}
return {
name: x,
age: y + _priVar,
log: log
};
}());
If you want to introduce lazy initialisation, you can use an extra getInstance function like in your implementation:
var getFoo = (function () {
var instance = null;
return function getFooInstance() {
if (instance) return instance;
var x = "Bob",
y = 24,
_priVar = 2;
function log() {
console.log("Hello");
}
return instance = {
name: x,
age: y + _priVar,
log: log
};
};
}());
A singleton should never use a constructor like in your code, that's just unnecessary. If you feel a need to pass arguments for initialisation, don't make it a singleton.
When defining an object literal its possible to use a self-invoking function so the function has access to private variables,
obj={
value:(function(){
var private;
return function(){
return true;
}
}())
};
But is it possible to do the same thing with a getter/setter in an object literal?
obj={
get value(){
return value;
},
set value(v) {
value=v;
}
};
[edit 2022]
A pretty old answer.
More actual: you can create a factory function. In the snippet the factory creates an object with (get and set) access (through the closure) to a private variable.
const obj1 = objFactory(`Hello`);
const obj2 = objFactory(`World`);
console.log(`${obj1.privateThing} ${obj2.privateThing}`);
obj1.privateThing = `Goodbye`;
console.log(`${obj1.privateThing} ${obj2.privateThing}`);
function objFactory(somethingPrivate) {
return {
get privateThing() { return somethingPrivate; },
set privateThing(value) { somethingPrivate = value; }
};
}
The old answer:
Not really. You can also create an Immediately Invoked Function Expression (IIFE) for obj though:
obj = function(){
var privatething = 'hithere';
return {
get value() {
return privatething;
},
set value(v) {
privatething = v;
}
};
}();
obj.value; //=> 'hithere';
obj.value = 'good morning to you too';
obj.value; //=> 'good morning to you too'
As per ES6 and later style, default values can also be set in the signature.
const _ = function(_x = 'leafy greens', _y = 'chicken', _z = 'noodle soup') {
// console.log(_x)
return {
_x,
_y,
_z,
get x() { return this._x },
set x(value) { this._x = value }
}
}()
console.log(_.x)
_.x = 'beef & pork'
console.log(_.x)
This works.
var obj = {a:1};
console.log(obj.a); //1
Object.defineProperty(obj,"a",{
get: function(){
return this.b;
},
set: function(x){
this.b = x;
},
configurable:true,
});
obj.a = 10;
console.log(obj); //10
for(var key in obj)
{
console.log(key)
}
If you don't want the property b to be enumerated while using for...in loop or Object.keys(), just add the line
Object.defineProperty(obj,"b",{enumerable:false})
Note : The above code can also be used as a listener, to detect changes in the property's value. (By implementing the needed function in the set method, after setting the value.)
var obj = {a:1};
console.log(obj.a); //1
Object.defineProperty(obj,"a",{
get: function(){
return this.b;
},
set: function(x){
this.b = x;
console.log("obj.a value has been changed to "+x);
},
configurable:true,
});
obj.a = 10;
obj.c = 20;
obj.a = 30;
Why am I getting undefined on the x.test()? It's an anonymous function.
var Calculator = function () {
// private stuff
var x = 55;
return {
// public members
y: x,
test: function () {
console.log(x);
}
};
};
var x = new Calculator();
console.log(x.y);
console.log(x.test());
You're logging the return value of x.test which is implicitly undefined:
console.log(x.y); // Logs 55
var x = x.test(); // Logs 55 (because of the console.log call in x.test)
console.log(x); // Logs undefined (because that's what x.test returned)
Did you mean to return the "private" x from the test method?
// ...
return {
y: x,
test: function () {
return x;
}
}
Because you are printing (console.log) the return of a function that doesn't return anything.
Just return the x value in your test function:
var Calculator = function () {
// private stuff
var x = 55;
return {
// public members
y: x,
test: function () {
return x;
}
};
};