How do I expose data from within ES6 blocks? - javascript

ES6 has introduced block scopes using let and const. What's the correct way to export data from within the block scope, so that I can access it from outside. Using IIFE you could just assign a the expression to a variable.
{
const add = (a, b) => a+b
// export add?
}
Using export within the block throws an error.
'import' and 'export' may only appear at the top level
One way I've found is to assign it to the global window object
{
const add = (a, b) => a+b
window.add = add
}
I'm just curious to know what the suggested way to do this is?

Create a function, and return the value you need.
const Add = () => {
return 'function add returned...';
};

You can also create a variable outside of the block and just assign it a value inside the block.
let myVar;
const myFunc = () => {
myVar = 'foo';
};

Related

getting an Uncaught TypeError: lake is not a function

Edited to add the whole hook
The below code is inside a custom hook. When I call the custom hook I get an unCaught TypeError telling me the arrow function is not a function. Could someone explain what I did wrong and would be the correct way to handle this?
const useHook = ({
Id,
}) => {
let Data = {};
arrowFunction(Id); //calling the arrow function a couple lines below
const arrowFunction = (Id) => {
const lakeHook = useLake();
if (Id) Data = lakeHook.getReference(Id);
if (Data.active){
console.log('data', Data);
return Data;
}
}
}
Variables declared with let and const are also hoisted but, unlike var, are not initialized with a default value. An exception will be thrown if a variable declared with let or const is read before it is initialized.
Docs: https://developer.mozilla.org/en-US/docs/Glossary/Hoisting?retiredLocale=it
You are trying to read the function stored in the const arrowFunction but that's not something allowed due to how it works hoisting in javascript with const variables. So what you need to do to call the function before the declaration is declaring it with the proper keywoard:
arrowFunction(Id);
function arrowFunction(Id){
//logic
}
Or alternatively call the function after creating it
const arrowFunction = (Id) => {
//logic
}
arrowFunction(Id);
const useHook = ({
Id,
}) => {
const lakeHook = useLake(); // hooks should be called only on top level
let Data = {};
const arrowFunction = (Id) => {
if (Id) Data = lakeHook.getReference(Id);
if (Data.active){
console.log('data', Data);
return Data;
}
}
arrowFunction(Id); //calling the arrow function a couple lines below
return ??? // declare return statement (optional);
}
Function Expression are not hoisted. Use Function Declaration instead.
lakeHook should be moved to a top level according to rules of hooks.
You probably want your custom useHook return something so declare return statement. (optional)

What is the difference between factory functions and module patterns? (more below)

So I'm trying to wrap my head around the concept of constructors, factory functions, IIFE, closures, module patterns and I find it really confusing when should I use which one. What caught my eye is that factory functions and module patterns are really similar, take this for example:
//module pattern
const calculator = (function(){
const add = (a,b) => (a+b);
const sub = (a,b) => (a-b);
const mul = (a,b) => (a*b);
const div = (a,b) => (a/b);
return {add, sub, mul, div}
})();
console.log(calculator.add(3,6));
// same with factory functions
function calc (){
const add = (a,b) => a+b;
const sub = (a,b) => a-b;
return {add, sub}
}
const calculator2 = calc()
console.log(calculator2.add(3,6))
Can anyone can tell me what is the practical difference? Any help appreciated!
If you are familiar with constructors, then you already know the concept of inheritance and prototypes, or giving our objects access to the methods and properties of another object. There are a few easy ways to accomplish this while using factories. Check this one out:
const Person = (name) => {
const sayName = () => console.log(`my name is ${name}`)
return {sayName}
}
const Nerd = (name) => {
// simply create a person and pull out the sayName function with destructuring assignment syntax!
const {sayName} = Person(name)
const doSomethingNerdy = () => console.log('nerd stuff')
return {sayName, doSomethingNerdy}
}
const jeff = Nerd('jeff')
jeff.sayName() //my name is jeff
jeff.doSomethingNerdy() // nerd stuff
This pattern is great because it allows you to pick and choose which functions you want to include in your new object.
Modules are essentially a syntax for importing and exporting code between different JavaScript files. Modules are actually very similar to factory functions. The main difference is how they’re created.
for example:
const calculator = (() => {
const add = (a, b) => a + b;
const sub = (a, b) => a - b;
const mul = (a, b) => a * b;
const div = (a, b) => a / b;
return {
add,
sub,
mul,
div,
}
})();
calculator.add(3,5) // 8
calculator.sub(6,2) // 4
calculator.mul(14,5534) // 77476
The concepts are exactly the same as the factory function. However, instead of creating a factory that we can use over and over again to create multiple objects, the module pattern wraps the factory in an IIFE (Immediately Invoked Function Expression).
The concepts are exactly the same as the factory function. However, instead of creating a factory that we can use over and over again to create multiple objects, the module pattern wraps the factory in an IIFE (Immediately Invoked Function Expression).
factory: use over and over again to create multiple object
module: Immediately Invoked Function
Reference
Module very useful whenever we want to hide certain parts of an object and only expose an interface to the user of the module. (source)
Example
// we used an immediately invoked function expression
// to create a private variable, counter
var counterIncrementer = (function() {
var counter = 0;
return function() {
return ++counter;
};
})();
// prints out 1
console.log(counterIncrementer());
// prints out 2
console.log(counterIncrementer());
// prints out 3
console.log(counterIncrementer());
As you can see, by using the IIFE, we have tied the counter variable to a function which was invoked and closed but can still be accessed by the child function that increments it. Since we cannot access the counter variable from outside of the function expression, we made it private through scoping manipulation.
Factory With a factory function, you can create as many user objects as you want. If you’re building a chat app, for instance, you can have a user object representing the current user, and also a lot of other user objects representing all the other users who are currently signed in and chatting, so you can display their names and avatars, too. (source)
Example:
const createUser = ({
userName,
avatar
}) => ({
userName,
avatar,
setUserName(userName) {
this.userName = userName;
return this;
}
});
console.log(createUser({
userName: 'echo',
avatar: 'echo.png'
}));

Why the () in this.state when using the current state as a parameter

I am reading about Reactjs, and one thing that I don't understand in the following syntax (taken from here)
this.setState(state => ({showWarning: !state.showWarning}))
is the () around the object. I understand that we use () for JSX, but the object {showWarning: !state.showWarning} is a JS object. Also I found this notation when using Redux as in
const mapStateToProps = state => ({...})
Why do we do that in React?
It's not specific to react. Arrow functions have a shorthand which allows you to skip the explicit return if you only have one statement. So a function like this:
const example = (val) => {
return 'foo'
}
can be shortened to this:
const example = (val) => 'foo';
But note that the way you do this is by leaving out the curly brackets of the function body. If you try to return an object, you're going to be sticking in curly brackets, so javascript thinks "ah, this is the function body", when really you want the brackets to mean an object literal. To clear up the ambiguity, you need to wrap the object in parentheses, so there's no possible way it could be interpreted as a function body.
const example2 = (val) => {
return { foo: 'bar' }
}
// can't become this:
//const example2 = (val) => {
// foo: 'bar' // this is not a key/value pair of an object! This is a labeled statement
//}
// so instead it becomes this:
const example2 = (val) => ({
foo: 'bar',
});
It's not exclusive to React.
When using Arrow functions, the expression to the right of the arrow is returned. But in the case of objects, the interpreter would interpret the braces as a multi-line function.
The parenthesis are there to denote that an object is to be returned as opposed to a function block declaration.
Quoted from the Syntax section of MDN:
(param1, param2, …, paramN) => { statements }
(param1, param2, …, paramN) => expression
// equivalent to: => { return expression; }
// Parentheses are optional when there's only one parameter name:
(singleParam) => { statements }
singleParam => { statements }
// The parameter list for a function with no parameters should be written with a pair of parentheses.
() => { statements }
// Parenthesize the body of a function to return an object literal expression:
params => ({foo: bar})
{showWarning: !state.showWarning} is definitely a valid javascript object but not everywhere it will work as an object because {} is also used for code block. If you return any object implicitly from an arrow function without () javascript will consider it a code block rather than an object
() is just used to make engine think that we are try to use an expression here not a code block which is statement
This is ES6 syntax for running a function that returns an object.
Because Javascript functions can create a new block by wrapping curly braces around, there is some ambiguity as to whether you are about to create this new block or if you're trying to return an object using implict return. So by wrapping the object in () you tell JS that you are trying to return the object inside implictly.
It just keeps the code lean and is more modern so that's why people use it.
Examples:
const ex1 = () => 1 // returns 1, no ambiguity
const ex2 = () => {return 1} // same as above, but with explicit return
const ex3 = () => {a: 1} // error! thinks it's a new block, not an object
const ex4 = () => ({a: 1}) // returns {a: 1} because wrapped in ()

Use of const in a Javascript class

In my JS component class, I have the following code at the top;
const {
getOwner
} = Ember;
What exactly does it mean ? Is the purpose to avoid code repetition ?
This is a new feature of JS present in ES6.
This is known as object destructure.
If you have an object like this.
const obj = { name: 'Stack Overflow' };
const { name } = obj;
console.log(name);
You can take a reference ->
Here for Destructure
And yeah about the const keyword.
The const keyword is used to declare a constant variable which is going to be same for the whole
and for const -> Here
try{
const a = 10;
a =12;
}catch(e){
console.log(e);
}
Is the purpose to avoid code repetition.
I don't really think so.
It is just a destructing assignment to assign Ember object's getOwner property to variable getOwner in your code. And const is there to make sure it is not overwritten by some other assignment

How to detect added global variables at runtime between two lines of code?

How to detect added global variables at runtime between two lines of code ?
I want to be able to tell what variable was added in between two lines of code at runtime without analyzing the source code. Just 1 variable is added.
Example:
"use strict";
//start
const myVariable = "10"; //detect this new variable
//end
const newVariableAdded = detectWhatIsNew();
// newVariableAdded should be "10" or "myVariable"
What I tried so far:
"use strict";
const notNew = Object.getOwnPropertyNames(window);
const detectWhatIsNew = function () {
let newString;
let key;
Object.getOwnPropertyNames(window).some(function (key) {
if (!notNew.includes(key)) {
notNew.push(key);
newString = key;
return true;
}
});
return newString;
};
//start
const myVariable = "10"; //detect this new variable
//end
const newVariableAdded = detectWhatIsNew();
// newVariableAdded should be "10" or "myVariable"
const and let are block-scoped, they don't create properties on the global object, but it's accessible by all code running within your enviroment (if declared outside a block, in the top level).
Your code only works for var or if you don't use any statement.
I don't think there's some approach that can do what you want.
One way is to use the var statement and split the code into multiple files so that the var statement does not get hoisted. There is a possibility to use a service worker to do split the files automatically.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Title</title>
</head>
<body>
<script src="prepare.js"></script>
<script src="addVariable.js"></script>
<script src="detectNewVariable.js"></script>
</body>
</html>
prepare.js
"use strict";
const notNew = Object.getOwnPropertyNames(self);
const detectWhatIsNew = _ => {3
/*returns an array*/
return Object.getOwnPropertyNames(self).filter(key => {
if (!notNew.includes(key)) {
notNew.push(key)
return true
}
});
};
addVariable.js
var myVariable = "10";
detectNewVariable.js
console.log(detectWhatIsNew()); // Array [ "myVariable" ]
Another way is to create globals using the window.variable = notation
What #EdmundoRodrigues says is almost correct, except that it works for var (IT DOESN'T in this case, but it works for inexistent global property assignment... "set", independently of undefined.
You can't detect the case of a variable (using var declaration) being added by var too, because the var statement declares variables instantly (sorry if my terms doesn't fit, English isn't my primary language), e.g.:
(_ => {
a = "10"
var a
alert(self.a) // undefined on window (global object)
// So the variable a can be assigned and used before the var
// keyword comes.
// If var [a] were not declared here, a would be global, or
// if it was strict mode, an exception would have been
// thrown.
}) ()
It's like this for var, except for let and const:
( _ => {
a = "10" // Uncaught ReferenceError: a is not defined(…)
let a
})()
Your function will only count global var statement used in next-separate scripts to be executed yet, and will also count fine any global object properties that were not existent earlier in the current executing expression/statement, independently of the undefined value.
const and let will be only visible in the entire scope until their declaration are executed, unlike var. And as #EdmundoRodrigues says, let and const variables are visible locally only, independently of the scope (even when the scope is global).
# Checking your code (note: I made a change to detectWhatIsNew to return all recent variables and declared myVariable with var).
"use strict"
const detectWhatIsNew = _ =>
Object.getOwnPropertyNames(self).filter(key =>
!notNew.includes(key) && notNew.push(key))
const notNew = Object.getOwnPropertyNames(self)
var myVariable
console.log(detectWhatIsNew()) // an empty array
This won't work for var, but it does make sense! Because the presence of var is instant, the Object.getOwnPropertyNames(self) call would have captured this "a" in any position.
console.log(notNew.indexOf( "myVariable")) // bigger than -1
But your function will still work for different ways of setting global variables, like:
self.myVariable2 = "19"
console.log(detectWhatIsNew()) // Array { "0": "myVariable2" }

Categories

Resources