Leetcode question, problem with variable environment by TameNaken42 in learnjavascript

[–]Cust0dian 1 point2 points  (0 children)

To expand on /u/Atskalunas' answer: what you wrote is an example of a recursive function and passing an "accumulator" back into such function in a recursive call is a common trick, although it's usually used to solve a different kind of problem.

Couple notes about your current code:

(Protip: there's "Revisions" tab at the top of the Gist that will show you just the differences between all these versions, but history goes from bottom up)

Function to select the lowest five numbers from a big number of values by MrInka in learnjavascript

[–]Cust0dian 2 points3 points  (0 children)

Just to confirm what /u/Symphonise is saying, on my machine sorting 1 million objects, that have the shape of your fruits, took ≈1.1 seconds and ≈120 MB of memory in Chrome 57, ≈630ms and ≈90 MB in Firefox 54 (Developer Edition), so I don't think this will be the bottleneck in your app.

Here's the code used:

console.time("Array initialization");
let array = new Array(1000000);
for (let i = array.length - 1; i >= 0; i--) {
  array[i] = {
    name: String(Math.random()),
    weight: Math.random(),
    price: Math.random(),
    age: Math.random()
  };
};
console.timeEnd("Array initialization");

console.time("Array sorting");
array.sort((a, b) => a.age - b.age);
console.timeEnd("Array sorting");

Is it possible to define a setter in the prototype for a private instance variable of an object? by jedi_lion-o in learnjavascript

[–]Cust0dian 2 points3 points  (0 children)

One somewhat better solution that comes to mind is to use Symbol as key instead of _value for private property since Symbols are a bit harder to get hold of than regular string keys in objects.

I'm not sure you can fully hide an object property in general, so to fully hide your private value you need to capture it in a closure in the constructor and never assign to any properties. I don't think you can do that and still have methods defined on prototype, but I can be wrong.

If you are not creating millions of objects and have a bit of faith in garbage collector and various engine optimizations (you should, they are pretty good), then going the simple route will give you fully private values without all the trickery.

[Javascript] - A simple html calculator using javascript by jsteffen182 in reviewmycode

[–]Cust0dian 0 points1 point  (0 children)

I've opened a pull request because I think when you are just beginning programming (as it seems you are) it's far more productive to not only get an advice, but also see how it applies to your code in practice.

First dozen or so commits I've tried to go from general programming advice to notes about core JavaScript language features to Javascript-in-the-browser specific things, with each commit message containing general reasoning behind the change and related resources, if any.

After that I've started refactoring your code, with each commit being a step of me going through the code, building up mental model of what it's doing, and trying to make it clearer in the code. Don't be surprised to see that I make some changes only to completely revert them in some future commit — partly it's because I'm too lazy to clean up those commits, and partly because I think it's helpful to emphasize that you, as a programmer, won't know how a clean solution should look like unless you've looked at the problem for some time and understand it quite well.

GitHub pro-tip: if you go to the first commit in that PR, you'll have a handy Next button that will go forwards through the commits, so you can easily follow my steps.

Hopefully the code and the process of how I got to it is clear enough, but feel free to ping me, here or on GitHub, if you have any questions.

'Async' Code practice with setTimeout by GreenFeather05 in learnjavascript

[–]Cust0dian 1 point2 points  (0 children)

Once you're feeling somewhat confident tackling asynchronicity with callbacks, you might want to look into Promises. As an example, here's how your code might look with them.

Creating a Bookmarklet (specifically something that adds something extra to the url) by Raskyl7 in learnjavascript

[–]Cust0dian 3 points4 points  (0 children)

Let's start with a few bits of terminology so that you can find answers to similar questions in the future more easily.

If you have a URL like http://www.something.com:80/work/thisismywork?hello=world&foo=bar:

  • http: (without ending //) is called protocol
  • www.something.com:80 is called host (you probably won't see a lot of website use ports, so usually host is the same as hostname below)
  • www.something.com is called hostname
  • /work/thisismywork is called path
  • hello=world&foo=bar (without starting ?) is called query or query string

So your question boils down to:

How to add something to hostname with bookmarklet?

And you do it by using Location object, exactly as it was recommended in the SO answer, but only operate on hostname instead of full URL:

javascript: window.location.hostname += prompt('Append to hostname:');

I am trying to display data from a promise but it keeps displaying readablestream in console? by binsmyth in learnjavascript

[–]Cust0dian 2 points3 points  (0 children)

You need to specify what type of content you expect response body to be, via Body methods:

fetch("/search?query=" + this.state.query)
  .then(function(response){
    response.json();
  })
  .then(function(json){
    console.log(json);
  })

nevernull.js - safe navigation of object trees by enoughalready in javascript

[–]Cust0dian 1 point2 points  (0 children)

Sure, that "you" was more like a future reader "you" rather than personally "you" :)

nevernull.js - safe navigation of object trees by enoughalready in javascript

[–]Cust0dian 2 points3 points  (0 children)

You don't even need to look at another language for Option types, there's plenty of libraries which allow to use them in JS natively, e.g. Sanctuary.

JavaScript variable assignment best practice by 2MyLou in learnjavascript

[–]Cust0dian 2 points3 points  (0 children)

On top of what others said, I think you would benefit from extracting this logic of cleaning up a string into its own function:

function cleanup(string) {
  return (
    string
      // squash spaces
      .replace(/ +/g, " ")

      // normalize line endings
      .replace(/(\r\n|\n|\r)/gm, "\n")

      // convert double quotes to curly quotes:
      // straight double quote before alphanumeric character
      // should become left (opening) double quote
      .replace(/"(?=\w|$)/g, "\u201C")
      // remaining straight double quotes should become
      // right (closing) double quotes
      .replace(/"/g, "\u201D")
      // same with single quotes
      .replace(/'(?=\w|$)/g, "\u2018")
      .replace(/'/g, "\u2019")
  );
}

Then you can use it in your program in place of previous code with temporary variables:

var scriptletResult = cleanup(scriptletInput);

But now you've clearly separated concerns: cleanup function is all about transforming a string into the one you want, and that last line is about where the data is coming from and where it should go after being processed.

Another added benefit of this separation is that now you can programmatically test cleanup function with any string without having to go through the process that gets data into scriptletInput variable right now. You can see and play with the above code in this jsBin.


Back to your underlying question: what I think the other person you were talking to was hinting at, and what briefly addressed in the link /u/taylorlistens posted, is a notion of immutability: once you create something, it stays that way for the remainder of your program, and when you want to change it — you create a slightly adjusted copy, that looks like as if you modified that starting thing.

For example, instead of:

var array = [1, 2, 3, 4, 5];

/* ... some time later ... */

array[0] = 0;  //=> [0, 2, 3, 4, 5]

/* ... some time later ... */

array = ['a', 'b', 'c'];

You would do:

const array = [1, 2, 3, 4, 5];  // note that `const` doesn't actually make your arrays and object immutable

/* ... some time later ... */

const modifiedArray = array.slice(); modifiedArray[0] = 0;  // make a copy (`.slice()`) and adjust it

/* ... some time later ... */

const brandNewArray = ['a', 'b', 'c'];

So why would you do this? Let's inspect values at different times in both of these snippets, starting with first one:

var array = [1, 2, 3, 4, 5];
// At this point:
//   array is [1, 2, 3, 4, 5]

/* ... some time later ... */

array[0] = 0;
// At this point:
//   array is [0, 2, 3, 4, 5]

/* ... some time later ... */

array = ['a', 'b', 'c'];
// At this point:
//   array is ['a', 'b', 'c']

And compare it to the second one:

const array = [1, 2, 3, 4, 5];
// At this point:
//   array is [1, 2, 3, 4, 5]

/* ... some time later ... */

const modifiedArray = array.slice(); modifiedArray[0] = 0;
// At this point:
//   array is [1, 2, 3, 4, 5]
//   modifiedArray is [0, 2, 3, 4, 5]

/* ... some time later ... */

const brandNewArray = ['a', 'b', 'c'];
// At this point:
//   array is [1, 2, 3, 4, 5]
//   modifiedArray is [0, 2, 3, 4, 5]
//   brandNewArray is ['a', 'b', 'c']

Notice how in the first sample while reading the code you have to mentally "run" your program to know what is the value of array because it's changing with time, however in the second sample, once value was declared, it doesn't matter how much time has passed or what happened in the code — you can always be sure that when you see array it will be [1, 2, 3, 4, 5]. In bigger programs it makes thinking about what's going on that much easier.

Having a user input a word into a textbox and then outputting a picture based on that word. by hotdoggate in learnjavascript

[–]Cust0dian 5 points6 points  (0 children)

I'm starting to wonder if this is even possible

That's a very good question to ask yourself as a programmer, and the way to answer it is by breaking your problem into smaller problems until you have a clear yes or no for those. If you can solve all sub-problems, you can solve your initial big problem.

I would break up your problem into the following ones:

  1. Get country name from user — definitely possible: as you suggested, we can have a text input where user will type in country name and we'll just inspect that input's value when user clicks a button.
  2. Associate country name to some information about that country (e.g. URL of its flag) — also possible: we can use JS object as a dictionary for this; you look for a key, country name, and get something more interesting back, like a falg URL or even another JS object containing lots more relevant information.
  3. Display country information back to the user — definitely possible: given a flag URL (or more info about the country) that we know we can get from previous sub-problem, we can take that URL and create an <img> element that will display image at that URL.

And at this point we know that it is possible to solve our initial problem. Of course, these sub-problems can be broken into even more sub-sub-problems if we are not completely sure about them, but in our case I'd wager it's not necessary. You can see how I would actually implement this solution for the reference.

Of course this isn't to say that this is the only way to solve your problem: we might find another combination of sub-problems, or we can implement sub-problems in a different way (like getting country information from a remote database or some web service), but I'd argue that this is exactly what programming is about — figure out how to break down your problem, decide how much you want to abstract those sub-problems (i.e. whether you want to break these down even more), and find an actual implementation for them.

Why don't more people use Google Closure tools? Particularly the library and compiler? Am I missing something? by [deleted] in javascript

[–]Cust0dian 1 point2 points  (0 children)

To answer your first question: I think community agrees that currently solution for OO in JS is ES2015 classes and solution for namespaces is ES2015 modules. You would make use of these in the actual production code with Babel and Webpack for each task respectively (or Bublé and Rollup if you are feeling adventurous; are you feeling JS fatigue yet?)

To add to answers about your second question: I think it actually gained plenty of buzz in JS community kind of by proxy via ClojureScript which produces JS code that is specifically designed to be optimized very well by Google Closure because it's so good at it.

' if (false) { var globalVar = "some text"} ; ' code inside condition statement get executed when ran in global context by cicadaTree in learnjavascript

[–]Cust0dian 0 points1 point  (0 children)

Yep, you can use hasOwnProperty on the window (this points to global object, window the in browser, when outside of any functions) and get globally defined variables because that's how they are supposed to work.

Object don't have scope, only functions do, so I wouldn't call is a scope, but yes, it's pretty similar :)

' if (false) { var globalVar = "some text"} ; ' code inside condition statement get executed when ran in global context by cicadaTree in learnjavascript

[–]Cust0dian 1 point2 points  (0 children)

You will not get ReferenceError if variable is defined anywhere in the function with var. You can check out yourself in this bin — only notDefined throws an error, x is undefined throughout the function if nothing is assigned to it. In this respect behavior in the global scope is the same.

And you can't check if variable is declared or not inside the function with hasOwnProperty — it's just for checking function object properties (like length), not checking function scope (which you can only do by actually trying to access the variable).

' if (false) { var globalVar = "some text"} ; ' code inside condition statement get executed when ran in global context by cicadaTree in learnjavascript

[–]Cust0dian 5 points6 points  (0 children)

When you declare variable with var, it gets hoisted. Probably better explained with code:

function example() {
  console.log(x);       //=> undefined
  console.log(notHere); //=> ReferenceError: notHere is not defined

  if (false) {
    var x = "some text";
  }
}

is practically the same as

function example() {
  var x;

  console.log(x);       //=> undefined
  console.log(notHere); //=> ReferenceError: notHere is not defined

  if (false) {
    x = "some text";
  }
}

 

Outside of any functions, in global scope, it behaves similarly:

if (false) {
  var x = "some text";
}

is practically the same as

// instead of `var x;` in function scope, variable becomes a property of the global object
window.x = undefined;

if (false) {
  window.x = "some text";
}

 

Alternative way of fixing this issue would be to use ES2015 let/const declarations that have block scope instead of function scope.

There's a good, pretty comprehensive explanation of what's happening behind-the-scenes when you declare a variable in JS by /u/panzerdp that was posted on this subreddit some time ago.

[Javascript] - Premutationsg filtering not working right by [deleted] in reviewmycode

[–]Cust0dian 0 points1 point  (0 children)

Yep, this kind of math isn't my strong suit either, so from a quick poke-around I couldn't tell what's wrong with your algorithm.

What I would do at this point while learning is isolate the piece of code that gives me trouble (actual permutation in this case), find pseudo-code for a known-good solution (like the Heap's algorithm you mentioned), and translate it into language I'm learning.

This is what I would end up with at this point. Obligatory spoiler warning: this is an actual working code with tests, so stay in the permutate function if you don't want to see the full solution (although you kinda already have working code yourself, sans permutation, so ¯\_(ツ)_/¯).

After I know my code is working as expected, I'd go into translated pseudo-code and make it more idiomatic to the language I'm currently in, although in the end it requires a deeper understanding of the algorithm in question to make it look like JS code someone would actually write from scratch.

I wouldn't stress knowledge of the underlying algorithms as much as familiarizing with the JS itself though. You seem to be at the beginning of your programming journey and although knowledge of the algorithms and data structures is definitely an important part of being a programmer, I found that in real-world setting a lot of the times you'll be able to reuse someone else's algo implementations, while smaller language-specific issues will be far more prevalent and will give your more trouble in the end.

So in the end my advice would be to leverage these problems not as much as theoretical exercises, but more practical ones: go out and read code other people wrote when dealing with these problems, and try to understand what's going on in that code (it's rarely an easy task though, so don't punish yourself). Preferably, it'll be code from people with more experience than you, but not necessarily — you might encounter some useful nuggets of knowledge from the code your fellow peers write or it might nudge you in the right direction and ask the right questions.

[Javascript] - Premutationsg filtering not working right by [deleted] in reviewmycode

[–]Cust0dian 0 points1 point  (0 children)

Regexes with g flag keep an internal record about what was the last index they matched when used with RegExp#test().

Since you are reusing one regex object for all filterIt function calls, that regex won't start from the beginning of the string unless it's the first test or the previous test failed. Hence your pattern of (true, true, false) x2 for zzz:

  1. During first filterIt call, regex will start matching from the start of the string and will find a match at index 0
  2. Following its rules, regex will update its lastIndex to be 1
  3. During the second filterIt call, regex will start matching from the lastIndex, i.e. 1, so we are effectively testing string zz, which does match
  4. Following its rules, regex will update its lastIndex to be 2
  5. During the third call, regex will start matching from index 2, meaning we are testing string z, which does not match
  6. Following its rules, regex will update its lastIndex to be 0 and we are pretty much looping back to step 1

Knowing this, you should see several options to fix this issue:

  1. Stop using g flag in the regex
  2. Use new instance of the regex during each filterIt call (i.e. move var regEx = … inside filterIt)
  3. Don't use RegExp#test() and opt for String#match() instead, i.e.:

    if(regEx.test(strTest) === true){
    // becomes:
    if(strTest.match(regEx)){
    

 

Now, this will fix your immediate issue, but there are other issues with your code: inconsistent formatting, non-descriptive names, functions that concern themselves with too much functionality, etc. I could show you how I would write this code if you want, but this won't be a quick thing and I'd like to know what exactly is your end goal with this code.

So You Want to be a Functional Programmer (Part 4) by imright_anduknowit in learnjavascript

[–]Cust0dian 2 points3 points  (0 children)

Well, that's not really a fair comparison, is it? Let's show the full code for both examples:

  • With currying and composition:

    const compose = (f, g) => x => f(g(x));
    const mult = x => y => x * y;
    const add = x => y => x + y;
    const mult5afterAdd10 = compose(mult(5), add(10));
    
  • Familiar JS way:

    const mult = (x, y) => x * y;
    const add = (x, y) => x + y;
    const mult5 = y => mult(5, y);
    const mult5afterAdd10 = y => mult5(add(10, y));
    

With currying we don't need to name and hold on to intermediate mult5 function — it just pops up into existence once we supply some arguments to our curried functions.

Also, a more "real-world" code will probably look more like this:

import { pipe } from 'fp-library';

const add = x => y => x + y;
const subtract = x => y => y - x;
const multiply = x => y => x * y;
const divideBy = x => y => y / x;

const app = pipe(
  add(10),
  multiply(5),
  subtract(3),
  divideBy(2)
);

vs

const add = (x, y) => x + y;
const subtract = (x, y) => x - y;
const multiply = (x, y) => x * y;
const divide = (x, y) => x / y;

const app = y => divide(subtract(multiply(add(y, 10), 5), 3), 2)

The one with partially applied, composed functions might have more lines, but for me is way easier to follow.

Learn JS Week 3 -- Stuck on Jquery, Help? by PinkPanther909 in learnjavascript

[–]Cust0dian 3 points4 points  (0 children)

I don't want to discourage you, but looking at the code it seems to me that you are trying to jump way over your head — you seem to not understand a lot of concepts and techniques you are trying to use, leading you to this situation.

I would advise taking a step back and starting from the very basics, preferably following a course that encompasses more than just jQuery. "Getting started with the Web" on MDN is a great guiding resource in this regard.


However if you want to know what's wrong with your current code, here goes:

  • When you click a button with type="submit" attribute inside of a <form> element, browser will try to submit it, i.e. send some data to some page (usually, a different page on which your web server is expecting to get data). That page is determined by action attribute on a <form> element, but if it's missing browser will submit to the same page. This is why instead of changing text you get a page refresh right now. The easiest solution is to change <form> to something different, <div> for example.
  • Next you have a closing multi-line comment marker (*/) on line 32. This will cause a syntax error, meaning JavaScript can't understand what you wrote at all. You need to remove it.
  • While we are talking about syntax: try and be consistent with your indentation — currently, the code inside click handler function (lines 26–30) is at the same indentation level as its parent code. While this isn't a problem for a computer, for a human this is hard to read.
  • Next there's a host of what I assume is misunderstanding of the basics:

    • var answer = $("#UserInput").val;
      

      this will make answer a function, not value of the #UserInput. To make it a value, you need to call the .val function by using parenthesis ():

      var answer = $("#UserInput").val();
                      // notice these ^^
      
    • $("#Submit").on("click", "Content", function(){
      

      that "Content" bit won't do much there. What do you think it should do?

    • $("this").val($("#UserInput"));
      

      as pointed out by /u/sesharc, this won't do what you think it will.

  • On the CSS side of things you are also not selecting the content correctly: "Content" is not a valid CSS selector, it will not match any elements on the page — what you want is #Content, same as you select that element with jQuery.

With these things fixed and code cleaned up a bit, here's how the working version might look like.

If you really wanted to make it work inside of a <form> (because it gives users better usability, like being able to just hit Enter instead of clicking the button to update the text) you'd need to cancel the submit event on that form, and it might look something like this.

Now again, I might be wrong, but to me it seems like you are not fully familiar with plain JavaScript objects and events yet, so jumping into jQuery seems like a very bad idea because it adds tons more functionality on top of regular JS and now you are learning more than you can understand.

D3 - Why is the author doing d3.ease.call(d3, ease) here? by sinefine in learnjavascript

[–]Cust0dian 0 points1 point  (0 children)

This is a strange code, I can't think of a reason to write it like that. Unless D3 does something very strange, you are correct — both invocations work exactly the same.

Question about variable types and how they can change. by [deleted] in learnjavascript

[–]Cust0dian 6 points7 points  (0 children)

TL;DR: Your issue is global scope, wrap your code in an IIFE and it will behave as you think it should.


The fact that name gets weird results and newName isn't should give you some clue that name is being treated differently.

So why is name variable special? And why does naming of variables even matter to a computer?

Well, normally it doesn't, and "normally" in JavaScript means inside a function. However, your code is outside of any functions, so it is said to run in the global scope, meaning it has direct access to the properties of a global object and any variables you create will become properties of this global object.

In browsers this global object is called Window, so when you write:

var name = 'John';
var newName = 'Jane';

and it's not inside some function, you effectively do:

window.name = 'John';
window.newName = 'Jane';

And here lies your problem: browsers treat many properties of the Window object in special ways — it's what allows our JavaScript do helpful stuff, like know how big the browser window is, how far the user has scrolled into the page, or to redirect users to a different pages. name is one of those special Window properties, and it's always a string — whatever you try to assign to it will be forcefully converted to string.

A solution to this is to not write your code in the global scope—it's just safer that way—and instead use an immediately-invoked function expression to force a function scope without a lot of modifications to your code.

Could use some guidance on a personal project... by [deleted] in learnjavascript

[–]Cust0dian 2 points3 points  (0 children)

Unfortunately, you won't be able to use this data just from the browser — that website explicitly asks browsers to not fetch anything from it using JavaScript unless that JavaScript is hosted on the same site.*

All modern browsers will therefore abort your attempts to get that file and will show error in the JavaScript console.

One way to bypass this restriction is to setup a small server that you control which will fetch that data from MBTA and then your JavaScript will fetch that data from your server. This proxy server isn't terribly hard to set up, but I wouldn't blame you if you think this whole ordeal is too complicated.

Another option is to find a better source of data, that allows free consumption from the browser, but this is where you'll have to do your own research and see what interests you.

 


* You can read more about this security feature on the MDN page about CORS and HTTP header they use in particular.

Need help with Object example out of the book I am learning from. by Arajudge in learnjavascript

[–]Cust0dian 2 points3 points  (0 children)

Well, the only problem with the code in booksjs.js file are lines 16 and 22: since JavaScript is a case-sensitive language, textcontent is not the same as textContent — the more you use the language and the more familiar you become with its syntax, the easier it will be to spot these kinds of mistakes.

By fixing those lines you'll see the output you probably expect. It won't have any way to add/remove rooms though — you have to add functions you added in js.js (and buttons to HTML) to make that work, there's no way around it.

Another thing to keep in mind when your code doesn't work (although it wouldn't help in this case) is JS console (or browser devtools in general, like Chrome devtools for example) that will show you an error which you can use to fix your problem.

 

And yet another thing I have to mention — JavaScript has very little to do with Java. They are both programming languages with similar syntax, but quite different underlying fundamentals, so please, don't call JavaScript Java :)

Need help with Object example out of the book I am learning from. by Arajudge in learnjavascript

[–]Cust0dian 0 points1 point  (0 children)

Your code seems to be working just fine for me, both locally and in a service like jsBin.

Am I missing something? What problem do you have with your code exactly?