How to reuse closure with different variables - javascript

I want to reuse the function sayMyName but with different variables. Please let me know if I'm structuring this the wrong way and what is the best practice what what I'm trying to do.
var sayMyName = function(myName) {
console.log(myName)
};
var name1 = function() {
// myName should not be a global variable
// because there may be more variables/functions
// that I'd want to closed inside sayMyName().
// Declaring all of them to the global scope is not ideal.
var myName = 'Walter';
sayMyName();
// I don't want to pass in myName as argument like this:
// sayMyName(myName);
// I want myName to be implicitly included in sayMyName()
// I want to pass in everything that is declared in name1 to sayMyName() implicitly.
};
var name2 = function() {
var myName = 'White';
sayMyName();
}
name1(); // should give me 'Walter'
name2(); // should give me 'White'

I'm not sure why you specifically want a closure, but by looking at your example it seems that a bind would be more appropriate than a closure.
var sayMyName = function(myName) {
console.log(myName)
};
var name1 = sayMyName.bind(undefined, 'Walter');
var name2 = sayMyName.bind(undefined, 'White');
name1(); // log 'Walter'
name2(); // log 'White'

Move your variable myName to the outermost scope:
var myName;
var sayMyName = function() {
console.log(myName)
};
var name1 = function() {
myName = 'Walter';
sayMyName();
};
var name2 = function() {
myName = 'White';
sayMyName();
}
name1(); // should give me 'Walter'
name2(); // should give me 'White'
Update: Thinking about it, if you're willing to use the non-standard, Error.stack attribute, are willing to use named functions, and are willing to use a naming convention, you could hackishly achieve your goal:
function sayMyName() {
try {
throw new Error();
}
catch (e) {
if (e.stack) { // non-standard attribute
var reNames = /^\s*at myNameIs([A-Z][^(\s]*)\s*\(/mg;
reNames.lastIndex = 0;
var buffer = [];
for (var match = reNames.exec(e.stack); null !== match; match = reNames.exec(e.stack)) {
buffer.push(match[1]);
}
console.log(buffer.join(" "));
}
}
}
function myNameIsWalter() {
sayMyName();
}
function myNameIsWhite() {
myNameIsWalter();
};
myNameIsWalter(); // "Walter"
myNameIsWhite(); // "Walter White"
... and if you're willing to use eval (bad !!!), then you could do fancier things like the following:
var sayMyName = function () {
try {
throw new Error();
}
catch (e) {
if (e.stack) { // non-standard attribute
var reNames = /^\s*at ([_a-zA-Z][_a-zA-Z0-9]+(\.[_a-zA-Z][_a-zA-Z0-9]+)*)/mg;
reNames.lastIndex = 0;
var reMyName = /\bmyName\s*=\s*(?:"([^"]*)"|'([^']*)')/g;
var identifier, definition, match, myName, buffer = [];
while (null !== (match = reNames.exec(e.stack))) {
try {
identifier = match[1];
if ("sayMyName" !== identifier) {
definition = eval(match[1] + '.toString()');
if (/\bsayMyName\(\)/.test(definition)) {
reMyName.lastIndex = 0;
buffer.length = 0;
while (null !== (myName = reMyName.exec(definition))) {
buffer.push(myName[1]);
}
console.log(buffer.join(" "));
}
}
}
catch (_) {
// continue
}
}
}
}
};
function name1() {
var myName = "Walter";
sayMyName();
}
function name2() {
var myName;
myName = "Walter";
myName = "White";
sayMyName();
}
name1(); // "Walter"
name2(); // "Walter White"
You could even use the non-standard, Function.caller attribute, which is probably the cleanest approach (if it works in your browser -- it's non-standard for a reason):
function sayMyName() {
var reMyName = /\bmyName\s*=\s*(?:"([^"]*)"|'([^']*)')/g;
var definition, buffer = [];
for (var caller = sayMyName.caller; caller; caller = caller.caller) {
definition = caller.toString();
if (/\bsayMyName\(\)/.test(definition)) {
reMyName.lastIndex = 0;
buffer.length = 0;
while (null !== (myName = reMyName.exec(definition))) {
buffer.push(myName[1]);
}
console.log(buffer.join(" "));
}
}
};
function name1() {
var myName = "Walter";
sayMyName();
}
function name2() {
var myName;
myName = "Walter";
myName = "White";
sayMyName();
}
name1(); // "Walter"
name2(); // "Walter White"
This is arguably no less code than just passing a parameter, though.

If you want closure then this is example.
function sayMyName(myName){
return function(){
console.log(myName); //myName is available from parent scope
return myName;
}
}
var name1 = sayMyName('Walter');
var name2 = sayMyName('White');
//no console output by now
name1(); //Walter
name2(); //White
//myName is not available in global scope
console.log(myName); //undefined

Related

javascript: 'this' object not accessible?

I'm using an example from here.
function Restaurant() {
this.mongoose = 'beans';
this.freedom = {bear: 'love', a: 12};
var myPrivateVar;
// Only visible inside Restaurant()
var private_stuff = function() {
myPrivateVar = "I can set this here!";
this.mongoose = 12;
this.freedom.a = 14; // <= 'a' undefined 2nd time
}
// use_restroom is visible to all
this.use_restroom = function() {
private_stuff();
}
// buy_food is visible to all
this.buy_food = function() {
private_stuff();
}
private_stuff.call(this);
}
var bobbys = new Restaurant();
bobbys.buy_food() // <= fails
I set this.freedom.a to 14 in private_stuff() and then I call bobbys.buy_food().
When that function is called, this.freedom apparently is undefined, so I can't set a.
Does anybody know why it fails on freedom and not on mongoose?
I appreciate comments, but if someone posts an 'Answer', then I can close this as solved, and give you the credit.
If you're interested in using this pattern correctly, its whole point is to avoid this (let alone .call(this)) altogether. Your "private" methods and properties are just variables in a closure, and public methods/props are attached to a local object, which is either a closed this or simply a literal:
function Restaurant() {
var self = this; // or {}
self.publicProp = '';
var privateProp = '';
var privateFunc = function() {
privateProp = 'hello';
self.publicProp = 'world';
}
self.publicFunc = function() {
privateFunc();
return privateProp;
}
// return self; // if used a literal above
}
var bobbys = new Restaurant();
console.log(bobbys.publicFunc())
console.log(bobbys.publicProp)
Now it should work :)
just use call in your buy food method.
function Restaurant() {
this.mongoose = 'beans';
this.freedom = {bear: 'love', a: 12};
var myPrivateVar;
// Only visible inside Restaurant()
var private_stuff = function() {
myPrivateVar = "I can set this here!";
this.mongoose = 12;
this.freedom.bear = 14; // <= 'a' undefined 2nd time
}
// use_restroom is visible to all
this.use_restroom = function() {
private_stuff();
}
// buy_food is visible to all
this.buy_food = function(...args) {
private_stuff.call(this, ...args);
}
private_stuff.call(this);
}
var bobbys = new Restaurant();
bobbys.buy_food()
function Restaurant() {
var ths = this;
this.mongoose = 'beans';
this.freedom = {bear: 'love', a: 12};
var myPrivateVar;
// Only visible inside Restaurant()
var private_stuff = function() {
myPrivateVar = "I can set this here!";
this.mongoose = 12;
ths.freedom.a = 14; // <= 'a' undefined 2nd time
}
// use_restroom is visible to all
this.use_restroom = function() {
private_stuff();
}
// buy_food is visible to all
this.buy_food = function() {
private_stuff();
}
private_stuff.call(this);
}
var bobbys = new Restaurant();
bobbys.buy_food()
Try this

javascript - private/public members/functions

I am testing what happens when I declare variables/methods with var, this, and global, and am wondering what is the best approach. I have the following code:
myApp.ConfirmationWindow = function (temptype) {
var _type = temptype;
this.type = temptype;
type2 = temptype;
this.getType = function () {
return _type;
}
this.showConfirmationWindow = function (message) {
var a = _type; //valid
var b = this.type; //valid
var c = type2; // valid
var d = this.getType(); // valid
this.showWindow(message);
showWindow2(message);
showWindow3(message);
}
this.showWindow = function (message) {
var a = _type; //valid
var b = this.type; //valid
var c = type2; // valid
var d = this.getType(); // valid
}
showWindow2 = function (message) {
var a = _type; //valid
var b = this.type; //invalid
var c = type2; // valid
var d = this.getType(); // invalid
}
var showWindow3 = function (message) {
var a = _type; //valid
var b = this.type; //invalid
var c = type2; // valid
var d = this.getType(); // invalid
}
};
Usage:
myApp.ConfirmationWindow1 = new myApp.ConfirmationWindow(1);
myApp.ConfirmationWindow1.showConfirmationWindow('Are you sure?');
The goal is to have the type variable and the showWindow function private. As you can see from my example, there are a lot of ways to achieve this. What is the recommended way?
I would suggest to use the module reveal pattern, where you keep the private variable in a closure. Here below a generic example. You can read more about the revealing pattern here:
let myVar = true;
let module = (function() {
// these are private variables (in a closure)
let _privateVariable = 'private',
_privateFunction = function() {
alert(_privateVariable);
};
let _publicVariable = 'public',
_publicFunctionGet = function() {
alert(_publicVariable);
},
_publicFunctionSet = function(value) {
_publicVariable = value;
};
// provide public functions to set the private variables
return {
publicFunctionSet: _publicFunctionSet,
publicFunctionGet: _publicFunctionGet
};
})();
module.publicFunctionSet('new public');
module.publicFunctionGet();
alert(myVar); // available to other part of your code
You can hide your private code using the var pattern in your example. To expose your private variables you use your instance functions. If you make them global or members of the function then they are public.
myApp.ConfirmationWindow = function (temptype) {
var _type = temptype;
this.getType = function () {
return _type;
}
var showWindow = function (message) {
var d = _type
}
this.showConfirmationWindow = function (message) {
showWindow(message);
}
};

How to implement inheritance in Screeps objects?

I've been toying around with Screeps for a while now and last night I decided to work out some of my behaviors into a class hierarchy by deriving two classes, Miner and Transporter from a Creep main class. However, whenever I do
console.log(_.functions(minerInstance));
I get the exact same function list as when I do
console.log(_.functions(transporterInstance));
Could someone tell me if I'm doing something wrong OR if I'm actually running into a limitation of the environment my code runs in?
This is my code:
////////////////////////////
// Creep.js
var Creep = function(creep, room) {
this.creep = creep;
this.room = room;
this.name = creep.name;
this.id = creep.id;
};
module.exports = Creep;
Creep.prototype = {
tick: function() {
console.log("Base class implementation of tick(), should never happen.");
},
getRole: function() {
return this.creep.memory.role;
}
};
////////////////////////////
// Miner.js
var Creep = require("Creep");
var Miner = function(creep, room) {
this.base = Creep;
this.base(creep, room);
//Creep.call(this, creep, room);
};
module.exports = Miner;
Miner.prototype = Creep.prototype;
Miner.prototype.tick = function() {
var creep = this.creep;
if (creep.memory.activity === undefined || creep.memory.activity === "") {
var target = creep.pos.findNearest(Game.SOURCES_ACTIVE);
this.mine(creep, target);
}
var act = creep.memory.activity;
if (act == "mine") {
var target = this.getTarget(creep);
if (target !== undefined) {
if (creep.energy < creep.energyCapacity) {
creep.moveTo(target);
creep.harvest(target);
} else {
console.log("Write dump to truck code");
/*var trucks = find.transporterInRange(creep, 1);
if (trucks.length) {
creep.moveTo(trucks[0]);
var amount = trucks[0].energyCapacity - trucks[0].energy;
creep.transferEnergy(trucks[0], amount);
}*/
}
}
}
};
Miner.prototype.mine = function(creep, target) {
creep.memory.target = target.id;
creep.memory.activity = "mine";
};
Miner.prototype.getTarget = function(creep) {
return Game.getObjectById(creep.memory.target);
};
////////////////////////////
// Transporter.js
var Creep = require("Creep");
var Transporter = function(creep, room) {
Creep.call(this, creep, room);
};
module.exports = Transporter;
Transporter.prototype = Creep.prototype;
Transporter.prototype.tick = function() {
var creep = this.creep;
if (creep.energy < creep.energyCapacity) {
var miner = this.room.findByRole(creep, "miner");
console.log(miner);
if (miner !== null) {
//console.log(miner[0].name);
//creep.moveTo(miner);
} else
console.log("no miners found");
} else {
console.log("moving to drop");
//var drop = find.nearestEnergyDropOff(creep);
//creep.moveTo(drop);
//creep.transferEnergy(drop);
}
};
With this line...
Miner.prototype = Creep.prototype;
... you tell JS that both prototypes are actually the same object. Hence any update for Miner.prototype will affect Creep.prototype too.
One possible approach is using Object.create when establishing the link between prototypes. Here goes a simplified example:
function Foo(a) {
this.a = a;
}
Foo.prototype.tick = function() { console.log('Foo ticks'); };
Foo.prototype.tock = function() { console.log('Foo tocks'); };
function Bar(a, b) {
this.base = Foo;
this.base(a);
this.b = b;
}
Bar.prototype = Object.create(Foo.prototype);
// as you inherit all the properties, you'll have to reassign a constructor
Bar.prototype.constructor = Bar;
Bar.prototype.tick = function() { console.log('Bar ticks'); };
var f = new Foo(1);
f.tick(); // Foo ticks
f.tock(); // Foo tocks
console.log(f); // Foo { a=1, ... }
var b = new Bar(1, 2);
b.tick(); // Bar ticks
b.tock(); // Foo tocks
console.log(b); // Bar { a=1, b=2, ... }

Javascript class extension

CONTEXT
I have one Base class called Entity and User and Group are both derived from this object; If I instantiate a user with the ID of 12 for example, the next time I try to do that it returns the same object. I store these in a prototype items variable. To keep these item variables separate I have to declare the User And Group functions separately although they contain the same code.
CODE
Application.prototype.Entity = function() {
};
Application.prototype.Entity.prototype.print = function() {
var container = $("<div class='user-tag'></div>");
container.append("<a class='friend_list ellipsis_overflow' style='background-image:url(\"" + this.entity.pic.icon + "\");'"
+ "href ='user?id=" + this.entity.id + "'>" + this.entity.name + "</a>");
return container;
};
//HOW TO GET RID OF THIS "REPETITION"
Application.prototype.User = function(entity) {
this.entity = entity;
this.entity.pic = this.entity.pic || Application.prototype.default.pic;
if (this.items[this.entity.id]) {
return this.items[this.entity.id];
} else {
this.items[this.entity.id] = this;
}
};
Application.prototype.Group = function(entity) {
this.entity = entity;
this.entity.pic = this.entity.pic || Application.prototype.default.pic;
if (this.items[this.entity.id]) {
return this.items[this.entity.id];
} else {
this.items[this.entity.id] = this;
}
};
// END REPEAT
Application.prototype.Group.prototype = new Application.prototype.Entity();
Application.prototype.User.prototype = new Application.prototype.Entity();
//Application.prototype.User.prototype.constructor = Application.prototype.Entity;
//Application.prototype.Group.prototype.constructor = Application.prototype.Entity; - these don't seem to work
//THESE items VARIABLES HAVE TO REMAIN SEPARATE
Application.prototype.Group.prototype.items = {};
Application.prototype.User.prototype.items = {};
QUESTION
I specifically would like to rid my code of the repetition mentioned above, but if you see any other unnecessary code, please comment. Thanks!
Something like this?
function userAndGroupConstructor(entity) {
this.entity = entity;
this.entity.pic = this.entity.pic || Application.prototype.default.pic;
if (this.items[this.entity.id]) {
return this.items[this.entity.id];
} else {
this.items[this.entity.id] = this;
}
}
Application.prototype.User = function() {
return userAndGroupConstructor.apply(this, arguments)
}
Application.prototype.Group = function() {
return userAndGroupConstructor.apply(this, arguments)
}
You get distinct constructors with distinct prototypes, but avoid duplication.
You can do this:
Application.prototype.Group = Application.prototype.User;
Since Application.prototype.User contains the function reference, you can just assign it to Application.prototype.Group.

Javascript Object-Oriented-Programming

I found a Module pattern in JS:
<script>
var MODULENAME = (function(my, $) {
my.publicVar = "5";
my.publicFn = function() {};
return my;
}(MODULENAME || {}, jQuery));
</script>
However I cannot perform instantiation. Does the module pattern allow for that?
Instantiantion means basically that you'll run a function using new.
So maybe you're looking for this?
var Some = function (param) {
var somePrivateVar = 'private';
this.somePublicVar = 'public';
this.method = function () {
return param;
};
};
var some = new Some('abla');
console.log(some.method());
// some.somePrivateVar === undefined
// some.somePublicVar === 'public'
In your case MODULENAME is an object (object, not a function) with publicVar and publicFn. It's not meant to be instantiated the same way you wouldn't call new jQuery().
Your module object can contain anything. Perhaps you're looking for including a constructor in it:
var MODULENAME = (function(my, $) {
var privateVar = 10;
my.SomeConstructor = function() {
this.publicVar = 5;
}
my.SomeConstructor.prototype.someMethod = function() {};
my.SomeConstructor.prototype.getPrivate = function() { return 10; };
return my;
}(MODULENAME || {}, jQuery));
var instance = new MODULENAME.SomeConstructor();
instance.publicVar; // 5
instance.privateVar; // undefined
instance.getPrivate(); // 10
You can do this also with prototype Inheritance :
var MyClass = function(name)
{
//sharing name within the whole class
this.name = name;
}
MyClass.prototype.getName = function(){
return this.name;//now name is visible to getName method too
}
MyClass.StaticMethod = function()
{
console.log("Im Static");
// and since is not in prototype chain, this.name is not visible
}
var myclass = new MyClass("Carlos");
console.log(myclass.getName())//print "Carlos"
MyClass.StaticMethod()// print "Im Static"
myclass.StaticMethod() // error
Se all this article

Categories