Javascript: Difference between revisions
No edit summary |
|||
(30 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
=== Basics === | === Basics === | ||
See [https://github.com/moodboom/Reusable/tree/master/JavaScript/scrap scraps] scripts: | |||
~/development/Reusable/JavaScript/scrap | |||
==== [[ES6]] ==== | |||
[[ES6]] is required learning! | |||
==== Scope ==== | |||
myglobal = 1; // global scope, defined outside of any scope | |||
var myvar = 1; // local scope, cacades into closures and blocks; OLDSKOOL, avoid | |||
let myblockvar = 3; // block scope | |||
const myconst = 4; // const, has block scope | |||
==== Sorting ==== | |||
You'd think the sort() call's comparison function would be a "less than" check, like in C++. NOPE. You MUST return -1 or 1, not a boolean result. Wtf were they thinking... Working example: | |||
data.sort(( a, b ) => { | |||
// DO NOT SIMPLY RETURN a.value < b.value, you will gnash and cry bitter tears... | |||
return ( a.value < b.value ) ? 1 : -1; | |||
}); | |||
==== Array find-or-fail ==== | |||
The old stupid anti-pattern that far too many rookies jump right in to: | |||
if find then find else fail. | |||
There are a couple ways to properly find-or-fail, here's one, I have a better one that I can't remember atm, doh... | |||
const targetType = "selected"; | |||
myArray.find( item => item.type === targetType )?.description || 'unknown' | |||
==== Immutability ==== | |||
* Don't think that const gives you a const variable or object. Only the variable binding is const, ie it can't be reassigned. | |||
* myVar.freeze() will make your var '''shallowly''' immutable - but what's the point of that? | |||
* Still waiting on a deep immutable standard solution. Ridiculous. As a workaround, use deep copies (also hard to do, see next item). | |||
==== Deep Copy ==== | |||
Assignment of a new object to an existing one makes the new object a '''reference''' to the existing: | |||
var a = { "value": 3 } | |||
var b = a; | |||
a.value = 4; // b.value will also now = 4. | |||
Obviously, often (for better immutability for example), we want a copy. It's hard to believe but deep copies are hard to accomplish out of the box in silly Javascript. According to [https://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-deep-clone-an-object-in-javascript/5344074#5344074 this guy's benchmark], this works well: | |||
var newAllocation = JSON.parse(JSON.stringify(deepObject)) | |||
For futureproofing and convenience, use my deepCopy() function wrapper, in [at.js]. | |||
==== Closures ==== | |||
If you declare a function within another function, then the local variables can remain accessible after returning from the function you called. | |||
The scope of the internal local variables is the lifetime of the function. So if you have a function, you have its local variables too. | |||
You must use the function keyword inside another function to create a closure. | |||
==== [https://github.com/moodboom/Reusable/blob/master/JavaScript/scrap/promises.js Promises] ==== | |||
=== Libraries === | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! Javascript and JQuery | |||
|- | |||
| | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! Formatting examples (numbers dates etc.) | |||
|- | |||
| | |||
// Javascript sucks at dates. | |||
// d3 to the rescue! | |||
var parseInitDate = d3.utcParse("%Y-%m-%dT%H:%M:%SZ"); | |||
var initDate = parseInitDate(initial_managed_value_date); | |||
var initDateString = | |||
initDate.getUTCFullYear() | |||
+"/"+ (initDate.getUTCMonth()+1) | |||
+"/"+ initDate.getUTCDate() | |||
+ " " + initDate.getUTCHours() | |||
+ ":" + initDate.getUTCMinutes() | |||
+ ":" + initDate.getUTCSeconds(); | |||
var rightNow = new Date; | |||
var initToNow_DecimalDays = parseFloat(rightNow - initDate) / 864e5; // 86,400,000 ms/day | |||
var initToNow_PercentOfYear = initToNow_DecimalDays / 365.0; | |||
var change_in_value = (parseFloat(total_managed_value) - parseFloat(initial_managed_value))/parseFloat(initial_managed_value); | |||
$('#initial_managed_value').val(initial_managed_value.toFixed(2)); | |||
$('#initial_managed_value_date').val(initDateString); | |||
$('#change_in_value').val((change_in_value*100.0).toFixed(1)+ "%"); | |||
$('#equivalent_apr').val((change_in_value/initToNow_PercentOfYear*100.0).toFixed(1)+ "%"); | |||
$('#total_managed_value_readonly').val(total_managed_value.toFixed(2)); | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! Array vs Object lifetime | |||
|- | |||
| | |||
// If the JSON data were an array, we would need to slice-to-clone to keep it around: | |||
// var dataCopy = data.slice(); | |||
// updateStockData(run,dataCopy); | |||
// We have an object so we can pass a reference, and it will keep the object around. | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! Event handlers | |||
|- | |||
| Three basic methods: | |||
* Attach a function to an event of a specific element; charts.js example: | |||
var label = jQuery('<label class="btn btn-sm btn-'+color+'"></label>').appendTo(action_button_bar); | |||
var input = jQuery('<input class="run-'+cmd+'" type="checkbox" autocomplete="off" value="'+cycle.run+'">').appendTo(label) | |||
.on('change', cycle.owned? function(){ | |||
patchPick(this.value,'{ "action" : "run-hold" }'); | |||
} : function() { | |||
patchPick(this.value,'{ "action" : "run-buy" }'); | |||
}); | |||
var text = jQuery('<span class="glyphicon glyphicon-'+glyph+'"></span> <span class="hidden-xs">'+cmd+'</span>').appendTo(label); | |||
* Add a function handler once, for a class of elements; picks.js example: | |||
$("input[type='checkbox'][class='run-top' ]").change(function() { patchPick(this.value,'{ "action" : "run-move-top" }'); }); | |||
* Event delegation: Javascript takes events and "bubbles them up" through the chain of parents; set up a handler on a parent to listen for these bubbles. | |||
* At end of handler, prevent further bubbling with stopPropagation() - still finishes the current event (eg following the href of an <a>): | |||
<pre> | |||
var datepicker = jQuery( | |||
'<div class="input-group date form-inline pull-left" data-provide="datepicker" id="datepicker'+cycle.run+'">'+ | |||
'<input type="text" class="input-sm form-control">'+ | |||
'<div class="input-group-addon">'+ | |||
'<span class="glyphicon glyphicon-th"></span>'+ | |||
'</div>'+ | |||
'</div>' | |||
) | |||
.on('changeDate', function(e){ | |||
alert('next '+cycle.run); | |||
e.stopPropagation(); | |||
}) | |||
; | |||
</pre> | |||
* Or use preventDefault() to stop completely: | |||
<pre> | |||
var datepicker_next = jQuery( | |||
'<a href="">My javascript action</a>' | |||
) | |||
.on('click', function(e){ | |||
alert('next '+cycle.run); | |||
e.preventDefault(); | |||
}) | |||
; | |||
</pre> | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! Debug clicks on ANY PAGE | |||
|- | |||
| | |||
* Press F12 => Sources => Event Listener Breakpoints righthand pane => Mouse => [x] click | |||
B O O M we have it captured and can step into ANYTHING. | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! JWT flow | |||
|- | |||
| Client is easy! | |||
<pre> | |||
Client application API | |||
-------- ----------- | |||
| | | |||
| GET /api/employees | | |||
|----------------------------------------------------->| | |||
| 403 Forbidden | | |||
|<-----------------------------------------------------| | |||
| | | |||
| | | |||
| POST /api/authenticate | | |||
| { login: "john.doe", password: "password" } | | |||
|----------------------------------------------------->| | |||
| 200 Success | | |||
| { token: "my.personal.token" } | | |||
|<-----------------------------------------------------| | |||
| | | |||
| | | |||
| GET /api/employees | | |||
| Header { "Authorization: Token "my.personal.token" } | | |||
|----------------------------------------------------->| | |||
| 200 Success | | |||
|<-----------------------------------------------------| | |||
| | | |||
</pre> | |||
|} | |||
|} | |||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="wikitable" | |||
! [[Node.js]] | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! Bootstrap | ! Bootstrap | ||
Line 261: | Line 453: | ||
| You have to know your display size (range) and the min and max of your data (domain), on each axis. From [https://bost.ocks.org/mike/bar/ Mike's docs]: | | You have to know your display size (range) and the min and max of your data (domain), on each axis. From [https://bost.ocks.org/mike/bar/ Mike's docs]: | ||
D3’s scales specify a mapping from data space (domain) to display space (range). | D3’s scales specify a mapping from data space (domain) to display space (range). | ||
D3’s scales can also be used to interpolate many other | D3’s scales can also be used to interpolate many other | ||
types of display-space values, such as paths, color spaces | types of display-space values, such as paths, color spaces | ||
Line 285: | Line 477: | ||
Watch out for Mike's examples where he (trickily) doesn't bother to set a domain because his data is in the [0..1] set, and that's the default domain, apparently. | Watch out for Mike's examples where he (trickily) doesn't bother to set a domain because his data is in the [0..1] set, and that's the default domain, apparently. | ||
|} | |} | ||
|}<!-- | |} | ||
<!-- | |||
Line 293: | Line 486: | ||
--> | --> | ||
{| class="wikitable" | {| class="wikitable" | ||
! [[ | ! [[Vega-lite]] | ||
|}<!-- | |} | ||
<!-- | |||
Line 301: | Line 495: | ||
--> | --> | ||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! Moment.js | |||
|- | |||
| Make sure to specify a format when using a STRING SOURCE, eg: | |||
moment(myinputdate, "HH:mm:ss MM-DD-YYYY") | |||
From that point on, you'll have a JavaScript date object. | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! Accounting.js | |||
|- | |||
| Simple money library used by another bigger one (money.js) that we shouldn't need. | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! auto AWS | |||
|- | |||
| | |||
* npm install -g aws-sdk | |||
* Add credentials here: C:\Users\Administrator\.aws | |||
* see existing scripts, anything is possible | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! install bootstrap | |||
|- | |||
| | |||
* npm install -g grunt-cli | |||
* mkdir mysite && cd mysite | |||
* npm install bootstrap | |||
* cd node_modules/bootstrap | |||
* npm install # to actually pull down dependencies | |||
* grunt dist # builds and minifies so you're good to go! | |||
|} | |||
{| class="wikitable" | {| class="wikitable" | ||
! [[ | ! [[yarn]] alternative to npm | ||
|}<!-- | |} | ||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> |
Latest revision as of 19:45, 24 February 2023
Basics
See scraps scripts:
~/development/Reusable/JavaScript/scrap
ES6
ES6 is required learning!
Scope
myglobal = 1; // global scope, defined outside of any scope var myvar = 1; // local scope, cacades into closures and blocks; OLDSKOOL, avoid let myblockvar = 3; // block scope const myconst = 4; // const, has block scope
Sorting
You'd think the sort() call's comparison function would be a "less than" check, like in C++. NOPE. You MUST return -1 or 1, not a boolean result. Wtf were they thinking... Working example:
data.sort(( a, b ) => { // DO NOT SIMPLY RETURN a.value < b.value, you will gnash and cry bitter tears... return ( a.value < b.value ) ? 1 : -1; });
Array find-or-fail
The old stupid anti-pattern that far too many rookies jump right in to:
if find then find else fail.
There are a couple ways to properly find-or-fail, here's one, I have a better one that I can't remember atm, doh...
const targetType = "selected"; myArray.find( item => item.type === targetType )?.description || 'unknown'
Immutability
- Don't think that const gives you a const variable or object. Only the variable binding is const, ie it can't be reassigned.
- myVar.freeze() will make your var shallowly immutable - but what's the point of that?
- Still waiting on a deep immutable standard solution. Ridiculous. As a workaround, use deep copies (also hard to do, see next item).
Deep Copy
Assignment of a new object to an existing one makes the new object a reference to the existing:
var a = { "value": 3 } var b = a; a.value = 4; // b.value will also now = 4.
Obviously, often (for better immutability for example), we want a copy. It's hard to believe but deep copies are hard to accomplish out of the box in silly Javascript. According to this guy's benchmark, this works well:
var newAllocation = JSON.parse(JSON.stringify(deepObject))
For futureproofing and convenience, use my deepCopy() function wrapper, in [at.js].
Closures
If you declare a function within another function, then the local variables can remain accessible after returning from the function you called.
The scope of the internal local variables is the lifetime of the function. So if you have a function, you have its local variables too.
You must use the function keyword inside another function to create a closure.
Promises
Libraries
Javascript and JQuery | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
Node.js |
---|
Bootstrap | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
D3 | ||||
---|---|---|---|---|
|
Vega-lite |
---|
Moment.js |
---|
Make sure to specify a format when using a STRING SOURCE, eg:
moment(myinputdate, "HH:mm:ss MM-DD-YYYY") From that point on, you'll have a JavaScript date object. |
Accounting.js |
---|
Simple money library used by another bigger one (money.js) that we shouldn't need. |
auto AWS |
---|
|
install bootstrap |
---|
|
yarn alternative to npm |
---|