I have a function that returns a variable and a function which edit the variable value.
But it's not working and I don't know why.
And what is the correct way to do this?
Here is my code:
function t(){
var test = 1;
var changeTest = function(){
test++;
}
return {
changeTest:changeTest,
test:test
}
}
var b = t();
b.changeTest();
console.log(b.test) // the value is 1 not 2
The value of test is a primitive and so it is indeed not a reference.
A solution: make the exposed test property a getter, so that the value of the private test variable is retrieved at the moment the property is accessed:
return {
changeTest:changeTest,
get test() { return test }
}
function t(){
var test = 1;
var changeTest = function(){
test++;
}
return {
changeTest,
get test() { return test }
}
}
var b = t();
b.changeTest();
console.log(b.test);
With this pattern, the test variable remains private, and you only expose the features you want to. So in this case you allow explicitly to read the test value, but not to write it.
NB: you can shorten the object literal notation to just:
return {
changeTest,
get test() { return test }
}
In changeTest you have to use this.test instead of test.
function t(){
var test = 1;
var changeTest = function(){
this.test++;
}
return {
changeTest:changeTest,
test:test
}
}
var b = t();
b.changeTest();
console.log(b.test) // the value is 1 not 2
If you would like to increase inside of the function, you need to use this keyword inside, just like the following:
function t(){
const changeTest = function() { this.test++; };
return { changeTest, test: 1 };
}
const b = t();
console.log('original value', b.test);
b.changeTest();
console.log('increased value', b.test);
The reason is why it is happening because you are not modifying the value inside, it is called lexical closure what you face with, as the documentations states:
A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function’s scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time.
Using the this keyword the code accesses the proper test variable.
For further explanation please read further here:
Closures: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
this: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
I hope this helps!
Related
function abc(){
var a = 'lorem';
var b = 'ipsum';
//... and so on - abot 20 variables.
// do something with the variables.
}
this variables I need in many functions so I tried to create a common function just for give them a value:
function givemevars(){
var a = 'lorem';
var b = 'ipsum';
...
}
and then
function abc(){
givemevers();
console.log(a);
}
result: undefined;
I know, I should firstly declare all that variables outside any function (like
var a; var b;...), but the question is - is there any shorter way?
update
I also tried:
function givemevars(){
a = 'lorem';
}
function abc(){
givemevers();
console.log(a);
}
result - undefined
function givemevars(){
a = 'lorem';
}
function abc(){
givemevars();
console.log(a);
}
abc();
You can re-structure you multiple variables to an object and wrap it to a method e.g giveMeVars() and just call it using object.key notation whenever you need any value from it.
function giveMeVars() {
const myVars = {
a: 'lorem',
b: 'ipsum',
c: 'zipsum'
//... and so on - abot 20 variables.
// do something with the variables.
}
return myVars;
}
function abc() {
let gotVars = giveMeVars();
console.log(gotVars.a);
}
abc();
Why your existing doesn't work?
Because it has typo on givemevars() and missing method invocation i.e abc(). Lets try like this way.
function givemevars() {
a = 'lorem';
}
function abc() {
givemevars();
console.log(a);
}
abc()
Okay, there are a couple things you need here.
First is an understanding of functional scope in javascript.
This will help you understand why your console.log is undefined;
Second, if you have 20 loose variables you might want to put them inside an object.
let variableContainer = {a:'ipsum', b:'lorum', c: 'whatever'};
variableContainer.d = 'something'; //add new variable or change existing
console.log(variableContainer.a); //access a
console.log(variableContainer); //view all
Now, you can just pass that object around to get its contents.
you are always going to have to declare all the variables, the question is where?
You can go with your first thought by declaring it outside a function, making a global object (or variable). From there you can call it anywhere in your script (including inside functions).
However, global variables are generally a bad practice. You had some of the right ideas before with you givemevars function. Try something like this:
function doWorkWithVariables(){
let variableObject = givemevars();
//now we do work with variables without having to make them global
console.log('vars', variableObject);
}
function givemevars(){
const myVariableObject = {
a: 'ipsum',
b:'lorem',
c:'something'
}
return myVariableObject;
}
En example can be found in Twitter'a typeahead.js here:
function () {
// ...
return this.each(initialize);
function initialize() {
// ...
}
}
Questions:
What are the scopes and what function sees what?
What is the reason for using such a construct (usage scenarios and advantages)?
Javascript has function based scope, which means that every thing defined inside a function is available from the first line, since the definition is "hoisted" by the complier.
That goes for both variable and function definitions - variable values however, are not available until after assignment.
You can read all about javascript scoping and hoisting here
This means that the function initialize is available from the first line of the wrapping anonymous function.
There is no real reason, and no advantages, for doing it that way, unless you count the code structure as an advantage.
Personally I don't see any reason to do this. For me even it looks a little bit weird. Martin is right. You should be careful, because the defined variables are not accessible like functions. For example this doesn't work:
var getValue = function(func) {
return func();
}
var f = function() {
return getValue(now);
var now = function() {
return 10;
}
}
alert(f());
However, this works:
var getValue = function(func) {
return func();
}
var f = function() {
return getValue(now);
function now() {
return 10;
}
}
alert(f());
I want to be able to assign a property to a function inside the function itself. I do not want to assign it to the object of invocation. So I want the equivalent of doing this:
var test = function() {
return true;
};
test.a = 'property on a function';
alert(test.a);
Instead of this, where the property is assigned to a global object:
var testAgain = function() {
this.a = "this property won't be assigned to the function";
return true;
};
testAgain();
alert(window.a);
Edit: To clarify, I'm wondering if there's something like this:
var test = function() {
function.a = 'property on a function';
};
alert(test.a); // returns 'property on a function'
Without knowing that the function is called test or having to execute it.
I know of course this isn't valid syntax
[is there a way to set a property on a function] without knowing that the function is called test or having to execute it.
Emphasis mine.
You can set a property on a function without knowing what its global variable name is necessarily going to be, however you do have to have a reference to the function in one way or another.
The module pattern is as close of a fit as I can think of:
window.test = (function () {
//the function could be named anything...
function testFn() {
...code here...
}
//...so long as the same name is used here
testFn.foo = 'bar';
return testFn;
}());
window.test.foo; //'bar'
The outer closure prevents testFn from being accessed anywhere globally, so all other references will have to use window.test.
This part of the answer is associated with the prior version of the question.
The simplest way of doing this is to use a named function:
var test = function testFn() {
testFn.foo = 'bar';
return true;
};
test.foo; //undefined
test();
test.foo; //'bar'
A better way of doing this is to use the module pattern so that you don't accidentally create issues with global leakage:
var test = (function () {
function ret() {
ret.foo = 'bar';
return true;
}
return ret;
}());
test.foo; //undefined
test();
test.foo; //'bar'
var testAgain = function() {
arguments.callee.a = "this property won't be assigned to the function";
return true;
};
testAgain();
alert(testAgain.a);
You can do this by simple using the name to assign the property like this:
var test = function () {
test.a = 'a';
return true;
};
When test is invoked, the property will be set.
Demo
You could use arguments.callee, as su- said, but that's considered really bad practice. Also, it won't work in strict mode.
var test = function() {
test.a = 'a';
};
Or you can use prototypes, read more here.
This is the javascript closure code I saw at Javascript Definitive Guide. I'd like to write it as C++11
var uniqueID1 = (function()
{
var id = 0;
return function() { return id++; };
})();
This is the cpp code I wrote. But it isn't be compiled. Can C++11 represent the same expression?
auto c = []() -> int (*)() { int x = 0; return [&x]() -> int { return x++; }};
I'm using VS2010
Edit:
This is the full javascript sample code I made. You can test easily how the code works at your web browser.
<head>
<script language="javascript">
var uniqueID1 = (function()
{
var id = 0;
return function() { return id++; };
})();
var uniqueID2 = (function()
{
var id = 0;
return function() { return id++; };
})();
</script>
</head>
<body>
<input value = "uniqueid1" type="button" OnClick="alert(uniqueID1());"></input>
<input value = "uniqueid2" type="button" OnClick="alert(uniqueID2());"></input>
</body>
</html>
OK, first let's break down what your JavaScript does.
function()
{
var id = 0;
return function() { return id++; };
}
This creates a function. A function with no name, which takes no parameters. This function, when called, will return a new function. The inner function will have access to a locally scoped variable, and this variable will be part of the state of that inner function.
Each time this function is called, it will return a new function. That new function will have its own state (var id = 0; has to do something, after all). Each call of the outer function will return a new function with new state.
This:
(function()
{
var id = 0;
return function() { return id++; };
})
Wraps the function in a pair of parenthesis. This is needed for operator precedence rules, to allow this to work:
(function()
{
var id = 0;
return function() { return id++; };
})()
This creates a function, and then calls the function. That's what the last () do at the end. It calls the outer function, which creates an inner function with its own scope and returns it.
In this expression, the outer function is lost. It's gone; you can't access it anymore. You created it for just long enough to call it, then let it drop into the trashcan of garbage collection.
Given all of this, we can see that this statement:
var uniqueID1 = (function()
{
var id = 0;
return function() { return id++; };
})();
Creates the outer function, calls the function which returns a new function, and then stores the inner function in a variable called uniqueID1.
If you need proof that this is true, try this in your HTML:
var uniqueMaker = function()
{
var id = 0;
return function() { return id++; };
};
var uniqueID1 = uniqueMaker();
var uniqueID2 = uniqueMaker();
You'll get the same answer as your copy-and-paste version.
If we want C++ code to mimic this, we need to perform each step with proper C++ code.
First, the inner function. In C++, lexical scoping does not exist. So you cannot return functions that reference variables in other scopes. You can only return a lambda that has a copy of variables from another scope. Also, lambdas cannot modify scope unless you explicitly allow it. Thus, the inner code must look like this:
int id = 0;
return [=]() mutable { return ++id; };
That's all well and good, but now we need to create a lambda that will return this stateful lambda function. In C++, functions that have state are not the same as function pointers. And since the type of a lambda is compiler-defined, there's no way to type its name. Therefore, we must employ std::function as the return type of the outer function.
[]() -> std::function<int()>
{
int x = 0;
return [=]() mutable { return x++; };
}
This creates a lambda function that, when called, will return an inner function with its own state. State that is independent from any subsequent calls to this function. Just like the JavaScript example.
Now, that's not enough. Remember, your JavaScript creates the outer function, calls it, and stores only its return value. The outer function itself is discarded. So we need to mimic this. Fortunately, this is easy enough in C++; it looks just like JavaScript:
([]() -> std::function<int()>
{
int x = 0;
return [=]() mutable { return x++; };
})()
Lastly, we stick it in a variable:
auto uniqueID1 = ([]() -> std::function<int()>
{
int x = 0;
return [=]() mutable { return x++; };
})();
The type of uniqueID1 will be std::function<int()>. It won't be the type of the outer function. The outer function is just a temporary that was used to create the inner scope.
I assume you're not asking for a literal translation, but rather how to best express this construct in C++. Your JavaScript construct is in some sense "faking a constructor", and your ID generator is best expressed as a simple class in C++. Then you just make instances of that class:
class UniqueID
{
unsigned int value;
public:
UniqueID() : value(0) { }
unsigned int operator()() { return ++value; }
};
Usage:
UniqueID gen1, gen2;
some_function(gen1());
another_function(gen2());
Foo x(Blue, "Jim", gen1());
This approach is lighter-weight than a std::function wrapper, although a straight-up lambda will produce a similar data structure (though you cannot know its type name). You can initialize value to -1 if you want the first ID to be 0 (though it might be useful to reserve 0 as a special value).
I'm creating an object with multiple functions.. i.e.:
var test = {
setA: function(){
console.log(a)
}
endB: function(){
console.log(a)
}
}
How do I declare variable a so that it can only be accessed in the test object and every function within that the object? and is there anything unique about accessing it than other variables?
I know I can declare a global variable but would rather avoid doing that.
var test = (function() {
var a = 'test';
return {
setA: function(){ console.log(a) }, // <-- was missing a comma
endB: function(){ console.log(a) }
};
})();
This places a in a function invocation which creates a new variable environment. Only function inside this environment will be able to access it.
Your object that contains the functions is returned from the function, and assigned to test. Those two functions will continue to have access to a.
Example: http://jsfiddle.net/yWdFw/
This pattern:
(function() {
// your code
})();
...is commonly called an immediately invoked function expression or IIFE. You're defining a function, and invoking it immediately. As such, its return value is what's being assigned to test.
An alternative to patrick's answer is adding an attribute to the object and then accessing it via this
var test = {
a: 'blah',
setA: function(){
console.log(this.a)
},
endB: function(){
console.log(this.a)
}
}