How to accede to the variable from the nested function in JavaScript?
function Foo() { // class Foo
this.name = 'myName';
this.bar = function() { // 'bar' method
return function() { // nested method
return this.name; // how to accede to that?
}
}
}
Is the variant bellow optimal :?
this.bar = function() { // 'bar' method
var innerName = this.name; // duplicated variable :-/
return function() { // nested method
return innerName;
}
}
The more usual approach is to keep a reference to the entire outer object:
function Foo() { // class Foo
var _self = this;
this.name = 'myName';
this.bar = function() { // 'bar' method
return function() { // nested method
return _self.name;
}
}
}
Like this:
function Foo() { // class Foo
var that = this;
this.name = 'myName';
this.bar = function() { // 'bar' method
return function() { // nested method
return that.name; // how to accede to that?
}
}
}
If you're in a ES6 capable environment, you can also arrow functions for that:
function Foo() {
this.name = 'myName';
this.bar = () = > () => this.name;
}
Related
This question already has answers here:
What is the 'new' keyword in JavaScript?
(17 answers)
Closed 3 years ago.
I have code like this:
function Thing() {
function foo() {
alert('1');
}
return { foo : foo }
}
window['myThings'] = {
bar : function() {
let t = new Thing();
t.foo = function() {
Thing.prototype.foo.call(this);
alert('2');
}
}
}
And have error: "Uncaught TypeError: Cannot read property 'call' of undefined". I want override object method with custom method, from which call parent method and then add some code. Where is my mistake?
P. S. Read article on the link from the comments and change code like this:
Thing = function () {
this.someVar = 1;
foo();
}
Thing.foo = function() {
alert('1');
}
window['myThings'] = {
bar : function() {
let t = new Thing();
t.foo();
}
}
And now i have an error: foo is not a function...
P. P. S. Change code like this:
function Thing() {};
Thing.prototype = function (arg) {
this.someVar = arg;
this.foo();
}
Thing.prototype.foo = function() {
alert('1');
}
window['myThings'] = {
bar : function() {
let t = new Thing(1);
t.foo();
}
}
myThings.bar();
And now: arg passed to constructor not stored in someVar or not readed from it...
Solution is here:
function Thing(arg) {
var private = 'private';
this.public = 'public';
this.init = function(arg) {
private = arg;
this.foo();
alert(private);
}
this.foo = function() {
alert('foo');
}
this.init(arg);
};
window['myThings'] = {
things : [],
bar : function() {
this.things[0] = new Thing('privateArg');
function AnotherThing(arg) {
Thing.call(this, arg);
var parentFoo = this.foo;
this.foo = function() {
// Call parent method
parentFoo();
// Run custom code
alert('foo foo');
}
}
// Parent init called with parent foo() method
this.things[1] = new AnotherThing(2);
// Customized foo() called
this.things[1].foo();
}
}
myThings.bar();
I am using JavaScript prototype chaining technique to chain functions as shown below:
var foo = (function () {
function fn(arg) {
if (!(this instanceof fn)) {
return new fn(arg);
}
this.arg = arg;
return this;
}
var func = function (element) {
return fn(element);
};
fn.prototype = {
bar: function () {
return this;
}
}
func.functions = fn;
return func;
}());
I would like to know how to access fn.prototype so I can add more functionality to the foo prototype outside its closure.
If I just simply do as follows, it won't work:
foo.prototype.baz = function () {
alert(this.arg);
}
foo("hello").baz();
However if fn assigned to the foo (func.functions = fn;) as it shown in the foo private closure I can do as follow and it will works:
foo.functions.prototype.baz = function () {
alert(this.arg);
}
foo("hello").baz();
Is there any other way to achieve this?
I think you are un-necessarily overcomplicating this. You can chain by simply doing this:
const foobar = function(){return this} // Initialize a new Object
const foo = text => {
const me = new foobar()
me.text = text
me.bar = a => (alert(me.text+": "+a), me)
return me
}
foo('A').bar('Test').bar('Test chained')
// Update the foobar class with baz
foobar.prototype.baz = function() {alert('BAZ worked!');return this}
foo('B').bar('1').baz().bar('2')
Note: Click Run code snippet to see the output
That's it!
Edit:
You can also do this with ES6 classes like:
class foobar {
constructor(text) {
this.text = text;
}
bar(a) {alert(this.text+": "+a);return this}
}
const foo = text => new foobar(text)
foo('A').bar('Test').bar('Test chained')
// Update the foobar class with baz
foobar.prototype.baz = function() {alert('BAZ worked!');return this}
foo('B').bar('1').baz().bar('2')
I have 2 Obj: I want to know that if they are Singleton?
a.
var OBJ = function () {
}
OBJ.prototype = {
setName : function (name) {
this.name = name;
},
getName : function () {
return this.name;
}
}
b.
var OBJ = {
setName : function (name) {
this.name = name;
},
getName : function () {
return this.name;
}
}
You can check it by creating two instances of class and compare them:
Print( a === b ); // prints: true
if prints true class is singleton
Or you can try this code for SingletonPattern:
function MyClass() {
if ( arguments.callee._singletonInstance )
return arguments.callee._singletonInstance;
arguments.callee._singletonInstance = this;
this.Foo = function() {
// ...
}
}
var a = new MyClass()
var b = MyClass()
Print( a === b ); // prints: true
Best Solution For Singleton Pattern
This will help you How to write a singleton class in javascript
function Cats() {
var names = [];
// Get the instance of the Cats class
// If there's none, instanciate one
var getInstance = function() {
if (!Cats.singletonInstance) {
Cats.singletonInstance = createInstance();
}
return Cats.singletonInstance;
}
// Create an instance of the Cats class
var createInstance = function() {
// Here, you return all public methods and variables
return {
add : function(name) {
names.push(name);
return this.names();
},
names : function() {
return names;
}
}
}
return getInstance();
}
More on http://www.javascriptkata.com/2009/09/30/how-to-write-a-singleton-class-in-javascript/
Also it can be possible duplicate of Javascript: best Singleton pattern and Simplest/Cleanest way to implement singleton in JavaScript?
I have this object, dive:
var dive = new Foo.Bar();
And Foo.Bar looks like this:
var Foo = {
Bar: function() {
...
return function() {
// do stuff, no return
};
}
};
I'd like dive to have all the prototypes of another, existing object, however. Let's say window.Cow.prototype is:
{
moo: function() { ... },
eat: function() { ... }
}
What do I need to do to Foo.Bar so that I can do this:
dive.moo();
dive.eat();
var Foo = {
Bar: function() {
//...
return this; // technically unnecessary, implied by 'new' operator
}
};
Foo.Bar.prototype = new Cow(); // the secret sauce
dive = new Foo.Bar();
dive.moo(); // moo's like a Cow
Here is a working example without the Bar constructor jsFiddle
Thank you for the start, jimbojw! You were close, but you gave me enough information to get it:
function Cow() {
return {
talk: function() {
alert("mooo");
}
};
}
var Foo = {
Bar: function() {
function result() {
alert("Foo.Bar says...");
};
result.prototype = new Cow();
return new result;
}
};
new Foo.Bar().talk();
If you want to encapsulate Foo.Bar.prototype = you can do it without changing default constructor behavior:
function Cow() {
this.talk = function() {
alert("mooo")
}
}
var Foo = {
Bar: function() {
var constructor = function() {
this.eat = function() {
alert("gulp")
}
}
constructor.prototype = new Cow()
return constructor
}()
}
var foo = new Foo.Bar()
foo.talk()
foo.eat()
How could I do this?
Class
var Factory = (function() {
var Class = function() {
this.name = 'John';
this.methods = {
get: function(callback) {
callback();
}
};
};
return {
createClass: function() {
return new Class();
}
};
}());
Usage
var MyClass = Factory.createClass();
MyClass.methods.get(function() {
this.name // => returns undenfined
});
Thanks for any help!
You need to save a reference to this in the outer Class function and call call:
var instance = this;
this.methods = {
get: function(callback) {
callback.call(instance);
}
};
var Class = function() {
// Save a reference to this that can be used in local closures.
var me = this;
this.name = 'John';
this.methods = {
get: function(callback) {
// Use 'call()', passing the reference to the 'Class' object
callback.call(me);
}
};
};
#SLaks - The declaration of scope as a Global variable is bad practice.
#Ferdinand Beyer - have you tested if it functions?
The better way will be the scope binding. The Prototype javascript framework produced a nice concept and we can easily implement it like
Function.prototype.bind = function(scope) {
var _function = this;
return function() {
return _function.apply(scope, arguments);
}
}
and then yoou code should have only a single change and it will maintin the scope of your class.
var Factory = (function() {
var Class = function() {
this.name = 'John';
var me = this;
this.methods = {
get: function(callback) {
callback();
}
};
};
return {
createClass: function() {
return new Class();
}
};
}());
var MyClass = Factory.createClass();
MyClass.methods.get(function() {
console.info(this.name) // => returns undenfined
}.bind(MyClass));
I mean only the function call get with .bind(MyClass)