This question already has answers here:
Accessing variables trapped by closure
(8 answers)
Closed 8 years ago.
I'm trying to reference the method UTCDate() from another JS file that loads after this file bootstrap-datepicker.js.
Is there a way for me to access this method.
I tried using just UTCDate() I even tried window.UTCDate().
Here is the original file bootstrap-datepicker.js and they seem to be calling it directly inside the datePicker itself.
(function($, undefined){
var $window = $(window);
function UTCDate(){
return new Date(Date.UTC.apply(Date, arguments));
}
function UTCToday(){
var today = new Date();
return UTCDate(today.getFullYear(), today.getMonth(), today.getDate());
}
function alias(method){
return function(){
return this[method].apply(this, arguments);
};
}
var DateArray = (function(){
var extras = {
get: function(i){
return this.slice(i)[0];
},
contains: function(d){
// Array.indexOf is not cross-browser;
// $.inArray doesn't work with Dates
var val = d && d.valueOf();
for (var i=0, l=this.length; i < l; i++)
if (this[i].valueOf() === val)
return i;
return -1;
},
remove: function(i){
this.splice(i,1);
},
replace: function(new_array){
if (!new_array)
return;
if (!$.isArray(new_array))
new_array = [new_array];
this.clear();
this.push.apply(this, new_array);
},
clear: function(){
this.length = 0;
},
copy: function(){
var a = new DateArray();
a.replace(this);
return a;
}
};
return function(){
var a = [];
a.push.apply(a, arguments);
$.extend(a, extras);
return a;
};
})();
That is how closures work: They close over variables.
function UTCDate(){
return new Date(Date.UTC.apply(Date, arguments));
}
is private to your IIFE.
You should better switch to The Revealing Module Pattern:
var myDateApp=function(){
...
function UTCDate(){
return new Date(Date.UTC.apply(Date, arguments));
}
...
return {
...
UTCDate:UTCDate,
...
};
}();
Then you could easily access the function UTCDate via myDateApp.UTCDate().
Or switch later on to AMD.
You can't without modifying the code to export that method outside the anonymous closure.
Related
I'm troubleshooting some 3rd party code on a client's website. The client was having issues with the code not working. I found that the issue was related to bound JS functions. Arguments that were passed to the bound function were undefined. I couldn't figure out why. Everything seems fine. However, I then found that the client has overridden the Bind function. Here is what they have:
Function.prototype.bind = function(scope) {
var _function = this;
return function() {
return _function.apply(scope, arguments);
};
};
So if I create a function
var sumFunction = function(a, b){
console.log("a: " + a);
console.log("b: " + b);
return a + b;
}
Then bind that function:
var boundFunction = sumFunction.bind(null, 10);
When I call that bound function I get the following:
console.log(boundFunction(20));
a: 20
b: undefined
NaN
I found a similar SO question that was using the same bind function. javascript custom scope binding function
It appears that it used to work? The SO question I linked seemed to work back in 2013, but now it doesn't form me.
Is this just outdated? JavaScript isn't my main strength, but my client will want to know why their function is causing the problem.
I found the overridden bind function to be odd. Especially the line return _function.apply(scope, arguments); It seems like passing the entire arguments object is incorrect. Shouldn't it only send the arguments in array position 1 and higher? I tried changing that to this to test:
Function.prototype.bind = function(scope) {
var _function = this;
var newArgs = Array.prototype.slice.call(arguments, 1)
return function() {
return _function.apply(scope, newArgs );
};
};
But now I just get the following:
console.log(boundFunction(20));
a: 10
b: undefined
NaN
When the function is bounded, there might be an array of arguments after the 1st, so use slice(1) to get them. When the function is called, get the all the arguments, and concat both args arrays.
Concat both arrays of arguments:
Function.prototype.bind = function(scope) {
var _function = this;
var args1 = Array.prototype.slice.call(arguments, 1);
return function() {
var args2 = Array.prototype.slice.call(arguments, 0);
return _function.apply(scope, args1.concat(args2));
};
};
var sumFunction = function(a, b){
console.log("a: " + a);
console.log("b: " + b);
return a + b;
}
var boundFunction = sumFunction.bind(null, 10);
console.log(boundFunction(20));
However, calling slice on arguments, might cause the V8 engine to skip optimisation on the function. A better way would be to just iterate the arguments manually, and add them to a single array:
Function.prototype.bind = function(scope) {
var args = [];
var _function = this;
for(var i = 1; i < arguments.length; i++) { args.push(arguments[i]); }
return function() {
var newArgs = args.slice(0);
for(var i = 0; i < arguments.length; i++) { newArgs.push(arguments[i]); }
return _function.apply(scope, newArgs);
};
};
var sumFunction = function(a, b){
console.log("a: " + a);
console.log("b: " + b);
return a + b;
}
var boundFunction = sumFunction.bind(null, 10);
console.log(boundFunction(20));
I am trying to simulate a simple Holder "class" in JavaScript with a "private" property that holds something and "public" getter and setter "methods" to access the value.
The approach exhibited by HolderA below is mentioned e.g. here. The other approach I more or less arrived at by mutation but I guess it must be recognizable as an idiom as well. I like it because it contains no this or prototype stuff and seems very elementary and functional. Is there a difference between the two?
The test code (I run it under nodejs) seems to suggest that the two approaches are identical except that in the first case the objects I get have typeof object whereas in the second function.
var test = function(o) {
var initialValueCorrect = (!(typeof o.getX()==='undefined'))&&(o.getX()===0);
var VALUE_TO_SET = 10;
o.setX(VALUE_TO_SET);
var getSetWorks = o.getX()===VALUE_TO_SET;
var xIsPrivate = (typeof o.x === 'undefined');
var xHasCorrectValue;
if (!xIsPrivate)
xHasCorrectValue = o.x === VALUE_TO_SET;
return {initialValueCorrect: initialValueCorrect,
getSetWorks : getSetWorks,
xIsPrivate: xIsPrivate,
xHasCorrectValue: xHasCorrectValue};
};
var HolderA = (function() {
function foo(x) {
this.getX = function() {
return x;
};
this.setX = function(_x) {
x = _x;
};
};
return foo;
})();
var createHolderB = (function() {
var x;
function foo(_x) {
x = _x;
return foo;
}
foo.getX = function() {
return x;
};
foo.setX = function(_x) {
x = _x;
};
return foo;
})();
var objects = [{object: new HolderA(0), name: "approach with constructor-invocation and 'this'"},
{object: createHolderB(0), name: "approach with normal function invocation and closed variable"}];
for (var i = 0; i<objects.length ; i++) {
var testResult = test(objects[i].object);
console.log('['+objects[i].name+']: the object is a: '+(typeof objects[i].object)
+'\n\n\t\t\t'+JSON.stringify(testResult)+'\n\n\n\n\n');
}
update
As Bergi has pointed out function createHolderB in my code above is plain wrong and only creates a singleton object. So, is not really a "constructor" function. To that end I've now created createHolderC which can be used to really create multiple objects with a hidden private property like this:
var objectC1 = createHolderC()(0);
Now, is there any material difference between HolderA and the createHolderC function or is the difference purely stylistic?
var createHolderC = function () {
return (function() {
var x;
function foo(_x) {
x = _x;
return foo;
};
foo.getX = function() {
return x;
};
foo.setX = function(_x) {
x = _x;
};
return foo;
})();
};
createHolderB does not create new holders like HolderA does. It's essentially a singleton pattern. You might also want to call it a module. Notice that createHolderB() === createHolderB.
createHolderC is still different from HolderA in that it returns function objects, not instances. You may see the differences better when you strip out the unnecessary IEFEs:
function HolderA(x) {
this.getX = function() {
return x;
};
this.setX = function(_x) {
x = _x;
};
// implicit `return this;` when called via `new`
}
function createHolderC() {
var x;
function foo(_x) {
x = _x;
return foo;
};
foo.getX = function() {
return x;
};
foo.setX = function(_x) {
x = _x;
};
return foo;
}
A typical factory would rather look like this:
function createHolderD(x) {
var foo = {};
foo.getX = function() {
return x;
};
foo.setX = function(_x) {
x = _x;
};
return foo;
}
(or even with return {getX: …, setX: …};), the only difference to HolderA is the prototypical inheritance then.
Basically both exhibits the private access behavior to the x variable. But the difference between those two are
Constructor function
var HolderA = (function() {
function foo(x) {
this.getX = function() {
return x;
};
this.setX = function(_x) {
x = _x;
};
};
return foo;
})();
This is a self executing function, where it returns Constructor foo.
That is the reason you are using new while creating this type of holder {object: new HolderA(0)
A function
var createHolderB = (function() {
var x;
function foo(_x) {
x = _x;
return foo;
}
foo.getX = function() {
return x;
};
foo.setX = function(_x) {
x = _x;
};
return foo;
})();
Even this is also a self executing function, but while execution it creates x variable and returns function foo, and foo access x by closure.
You are creating this type of holder just by normal function call object: createHolderB(0).
Both cases are really bad in practice.
If you're making closures (anonymous functions) that hold your "private variable" scope, it means you're creating those functions for every instance of the class. That costs memory and performance. I used to create classes like this, but then once I was making large number of instances and found out that it hits performance hard.
Just as in Python, make private variables private by some convention, like underscore in _name. Then you can break it for debug reasons (because variables in closure scope are not accessible).
This is how I would do it:
function MyClass(arg) {
this._privateVar = arg;
}
MyClass.prototype.getPrivateVar = function() {
return this._privateVar;
}
You can also make getters and setters:
Object.defineProperty(MyClass.prototype, "privateVar", {
get: function() {
return this._privateVar;
}
}
But don't try to push javascript into things it's not designed to, or you'll pay with performance, code readability and debugging complexity. Applies to other languages too.
var object = {}; //lots of stuff in here
var func = object.dosome;
object.dosome = function(a,b) {
func(a,b);
//someth else here i need to add
}
This works but ugly.
So is there a way to supplement object.dosome method, without creating a new variable containing it's function?
Some sort of parent.dosome?
maybe create a class Object and define in its protoype the dosome() method.
var Object = new function() {}; //lots of stuff in here
Object.prototype.dosome = function(a,b) {
func(a,b);
}
//and then
var myObject = new Object();
I think you should read a little about JS OOP. ES6 adds some nice syntactic sugar that can help you achieve what you want in fewer lines of code. Read more here.
However, if you don't want to have problems with the prototype chains, here's a simpler way of achieving what you want:
function chain (baseFunc, func) {
return function () {
var args = [].slice.call(arguments, 0);
args.unshift(baseFunc);
return func.apply(this, args);
};
}
Usage:
var obj = {
doSome: function (a, b) { return a + b; }
};
obj.doSome(4, 5); // 9
obj.doSome = chain(obj.doSome, function (baseFunc, a, b) {
var result = baseFunc(a, b);
return result + 10;
});
obj.doSome(4, 5); // 19
You can go one step further and get rid of the assignment:
function extend (instance, method, func) {
instance[method] = chain(instance[method], func);
}
extend(obj, "doSome", function (baseFunc, a, b) {
var result = baseFunc(a, b);
return result + 2;
});
obj.doSome(4, 5); // 21
I have some Javascript code spread over multiples files, yet I want to facilitate minification with an IFFE. Some methods must remain public.
Wikipedia suggests the implementation of accessors:
var counter = (function(){
var i = 0;
return {
get: function(){
return i;
},
set: function( val ){
i = val;
},
increment: function() {
return ++i;
}
};
}());
Unfortunately, declaring these from return is not easy when such functions are declared in multiple files.
Is the following a proper solution? If not, what is?
var counter = (function(){
var i = 0;
// Import js file 1...
this.get = function(){ return i; };
// Import js file 2...
this.set = function( val ){ i = val; };
// Import js file 3...
this.increment = function() { return ++i; };
return this;
}());
P.S.: I want to be able to perform the following calls:
counter.get();
counter.set(33);
counter.increment();
It seems like the pattern that you are interested in is something like this:
//file 1
var xy = (function (that) {
that.prop1 = 1;
return that;
}(xy || {}));
//file2
var xy = (function (that) {
that.prop2 = 2;
return that;
}(xy || {}));
This will result in a single global object xy that has two properties:
xy = {
prop1: 1,
prop2: 2
};
I have an object which has several properties that are set when the object is created.
This object recently changed to object literal notation, but I've hit a bit of a problem that searching on the net doesn't reveal.
Simply stated I need to do this:
Star = function(_id, _x, _y, _n, _o, _im, _c, _b, _links) {
var self = {
id: _id,
// other properties
links: [],
for (var i=0,j=0;i<8;i++) { //<- doesn't like this line
var k = parseInt(_links[i]);
if (k > 0) {
this.links[j++] = k;
}
},
// other methods
};
return self;
};
How do I initialise a property in the constructor in object literal notation?
You can create the array on the fly using an anonymous function:
Star = function(_id, _x, _y, _n, _o, _im, _c, _b, _links) {
var self = {
id: _id,
// other properties
links: (function() {
var a = [];
for (var i=0;i<8;i++) {
var k = parseInt(_links[i]);
if (k > 0) {
a.push(k);
}
}
return a;
})(),
// other methods
};
return self;
};
You can do it after the literal is defined:
Star = function(_id, _x, _y, _n, _o, _im, _c, _b, _links) {
var self = {
id: _id,
// other properties
links: [],
// other methods
};
for (var i=0,j=0;i<8;i++) {
var k = parseInt(_links[i]);
if (k > 0) {
self.links[j++] = k;
}
}
return self;
};
For this specific example, you could use an anonymous function, like this:
Star = function(_id, _x, _y, _n, _o, _im, _c, _b, _links) {
var self = {
id: _id,
// other properties
links: (function(){
var links = [];
for (var i=0;i<8;i++) {
var k = parseInt(_links[i]);
if (k > 0) {
links.push(k);
}
}
return links;
})(),
// other methods
};
return self;
};
You can't. Object notation doesn't allow this. However, you can add the properties AFTER initializing your object.
By the way, self is a defined object already, which is an alias for the window object. While you ARE defining a temporary object named self [and thus, you aren't getting rid of window.self] this isn't something you shold be doing. Act as if self was a keyword and your current usage of it is illegal.