An introduction to JavaScript for data scientists.
software-tools-books / js4ds Goto Github PK
View Code? Open in Web Editor NEWJavaScript for Data Science
Home Page: https://third-bit.com/js4ds/
License: Other
JavaScript for Data Science
Home Page: https://third-bit.com/js4ds/
License: Other
And note: we must return exactly one node, because this is one function call
What does this mean? Why?
This trick of capturing a reference to a value inside something else
is called a closure
This entire section on closures is really complex, I must have read it 4 times and still feel it was pretty hard for me to follow the figures. I think why I'm so lost is I'm missing an overall picture of the importance of closures and why and when they are valuable. Am I right in thinking that add_1 and add_2 are closures because they share the same function body definition, but store different values? I think the sentence above could make clearer what it means by 'a value inside something else'
new ClassName(...)
creates a new blank object and inserts a (hidden) reference to the class so that the object can find its methods.new
then calls the specially-named methodconstructor
to initialize the object's state. Inside the constructor and other methods,
the object being operated on is referred to by the pronounthis
.
The description is easy to follow outside of the text I've highlighted in bold because I can find those keywords within the code chunks. The bold part, however, is puzzling.
What does this mean by "a hidden reference"? I followed the link to the glossary but I'm still what that means in the context of this example - is the method everything inside constructor? Before even grasping what a method is, the next sentence calls constructor a specially-named method - does square have other methods besides this one that aren't named?
I also think this is the first time the reader is seeing the phrase 'state' in reference to an object [only stateful and stateless are included in the glossary] - does it refer to the data/value you pass to it? In trying to look this term up I found reference to "internal" and "external" states, only muddying the term further!
Creating a Component for Names
Create a new React component that renders a name,
and modify the example to use it instead of always displaying names in<li>
elements.
I don't understand what this question is asking....
const first = transform(data, (x) => { return x[0] })
console.log(`first: ${first}`)
A function that is created this way is sometimes called an anonymous function,
since its creator doesn't give it a name.
When JavaScript programmers use the term "callback function",
they usually mean a function defined and used like this.
I have a conceptual understand of using a function iteratively on all strings within data
but I'm unclear on what is exactly anonymous about the above function [it looks like we're assigning the function to const first
wouldn't leaving this out make it anonymous?]
const counter = () => {
const paragraphs = document.querySelectorAll('p')
return paragraphs.length
}
const fill = document.getElementById('fill')
fill.innerHTML = `number of paragraphs: ${counter()}`
This did not result in seeing number of paragraphs: 2
on the page! Currently, the HTML includes <div class="fill"></div>
. If I change it to <div id="fill"></div>
then the code does run as desired. I tried looking for the function getElementByClassName but it did not work either. Why have we specified the class as fill rather than the id here?
Running:
const fs = require('fs-extra')
let total_size = 0
const files = ['jane-eyre.txt', 'moby-dick.txt',
'life-of-frederick-douglass.txt']
Promise.all(files.map(f => fs.stat(f))).
then(stats => stats.reduce((total, s) => {return total + s.size}, 0)).
then(console.log)
Resulted in the following error (not 2594901
)
DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Is this error also because I don't have these text files in some directory? It seems like I need some additional directions in order to be able to run this code and the following chunks pertaining to these txt files.
The first exercise in the object-oriented programming chapter doesn't make sense unless you know how to do temp=a, a=b, b=temp - explain that much earlier on.
const anotherName = oneMore
console.log(anotherName(5))
6
Doing this does not call the function: as Figure 3 shows, it creates a second name that refers to the same block of instructions.
My confusion here was with the first part of the explanation, "doing this does not call the function" because you do get the output of 6, which I thought meant the function was properly called/executed. Only after googling to ensure I understood the difference between defining a function and calling a function did I realize this sentence was referring to const anotherName = oneMore
and not the line after it.
Maybe adding a sentence about how we can use this new assignment to call the same function would help to clarify? (Or leaving out the console.log statement entirely?)
const trim = (text) => { return text.trim() }
const dot = (text) => { return text.replace(/ /g, '.') }
const original = ' this example uses text '
const trimThenDot = pipeline(original, trim, dot)
console.log(`trim then dot: |${trimThenDot}|`)
I spent some time looking up what str.trim as well as str.replace, despite the short explanation because I wanted to know more about the regex. Maybe including the function in the short definition and elaborating on how / /g is replacing every space will help?
Let’s use this to combine a function that trims blanks off the starts and ends of strings (
trim
) and another function that replaces all spaces with dots:
the notation {a, b} produces an object {"a": a, "b", b}:
I believe this is missing a colon and should be {"a": a, "b:", b}?
The code is dissected and explained only AFTER the concept of event listeners is introduced. I found myself struggling to interpret the code and not wanting to go on to the next topic before I grasped it, only to find an explanation for it below. Perhaps just personal preference, but I think putting the explanation starting on line 439 directly after this code is introduced and then talking about how this doesn't work would have more of a logical flow to it.
const sortLists = () => {
const allLists = Array.from(document.querySelectorAll('#sorted'))
lists.forEach((list) => {
const children = Array.from(list.childNodes)
.filter(c => c.nodeName !== '#text')
children.sort((left, right) =>
left.textContent.localeCompare(right.textContent))
while (list.firstChild) {
list.removeChild(list.firstChild)
}
children.forEach(c => list.appendChild(c))
})
}
const creature = {
'order': 'Primates',
'family': 'Callitrichidae',
'genus': 'Callithrix',
'species': 'Jacchus'
}
console.log(`creature is ${creature}`)
console.log(`creature.genus is ${creature.genus}`)
for (let key in creature) {
console.log(`creature[${key}] is ${creature[key]}`)
}
creature is [object Object]
creature.genus is Callithrix
creature[order] is Primates
creature[family] is Callitrichidae
creature[genus] is Callithrix
creature[species] is Jacchus
I understand the interpolation extracting the text for the key and value but I don't understand why we get the first line creature is [object Object] from console.log(creature is ${creature}
). Why does this give us the typeof as a result?
Different random numbers produce different behaviors
I see that if (this.hasEgg && ((season === 'winter') || (season === 'spring')))
[Line 382] is contingent on the random number generated in this.hasEgg = Math.random() < 0.5
[Line 375] but I don't understand explicitly what is being passed to the if statement. Does this.hasEgg just have to be true? Wouldn't generating a number for it, no matter the number, always render this true?
I'd like to see some advice about how to debug JS near the start of the book. Probably in Core?
I learned about debugger
last week and can see how that might be very useful for debugging things in the browser. I would love to hear other suggestions from people with more JS experience than I.
These script tags were giving me some errors and the visual wasn't rendering
<script src="https://cdnjs.cloudflare.com/ajax/libs\
/vega/3.0.7/vega.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs\
/vega-lite/2.0.1/vega-lite.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs\
/vega-embed/3.0.0-rc7/vega-embed.js"></script>
I was able to replaced the code with the vega scripts below and the graph rendered
<script src="https://cdn.jsdelivr.net/npm/vega@5"></script>
<script src="https://cdn.jsdelivr.net/npm/vega-lite@3"></script>
<script src="https://cdn.jsdelivr.net/npm/vega-embed@4"></script>
if (x) {
something
}
is confusing because most examples include a comparison or some other explicit test inside the test, so explain that:
if (x === true) {
}
isn't necessary because it's true
when x
is true
and false
when x
is false
. See #192.
const otherValues = [true, undefined, null]
for (let value of otherValues) {
console.log('the type of', value, 'is', typeof value)
}
It's a bit confusing that this code chunk is described out of order addressing let
before describing the brackets and an array. Also, the explanation is quite hard to follow. I spent a lot of time trying to translate every word within each line. After much consideration here's a stab at how I would put it (which I'm sure could be improved!)
The array otherValues is defined using brackets containing three elements.
the first line of a for loop:
of otherValues
<body>
<h1>Pass Parameters</h1>
<div id="app"></div>
<script type="text/babel">
const allNames = ['McNulty', 'Jennings', 'Snyder',
'Meltzer', 'Bilas', 'Lichterman']
const ListElement = (props) =>
(<li id={props.name}><em>{props.name}</em></li>)
ReactDOM.render(
<ul>{allNames.map((name) => <ListElement name={name} /> )}</ul>,
document.getElementById('app')
)
</script>
</body>
It'd be helpful to break this down line-by-line in the text because I'm still pretty confused about what we've done here. Are we generating unique ids for each element in the list so we can refer to them (and style them) individually? I guess I'm unclear on what the output of this would be and how it differs from the chunk before. Maybe providing an example of when/why this would be necessary would help?
function limits (values) {
if (!values.length) {
return [undefined, undefined]
}
let low = values[0]
let high = values[0]
for (let v of values) {
if (v < low) low = v
if (v > high) high = v
}
return [low, high]
}
I like how the paragraph following this code chunk begins, I can follow that the function is named limits and its parameter is values but it's unfortunate the explanation stops there as I'd like to be walked through what the rest of the function is doing line by line.
and constructs the HTML nodes we need.
I think this is the first time I'm being introduced to the term node. I see it's in the glossary, maybe include a link to it here.
Line 93: const aNumber = 123.45
This is the first time const is used and while typeof
is described what does this do? How is it different from var? Does it define a constant value?
We wrap the call in document.querySelectorAll with Array.from because the former’s result isn’t actually a JavaScript array.
Is Array.from
the function to coerce something into an array? I'm a little confused because until this point we've put predefined constants before the .
(ie: myStr.push). Is Array
a placeholder for whatever we feed into the function?
I like how this section is broken down line for line. However, it's a little disappointing that we don't end with an executable example I can run and take apart - would it be possible to generate some toy example to see the code in action? I've tried playing around to create this myself to no avail.
I tried substituting this chunk in place of the console.log() line
const container = document.getElementById('fill')
const headings = Array.from(document.querySelectorAll('h2'))
const items = headings
.map((h) => `<li><a href="#${h.id}">${h.innerHTML}</a></li>`)
.join('')
container.innerHTML = '<ul>' + items + '</ul>'
Again I got the error
Uncaught TypeError: Cannot set property 'innerHTML' of null
Really minor, but it seems the colors are rendering a little wonky on this line:
<ul>{allNames.map((name) => <li>{name}</li> )}</ul>
const srcDir = process.argv[2]
What is this line?
Ordering
What happens if you change the order in which the JavaScript files are loaded in your web page? For example, what happens if you load app.js before you load ListElement.js?
We've used app.js within the text but we never saved listElements to its own external JS file. I'm a little confused about what the question is asking. Is this referring to the code below and saving it to its own file?
const allNames = ['McNulty', 'Jennings', 'Snyder',
'Meltzer', 'Bilas', 'Lichterman']
const ListElement = (props) =>
(<li id={props.name}><em>{props.name}</em></li>)
ReactDOM.render(
<ul>{allNames.map((name) => <ListElement name={name} /> )}</ul>,
document.getElementById('app')
)
And then, are we loading this new script and app.js within this code below:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello Separate</title>
<script src="https://fb.me/react-15.0.1.js"></script>
<script src="https://fb.me/react-dom-15.0.1.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.js"></script>
<script src="listElement.js"></script>
<script src="app.js"></script>
</head>
<body>
<h1>Hello Separate</h1>
<div id="app"></div>
</body>
</html>
Doing this results in a small error Uncaught SyntaxError: Unexpected token <
so I think rather than guessing, clarifying what code chunks we should be playing with would help guide the exercise a bit!
then the error message won’t appear because the call to fetch doesn’t raise an exception right away
What is meant here by exception? Does "right away" mean try/catch is time limited? I ran the code and it's clear it doesn't work, but I don't understand why.
report something sensible if we mis-type a year as 2108
Changing to this typo actually does give a result. I rewrote the query as https://api.nasa.gov/neo/rest/v1/feed?api_key=DEMO_KEY&start_date=0-08-20
in order to get the error catch, though
The callback function inside forEach creates an array containing the child nodes of the main list element, then filters that list to remove any top-level text nodes.
I'm unclear on what is meant by top level text nodes? Would that be like filtering out the nodeToRemove and sorting based on One, Two, Three?
const data = ['this', 'is', 'a', 'test']
const concatFirst = (accumulator, nextValue) => {
return accumulator + nextValue[0]
}
let acronym = data.reduce(concatFirst, '')
console.log(`acronym of ${data} is ${acronym}`)
I understand the concatFirst function but I'm tripping up on data.reduce (and the values it's taking) - why can't we just print the result of concatFirst?
When I run:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello Separate</title>
<script src="https://fb.me/react-15.0.1.js"></script>
<script src="https://fb.me/react-dom-15.0.1.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.js"></script>
<script src="app.js"></script>
</head>
<body>
<h1>Hello Separate</h1>
<div id="app"></div>
</body>
</html>
Along with:
ReactDOM.render(
<p>Rendered by React</p>,
document.getElementById("app")
)
I'm not getting the error:Error: _registerComponent(...): Target container is not a DOM element.
, as the texts suggests. I'm getting the error Uncaught SyntaxError: Unexpected token <
and I can't seem to locate the <
causing me issues! It looks like it stems from <p>Rendered by React</p>,
within app.js (and I think this same issue is what's causing me problems with exercise 3...)
Here, we are turning each link into an object whose "node" key has the link’s DOM node as its value, and whose "text" key has the node’s text, split on commas and with leading and trailing whitespace trimmed off. But we’re not done looking at this stage of our pipeline:
I'm having some trouble picturing this node, can we get some toy example of what this looks like? I think seeing what we're performing the split and trim on would be useful
Removing Text Nodes
In the example that sorts the items in lists, we remove all the text nodes from the list of child nodes before sorting. Why? What happens if remove the line:
.filter(c => c.nodeName !== '#text')
The code still ran when I removed this line and there were no errors in the dev console...
We can do this with synchronous operations
I used Data Wrangling in JavaScript to learn what this means (as well as asynchronous) and seeing some schematics of the two made understanding callbacks SO much clearer and less esoteric. I think introducing those two terms in the chapter on callbacks might be useful rather than seeing it for the first time here? I'd also recommend including them in the glossary
I don't understand what this question is asking. It first refers to using the clip code discussed under modules but then there is a code chunk included about key value pairs and I'm not sure how to tie the two together
Explain what is happening in the assignment statement in this program.
Use this technique to rewrite src/basics/import.js
so that clip
can be called directly as clip(...)
rather than utilities.clip(...)
.
const creature = {
genus: 'Callithrix',
species: 'Jacchus'
}
const {genus, species} = creature
console.log(`genus is ${genus}`)
console.log(`species is ${species}`)
typeof is an operator *not* a function
I had to google the difference to make sure I was certain on the distinction between operator and function. Perhaps this can be followed by an example [i.e. multiplication operator = AB, multiplication function f(A,B) = AB? ]
We’re going to want the nodes those strings came out of later on as well
Why?
A More Robust Table of Contents
Modify the table of contents example so that if an h2 heading doesn’t have an id, it is still included in the table of contents.
I added <h2>Test</h2>
to the HTML and this worked without error, despite not having an id?
I tried replacing the console.log line as advised in the text and running the code below:
const counter = () => {
const paragraphs = document.querySelectorAll('p')
return paragraphs.length
}
const fill = document.getElementById('fill')
fill.innerHTML = `number of paragraphs: ${counter()}`
But got the following error:
Uncaught TypeError: Cannot set property 'innerHTML' of null
Full code below:
<html>
<head>
<meta charset="utf-8"/>
</head>
<body>
<h1>Title</h1>
<div class="fill"></div>
<h2 id="one">First <em>emphasized</em></h2>
<p>stuff</p>
<h2 id="two">Second <code>with code</code></h2>
<h3>stuff</h3>
<h2 id="three">Third</h2>
<p>stuff</p>
<script>
const counter = () => {
const paragraphs = document.querySelectorAll('p')
return paragraphs.length
}
const fill = document.getElementById('fill')
fill.innerHTML = `number of paragraphs: ${counter()}`
</script>
</body>
</html>
const impure = (values) => {
for (let i in values) {
values[i] += 1
}
}
and would politely, even patiently, suggest that it be rewritten like this:
const pure = (values) -> {
result = []
for (let v of values) {
result.push(v + 1)
}
return result
}
What exactly is the difference here?
I tried running the chunks to dissect them but even when I created fake data to run the impure function I ran the first chunk along with
const data = [4, 5, 7]
console.log(impure(data))
And got the result undefined
The second chunk resulted in an error:
(function (exports, require, module, __filename, __dirname) { const pure = (values) -> {
SyntaxError: Unexpected token >
at new Script (vm.js:80:7)
at createScript (vm.js:274:10)
at Object.runInThisContext (vm.js:326:10)
at Module._compile (internal/modules/cjs/loader.js:664:28)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)
at Module.load (internal/modules/cjs/loader.js:600:32)
at tryModuleLoad (internal/modules/cjs/loader.js:539:12)
at Function.Module._load (internal/modules/cjs/loader.js:531:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:754:12)
at startup (internal/bootstrap/node.js:283:19)
I changed const pure = (values) -> {
to const pure = (values) => {
and the code ran. When I added the same two lines of code (replacing impure with pure) I did get the predicted output. [ 5, 6, 8 ]
Are the values within data
being changed in the first chunk and in the second the new values are being saved to a separate array rather than overriding old values? I came to this conclusion from a combination of the text and running the code below but even with this exploration I'm still skeptical if I've come to the correct conclusion
data = [4, 5, 7]
const impure = (values) => {
for (let i in values) {
values[i] += 1
}
}
impure(data)
const pure = (values) => {
result = []
for (let v of values) {
result.push(v + 1)
}
return result
}
console.log(pure(data))
[ 6, 7, 9 ]
const pipeline = (initial, operations) => {
let current = initial
for (let op of operations) {
current = op(current)
}
return current
}
I don't think we've been introduced to something like the line let current = initial
(are we using let instead of const because we want to assign it at the local level rather than globally?)
The for loop I'm familiar with from chapter 2 so I have a vague notion of what it's doing here but if someone asked to me to describe what each line of code is doing I don't think I'd be able to answer them succinctly. Probably wouldn't hurt to revisit explicitly what is happening line-by-line so I'm more confident before moving on.
After giving the example of a nested array ending on line 186, I spent some time again translating this code block into english. I think before jumping into what the function shows us (that arrays can be heterogenous) the reader can immensely benefit from a sentence or two on what the inner and outer loops are doing. I created a short description using Mike Myer's "A Smarter Way to Code JavaScript" but this is still pretty wordy and confusing:
The inner loop runs a complete cycle of iterations on each iteration of the outer loop. Since the outer loop counter is pair
and the inner is element
, element will loop through all the values until you've reached the end within pair[0] (0,1). Once you've reached the end of pair, pair will increment to 1 and element will loop through pair[1] values.
class Person {
constructor (name) {
this.name = name
}
greeting (formal) {
if (formal) {
return `Hello, my name is ${this.name}`
} else {
return `Hi, I'm ${this.name}`
}
}
farewell () {
return `Goodbye`
}
}
I got a little overwhelmed by the child chunk below this one so I revised this code and played around trying to print the greeting for longer than I'd like to admit, only to continue reading and see a section entitled Let's Try it Out! which does exactly that.
I suggest reorganizing: placing the first part of the code chunk (below) after the parent and the second after the child.
const parent = new Person('Hakim')
console.log(`parent: ${parent.greeting(true)} - ${parent.farewell()}`)
There's a comment here on how to access developer tools using Firefox- maybe add a quick note how it's View > Developer > Javascript Console
if using Chrome? Took me some poking around...
I followed the instructions npm install parcel-bundler
in my current working directory, then ran:
node_modules/.bin/parcel serve -p 4000 src/dynamic/pass-params.html
I adapted the src/dynamic/pass-params.html
to my pathway (maybe this should be explicitly stated to do so?) and this ran but I've been poking around (unsuccessfully) looking for node_modules folder. Should I have installed parcel-bundler within it's own project rather than my current working directory? I know it exists because it worked...
I think because I don't know where I am I'm also very confused where this would go:
"scripts": {
"dev": "parcel serve -p 4000",
...
}
I think this section can be restructured a bit as this is my first time initiating a project! I was able to serve the webpage, but I'd greatly benefit from spelling out step by step how to create a project and what to name our files in this section so I can follow along and see where node_modules/.bin
, ./dist
, package.json
and the other mentioned directories and files are located.
Rather than printing multiple strings and expressions
you might consider adding what this looks like in brackets [string1 + string2] before describing the alternative
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.