I need to do a bit of quick testing with my code (getting the value of some variables inside a function), and I want to globalise them, so I can access them through the console.
I know this method:
function foo() {
var foo = 'foo';
window.foo = foo; // Make foo global
}
But what if I had something like this:
function foo() {
var foo1 = 'foo';
var foo2 = 'foo';
var foo3 = 'foo';
var foo4 = 'foo';
var foo5 = 'foo';
var foo6 = 'foo';
var foo7 = 'foo';
var foo8 = 'foo';
}
What would be a quicker way to globalise all those variables, without going window.foo1 = foo1, window.foo2 = foo2, etc.?
I don't wish this to be a code golf question, just a normal programming question.
I don't think there's a way to do this. See this:
Access all local variables
Have you tried simply debugging in the console? With Chrome, you can set a breakpoint and then inspect all values. Check out this tutorial:
https://developers.google.com/chrome-developer-tools/docs/scripts-breakpoints
Why not a single globals object instead of a bunch of variables?
function foo() {
window.globals = {
foo1 = 'foo',
foo2 = 'foo',
foo3 = 'foo',
foo4 = 'foo',
foo5 = 'foo',
foo6 = 'foo',
foo7 = 'foo',
foo8 = 'foo'
};
}
If they're all simply named like that, you can take advantage of a little known trick, variables are actually dictionaries:
function foo() {
var foo1 = 'foo';
var foo2 = 'foo';
var foo3 = 'foo';
var foo4 = 'foo';
var foo5 = 'foo';
var foo6 = 'foo';
var foo7 = 'foo';
var foo8 = 'foo';
for (var i = 1; i <= 8; i++) {
window["foo" + i] = eval("foo" + i);
}
}
document.write("Running foo...<br/>");
foo();
document.write("Printing foo...<br/>");
for (var i = 1; i <= 8; i++) {
document.write(window["foo" + i]);
}
document.write("<br/>Just one: " + foo3);// Normal variable notation
Related
In php we can do something like this:
$foo = 1;
$bar = 2;
$fn = function() use ($foo, $bar) {
return $foo;
};
$foo = 3;
echo $fn(); // gives 1
How to do it in javascript?
I try it like this, but failed:
var foo = 1;
var bar = 2;
var fn = function() { return foo; }.bind(foo,bar);
foo = 3;
console.log(fn()); // gives 3, instead of 1
bind is a method to explicitly define the this value and the values passed to the initial arguments of the function.
The arguments that can be passed to a function are defined when the function is created.
var fn = function(foo) { console.log(foo) }
JavaScript doesn't have any features to modify what arguments a function accepts after it has been created.
The scope of a function is also defined when it is created and can't be changed later. If you don't shadow foo with an argument name, then it will read foo from the scope it is defined in.
var foo = 1;
var fn = function(foo) { return foo; }.bind({}, foo);
foo = 3;
console.log(fn());
or through context
var foo = 1;
var fn = function() { return this.foo; }.bind({foo});
foo = 3;
console.log(fn());
So I was thinking if a literal object can inherit properties and methods from a class. Here is the code
var Foo = function(val1, val2) {
this.prop1 = val1;
this.prop2 = val2;
}
var bar = {
//how to inherit properties from Foo class; also add new property
prop3: 'val3'
};
You could achieve this by creating an instance of Foo and then adding properties to that instance like so:
var Foo = function(val1, val2) {
this.prop1 = val1;
this.prop2 = val2;
}
var x = new Foo('valOfProp1', 'valOfProp2');
x.prop3 = 'valOfAddedProp';
Theres no inheritance in your code. Inheritance would look like this:
var Foo = function(val1, val2) {}
Foo.prototype={
prop1:val1,
prop2:val2
};
var bar = {
//how to inherit properties from Foo class; also add new property
prop3: val3
};
And now you could do:
Object.setPrototypeOf(bar, /*to*/ Foo.prototype);
or creating another object:
var instance=new Foo();
Object.assign(instance,bar);
You may do as follows;
var Foo = function(val1, val2) {
this.prop1 = val1;
this.prop2 = val2;
};
Foo.prototype.getProp = function(p){
return this[p]; // NOT!! this.p
};
var bar = {
//how to inherit properties from Foo class; also add new property
prop3: "val3"
};
Object.setPrototypeOf(bar,Foo.prototype);
console.log(bar.getProp("prop1"));
console.log(bar.getProp("prop2"));
console.log(bar.getProp("prop3"));
I come across singleton pattern, it's quite tricky to understand how to implement it, and I know some people would suggest to avoid it most of the time, so below is specific singleton variation that I find it easy to understand, but somehow I feel that this is not the best implementation of this pattern, can you guys suggest better form of this pattern.
var Foo = (function () {
var instance;
var _priVar = 2;
var log = function() {
console.log("Hello");
};
function Singleton(x, y) {
if (instance) {
return instance;
}
this.name = x;
this.age = y + _priVar;
this.log = log;
instance = this;
}
Singleton.getInstance = function () {
return instance || new Singleton();
}
return Singleton;
}());
and my goal is that when we do following
var a = new Foo("Bob", 24);
var b = new Foo();
var c = Foo();
var d = Foo.getInstance();
we will still get
a == b // true
a == c // true
a == d // true
a.name // 'Bob'
b.age // 26
c.log // 'Hello'
d.name // 'Bob'
The simplest singleton, also known as module pattern, consists of an object literal:
var foo = (function () {
var x = "Bob",
y = 24,
_priVar = 2;
function log() {
console.log("Hello");
}
return {
name: x,
age: y + _priVar,
log: log
};
}());
If you want to introduce lazy initialisation, you can use an extra getInstance function like in your implementation:
var getFoo = (function () {
var instance = null;
return function getFooInstance() {
if (instance) return instance;
var x = "Bob",
y = 24,
_priVar = 2;
function log() {
console.log("Hello");
}
return instance = {
name: x,
age: y + _priVar,
log: log
};
};
}());
A singleton should never use a constructor like in your code, that's just unnecessary. If you feel a need to pass arguments for initialisation, don't make it a singleton.
var foo = {};
foo.c = foo = {};
console.log(foo.c);
why the result is undefined?
i thought it is supposed to be '[object Object]'
Strange things are happening here in the assignments:
foo.c = (foo = {})
The reference to foo.c is resolved first and points to the old foo object, before the inner expression is evaluated where foo is re-assigned with the {} emtpy object literal. So your code is equivalent to
var foo1 = {};
var foo2 = {};
foo1.c = foo2;
console.log(foo2.c) // obviously undefined now
You can also try
var foo = {}, old = foo;
foo.c = foo = {};
console.log(old, foo, old.c===foo); // {c:{}}, {}, true
JavaScript engine splits such assignment:
a = b = c = 1;
As follow:
a = 1;
b = 1;
c = 1;
And not as:
c = 1;
b = c;
a = b;
There is a slightly but important difference – mostly, it involves getters, please check Multiple variable assignments in one row for further details – and that's mostly why your code doesn't behave like expected, because the initial expectations are based on false assumptions.
Is it possible?
I'm trying to do the following thing:
var foo = 'foo';
var bar = 'bar';
var x;
var y;
var array1 = [x, [foo, y]];
var array2 = [x, [foo, bar], [foo, y]];
console.log(array1[0]); //undefined
console.log(array1[1][1]); //undefined
console.log(array2[0]); //undefined
console.log(array2[2][1]); //undefined
array1[0] = 'working';
array2[0] = 'working';
y = 'hello';
console.log(array1[0]); //working
console.log(array1[1][1]); //undefined
console.log(array2[0]); //working
console.log(array2[2][1]); //undefined
Although it's obvious to define value when you know where the binding value exist ,x in this case, it's hard to bind a value to values with unknown location, y in this case.
Any thoughts? Thanks.
It sounds like what you want is some kind of wrapper:
var x = {};
var y = {};
var array = [x, [foo, y]];
console.log(array[0].value); // undefined
console.log(array[1][1].value); // undefined
x.value = "hello";
y.value = "goodbye";
console.log(array[0].value); // hello
console.log(array[1][1].value); // goodbye