Function argument instead of direct ref - javascript

I feel weird about this question.
Somehow I feel the answer should be quite obvious. Yet it isn't.
In Java Script, considering that inside another object's scope I can directly access a variable in any surrounding scope and mutate the crap out of it. Why would I choose to pass those variable as arguments to a function instead of referencing directly? What's the best practice? When would one choose to pass something as arguments instead of using the direct reference method? Is it just a matter of if I want a reference to the actual var or just its value, analogous to the kind of system employed in the C-family of languages?
For example:
Why would I do this:
var foo= 1;
var bar = function(foo) {
return foo + 2;
}
Instead of:
var foo = 1;
var bar = function() {
return foo + 2;
}
This makes a bit sense:
var bar = function(foo) {
return foo + 2;
}
foo = bar(42); // foo = 44

The use depends on the type of problem you want to solve
The global range variables are dealt with when the value can be reused in other operations
let Person = (() => {
let Person = function() {
this.name = null;
}
/**
* You can also occupy private variables so that you
* can not access them externally to your logic
*/
let privateVariable = null;
Person.prototype = {
setName: (name) => {
this.name = name;
}, getName: () => {
return this.name;
}
}
return Person;
})();
// Use:
person = new Person();
person.setName('Alan');
console.log(person.getName()); // log: Alan
On the other hand there are when you occupy variables of local scope
The local range variables are dealt with when you will not occupy that value in subsequent operations. It is a very common use in libraries
let Library = (() => {
/*
* When dealing with this type of programming all the logic
* of your program falls into the functions but when
* you use an anonymous function like this
* you can define variables to support you
*
**/
let CONSTANT = 2;
return {
operation1: (param1) => {
return param1 * 2;
},
operation2: (param1) => {
return param1 * CONSTANT;
}
}
})();
// Use:
let result = Library.operation1(42);
console.log(result); // 84
I hope this works for you, regards

I can directly access a variable in any surrounding scope and mutate the crap out of it.
Yes, and that's one of the things one wants to protect against.
Why would I choose to pass those variable as arguments to a function instead of referencing directly?
Reusability, basically. By passing the value explicitly, one can a) also pass other values than that of the variable in scope b) easily refactor the code by putting the function declaration in a different scope, without having to rewrite it.
Also, dependency injection: even when you expect the variable to be a constant that you want to reference, making it a parameter allows injecting mocks etc.
What's the best practice?
To choose wisely :-) The above advantages of putting everything in parameters are met by the disadvantage of having everything in parameters - long parameter lists and having to pass everything around have quite some overhead. So when you don't absolutely need to reuse the function, and don't need to inject any other values (e.g. in case of a given constant), there's no reason to do it.

Related

Differences between "this" in JavaScript and ActionScript

My background is heavy in JavaScript. I have a very advanced understanding of both ES5 and ES6. At work I was recently assigned a project involving an older flash application, which uses AS2. It is my understanding that ActionScript is very similar to ES5, but with classes and optional strict typing (akin to TypeScript and Flow), as well as a few other classic OO features. It is fairly straightforward so far, but I'm having trouble understanding how this and references work in ActionScript.
This is my understanding for JavaScript. this in a function can reference:
A bound variable, if using Function.bind() (as well as Function.call() and Function.apply()), which cannot be changed in the bound function, for example:
function func() {
return this.number;
}
var bound = func.bind({ number: 2 });
console.log(bound()); // 2
An object, if the function is called as a method on that object, for example:
function func() {
return this.number;
}
var obj = { number: 2, func: func };
console.log(obj.func()); // 2
An instance of a class, if that function is defined on the prototype of that class, for example:
function Class() {
this.number = 2;
}
Class.prototype.func = function func() {
return this.number;
}
console.log(new Class().func()); // 2
The global object, if the function is called without any kind of binding or object or instance attached to it, for example:
var number = 2;
function func() {
return this.number;
}
console.log(func()); // 2
In ActionScript things seem to be a bit different. For one thing, you can access class members without this if you are doing it within a method of that class, similar to languages like C# and Java:
class MyClass {
private var number:Number = 2;
public function func():Number {
return number;
}
}
trace(new MyClass().func()); // 2
Also, the ActionScript standard library doesn't seem to have a Function.bind() method, though it does have Function.apply() and Function.call() which seem to work just like the JavaScript variations: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/2/help.html?content=00001072.html#265677. There also don't seem to be prototypes, which makes sense because classes are more abstract syntactic structures rather than functions (just like C#/Java) based on my understanding.
So my question is, excluding the lack of Function.bind() and Function.prototype, are the rules the same between ActionScript and JavaScript?
In addition, what happens if I do this:
class SomeClip extends MovieClip {
private var childClip:MovieClip;
private var number:Number = 2;
public function SomeClip() {
this.onLoad = function() {
// SomeClip onLoad hander, `this` will be the SomeClip instance
childClip._visible = true; // How is childClip resolved here?
childClip.onRelease = function() {
// childClip onRelease handler, `this` will be childClip
trace(number); // How is number resolved here?
};
};
}
}
Basically, if you access a member without this in an event handler, or some other loose function that is not a method of the class, what happens? I would guess that in the first case, it would resolve to this.childClip and work as one would expect, but in the second case, the resolution would fail because the onRelease handler's closure won't contain a reference to the SomeClip instance.
I see the comments that have been written so far are more focused on JS, so I'll try my best to answer from an ActionScript perspective.
In the world of AS2/AS3, functions that are defined as methods on a class have their this value bound to the class. This is typical of many higher-level languages with modern classes, such as Java, Haxe, etc. As such, in ActionScript you'll rarely find the need to use the this keyword other than cases where a variable name might be shadowed by a function argument:
public function Point(x:Number = 0, y:Number = 0)
{
// A rare but necessary use-case of "this" in AS2/AS3
this.x = x;
this.y = y;
}
On the other hand, if the function you provide is anonymous as in the example you wrote, the behavior depends on whether or not you prepend this:
childClip.onRelease = function() {
trace(number);
};
In this case ActionScript is able to determine number is a member of the class, and will print 2 like you expected since. This is because the interpreter looks for the next closest thing in the stack. In other words, you were ambiguous by excluding this so it knows it needs to perform a lookup.
However if you were to trace(this.number) instead, you would find that you get an undefined (and possibly even an error). This is because this is not a member variable on the class, and now points to a "global object" similar to JS. To avoid dancing with the global object, it's common practice for ActionScript developers to define all of their listeners as class instance methods:
class MyClass extends EventDispatcher
{
private function MyClass()
{
addEventListener(Event.CHANGE, onChangeEvent);
}
private function onChangeEvent(e:Event) {
trace(this); // refers to this class, and no need for bind() like JS
}
}
Well organized AS3 code will almost never contain inline anonymous functions, since it's much easier to handle garbage collection by using explicit function references.
One last thing to note - you can expect functions that are methods of regular Objects in ActionScript to behave like JavaScript where passing them around via event listeners will result in the context of this being lost, and Flash will not do the magic lookup to locate the variable you referenced:
var obj = {
func: function () {
trace(this); // weird global object
}
};
addEventListener(Event.CHANGE, obj.func);
Hope that helps!
In AS2 functions are not bound and get "this" reference passed (evidently via Function.apply or by the object reference) in the moment of call:
function getIndex()
{
trace(this.index);
}
var A = {index:1, getIndex:getIndex};
var B = {index:2, getIndex:getIndex};
A.getIndex(); // 1
B.getIndex(); // 2
B.getIndex.apply(A); // 1
Binding methods to certain objects was called "delegating": http://help.adobe.com/en_US/AS2LCR/Flash_10.0/help.html?content=00001842.html#1001423 In a nutshell, functions are objects too and you can create special function object that has references to both method to call and "this" object to pass:
function getIndex()
{
trace(this.index);
}
function bind(method, target):Function
{
var result:Function = function()
{
// arguments.callee is always a reference
// to the current function object
arguments.callee.method.apply(arguments.callee.target);
}
result.method = method;
result.target = target;
return result;
}
var A = {index:1};
var B = {index:2};
A.getIndex = bind(getIndex, A);
B.getIndex = bind(getIndex, B);
A.getIndex(); // 1
B.getIndex(); // 2
B.getIndex.apply(A); // 2
Then, if you don't use "this" reference, once you address some variable by its name there are several contexts that are searched for such a variable in order:
local function variables
local wrapper function variables (this one is truly horrible for no one really knows where these variables exist and it is a potent memory leak)
MovieClip, that holds the function code, local variables
global variables
Play with the following code, comment some "index" variables and you'll see it:
// Global variable.
_global.index = 6;
// MovieClip local variable.
var index = 5;
function wrap():Function
{
// Wrapper function local variable.
var index = 4;
return function()
{
// Function local variable.
var index = 3;
trace(index);
}
}
wrap()();

javascript get function results outside of function

$(document)/ready(function(){
if (this == that) {
var myobject = {};
var variable = 55;
function dothisandthat(variable);
alert(JSON.stringify(myobject));
}
})
function dothisandthat(variable) {
//Do something
myobject["first"] = variable + 5;
myobject("second") = variable + 10;
}
How can i get myobject to be used in my function, and then call the object outside of the function again?
It can be globally available if you just do myobject = {} or window.myobject = {}, or even $.myobject = {}. Attach it to some global object like window, or since you are using JQuery, the JQuery $ object, and then you can use that throughout.
Or as #Pointy said, just add the parameter to the method:
function dothisandthat(variable, myObject) {
Well, with an object oriented approach, you would usually tell the object to modify it's internal state, which solves your scoping problems at the same time.
function MyObject() {
this.first = 0;
this.second = 0;
}
MyObject.prototype.doThisAndThat = function (variable) {
this.first = variable + 5;
this.second = variable + 10;
};
$(document).ready(function () {
//...
var myObject = new MyObject();
myObject.doThisAndThat(55);
alert(JSON.stringify(myObject));
//...
});
However, if you want to use a functional approach (data and behavior lives separately) you must make myObject available in the doThisAndThat's scope. There are a few ways to do this:
Pass the object as an argument to the function. That's usually the way I prefer since it makes dependencies explicit.
Please note that a pure functional approach would not mutate the object passed-in to the function, but would return a modified copy of the object since data structures are usually immutable.
Rely on a closure. In this case, you would simply have to move the doThisAndThat function declaration inside the document ready callback.
Rely on global variables or well-know objects. I would avoid this solution most of the time since it makes your dependencies hidden and your code harder to test.

How to use scope in JavaScript for Function constructor?

If I were to make a new function using the Function constructor, how could I give it a non-temporary scope to access besides window (meaning the scope only has to be evaluated once, not every time the function is called)? The purpose is to construct multiple variables that require some pretty costly calculations, and I don't want to reconstruct them every time the function is called, but I also don't want to store them in window. Any ideas?
You could bind your function to the specific context using bind keyword:
var context = {};
var f = new Function("args", "return this").bind(context);
f(); // context
Since bind is defined in ECMA 5th, it may not be present in all browsers, here's a workaround
For the above described purpose, you use static functions. You cannot prevent scope from being evaluated at every call, because this is the way JavaScript works, but you can speed it up by not having window in the scoping chain.
var namespace = {};
namespace.someMethod = function() {
// do something here.
};
Now anywhere in your code, you can call that method by using namespace.someMethod();. Just be careful. The above is a static method. You can call it without instantiating. But you MUST NOT use this.property inside a static function. It is a potentially very dangerous operation, as it may give an extension access to the global object and basically un-restricted permissions.
And the above is a static JavaScript method. It does not have window in the scoping chain.
Here's how to create a constructor using the same pattern. When you want to use a constructor, you always instantiate before using. For that you have the new keyword.
var namespace = {};
namespace.coordinate = function(x, y) {
this.x = x;
this.y = y;
};
namespace.coordinate.prototype.addCoordinates = function() {
return this.x + this.y;
};
Now anywhere in your code you can do:
var coordinateObject = new namespace.coordinate(5,10);
// you have created a new instance.
alert(coordinateObject.addCoordinates());// will alert 15;
// now you can make as many as you want. They will behave as instances.
// This means they do not interfere with each other in any way.
// They just have the same properties and methods, but the instance values
// Can be entirely different.
var secondCoordinateObject = new namespace.coordinate(10, 25);
alert(secondCoordinateObject.addCoordinates());// will output 35.
You have successufully created an instance of your namespace.coordinate class. Using the pattern I gave you, you can replicate almost the entire functionality of Java or C or any other Object Oriented language.
var yourNamespace = {
func1: function() {
},
func2: function() {
}
};
...
yourNamespace.func1();
you can call the function that you want by calling the function from name space like this yourNamespace.func1();
The ever-growing method of creating, storing, hiding, revealing, and grouping variables & functions is through the magic of "closures", Javascript's most powerful and yet unsung feature:
var groupObj = (function (setUp) {
// maintained by reference, hidden
var _priVar = setUp * 2;
// maintained by reference, revealed (through returned object)
var _pubVar = 8;
var _pubFunc = function (x) {
_priVar += x;
_pubVar += x;
}
var lostVar = setUp * 99; // not referenced, hidden, so evaporates!
return {
'pubVar' : _pubVar,
'pubFunc' : _pubFunc
}
}(4)); // runs immediately with 4 as setUp, revealing pubVar & pubFunc
Then...
groupObj.pubFunc(7); // runs public function, adds 7 to both variables
alert('public variable: ' + groupObj.pubVar); // alerts public variable
A closure occurs whenever there is a function inside of another function. A variable inside of the outter function will be maintained so long as it is referenced by the inner function, kind of a "no-mans land" where a variable is forced to exist by a reference to it from a lower scope, but is hidden from the higher scope due to the innate principles of Javascript.
There are a few other ways to use closures, replacing the object constructor, one-off conflict-free private functions, and more. There are many posts here about them.

Define JavaScript get and set function in object without using "this"?

I have a simple global object with a get and set function. JSlint is not liking that I am using "this" in the get and set function because it violates "use strict". What would I replace "this" with so that it would not violate "use strict" (i.e. how go I reference the same thing "this" is referencing without using "this")?
function fnDirty() {
"use strict";
var bIsdirty = false;
this.get_bIsdirty = function() {return bIsdirty; };
this.set_bIsdirty = function(x) {bIsdirty = x; };
}
var GV_oDirty = new fnDirty();
By convention, constructor functions begin with capital letters. JSLint will allow use of this in strict mode if you are in a constructor function but yours begins with a lowercase letter so it does not get recognized as a constructor.
function FnDirty() {
//your code
}
To answer your remaining question: "What is the roundabout way of doing this without a constructor?"
Brian had the right-ish idea -- but what he was really creating was a singular object with private properties, rather than a factory.
So to that end, if you wanted a function which granted each instance of the "class" its own unique copy of the private property, you could do this (I'm going to illustrate an actual class of something more useful than "Foo" and "Bar", to better-illustrate the concept -- it should be very simple to recompose this into whatever your intended use is):
var makeWallet = function (starting_amount) {
var amount = starting_amount,
overdraft = 1000,
addAmount = function (added_funds) { amount += added_funds; },
deductAmount = function (extracted_amound) {
if (is_sufficient_funds(amount, overdraft, extracted_amount)) {
amount -= extracted_amount;
return makeWallet(extracted_amount);
}
},
// other needed public/helper methods here...
// checkBalance(), is_sufficient_funds(), etc...
public_interface = {
// add all public-API methods you need here
addFunds : addAmount,
deductFunds : deductAmount
};
return public_interface;
};
Now, you've got a function which will return an object. Each object has methods which access that object's own "private" (ie: closed-over) amount variable, which is unique to those methods and only accessible to those methods.
Whether you build the functions as vars in the private scope, or build them as function declarations in the private scope, or put them directly into a return { func1 : () {...},... }; is irrelevant, as long as they're defined inside of that function when it's called (ie: not on the prototype chain -- which you CAN'T use in this pattern, anyway -- you will NOT call this function with new).
Okay, so that's all well and good. You've now got a working wallet-maker (without the security and user-features, yadda-yadda... ...homework).
But what if you wanted to add PRIVATE STATIC members to that?
What if you needed to keep track of serial keys, so that you could issue bank cards to people? Or you needed to track the branch-number? This is where Brian's IIFE comes into play. Except that instead of returning the finished wallet object, it's going to return the wallet FACTORY.
var makeWallet = (function () {
var serial_num = 0,
branch_num = "A011002z";
function walletMaker = function (starting_amount) {
/*same function as before, except that you ALSO call:
serial_num += 1; in the construction of the wallet, and assign the id */
var id = serial_num += 1;
return wallet;
}
// then you return the wallet-factory
// which becomes the new value of the outer function
return walletMaker;
}());
Now you've got static properties (in the outermost closure, that the wallet-factory will have permanent access to, as "static" members), AND you have instance-based private members, which inner-methods, added during the creation of the instance-object, will have complete access to.
The only downsides to this are:
Lose the prototype ability for this particular class, because you aren't using a constructor. Meh. If your objects need this setup, then it's worth not having it...
...if they don't, and public-everything is cool, then just use a constructor, and prototype -- or just build inline objects, with no methods, and build services (functions) to operate on each similarly-built object.
If you build all objects this way, you're going to suffer a memory penalty, when you make thousands of these, or tens of thousands of these objects, each with their own copies of functions (to enclose the private references). Again, this is the price you pay for the functionality. Take the memory hit where security/clean interfaces are a must, and don't, where you don't need to.
Also goes without saying, but avoid using this in financial-institutions, as client-facing code isn't the best place to trust with the power to add and remove real money...
Hope that clears things up.
You can use an alternative approach:
var fnDirty = (function() {
var _isDirty = false;
return {
get_dirty: function() { return _isDirty; },
set_dirty: function(val) { _isDirty = value; }
};
})();

Javascript closures -- what is the difference between these

EDIT
With the number of responses saying "you can make private things!" below, I'm going to add this to the top as well:
I know you can emulate private variables within a closure. That is not what I'm asking. I'm asking, given the two examples below where I'm "exporting" EVERYTHING from the closure, what is the fundamental difference between these two examples.
Given these two methods of creating objects/methods:
var test = {}
test = (function(){
var a_method = function(print_me){
return "hello "+print_me;
}
return {print_me: a_method};
})();
test.print_me2 = function(print_me2){
return "hello "+print_me2;
}
test.print_me('world');
>>> returns "hello world"
test.print_me2('world');
>>> returns "hello world"
I understand that the first method allows for private variables (which as a python developer at heart i don't really care to use), but both seem rather equivilent to me, only the first one looks "cooler" (as in all the big javascript people seem to be doing it that way) and the second way looks very passé.
So, like, what is the difference?
I've looked through the closure questions here -- most of them center around what or why do you use them; I understand their utility, I just want to know why you'd do the first over the second and what benefits it has.
I'd prefer hard evidence over conjecture -- not looking for a "this is how the cool kids are doing it" or "i heard that mozilla does better memory usage when you use a closure", but rather qualitative evidence towards one being 'better' than the other.
The difference between the methods is the anonymous function wrapper that creates a closure, but also that the first method replaces the entire object while the second method just sets a property in the existing method.
There are different ways of adding methods to an object. You can put them there when you create the object:
var test = {
print_me: function(text) { return "hello " + text; }
};
You can add a method as a property to an existing object:
var test = {};
test.print_me = function(text) { return "hello " + text; };
You can make a constructor function, and add methods to its prototype:
function Test() {}
Test.prototype.print_me = function(text) { return "hello " + text; };
var test = new Test();
As Javascript has a prototype based object model, the last one is how methods were intended to be created. The other ways are just possible because an object property can have a function as value.
You can use a function wrapper around any code where you want local variables, so you can do that with the second way of setting the property:
test.print_me2 = (function(){
var method = function(print_me2) {
return "hello "+print_me2;
}
return method;
})();
In the first example, the closure is used to keep local variables out of the global scope.
var thisIsGlobal = 2;
var test = (function () {
var thisIsLocal = 3;
return function () {
return thisIsLocal;
};
}());
What you get is a function test which when invoked returns the value of the local variable thisIsLocal. There is no way to change the value of the variable. You can be look at it as to a private variable.
The first method you present (an anonymous function which is executed immediately) keeps your program out of the global scope. Within that private scope you can decide what properties you want to expose as your API:
(function(win){
var a, b, c = 1;
function init(){
return aa(b);
}
function exit(){
if(cc()){
return a;
}
}
function aa(){
}
function bb(){
}
function cc(){
}
win.myProgram = {init: init,
exit: exit };
})(window);
// We now have access to your API from within the global namespace:
myProgram.init();
//etc

Categories

Resources