801 Matching Annotations
  1. Nov 2020
    1. Microbundle also outputs a modern bundle specially designed to work in all modern browsers. This bundle preserves most modern JS features when compiling your code, but ensures the result runs in 90% of web browsers without needing to be transpiled. Specifically, it uses preset-modules to target the set of browsers that support <script type="module"> - that allows syntax like async/await, tagged templates, arrow functions, destructured and rest parameters, etc. The result is generally smaller and faster to execute than the esm bundle
    1. The rule is written @forward "<url>". It loads the module at the given URL just like @use, but it makes the public members of the loaded module available to users of your module as though they were defined directly in your module. Those members aren’t available in your module, though—if you want that, you’ll need to write a @use rule as well.

      Just like how you have to also import (@use) a JS module if you want to use it locally, even if you export (@forward) it.

  2. Oct 2020
    1. Another example:

      const expensiveOperation = async (value) => {
        // return Promise.resolve(value)
          // console.log('value:', value)
          await sleep(1000)
          console.log('expensiveOperation: value:', value, 'finished')
          return value
      }
      
      var expensiveOperationDebounce = debounce(expensiveOperation, 100);
      
      // for (let num of [1, 2]) {
      //   expensiveOperationDebounce(num).then(value => {
      //     console.log(value)
      //   })
      // }
      (async () => { await sleep(0   ); console.log(await expensiveOperationDebounce(1)) })();
      (async () => { await sleep(200 ); console.log(await expensiveOperationDebounce(2)) })();
      (async () => { await sleep(1300); console.log(await expensiveOperationDebounce(3)) })();
      // setTimeout(async () => {
      //   console.log(await expensiveOperationDebounce(3))
      // }, 1300)
      

      Outputs: 1, 2, 3

      Why, if I change it to:

      (async () => { await sleep(0   ); console.log(await expensiveOperationDebounce(1)) })();
      (async () => { await sleep(200 ); console.log(await expensiveOperationDebounce(2)) })();
      (async () => { await sleep(1100); console.log(await expensiveOperationDebounce(3)) })();
      

      Does it only output 2, 3?

    1. In contrast, an object's actual prototype (obtained with Object.getPrototypeOf) is the real and only definition of an object's nature -- even in the possible case that its prototype has been changed after creation (either though the spec compliant Object.setPrototypeOf or by changing the commonly implemented __proto__ property).
    1. If the react cargo cult didn't have the JSX cowpath paved for them and acclimated to describing their app interface with vanilla javascript, they'd cargo cult around that. It's really about the path of least resistance and familiarity.
    2. hyperscript is much simpler to refactor and DRY up your code than with JSX, because, being vanilla javascript, its easier to work with variable assignment, loops and conditionals.
    1. However, this would lead to further divergence. Tooling that is built around the assumptions imposed by template literals wouldn't work. It would undermine the meaning of template literals. It would be necessary to define how JSX behaves within the rest of the ECMAScript grammar within the template literal anyway.
    1. This is valid javascript! Or harmony or es6 or whatever, but importantly, it's not happening outside the js environment. This also allows us to use our standard tooling: the traceur compiler knows how to turn jsx`<div>Hello</div>`; into the equivalent browser compatible es3, and hence we can use anything the traceur compile accepts!
    1. perhaps, imo this would make more sense. but it would slow down Parcel significantly as packages who don't have a browserslist or something similar will all get compiled (and most packages actually do target commonjs, which makes this prob not such a good idea). Which unfortunately is way too many packages. It would be great if tools like babel actually enforced a similar pattern to Parcel and use browserlist file or package.json instead of allowing defining target env in babel. Or at least not encourage it.
  3. Sep 2020
    1. // LoginApi.js return loginDao.login(username, password).then(function (res) { store.dispatch(loginSuccess()); log.log("[loginApi.login] END"); return true; }, function (err) { store.dispatch(loginFail()); errorUtils.dispatchErrorWithTimeout(errorLogin); log.log(err); return false; }); // never supposed to reject
  4. Aug 2020
    1. find every email on a web page that you're on. The big kahuna - this works for every website. Inject it into a site with Chrome DevTools (more here)

      Use this code below to find every e-mail on a webpage:

      var elems = document.body.getElementsByTagName("*");
      var re = new RegExp("(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)");
      for (var i = 0; i < elems.length; i++) {
          if (re.test(elems[i].innerHTML)) {
              console.log(elems[i].innerHTML);
          }
      }
      
  5. Jul 2020
  6. Jun 2020
    1. What would be nice is if JavaScript had a built-in way to do what I can do in Ruby with:

      > I18n.interpolate('Hi, %{name}', name: 'Fred')
      => "Hi, Fred"
      

      But to be fair, I18n comes from i18n library, so JS could just as easily (and I'm sure does) have a library that does the same thing.

      Update: Actually, you can do this in plain Ruby (so why do we even need I18n.interpolate?):

      main > "Hi, %{name}" % {name: 'Fred'}
      => "Hi, Fred"
      
      main > ? String#%
      
      From: string.c (C Method):
      Owner: String
      Visibility: public
      Signature: %(arg1)
      Number of lines: 9
      
      Format---Uses str as a format specification, and returns the result
      of applying it to arg. If the format specification contains more than
      one substitution, then arg must be an Array or Hash
      containing the values to be substituted. See Kernel::sprintf for
      details of the format string.
      
         "%05d" % 123                              #=> "00123"
         "%-5s: %016x" % [ "ID", self.object_id ]  #=> "ID   : 00002b054ec93168"
         "foo = %{foo}" % { :foo => 'bar' }        #=> "foo = bar"
      

      I guess that built-in version is fine for simple cases. You only need to use I18n.translate if you need its more advanced features like I18n.config.missing_interpolation_argument_handler.

  7. May 2020
  8. developer.mozilla.org developer.mozilla.org
    1. Mozilla does not permit extensions distributed through https://addons.mozilla.org/ to load external scripts. Mozilla does allow extensions to be externally distributed, but https://addons.mozilla.org/ is how most people discover extensions. The are still concerns: Google and Microsoft do not grant permission for others to distribute their "widget" scripts. Google's and Microsoft's "widget" scripts are minified. This prevents Mozilla's reviewers from being able to easily evaluate the code that is being distributed. Mozilla can reject an extension for this. Even if an extension author self-distributes, Mozilla can request the source code for the extension and halt its distribution for the same reason.

      Maybe not technically a catch-22/chicken-and-egg problem, but what is a better name for this logical/dependency problem?

    1. Now, a couple of years later, my guidelines for JS are:

      Advices on using JavaScript from a long time programmer:

      1. Use TypeScript instead.
      2. Push as much logic to the server as possible
      3. Use a framework like Vue or React if you need front interactivity
      4. Don't skip unit tests
  9. Apr 2020
    1. In Python, when trying to do a dubious operation, you get an error pretty soon. In JavaScript… an undefined can fly through a few layers of abstraction, causing an error in a seemingly unrelated piece of code.

      Undefined nature of JavaScript can hide an error for a long time. For example,

      function add(a,b) { return + (a + b) }
      add(2,2)
      add('2', 2)
      

      will result in a number, but is it the same one?

    1. The “universal” label that has been slapped on to it is superfluous, but it does have its merits. Now that we have a commonly known term to refer to environment agnostic JavaScript code, it allows library authors to list it as a feature and be fashionable doing it. I’m happy with the term “universal” being fashionable because it makes developers think about their dependencies on the runtime environment. In the end this will help the JavaScript ecosystem mature and allow libraries to be used everywhere.
    2. Running the same code in the browser and on the server in order to avoid code duplication is a very different problem. It is simply a matter of good development practices to avoid code duplication. This however is not limited to isomorphic applications. A utility library such as Lodash is “universal”, but has nothing to do with isomorphism. Sharing code between environments does not give you an isomorphic application. What we’re referring to with Universal JavaScript is simply the fact that it is JavaScript code which is environment agnostic. It can run anywhere. In fact most JavaScript code will run fine on any JavaScript platform.
    3. Isomorphism itself is not purely a JavaScript thing. You can also build an isomorphic application in Dart or even use two different languages/stacks to render the same result. In fact there are many “isomorphic” applications which render a full HTML document on the server using PHP, Java or Ruby and use JavaScript and AJAX to create a rich user experience in the browser. This was the way things were done before the rise of Single Page Applications. The only real reason isomorphism is tied to JavaScript is because it’s the only language widely supported in the browser, and so at least part of the whole thing will use JavaScript. There’s no such thing as Isomorphic JavaScript, only isomorphic applications.
    1. Let's reason through our memoizer before we write any code.

      Operations performed by a memoizer:

      • Takes a reference to a function as an input
      • Returns a function (so it can be used as it normally would be)
      • Creates a cache of some sort to hold the results of previous function calls
      • Any future time calling the function, returns a cached result if it exists
      • If the cached value doesn't exist, calls the function and store that result in the cache

      Which is written as:

      // Takes a reference to a function
      const memoize = func => {
        // Creates a cache of results
        const results = {};
        // Returns a function
        return (...args) => {
          // Create a key for results cache
          const argsKey = JSON.stringify(args);
          // Only execute func if no cached value
          if (!results[argsKey]) {
            // Store function call result in cache
            results[argsKey] = func(...args);
          }
          // Return cached value
          return results[argsKey];
        };
      };
      
    2. The biggest problem with JSON.stringify is that it doesn't serialize certain inputs, like functions and Symbols (and anything you wouldn't find in JSON).

      Problem with JSON.stringify.

      This is why the previous code shouldn't be used in production

    1. What is a Function Expression?A JavaScript function can also be defined using an expression.A function expression can be stored in a variable:var x = function (a, b) {return a * b};After a function expression has been stored in a variable, the variable can be used as a function. Functions stored in variables do not need function names. They are always invoked (called) using the variable name.

      Test question: What is function expression?

  10. javascript.info javascript.info
  11. developer.mozilla.org developer.mozilla.org
    1. 对象属性的命名规则 通过[]操作符为对象添加属性时,属性名称可以是任何字符串(包括只包含空格的字符串和空字符串); 通过.操作符为对象添加属性时,属性名称必须是合法的标识符名称; 如果属性名包含非法的标识符字符,则只能采用obj[“propertyName”]的形式; 如果属性名是合法的标识符,读取时即可以采用obj.propertyName,也可以采用obj[“propertyName”]的形式;

      除此之外,根据下面的介绍,也可以用数字和布尔值作为属性名,但会自动转换为字符串。

    1. We really only need to test that the button gets rendered at all (we don’t care about what the label says — it may say different things in different languages, depending on user locale settings). We do want to make sure that the correct number of clicks gets displayed

      An example of how to think about tests. Also asserting against text that's variable isn't very useful.

    2. It’s still a good idea to keep your code in three different buckets, and keep these buckets isolated from each other:Display/UI ComponentsProgram logic/business rules — the stuff that deals with the problem you’re solving for the user.Side effects (I/O, network, disk, etc.)

      How do I organize my code like this? What's the directory structure look like.

    1. Any JavaScript style guide that is up-to-date for ES6 is going to cover nearly all TypeScript constructs except for type annotations, so I would start with your favorite JS style and decide on what you want the rules for type annotations to be

      可惜这个问题被关了。因此显得有点老。不过他的建议也不错。使用用JS的风格。

  12. Mar 2020
    1. How do you leverage browser cache when Google’s very own Analytics.js has it’s expiry time set to 2 hours? How do you minimize DNS requests when Google advices you to copy their tracking code, linking to an externally hosted Javascript file?If that isn’t bad enough already, Google’s advice is to avoid hosting the JavaScript file locally. And why? To ensure you get access to new features and product updates.
    2. Why should I host analytics.js locally?The Complete Analytics Optimization Suite for WordPress gives you the best of both worlds. After activation it automagically downloads the latest version of analytics.js from Google’s servers, places the necessary tracking code in your WordPress theme’s header and keeps the local Javascript file up-to-date using an adjusted version of Matthew Horne’s update analytics script and wp_cron(). This way you can minimize DNS requests, leverage browser cache, track your visitors and still follow Google’s recommendation to use the latest features and product updates.
    1. Javascript, APIs and Markup — this stack is all about finding middleground from the chaos of SSR+SPA. It is about stepping back and asking yourself, what parts of my page change and what parts don’t change?

      JavaScript, APIs and Markup (JAM Stack) - middleground between SSR + SPA.

      Advantages:

      • The parts that don’t change often are pre-rendered on the server and saved to static HTML files. Anything else is implemented in JS and run on the client using API calls.
      • Avoids too much data transfer (like the hydration data for SSR), therefore finds a good tradeoff to ship web content
      • Allows to leverage the power and cost of Content delivery networks (CDNs) to effectively serve your content
      • With serverless apps your APIs will never need a server to SSH into and manage
    1. TL;DR;

      Don't use:

      • No global vars.
      • Declare variables using "var".
      • Declare functions using "function" keyword.
      • Avoid use "for" in loops.
      • Array push, inmutability.
      • Class.
      • Use delete to remove a object atribute.
      • Avoid nested if.
      • else if.
      • Heavy nesting.
      • Avoid to add prototype to functions that could be used in a module.

      Use:

      • Common code in functions, follow D.R.Y principle.
      • Shorcut notation.
      • Spread operator over Object.assign (airbnb 3.8).
      • Pascal case naming.
      • Modularize your code in modules.
      • const and let!.
      • Literal syntax for object creation (airbnb 3.1).
      • Computed property names when creating objects (airbnb 3.2).
      • Property value shorthand (airbnb 3.4).
      • Group your shorthand properties at the beginning of your objec (airbnb 3.5).
      • use the literal syntax for array creation (airnbnb 4.1).
      • Use array spreads ... to copy arrays. (airbnb 4.3).
      • use spreads ... instead of, Array.from. (airbnb 4.4).
      • Use return statements in array method callbacks (airbnb 4.7).
    2. Don’t use iterators, prefer js higher-order functions instead of for / for..in
      // bad
      const increasedByOne = [];
      for (let i = 0; i < numbers.length; i++) {
        increasedByOne.push(numbers[i] + 1);
      }
      
      // good
      const increasedByOne = [];
      numbers.forEach((num) => {
        increasedByOne.push(num + 1);
      });
      
    3. Ternaries should not be nested and generally be single line expressions.

      e.g.

      const foo = maybe1 > maybe2 ? 'bar' : maybeNull;
      

      Also:

      // bad
      const foo = a ? a : b;
      const bar = c ? true : false;
      const baz = c ? false : true;
      
      // good
      const foo = a || b;
      const bar = !!c;
      const baz = !c;
      
    4. Use JSDOC https://jsdoc.app/about-getting-started.html format.

      Standardise your JavaScript comments:

      1. Use block comment
        /** This is a description of the foo function. */
        function foo() {
        }
        
      2. Use JSDOC tag to describe a function: ```javascript /**
      • Represents a book.
      • @constructor
      • @param {string} title - The title of the book.
      • @param {string} author - The author of the book. */ function Book(title, author) { } ```
    5. When JavaScript encounters a line break without a semicolon, it uses a set of rules called Automatic Semicolon Insertion to determine whether or not it should regard that line break as the end of a statement, and (as the name implies) place a semicolon into your code before the line break if it thinks so. ASI contains a few eccentric behaviors, though, and your code will break if JavaScript misinterprets your line break.

      Better place a semicolon (;) in the right place and do not rely on the Automatic Semicolon Insertion

      e.g.

      const luke = {};
      const leia = {};
      [luke, leia].forEach((jedi) => {
        jedi.father = 'vader';
      });
      

      ```