var abc = {
'a': 10,
'b': 10,
c: function() {
//like if I have many many functions in c
init_a();
multiple();
function init_a() {
abc.a = 30;
}
function multiple() {
alert(abc.a * abc.b);
}
function minus() {
alert(abc.a - abc.b);
}
return {
function myalert() {
var result = abc.a + abc.b;
alert(result);
}
}
},
d: function() {
abc.c.myalert(); // ??? error??
abc.c().myalert(); // ??? error?? **it run all functions in c but not just myalert, strange things happening...
}
}
abc.d();
whats the correct syntax to call the 'myalert()' function in function d?
The myalert() function iswas local to abc.c(), so that's not possible.
You could let c() return myalert() though:
c: function() {
return function myalert() {
// whatever
}
}, d: function() {
this.c()()
}
Note that the returned function doesn't have to be named, i.e. return function() { .. }.
Update
If you want to call it like this.c().myalert(), then c() needs to return an object instead of the function directly:
c: function() {
return {
myalert: function() { ... }
}
}
Update 2
Your c() function now contains other statements besides the declaration of myalert(). When called, init_a() and multiple() get called before it returns.
I would suggest refactoring your code, such as, move myalert() into the main object instead:
var abc = {
a: 10,
b: 10,
c: function() { ... }
myalert: function() { ... }
d: function() {
this.myalert();
}
}
You can return an object from c that contains myalert:
var abc = {
'c': function() {
return {
myalert: function() {
alert('foo');
}
};
},
'd': function(){
abc.c().myalert(); // foo
}
};
abc.d();
Demo: http://jsfiddle.net/g2KEK/
c: function() {
return {
myalert : function() {
// whatever
}
}
}, d: function() {
this.c().myalert()
}
Related
I have a question about .bind() function.
I have this code and it outputs Window object and I don't understand why. Could you explain to me why bind(this) had no effect on the function?
let vakho = {
name: "salome",
a: function () {
let something = function () {
return this;
}
something.bind(this)
return {
f: function () {
return something();
}
}
},
}
console.log(vakho.a().f())
.bind returns a new function with the attached context. You need to assign the result to the something again.
let vakho = {
name: "salome",
a: function () {
let something = function () {
return this;
};
something = something.bind(this); // Assign to the something
return {
f: function () {
return something();
}
}
},
}
console.log(vakho.a().f());
console.log(vakho.a().f().name);
I have an array of objects containing references (bound by the .bind() method) to my class functions. When I access them directly, like array[3].myFunction, everything works fine. But the strange behavior occurs when I try to access these function iterating over the array. I've tried by Array.forEach(), for-in, for-of and Array.map() function, but the result is always the same - I get the first function four times. What am I doing wrong here? Thanks in advance.
var Container = function() {
this.function1 = function() {
console.log('function 1 invoked');
};
this.function2 = function() {
console.log('function 2 invoked');
};
this.function3 = function() {
console.log('function 3 invoked');
};
this.function4 = function() {
console.log('function 4 invoked');
};
this.array = [
{ key: '1', myFunction: this.function1.bind(this) },
{ key: '2', myFunction: this.function2.bind(this) },
{ key: '3', myFunction: this.function3.bind(this) },
{ key: '4', myFunction: this.function4.bind(this) },
];
};
var container = new Container();
// Just printing the results below
console.log('direct access:');
console.log(container.array[3].myFunction);
console.log('forEach:');
container.array.forEach(el => {
console.log(el.myFunction);
});
console.log('for in:');
for (let i in container.array) {
console.log(container.array[i].myFunction);
}
console.log('map:')
container.array.map(el => {
console.log(el.myFunction);
});
PLNKR: http://plnkr.co/edit/mn8iGh4F3GcJXTNWXMiJ?p=preview
Have a look below. All seems to be working.
When you do console.log(el.myFunction), it will actually print the handle and not executing it where all handle looks same as function () { [native code] }
When you invoke the function instead el.myFunction(), you can see all they are calling the right functions and print the results respectively.
You can check the function invocation below.
var Container = function() {
this.function1 = function() {
console.log('function 1 invoked');
};
this.function2 = function() {
console.log('function 2 invoked');
};
this.function3 = function() {
console.log('function 3 invoked');
};
this.function4 = function() {
console.log('function 4 invoked');
};
this.array = [
{ key: '1', myFunction: this.function1.bind(this) },
{ key: '2', myFunction: this.function2.bind(this) },
{ key: '3', myFunction: this.function3.bind(this) },
{ key: '4', myFunction: this.function4.bind(this) },
];
};
var container = new Container();
// Just printing the results below
console.log('direct access:');
container.array[3].myFunction();
console.log('forEach:');
container.array.forEach(el => {
el.myFunction();
});
console.log('for in:');
for (let i in container.array) {
container.array[i].myFunction();
}
console.log('map:')
container.array.map(el => {
el.myFunction();
});
My issue is I have 2 inner objects in my js class and I'm trying to use the methods from one of those objects in my other object (examples of what I'm trying to do below). I understand why this doesn't work because of a the scope. I'm just wondering if there is a way to get it to work.
var Class1 = {
self : this,
Obj1 : {
Obj1Method : function () {
alert("Do something");
},
Obj1Method2 : function () {
alert("Do something else");
},
InnerObj1 : {
InnerNestObj1Method : function (val) {
alert(val + 2);
}
}
},
Class1Method2 : function () {
this.Obj1.Obj1Method2();
},
Obj2 : {
Obj2Method : function (val2) {
self.Obj1.InnerObj1.InnerNestObj1Method(val2);
},
Obj2Method2 : function () {
self.Class1Method2();
}
}
};
Class1.Obj1.InnerObj1.InnerNestObj1Method(3); //works
Class1.Class1Method2(); //works
Class1.Obj2.Obj2Method2(); //No bueno
Class1.Obj2.Obj2Method(5); //No bueno
You can fix your example by replacing self with Class1.
The line self : this, is setting Class1.self to point to the global object (this when that line is evaluated).
var Class1 = {
self : this,
Obj1 : {
Obj1Method : function () {
alert("Do something");
},
Obj1Method2 : function () {
alert("Do something else");
},
InnerObj1 : {
InnerNestObj1Method : function (val) {
alert(val + 2);
}
}
},
Class1Method2 : function () {
this.Obj1.Obj1Method2();
},
Obj2 : {
Obj2Method : function (val2) {
Class1.Obj1.InnerObj1.InnerNestObj1Method(val2);
},
Obj2Method2 : function () {
Class1.Class1Method2();
}
}
};
Class1.Obj1.InnerObj1.InnerNestObj1Method(3); //works
Class1.Class1Method2(); //works
Class1.Obj2.Obj2Method2(); //bueno
Class1.Obj2.Obj2Method(5); //bueno
What happens when you do self: this
// If this is running in non strict mode, from the global scope, `this` points
// To the global object because there was no function call setting `this`
var Class1 = {
self : this,
};
What you need to understand is that this is set by whoever called the function using this. In the example above, there is no caller, so the runtime sets this to point to the global object.
Here's how you could you could make your object a bit more reusable and give yourself a reference to the outer object:
function createClass() {
var self = {
Obj1: {
Obj1Method: function() {
alert("Do something");
},
Obj1Method2: function() {
alert("Do something else");
},
InnerObj1: {
InnerNestObj1Method: function(val) {
alert(val + 2);
}
}
},
Class1Method2: function() {
self.Obj1.Obj1Method2();
},
Obj2: {
Obj2Method: function(val2) {
self.Obj1.InnerObj1.InnerNestObj1Method(val2);
},
Obj2Method2: function() {
self.Class1Method2();
}
}
};
return self;
}
var Class1 = createClass();
Class1.Obj1.InnerObj1.InnerNestObj1Method(3); //works
Class1.Class1Method2(); //works
Class1.Obj2.Obj2Method2(); //works
Class1.Obj2.Obj2Method(5); //works
You can do it with Classes:
"use strict"
class Class1 {
constructor() {
this.Obj1 = {
Obj1Method: function() {
alert("Do something");
},
Obj1Method2: function() {
alert("Do something else");
},
InnerObj1: {
InnerNestObj1Method: function(val) {
alert(val + 2);
}
}
};
var self = this;
this.Obj2 = {
Obj2Method: function(val2) {
self.Obj1.InnerObj1.InnerNestObj1Method(val2);
},
Obj2Method2: function() {
self.Class1Method2();
}
};
}
Class1Method2() {
this.Obj1.Obj1Method2();
}
};
var c1 = new Class1();
c1.Obj1.InnerObj1.InnerNestObj1Method(3); //works
c1.Class1Method2(); //works
c1.Obj2.Obj2Method(3); //works
c1.Obj2.Obj2Method2(); //works
I have something like this:
var yourNamespace = {
foo: function() {
.....
},
bar: function() {
function foobar() {....
}
}
};
Is there a possibility to call inside of foo, the foobar function inside of bar?
With your exact structure you cannot however you can do something like that :
var yourNamespace = {
foo: function() {
.....
yourNamespace.foobar()
},
bar: function() {
function foobar() {....}
yourNamespace.foobar = foobar;
}
};
Or nicer, (IMO) :
var yourNamespace = {
foo: function() {
.....
yourNamespace.bar.foobar()
},
bar: function() {
yourNamespace.bar.foobar = function() {....}
}
};
Please note: in both case, bar() must run before foo() otherwise foobar is undefined
This is just a simple Module pattern. What you should do is make bar it's own module, and return foobar from that module. Example:
var yourNamespace = {
foo: function() {
this.bar.foobar();
},
bar: {
abc: '',
foobar: function() {
console.log('do something');
}
}
};
Or you could do something more like this:
var yourNamespace = {
foo: function() {
var bar = this.bar();
},
bar: function() {
var abc = '';
function foobar() {
console.log('return abc or do something else');
return abc;
}
return {
foobar: foobar
}
}
};
How to call getStartPoint() in startPoint, in the below code?
var obj = (function () {
return {
defaults: {
prop: {
getStartPoint: function () {
// more login ...
},
getEndPoint: function () {
// more login ...
},
startPoint: this.getStartPoint(),
endPoint: this.getEndPoint(),
}
}
};
})();
I am getting error
Uncaught TypeError: Object ... has no method 'getStartPoint'
in all these: getStartPoint(), this.getStartPoint(), obj.defaults.prop.getStartPoint()
One possible solution:
var obj = (function () {
function getStartPoint() {
console.log("getStartPoint");
}
function getEndPoint() {
console.log("getEndPoint");
}
return {
defaults: {
prop: {
getStartPoint: getStartPoint,
getEndPoint: getEndPoint,
startPoint: getStartPoint(),
endPoint: getEndPoint()
}
}
};
})();
Another:
function Obj() {
if (!(this instanceof Obj)) return new Obj();
this.defaults = {
prop: {
startPoint: this.defaults.prop.getStartPoint(),
endPoint: this.defaults.prop.getEndPoint()
}
};
}
Obj.prototype = {
defaults: {
prop: {
getStartPoint: function () {
console.log("getStartPoint");
},
getEndPoint: function () {
console.log("getEndPoint");
}
}
}
};
var obj = new Obj();