This question already has answers here:
ES6 destructuring object assignment function parameter default value
(5 answers)
Closed 4 years ago.
function drawES2015Chart({size = 'big',cords = {x: 0,y: 0},radius = 25} = {}) {
console.log(size, cords, radius);
// do some chart drawing
}
drawES2015Chart({
cords: {x: 18, y: 30},
radius: 30
});
I found this snippet on Mozilla's developer site under Destructuring assignment.
I was learning about ES6 destructuring assignment but have got bogged down here, I can't grasp how this function accepts an argument and sets default values?
Consider this simpler example:
function foo({ bar }) {
console.log(bar);
}
You can call this like foo({ bar: 42 }); and get 42 in the console.
But say you want a default parameter, you want bar and baz, but make baz optional, with a default value of true, you can do it like so:
function foo({ bar, baz = true }) {
console.log(bar, baz);
}
Call that one with foo({ bar: 42 }) would result in 42, true.
Now say we want all of the arguments to be optional:
function foo({ bar = 42, baz = true }) {
console.log(bar, baz);
}
foo({}); // 42, true
// however
foo(); // TypeError: Cannot destructure property `bar` of 'undefined' or 'null'.
Oops, you can't destructure a value that wasn't passed. So you need that parameter to have a default too:
function foo({ bar = 42, baz = true } = {}) {
console.log(bar, baz);
}
foo(); // 42, true. Yey!
Therefore, for your specific example:
function drawES2015Chart({size = 'big', cords = {x: 0, y: 0}, radius = 25} = {}) {
...
}
accepts one optional parameter, an object with three optional keys:
size is an optional key with a default value of big
cords is an optional key with a default value of {x: 0, y: 0}
radius is an optional key with a default value of 25
And because all of the keys are optional, we assume that empty input is equivalent to empty object, which would in turn use all of the default values for our keys.
Here {size = 'big', cords = {x: 0, y: 0}, radius = 25} is a optional object and size, cords, radius are keys with default values while {} is making as optional.
The final = {} defaulting the entire argument object to make sure that it is not destructure to undefined.
function drawES2015Chart({size = 'big', cords = {x: 0, y: 0}, radius = 25} = {}) {
console.log(size, cords, radius);
// do some chart drawing
}
drawES2015Chart();
function drawES2015Chart1({size = 'big', cords = {x: 0, y: 0}, radius = 25} ) {
console.log(size, cords, radius);
// do some chart drawing
}
//drawES2015Chart1();// throws TypeError
drawES2015Chart1({});
This Function accepts an Object with certain keys. Therefore you can destructure the object based on the keys. Using the assignment operator (=), this function also provides default values for each key (size, chords, radius)
function drawES2015Chart({ size = 'big' }) {
// do some chart drawing
}
//We invoke like this
let obj = { size: 'small'}
drawES2015Chart(obj)
To give you a simple and clearer picture, we can look at exactly one parameter and see the steps before condensed. Originally the code will be as below:
V1:
function drawES2015Chart(parameter) {
var size = parameter.size || 'big';
}
Then next we can condense a lil bit since we only using size in this method to below:
V2:
function drawES2015Chart({ size }) {
var size = size || 'big';
}
Then at last we condensed again to set default value as below:
function drawES2015Chart({ size = 'big' }) {
}
Related
When I study electron, I found 2 ways of getting BrowserWindow object.
const {BrowserWindow} = require('electron')
and
const electron = require('electron')
const BrowserWindow = electron.BrowserWindow
What is the difference between const and const {} in JavaScript?
I can't understand why the const {} can work. Do I miss anything important about JS?
The two pieces of code are equivalent but the first one is using the ES6 destructuring assignment to be shorter.
Here is a quick example of how it works:
const obj = {
name: "Fred",
age: 42,
id: 1
}
//simple destructuring
const { name } = obj;
console.log("name", name);
//assigning multiple variables at one time
const { age, id } = obj;
console.log("age", age);
console.log("id", id);
//using different names for the properties
const { name: personName } = obj;
console.log("personName", personName);
const {BrowserWindow} = require('electron')
Above syntax uses ES6. If you have an object defined as:
const obj = {
email: "hello#gmail.com",
title: "Hello world"
}
Now if we want to assign or use email and title field of obj then we don't have to write the whole syntax like
const email = obj.email;
const title = obj.title;
This is old school now.
We can use ES6 Destructuring assignment i.e., if our object contains 20 fields in obj object then we just have to write names of those fields which we want to use like this:
const { email,title } = obj;
This is ES6 syntax-simpler one
It will automatically assign email and title from obj, just name has to be correctly stated for required field.
This is one of the new features in ES6. The curly braces notation is a part of the so called destructuring assignment. What this means is that, you no longer have to get the object itself and assign variables for each property you want on separate lines. You can do something like:
const obj = {
prop1: 1,
prop2: 2
}
// previously you would need to do something like this:
const firstProp = obj.prop1;
const secondProp = obj.prop2;
console.log(firstProp, secondProp);
// etc.
// however now you can do this on the same line:
const {prop1, prop2} = obj;
console.log(prop1, prop2);
As you have seen in the end the functionality is the same - simply getting a property from an object.
There is also more to destructuring assignment - you can check the entire syntax in MDN: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
Other answers are good enough. I would suggest some useful features of Destructuring assignment
Firstly, Let's look at the following define:
The destructuring assignment syntax is a JavaScript expression that
makes it possible to unpack values from arrays, or properties from objects, into distinct variables.
Features:
Destructure an array, index of each item in array act as property (Due to an Array is an object in JavaScript)
> const {0: first, 1: second} = [10, 20]
console.log(first); // 10
console.log(second); // 20
Combine with Spread ... operator
> {a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40}
console.log(a); // 10
console.log(b); // 20
console.log(rest ); // {c: 30, d: 40}
Default values
const {a = 10, b = 20} = {a: 1};
console.log(a); // 1
console.log(b); // 20
Assigning to new variable names
const {p: a, q: b} = {p: 10, q: 20};
console.log(a); // 10
console.log(b); // 20
This question already has answers here:
Self-references in object literals / initializers
(30 answers)
Closed 5 years ago.
I am trying to create a JSON object to store some parameters for a program. Some of the parameters need to be calculated from others as they are being defined. I would like to do this within the object definition but maybe this is not possible
var params = {
a: 50,
b: 70,
c: this.a+this.b
}
Result
What happens
>params.c
NaN
What I wished happened
>params.c
120
Edit
After doing some further reading, I think I am using Object Literal Notation instead of JSON.
You can use this approach:
To avoid re-calculation, use the function Object.assign.
The get syntax binds an object property to a function that will be called when that property is looked up.
var params = {
a: 50,
b: 70,
get c() {
console.log('Called!');
return this.a + this.b;
}
};
console.log(params.c); // Prints 120 then Called!
console.log(params.c); // Prints 120 then Called!
var params = Object.assign({}, {
a: 50,
b: 70,
get c() {
console.log('Called from function Object.assign!');
return this.a + this.b;
}
});
params.a = 1000; // To illustrate.
console.log(params.c); // Prints 120
console.log(params.c); // Prints 120
.as-console-wrapper {
max-height: 100% !important
}
Resources
Object initializer
getter
Personally, I would create constants (since magic numbers are the devil), but this is an overly-simplistic example:
const FIFTY = 50;
const SEVENTY = 70;
var params = {
a: FIFTY,
b: SEVENTY,
c: FIFTY + SEVENTY
};
What I would recommend doing is starting with an object that does not contain c, and taking the calculation outside of the object. Once the calculation has occurred, simply add the sum back to the object as a new key/value pair:
var params = {
a: 50,
b: 70,
}
var sum = 0;
for (var el in params) {
if (params.hasOwnProperty(el)) {
sum += params[el];
}
}
params['c'] = sum;
console.log(params);
I have a javascript function like this
function drawImageOnCanvas(canvas, texturePath, color, type, onCall, modelPath, scene, pX, pY, pZ, scale, transform) {}
Here onCall, modelPath, scene, pX, pY, pZ, scale, transform are optional parameters. How can i pass value only for scale. Is there any way to define parameter name and pass value?
You can use an object as the function's parameter.
function drawImageOnCanvas(canvas, options){
var scale = options.scale;
}
And in call site:
drawImageOnCanvas(canvas, {scale: 2});
Also to handle optional parameters, you can check their existence using an if or || or ?:.
var color = /*default color*/;
if (options.color){
color = options.color;
}
Or
var color = options.color || /*default color*/;
Or
var color = options.color ? options.color : /*default color*/;
Note: If options contains parameters having false, 0, etc values then the methods above are not suitable anymore. For example, assume we have a parameter called isActive, then passing {isActive: false} will lead to the /*default isActive*/. To address this problem, you can use .hasOwnProperty or in.
var options = {scale: 2, isActive: false};
console.log('isActive' in options); // true
console.log(options.hasOwnProperty('isActive')); // true
console.log(options.isActive); // false
Anytime you have a function with many optional parameters, a much better option is to use a single parameter for all the optional parameters as an object.
In ES6, this case be more easily accomplished using destructuring and default parameters.
function drawImageOnCanvas(canvas, {scale = 1} = {}) {
...
}
Then you can call the function like this:
drawImageOnCanvas(canvas, { scale: 2 });
function test({ x = 10 } = {}) {
console.log(x);
}
test({ x: 100 }); // passing x
test({ y: 200 }); // not passing x
test(); // not passing anything still works
You create an array having .length equal to the number of expected parameters to function, set parameters passed to function as elements of an array, set index 10 of array to value for scale, use rest element to pass array of parameters to function, destructuring assignment within function to define named variables
function drawImageOnCanvas(canvas, texturePath, color, type, onCall
, modelPath, scene, pX, pY, pZ, scale, transform) {
console.log(canvas, texturePath, color, type, scale);
}
var args = Array.of(document.createElement("canvas"), 1, 2, 3, ...Array(7));
args[10] = {scale:456};
drawImageOnCanvas(...args);
Lets say I want to process some property x of objects in collection array. But collection may contain objects without such property or even undefineds. For example
let array = [
{x: 1},
{x: 2},
{},
{x: 4},
undefined
]
The idea is protect my self from such edge cases with default parameter. Let it be 0. I was trying to solve this as
array.map(({x: x = 0}) => process(x))
But it fails on undefined. Is there any way to solve this issue with default parameters and destructuring without writing check/set code inside of map function?
You can give the default object a default value
array.map(({x : x = 0} = 0) => process(x));
You can use .filter before .map in order to clean all falsy values like null, 0, '', false
array = array
.filter((el) => el)
.map(({x: x = 0}) => process(x));
Example
In MDN there is good description
Default function parameters allow formal parameters to be initialized with default values if no value or undefined is
passed.
so null is value., so if you pass null to function default value does not used, for example
function test(x = 10) {
console.log(x);
}
test(undefined); // 10
test(); // 10
test(null); // null
test(0); // 0
test(''); // ''
Example
Is there a way to set the value of a property within an object relative to another property within the same object?
For example:
var myObj = {
prop1 = 10,
prop2 = prop1 + 5
};
alert(myObj.prop2); //Alerts 15
Another example would be for when I create objects within an object aswell
var mainObj = {
obj1: {x: 100, y:100},
obj2: {x: obj1+10, y: obj1+10}
};
alert(mainObj.obj2.x); //Alerts 110
I want certain properties to stay relative to other properties in the same object, so that when I change one property, it will affect the other property.
You can declare your properties as functions
var obj = {
prop1:1,
prop2:function(){
return this.prop1 + 1;
}
}
If you don't care about backwards compatibility with browsers that only support ECMAScript 3, you can use accessors (setters and getters) featured in ECMAScript 5:
var myObj = Object.create(null, {
prop1: {
writable: true,
configurable: true,
value: 10
}, prop2: {
get: function() {
return this.prop1 + 5;
}
}
});
myObj.prop1 // 10
myObj.prop2 // 15
myObj.prop1 = 20 // 20
myObj.prop2 // 25
myObj.prop2 = 6 // 6
myObj.prop2 // 25
See also the Object.defineProperty() method, which allows you to add accessors to already existing objects.