This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 6 years ago.
class UrlProvider {
constructor(root) {
this.root = root;
}
getUrl() {
return this.root + "/api/Situations";
}
}
class Repository {
constructor(urlProvider) {
this.urlProvider = urlProvider;
}
getAsync() {
var self = this;
return httpGetAsync(self.urlProvider.getUrl()).then(function(d) {
return d.map(x => new Situation(x));
});
}
}
class PromiseCacher {
constructor(cache, promise) {
var self = this;
self.cache = cache;
self.promise = promise;
}
runAsync() {
var self = this;
return self.promise().then(function (d) {
self.cache.set(d);
return d;
});
}
}
var urlProvider = new UrlProvider(appsettings.url);
var repository = new Repository(urlProvider);
var cache = new Cache();
var promiseCacher = new PromiseCacher(cache, repository.getAsync);
promiseCacher.runAsync()
When debugging the above code, chrome will crash inside the getAsync function of the repository because self.urlProvider is undefined.
Inside the repository getAsync function 'this' is referring to the instance of PromiseCacher which is what actually calls it.
What's going on?
Re-writing
var promiseCacher = new PromiseCacher(cache, ()=> repository.getAsync());
makes it work as I would expect.
That's because first of all repository.getAsync is not a promise. Instead it is a function. By storing the reference of repository.getAsync to a different object property you "alter" its this value. Take a look at the following example:
var obj = {
a: 42,
func: function(){
return this.a;
}
};
obj.func(); // 42
var b = obj.func;
b(); // undefined
The example is comparable to your code:
class Repository{
// urlProvider = ...
getAsync (){ /* ... */ }
}
var repo = new Repository(/* ... */);
repo.getAsync(); // works
var cacher = new PromiseCacher(/* ... */);
cacher.promise = repo.getAsync;
cacher.promise(); // does not work
Related
This question already has answers here:
Private properties in JavaScript ES6 classes
(41 answers)
Closed 5 years ago.
I want to build a class using javascript like in c, the main problem is private attribute.
var tree = {
private_var: 5,
getPrivate:function(){
return this.private_var;
}
};
console.log(tree.private_var);//5 this line want to return unaccessible
console.log(tree.getPrivate());//5
so I want to detect the access from tree.private_var and return unaccessible, and this.private_var return 5.
My question is: Is there any way to set private attribute in javascript?
EDIT: I saw this way
class Countdown {
constructor(counter, action) {
this._counter = counter;
this._action = action;
}
dec() {
if (this._counter < 1) return;
this._counter--;
if (this._counter === 0) {
this._action();
}
}
}
CountDown a;
a._counter is not accessible?
but
Define tree as a function instead of JavaScript object, define private variable in the function by var keyword, define public getting function by this. keyword and create a new instance by using the function
var Tree = function(){
var private_var = 5;
this.getPrivate = function(){
return private_var;
}
}
var test = new Tree();
test.private_var; //return undefined
test.getPrivate(); //return 5
In ES6, you can do this but it is not supported by IE so I wouldn't recommend
class Tree{
constructor(){
var private_var =5;
this.getPrivate = function(){ return private_var }
}
}
var test = new Tree();
test.private_var; //return undefined
test.getPrivate(); //return 5
This question already has answers here:
Are ES6 classes just syntactic sugar for the prototypal pattern in Javascript?
(7 answers)
Closed 6 years ago.
When I research online, I'm finding different answers.
class Foo {
constructor() {
this.data = [];
}
add(x) {
//
}
}
Is the above code equivalent to Code A or Code B?
Code A:
function Foo() {
this.data = [],
this.add = function(x) {
//
}
}
Code B:
function Foo() {
this.data = []
}
Foo.prototype.add = function(x) {
//
}
Code B in your example, here is an example taken from https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Classes
class Animal {
speak() {
return this;
}
static eat() {
return this;
}
}
let obj = new Animal();
let speak = obj.speak;
speak(); // undefined
let eat = Animal.eat;
eat(); // undefined
is the same as
function Animal() { }
Animal.prototype.speak = function(){
return this;
}
Animal.eat = function() {
return this;
}
let obj = new Animal();
let speak = obj.speak;
speak(); // global object
let eat = Animal.eat;
eat(); // global object
Be aware this is using ES6 notation and is not fully supported at time of writing. See here for what supports ES6 - https://kangax.github.io/compat-table/es6/
This question already has answers here:
Javascript "this" pointer within nested function
(9 answers)
Closed 6 years ago.
I have the following JS-Object:
var obj = function(){
this.var1 = "var1";
this.getvar1 = function(){
return this.var1;
}
this.call1 = function(){
this.getvar1();
}
}
all methods have to be public
all properties have to be public as well
Problem:
If i try to call a public method of the obj-Object from inside another public method of the obj-Object, the "this" keyword refers to the public method itself instead of the Object.
Is there a way to get around this?
You can assign this to a variable(self) and use that:
var obj = function(){
var self = this;
self.var1 = "var1";
self.getvar1 = function(){
return self.var1;
}
self.call1 = function(){
self.getvar1();
}
}
You just forgot to return from call1. Add return and it will work as expected:
var obj = function() {
this.var1 = "var1";
this.getvar1 = function() {
return this.var1;
}
this.call1 = function() {
return this.getvar1();
}
}
var a = new obj()
console.log( a.call1() )
Maybe you meant this:
const obj = {
var1: 'var1'
,getvar1() {
return this.var1
}
,call1() {
return this.getvar1()
}
}
console.log(obj.call1())
I am new to IIFE and trying to implement namespace in JavaScript on a Siungleton JavaScript class:
I have a JavaScript class (say main class):
var myIIFE = (function () {
var x = null;
//constructor function
var myIIFE = function() {
var a = new IIFE.InsideIIFE(); //says not a constructor
}
myIIFE.prototype = {
//some methods
}
function createIstance() {
return new myIIFE();
}
return {
getInstance: function() {
if (!this.instance) {
this.instance = createInstance();
}
return this.instance;
}
};
})();
Then I have another JavaScript namespaced class:
myIIFE.InsideIIFE = (function() {
var inside = function() {}
inside.prototype = { //some methods }
return inside;
});
I want to create an object of myIIFE.InsideIIFE in myIIFE, and this is throwing me an error:
myIIFE.InsideIIFE is not a constructor
Am I doing something wrong? Or if this is a correct approach then what changes I should make.
I tried using new this.InsideIIFE() and just InsideIIFE, but non of them worked.
edit:
From my analysis, I understand that myIIFE (the parent) is an object as it return an object at:
return {
getInstance: function() {
//method body
}
}
There are many issues with this code, let's try to run it in our heads, from the start:
var myIIFE = (function () {
....
})();
This results in myIIFE being an object, to be precise, this object:
{
getInstance: function() {
if (!this.instance) {
this.instance = createInstance();
}
return this.instance;
}
}
So, then I assume, you do
myIIFE.getInstance()
Which tries to return new myIIFE();
It runs into myIIFE() and tries to do this:
new IIFE.InsideIIFE();
I assume you meant to write
new myIIFE.InsideIIFE();
because IIFE is not defined it anywhere in the code you provided.
Let's see what is myIIFE.insideIIFE
var myIIFE.InsideIIFE = (function() {
var inside = function() {}
inside.prototype = { //some methods }
return inside;
});
First of all you start with var, which is wrong, because myIIFE is already defined and you are just adding a new property to it. so it should be simply
myIIFE.InsideIIFE = (function() {
var inside = function() {}
inside.prototype = { //some methods }
return inside;
});
and it should work.
In general, it seems by your code, like you have not grasped the whole "constructor function" concept very well. I would suggest you take look at the following links, they should help.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript
I received error of Uncaught TypeError: object is not a function on the line with new
it can only run if I do var item = mylib;
However, I am not really clear what is the issue here.
(function(window){
function mylib (){
var Library={};
Library.localVar1="One";
Library.localVar2="Two";
Library.func1 = function (){
console.log("func1 output"+Library.localVar1)
return true;
}
Library.func2 = function (){
Library.func2Var1 = "func2One";
console.log("func2 output"+Library.localVar2)
return Library.func2Var1;
}
return Library;
}
//define globally if it doesn't already exist
if(typeof(Library) === 'undefined'){
window.mylib = mylib();
}
else{
console.log("Library already defined.");
}
})(window);
var item = new window.mylib;
console.log(item.localVar2,"var2");
console.log(item.func2(),"func2");
console.log(item.func1(),"func1");
As you use var item = new window.mylib; I assume you want to create a new instance from Library.
But in your code, Library is an Object, not a constructor, constructor should be a Function. So you'll get that error.
(function(window){
function mylib (){
var Library = function() {
// Set self's variable
this.localVar1="One";
this.localVar2="Two";
}
// Use prototype to define the shared function.
Library.prototype.func1 = function (){
console.log("func1 output"+this.localVar1)
return true;
};
Library.prototype.func2 = function (){
Library.func2Var1 = "func2One";
console.log("func2 output"+this.localVar2)
return Library.func2Var1;
};
return Library;
}
//define globally if it doesn't already exist
if(typeof(Library) === 'undefined'){
window.mylib = mylib();
}
else{
console.log("Library already defined.");
}
})(window);
var item = new window.mylib(); // Create a instance of Library
console.log(item.localVar2,"var2");
console.log(item.func2(),"func2");
console.log(item.func1(),"func1");