I've come across this pattern in an open-source project and have never come across it before, and was wondering the reasoning for doing it:
doSomething(blah = blurgh);
It is a shortcut to do in a single statement : assigning a variable and using the assigned variable as argument of a function.
So instead of writing it :
blah = blurgh;
doSomething(blah);
You write just :
doSomething(blah = blurgh);
It assigns it as a default value for the argument:
function someFunc(thing = "default string") {
console.log(thing);
}
someFunc() // default string
someFunc('another string') // another string
You can assign anything you want as the default value, even a previous argument
function someFunc(arg1, arg2 = ar1) {...}
It will use the default value even if you pass null explicitly.
Related
How can I get the value of the default parameters/arguments dynamicly without using the parameter variable?
function someFunc(param1 = 'value', param2 = 'value') {
console.log(arguments.length);
console.log(arguments[0]);
}
someFunc(); //0 undefined
I wanted to do the same, in order to assign several attributes to the instance of my class.
This approach might not help you since it uses one object argument instead of two arguments, still worth to mention:
class MyClass{
constructor(params={param1:3.1415, param2:'Hello'}){
//*assign* effectively destructures the params arg
Ojbect.assign(this,params);
}
}
Similarly your example would look like this:
function someFunc(params = {param1:'value', param2: 'value'}) {
console.log(Object.keys(params).length);
console.log(params['param1']);
}
Note that this approach requires your argument to be an object and that given one of the two arguments the other one will not be present in the default object.
You don't. Think about it this way. How do you get the default value with the old method?
function someFunc(param1, param2) {
param1 = param1 || 'value';
param2 = param2 || 'value';
console.log(arguments.length);
console.log(arguments[0]);
}
someFunc(); //0 undefined
Your best bet is to store the default value in a variable, and compare it in runtime. But that is kind of pointless.
Let's say I have a variable myvar, and I don't have a variable myvar2. I can run the following without a problem:
typeof myvar
// ⇒ 'string'
typeof myvar2
// ⇒ 'undefined'
typeof and delete are the only functions I know of which don't throw errors when given an undefined parameter like this. I looked at the language spec for typeof and to my uninitiated eyes it seems to use internal functions like IsUnresolvableReference.
Edit: I'd been working in a language that checks type with a synonymous function, and hadn't noticed typeof is actually an operator in JavaScript. I've removed parentheses from the code here but left the above as written.
When I create a function:
function myFunc(input_variable) {
return("hello");
}
... as expected this throws a ReferenceError when passed myvar2 as a parameter, unless I run var myvar2;.
If I wrap the return in a try/catch statement to handle the myvar2 not defined case, I still get the same error, as the variable seems to be checked for a resolvable reference upon entry into the function (upon runtime?) :
function myFunc(input_var) {
try {
return "hello";
} catch(error) {
if (error.name === 'ReferenceError'){
return "world";
}
}
}
I was wondering how I can make a function that accepts unresolved references. My general guess is that, if it's a standard behaviour of functions, then perhaps I could modify some prototype for this construction specifically...? I'm aware prototypes are for objects, I'm wondering if this level of control over function is possible somehow?
By way of context, I always find myself writing function(input_var) :
if (typeof input_var == 'undefined' || my_settings.input_var_is_optional === true)
var input_var = 'Sometimes variables are optional. This is my default value.';
return dealWith(input_var);
} else if (typeof input_var == 'string') {
return dealWith(input_var);
} else {
// Already checked that input_var isn't optional, so we have a problem
return false; // or throw a TypeError or something like that
}
but the verbosity of all that plain puts me off writing type checking into my code, making it less robust to use functions more freely, or to pass onto other developers.
I'd like to write a type handling function, e.g.
For a function myFunc(input_var), if the variable passed in as parameter input_var has been defined, check if it's a string, else set it as "default_value". If it wasn't defined, also set it as "default_value", else it's a valid string, so just use input_var as is.
...but it's sabotaged by the fact that I can't actually pass anything in that's undefined, effectively stopping me from isolating this complexity in a separate function to which I could just pass 2 parameters: input_var (the real deal, not just its name), and expected_type.
function typeTest(input_var, expected_type) {
var is_optional_value = (typeof expected_type != 'undefined'
&& expected_type === true);
var optional_str = is_optional_value ? "|(undefined)" : ''
var type_test_regex = RegExp('^(?!' + expected_type + optional_str + '$)');
var is_expected_type = type_test_regex.test(typeof(input_var));
}
For example, to check that an optional variable passed into a function was both defined, and was defined as a string,
var myvar = 'abc'
// myvar2 is never defined
// Mandatory type (expecting a string):
typeTest(myvar, 'string'); // true
// if (/^(?!string)$)/.test(typeof(myvar))
typeTest(myvar2, 'string'); // throws error
// Mandatory type (expecting a number):
typeTest(myvar, 'number'); // false
typeTest(myvar2, 'number'); // throws error
// Optional type ("expected is true"):
typeTest(myvar, true); // true
// if (/^(?!string|(undefined)$)/.test(typeof(myvar))
typeTest(myvar2, true); // throws error
I was wondering how I can make a function that accepts unresolved references.
You can't. When you access an undeclared variable, the ReferenceError occurs before the function even gets called. There's nothing you can do inside the function to recover from this, because it hasn't even been called.
typeof and delete are the only functions I know of which don't throw errors when given an undefined parameter like this.
typeof and delete are not functions. That's why.
For example, to check that an optional variable passed into a function was both defined, and was defined as a string.
There's nothing stopping you from doing this. There is a difference between:
variables with the value undefined
parameters that have not been passed a value
undeclared variables.
There is no problem in dealing with the first two:
function hasType(val, type) {
return typeof val === type;
}
function myFunc(param1, param2) {
console.log('param1: ', hasType(param1, 'string'));
console.log('param2: ', hasType(param2, 'string'));
}
myFunc('hello');
There is no need to check whether someone is trying to call your functions with undeclared variables. If they are, then the problem is with their code and they need to fix it. If they are taking advantage of optional parameters, that is a different matter, and you can handle for that scenario just fine.
as the variable seems to be checked for a resolvable reference upon entry into the function
It is checked before entry.
Given foo(bar), the logic for resolution is "Get foo, then get bar, then call foo with the value of bar as an argument.
If bar isn't declared then you'll get a ReferenceError before the function is called in the first place.
typeof and delete are the only functions I know of which don't throw errors when given an undefined parameter like this.
From the documentation you link to:
The typeof Operator
The delete Operator
They aren't functions.
I was wondering how I can make a function that accepts unresolved references.
You can't.
For example, to check that an optional variable
If you want an argument to be optional then either:
Explicitly pass undefined:
typeTest(undefined, 'string');
Put the optional argument last in the arguments list:
typeTest('string');
Pass an object:
typeTest({ argument_name: 'string' });
You can using a function slide.
function attempt(f){
console.log(f());
}
attempt( function (){ return nomansland} );
//later an ajax call declares it:
var nomansland = "ok";
attempt( function (){ return nomansland} );
I'm confused by the = vs. : when assigning a value to a property in an object
Now I know that there are a couple ways to create an object:
Object Literal
Object Constructor
With an object Literal you would use ":" to assign a value to a property:
var myObject = {firstName: "John", lastName="Smith" };
There we are using ":" to set the value to the property.
I also know a function itself is an object. And you can probably expose public properties from there as part of the function being an object?
So is it if you're assigning a function to a property that you'd use "="? I am assuming yet but what about something like this:
var phantom = require('phantom');
var World = function World(callback) {
phantom.create("--web-security=no", "--ignore-ssl-errors=yes", { port: 12345 }, function (ph) {
var phantomProcess = ph;
createBrowserPage = function(){
phantomProcess.createPage(function(page) {
this.headlessPage = page;
})
};
});
callback();
};
module.exports.World = World;
I assume I have this right in that I want to expose createBrowserPage through exports. I wouldn't use createBrowserPage: and use a ":" instead of "=" to assign that anonymous function to the createBrowserPage property right?
= is used for assignment in a Javascript statement as in:
variable = "foo";
: is used in an object literal declaration between a property name: value as in:
var obj = {
prop1: value1,
prop2: value2
};
If you want to expose your createBrowserPage() function through exports, you have several options, some of which involve creating an object and some of which involve assigning a property to an object. Which you choose and how you declare it leads to whether you use : or =. It depends upon which way you choose to write the javascript code that exposes createBrowserPage(). There is no single answer there. I will offer you a couple options.
If, in one statement, you want to assign one new property to the exports object, then you would use = like this:
module.exports.myFunc1 = myLocalFunction1;
If, in one statement, you wish to assign all your exported functions, then you would assign an object that was assigned with =, but used : in the declaration of the object like this:
module.exports = {
myFunc1: myLocalFunction1,
myfunc2: myLocalFunction2
};
In the first example, you are adding one new property to the exports object and assigning that property a value.
In the second example, you are declaring a new Javascript literal object (which uses prop: value syntax to declare its properties. And, then you are assigning that whole object to module.exports which actually replaces the entire existing exports object with a new one and this new object has two properties on it.
Your question is a bit confusing, but if you're interested in the precise meaning and grammar of : and = it's like this:
The colon (:) symbol is not an operator, it is part of the litteral object notation syntax and separates property names (a litteral string or simple identifier) from their value (any expression). Colons are only used in that context and as part of the trinary conditional operator (?:).
Something in curly brackets is parsed as a litteral object if and only if the { is not the first character in the instruction (otherwise it defines a block) and does not follow a function expression or declaration.
The assignment operator (=) (spec) is a binary operator, it can be used in any expression as long as its left operand is a valid left-hand-side expression, and it returns the value of the right operand. Unless strict mode is used, it will silently fail to assign a value to read-only properties.
let say I've got this kind of code:
var obj1 = {test: false};
function testCondition(condition){
if (!condition){
testCondition(condition);
}
}
testCondition(obj1.test);
above code will pass false as argument to testCondition. How can I do to pass reference to obj1.test instead of passing it's value?
EDIT
wow, thanks for quick responses!! :) But I would like to add, that I cannot pass the whole object, because I would like to build one generic function/method which would just check parameter and do onComplete callback or onError callback. Above code is only example of situation where I am right now.
You have two choices, from what I can see:
Pass the object itself, instead of its member. You can then access and modify the member:
function testCondition(object) {
if (!object.test) {
testCondition(object);
}
}
testCondition(obj1)
Alternatively, since you're changing a single value, you can have that value be returned by the function:
function testCondition(condition) {
if (!condition){
return testCondition(condition);
}
}
obj1.test = testCondition(obj1.test);
FYI, your code as you've displayed it right now will cause an infinite recursion if condition is false.
What's wrong with return values?
Alternatively you can wrap the argument in an object:
function foo(arg) {
var val = arg.val;
// do something with val
arg.val = val;
}
var arg = {val:"bar"};
foo(arg);
// do something with arg.val
You can't.
Pass obj1 instead, then examine condition.test inside the function.
You can't. JavaScript passes objects and arrays by reference, primitives (integers, strings, booleans) by value. What you're asking for is impossible, except by bad work-arounds:
function ugly(result) {
result.success = true;
}
var result = {};
ugly(result);
Instead, just return your value. It's how JavaScript is meant to work.
pass the whole object instead of its property:
testCondition(obj1);
and then
if(!passedObj.test){
etc...
Recently i found myself attaching function arguments to a variable inside the function scope so that i was not referencing the argument every time it was used.
Is there any benefit to this practice?
For example:
function populateResultCount(count){
var count = count;
return $('.resultCounter').text(count);
};
Could easily be re-written like so:
function populateResultCount(count){
return $('.resultCounter').text(count);
};
And would still function correctly.
There's no functional difference between the two. Go with the simpler version.
If you're not using the argument that's passed in, there is no difference. In your first example, you can potentially confuse future maintainers because of var count = count, i.e., you're declaring a variable that has the same name as the argument, and that isn't a best practise.
So, if you can, use your second form. Its intent is clearer and there is no room for confusion.
I can see no benefit to this unless you are manipulating the data somehow. Your variable without the additional assingment can still not be accessed outside of the function.
function Test (count) {
this.increment = function() {
count++;
}
this.getCount = function() {
return count;
}
}
var test = new Test(10);
<button onclick="test.increment(); alert(test.getCount());">Increment</button>
You can do something like that even with the argument. So I think they are same.
All the other answers are correct: There's no reason to "re-assign" a passed argument inside the function.
The only thing I can think of, where you'd mess with reassigning arguments, is if you have optional arguments/default values
function xyz(optionalArgument) {
optionalArgument = optionalArgument || "no argument given";
...
}
But in that case, it'd be better to write it as
function xyz( /* optionalArgument */ ) {
var optionalArgument = arguments[0] || "no argument given";
...
}
Note that the || trick will give you the right-hand side's value, if the left-hand side is a falsy value. I.e. if you're ok with the optional argument being something that's falsy (like explicitly passing null, 0, etc), you'd have to do something like var arg = typeof arguments[x] === 'undefined' ? defaultValue : arguments[x];