var t = 0;
function addDiv()
{
var div = document.createElement("div");
t++;
div.setAttribute("id", "box" + t);
document.body.appendChild(div);
AddStyle();
}
var h = 0;
var p = 1;
function doMove()
{
var okj = document.getElementById("box" + p);
if (p <= t) {
p++;
}
var g = setInterval(function () {
var go = parseInt(okj.style.left, 0) + 1 + "px";
okj.style.left = go;
}, 1000 / 60);
}
My question is that after the p increments that is p++ will my var p = 1 be incremented everytime I call doMove? Please help me regarding this matter.
By definition global variables have global scope, so you can increment them or re-assign them within a function and that will work, how fantastic is that!
Although as Borgtex has pointed out your if statement won't work
if (p <= t) {
p++;
}
You have declared the variable t in another function so your doMove() function does not have access to it, therefore this statement will always return false; If you make t a global variable or pass it into your doMove() function as a parameter then this will work.
var p = 1; // this variable is global
function varTest(){
p++ //This will work because p is global so this function has access to it.
var t = 0;
}
function anotherTest(){
if(p<t){ //This will return false - t is not in scope as it was defined in another function
alert("supercalifragilisticexpihalitoscious");
}
}
Related
I'm appending onclick events to elements that I'm creating dynamically. I'm using the code below, this is the important part only.
Test.prototype.Show= function (contents) {
for (i = 0; i <= contents.length - 1; i++) {
var menulink = document.createElement('a');
menulink.href = "javascript:;";
menulink.onclick = function () { return that.ClickContent.apply(that, [contents[i]]); };
}
}
First it says that it's undefined. Then I changed and added:
var content = content[i];
menulink.onclick = function () { return that.ClickContent.apply(that, [content]); };
What is happening now is that it always append the last element to all onclick events( aka elements). What I'm doing wrong here?
It's a classical problem. When the callback is called, the loop is finished so the value of i is content.length.
Use this for example :
Test.prototype.Show= function (contents) {
for (var i = 0; i < contents.length; i++) { // no need to have <= and -1
(function(i){ // creates a new variable i
var menulink = document.createElement('a');
menulink.href = "javascript:;";
menulink.onclick = function () { return that.ClickContent.apply(that, [contents[i]]); };
})(i);
}
}
This immediately called function creates a scope for a new variable i, whose value is thus protected.
Better still, separate the code making the handler into a function, both for clarity and to avoid creating and throwing away builder functions unnecessarily:
Test.prototype.Show = function (contents) {
for (var i = 0; i <= contents.length - 1; i++) {
var menulink = document.createElement('a');
menulink.href = "javascript:;";
menulink.onclick = makeHandler(i);
}
function makeHandler(index) {
return function () {
return that.ClickContent.apply(that, [contents[index]]);
};
}
};
A way to avoid this problem altogether, if you don't need compatibility with IE8, is to introduce a scope with forEach, instead of using a for loop:
Test.prototype.Show = function (contents) {
contents.forEach(function(content) {
var menulink = document.createElement('a');
menulink.href = "javascript:;";
menulink.onclick = function() {
return that.ClickContent.call(that, content);
};
});
}
var add = (function () {
var counter = 0;
return function () {
var reset = function() {
counter = 0;
}
return counter += 1;
}
})();
This is a self-invoking function that creates a "private" variable. How would I create a function reset that will reset the counter to 0? I've tried declaring the function inside the closure, but when I call it using add.reset(), it tells me this method is undefined.
You should return the reset function as a method of the object returned by the IIFE. That object needs to be the add function, so put the reset method on it. Just do it like you would in a global context, but inside a closure and return the add function, e.g.:
var add = (function(){
var counter = 0;
function add(n) {
counter += n || 0;
return counter;
}
add.reset = function(){
counter = 0;
return counter;
}
return add;
}())
console.log(add(1)) // 1
console.log(add(4)) // 5
console.log(add.reset()); // 0
However, it would make more sense (to me) to have a counter object that has add and reset methods.
I would recommend that instead of trying to put the function inside your closure, you put your variable outside your closure, like this:
var counter = 0;
var add = function() {
return counter += 1;
};
var reset = function() {
counter = 0;
};
That way the variable has proper scope for what you are trying to accomplish with it.
If you want to explicitly keep the counter declared inside the closure, you need to declare reset (even if you don't give it a value) outside the closure. To use your code, it would look like this:
var reset;
var add = (function () {
var counter = 0;
return function () {
reset = function() {
counter = 0;
}
return counter += 1;
}
})();
Now reset is outside the scope of the add function, so it keeps the value assigned within it!
To be fair, though, there's no reason to assign reset every time you can the result of add... It might be better to do something like:
var reset;
var add = (function () {
var counter = 0;
reset = function() {
counter = 0;
}
return function () {
return counter += 1;
}
})();
Or better still, if you want add.reset() to work:
var counter = function () {
var counter = 0;
this.reset = function() {
counter = 0;
}
this.add = function () {
return counter += 1;
}
};
var add = new counter();
Then add is a full object, which more or less sounds like what you want.
Or if you want to stick with the self invoking function:
var add = (function () {
var counter = 0;
return function () {
this.reset = function() {
counter = 0;
}
return counter += 1;
}
})();
Would probably work. It would be a slightly unusual paradigm from what I've seen though...
If you would like to keep the privacy of your current count, here is an answer that uses an object:
function counter() {
var count = 0;
this.reset = function() {
count = 0;
return count;
};
this.add = function() {
return ++count;
};
}
Then for instance:
var counter1 = new counter();
counter1.add();
console.log(counter1.add());
console.log(counter1.reset());
I'm writing a counter to count an object, and it looks like this:
function myFunc(param) {
this.param = param;
param.foo = function() {
var object = window.JSON.parse(data);
for (i in object) {
counter++;
}
}
}
var foo = new myFunc('data.json');
var counter = 0;
document.write(counter); // displays 0
How can I achieve to get the counter value outside the function? I tried almost everything, from window to return to separate functions.
Any clue?
Update
I prefer a better design like this
function myFunc(param) {
this.param = param;
param.foo = function() {
var object = window.JSON.parse(data);
var counter = 0;
for (i in object) {
counter++;
}
return counter;
}
}
var foo = new myFunc('data.json');
document.write(counter); // displays undefined
Update 2
Sorry, thought it would be easier to have a sample code. But here's the real one: https://gist.github.com/BobWassermann/e709ec303477a015b609
I think you have a couple issues here.
First, you're setting your counter to 0 just before you write. It will always be 0 no matter what you do, even with hoisting.
Second, you never call the foo function, so your counter is never incremented.
Third, param.foo isn't public. I think you want it to be this.foo = function(){ ... }.
Here's a simplified version of the code you posted with my tweaks:
var counter = 0;
var foo;
function myFunc() {
this.foo = function() {
counter = 1000;
}
}
foo = new myFunc();
foo.foo();
document.write(counter);
JSFiddle: http://jsfiddle.net/dgrundel/2ojw2332/2/
Note that JSFiddle doesn't allow document.write, so replaced that part.
function myFunc(param) {
this.param = param;
this.foo = function () {
var object = window.JSON.parse(this.param),
counter = 0,
i;
for (i in object) {
counter++;
}
return counter;
};
}
var foo = new myFunc('{"a":99}');
out(foo.foo());
function out(s) {
document.getElementById('out').innerHTML = '<pre>' + s + '</pre>';
}
<div id="out"></div>
As #Nina Scholz pointed out earlier, I'm retrieving the data asynchron. Javascript started painting the dom before all the values where loaded.
This fixed my problem:
if (document.readyState) {
setTimeout(function() {
var objLen = Object.keys(obj).length;
console.log(objLen);
}, 100);
}
I'm waiting for the document to be ready, then add an additional timeout as buffer.
Can someone advise me on below Javascript -
1) How can I use the "Base" variable?
2) In callShowMsg function, a local variable "ns" is used to alias the namespace.
Is it possible to use a global variable to alias the namespace? It will avoid the need to declare local variable in each function.
Thanks in advance.
My code is,
var Base = namespace("MyCo.MyApp.Myprogram");
MyCo.MyApp.Myprogram =
{
showMsg: function (pMsg)
{
alert(pMsg);
},
callShowMsg: function (pMsg)
{
var ns = MyCo.MyApp.Myprogram;
ns.showMsg('Hello');
}
}
something like this: (YUI with some fallback for custom namespace). Though I believe you do not have to "namespace" or reference the obj. Just refer to it as "this".
So, if you are within the obj, you can call the methods like so: this.showMsg('somevalue')
function createNamespace() {
var uniqueNS = "MyCo";
var a = arguments, o, i = 0, j, d, arg,
ns = this,
PERIOD = ".";
// force namespace to MyCo
ns.uniqueNS = ns.uniqueNS || {};
ns = ns.uniqueNS;
for (; i < a.length; i++) {
o = ns; //Reset base object per argument or it will get reused from the last
arg = a[i];
if (arg.indexOf(PERIOD) > -1) { //Skip this if no "." is present
d = arg.split(PERIOD);
for (j = (d[0] == uniqueNS) ? 1 : 0; j < d.length; j++) {
o[d[j]] = o[d[j]] || {};
o = o[d[j]];
}
} else {
o[arg] = o[arg] || {};
o = o[arg]; //Reset base object to the new object so it's returned
}
}
return o;
}
var Base = createNamespace("MyCo.MyApp.Myprogram");
Base =
{
showMsg: function (pMsg)
{
alert(pMsg);
},
callShowMsg: function (pMsg)
{
this.showMsg(pMsg);
}
}
Base.showMsg('ok');
I dont think there is some function like namespace like you wrote above,
You can do something like that:
var MYAPPLICATION = {
calculateVat: function (base) {
return base * 1.21;
},
product: function (price) {
this.price = price;
this.getPrice = function(){
return this.price;
};
},
doCalculations: function () {
var p = new MYAPPLICATION.product(100);
alert(this.calculateVat(p.getPrice()));
}
}
Or If you want to use nested namespaces you can try this:
var MYAPPLICATION = {
MODEL: {
product: function (price) {
this.price = price;
this.getPrice = function(){
return this.price;
};
}
},
LOGIC: {
calculateVat: function (base) {
return base * 1.21;
},
doCalculations: function () {
var p = new MYAPPLICATION.MODEL.product(100);
alert(this.calculateVat(p.getPrice()));
}
}
}
How can I use the "Base" variable?
That is going to depend on what value got returned by the namespace function. This is not a standard JS function and its probably specific to the libraries you are using so I cant answer.
Is it possible to use a global variable to alias the namespace?
Of course.
var ns = {
callShowMsg: function (pMsg)
{
ns.showMsg('Hello');
}
}
MyCo.MyApp.Myprogram = ns;
You can also make ns into a local function instead of a global by putting it inside an initialization functions intead of putting it on the script toplevel. The most common way of doing that is using an immediately invoked anonymous function:
(function(){
var ns = {
callShowMsg: function (pMsg)
{
ns.showMsg('Hello');
}
}
MyCo.MyApp.Myprogram = ns;
}());
I want to create a function such that
each time the function runs, the value of variable P will increase;
the number of times the function runs is set by the variable runtimes.
For example:
var runtimes = '25';
var P = '1';
function send(){
//some function
}
After the first run, variable P will be 2 and the second run will start.
How can I do this?
You can call the function from a loop:
var runtime = 25;
var P = 1;
function send(){
P++;
}
for (var i = 0; i < runtime; i++) {
send();
}
Or keep track of the iterations in the function itself and call it once:
var iterations = 0;
var runtime = 25;
var P = 1;
function send(){
P++;
if (++iterations < runtime) {
send();
}
}
send();
var runtime = 25;
var P = 1;
for(var P = 1; P < runtime; send(), P++) { }
function send(){
//some function
}
function sendMultipleTime(){
var runtime = 25;
var P = 1;
while(P<=25)
send();
P++;
}
function send(){
}
You can use a simple for loop, if I've understood the question correctly.
var runtime = 25;
var P = 1;
for (var i = P; i <= runtime; i++) {
function send() {
console.log(i + ' ' + P + ' ' + runtime);
}
send();
P++;
}