Improve js knowledge by reading source code

Improve Your JavaScript Knowledge By Reading Source Code

Originally written by Carl Mungazi, front-end developer at London-based energy startup Limejump. He took the time to dig deep into all the JavaScript.

Summary: When you’re in the early stages of your programming career, delving into the source code of open source libraries and frameworks can be a daunting task. In this article, Carl Mungazi shares how he overcame his fear and started using source code to improve his knowledge and skills. He also uses Redux to demonstrate how he destroys the library.

Do you remember the first time you dug deep into the source code of a library or framework you used a lot? For me, that moment was my first job as a front-end developer three years ago.

We have just completed a rewrite of the internal legacy framework for creating e-learning courses. At the beginning of the rewrite, we spent time researching a number of different solutions, including Mithril, Inferno, Angular, React, Aurelia, Vue and Polymer. Because I was a very beginner (I had just switched from journalism to Web development), I remember feeling intimidated by the complexity of each framework, rather than understanding how each framework worked.

As I began to delve more deeply into Mithril, the framework we chose, my understanding grew. Since then, my knowledge of JavaScript — and programming in general — has been greatly helped, and I’ve spent a lot of time delving into the contents of the libraries I use every day at work or on my own projects. In this article, I’ll share some ways you can take your favorite library or framework and use it as an educational tool.

The following is an introduction to the code I first read through Mithril’s HyperScript functions

The benefits of reading source code

One of the main benefits of reading source code is that it increases the amount of knowledge you can learn. When I first saw Mithril’s code base, I had a vague idea of what the virtual DOM meant. When I finished, I learned that the virtual DOM is a technique that involves creating a tree of objects that describes what the user interface should look like. The tree is then converted to the DOM element document.createElement using the DOM API. Updates are performed by creating a new tree that describes the future state of the user interface and then comparing it to objects in the old tree.

I’ve read this stuff in various articles and tutorials, and it’s been very helpful to me, and it’s been very enlightening to see it in action in the applications we’ve released. It also tells me what questions to ask when comparing different frameworks. For example, I now ask questions such as “How does the way each framework performs updates affect performance and user experience?” “Rather than focusing on Stars on GitHub.

Another benefit is to increase your appreciation and understanding of good application architecture. While most open source projects generally follow the same structure as their repositories, each project is different. Mithril’s structure is very flat, and if you’re familiar with its API, you can guess about folders like code Render, Router, and Request. React’s structure, on the other hand, reflects its new architecture. Maintainers separate modules responsible for UI updates (react-Reconciler) from those responsible for rendering DOM elements (React-DOM).

One of the benefits of this is that developers can now write their own custom renderers for the React-Reconciler through hooks. The module bundle Parcel I recently looked at also has folders like React Packages. The key module, named parcel- Bundler, contains the code responsible for creating bundles, starting hot module servers, and command-line tools.

Soon, the source code you’re reading will lead you into the JavaScript specification.

Another benefit — much to my surprise — is that you can more easily read the official specifications that define how JavaScript as a language works. The first time I read the specification was when I investigated the difference between throw Error and Throw New Error (the spoiler alert is None). I looked into this because I noticed that Mithril uses throw Error to implement its M functionality, and I wondered if it would be better to use it than throw New Error. From then on, I also learned that logical operators && and | | not necessarily return Boolean values, find out how the = = operation is mandatory rules of the conversion value, and the Object. The prototype. ToString. Call ({}) returns’ [Object Object] ‘reason.

Tips for reading source code

There are many ways to work with source code. I’ve found the easiest way to do this is to select a method from a library of your choice and document what happens when you call it. Instead of documenting each step, try to identify the overall flow and structure.

I recently logged reactdom.render this way and learned a lot about React Fiber and the reasons behind its implementation. Thankfully, because React is a popular framework, I came across many articles written by other developers on the same issue, which saved me a lot of detour.

The in-depth discussion also introduces the concept of cooperative scheduling to me, the window. The requestIdleCallback method and the list of links real example (React by update to deal with them in the queue, queue is a list of links to update priority). When doing this, it is recommended to create a very basic application using the library. This makes debugging easier because you don’t have to deal with stack traces caused by other libraries.

If I didn’t go further, I would either open /node_modules to the folder in the project I was working on, or I would go to the GitHub repository. This usually happens when I encounter bugs or interesting features. When reading code on GitHub, make sure the code you’re reading is up to date. You can see the code in a submission with the latest version tag by clicking on the button for changing the branch and selecting Tags. Because the code base and framework are constantly being updated iteratively, you certainly don’t want to learn about things that might be removed in the next release, so keep an eye out for the latest release.

Another, more complicated way to read source code is what I like to call a “cursory glance.” Early on when I started reading the code, I installed express.js, opened its /node_modules folder and installed its dependencies. If the README file doesn’t make sense to me, I’ll just read the source code. Doing so led me to the following interesting discovery:

  • Express relies on two modules that merge objects but do so in very different ways.merge-descriptorsIt only adds attributes found directly on the source object, it also incorporates non-enumerable attributes, andutils-mergeIterate only over the enumerable properties of an object and those found in its stereotype chain.merge-descriptorsuseObject.getOwnPropertyNames()andObject.getOwnPropertyDescriptor()At the same timeutils-mergeusefor.. in;
  • setprototypeofModules provide a cross-platform way to set up instantiated object prototypes;
  • escape-htmlIs a 78-line module for escaping a string of content so that you can interpolate within the HTML content.

While these findings are not immediately applicable, they give you an idea of the dependencies your code base or framework uses.

Browser debugging tools are your best friend when it comes to debugging front-end code. In addition, they allow you to interrupt the program at any time and check the current state before deciding whether to skip the function or enter or exit the program. If the code is already compressed, it may not debug well. My personal preference is to copy uncompressed code to a relevant file in the /node_modules folder and parse it.

Case study: Redux’s Connect connection feature

React-Redux is a library for managing the state of React applications. When dealing with a popular library like this, I first search for articles that have written about its implementation. In this case study, I came across this article. This is another benefit of reading source code. The research phase will usually lead you to reading articles that will improve your own thinking and understanding.

Connect is a React-Redux function that connects the React component to the application’s Redux store. How did he do it? According to the documentation, it does the following:

“… Return a new, connected component class that wraps the component you passed in.

After watching it, I will ask the following questions:

  • Do I know that functions take any patterns or concepts of input and then return the same input with other functionality?
  • If I knew of any such patterns, how would I implement this based on the explanations given in the documentation?

In general, the next step is to create a very basic sample application to use, Connect. However, in this case, I chose to use the new React application we built on Limejump because I wanted connect to understand in the context of the application that would eventually go into production.

The component I focus on looks like this:

class MarketContainer extends Component {
 // code omitted for brevity
}

const mapDispatchToProps = dispatch= > {
 return {
   updateSummary: (summary, start, today) = > dispatch(updateSummary(summary, start, today))
 }
}

export default connect(null, mapDispatchToProps)(MarketContainer);
Copy the code

It is a container component that wraps around four smaller connected components. The first exported connect method you’ll encounter in a file is a comment: Connect is the look on connectAdvanced. Without going too far, we had our first learning moment: an opportunity to observe facade design patterns. At the end of the file, we see that Connect exports a call to a function called createConnect. Its arguments are a bunch of defaults that have been deconstructed, as follows:

export function createConnect({ connectHOC = connectAdvanced, mapStateToPropsFactories = defaultMapStateToPropsFactories, mapDispatchToPropsFactories = defaultMapDispatchToPropsFactories, mergePropsFactories = defaultMergePropsFactories, selectorFactory = defaultSelectorFactory } = {})
Copy the code

Again, we hit another learning moment: exporting the calling function and deconstructing the default function arguments. The deconstruction part was a learning moment, as the code was written as follows:

export function createConnect({ connectHOC = connectAdvanced, mapStateToPropsFactories = defaultMapStateToPropsFactories, mapDispatchToPropsFactories = defaultMapDispatchToPropsFactories, mergePropsFactories = defaultMergePropsFactories, selectorFactory = defaultSelectorFactory })
Copy the code

It will cause this error to occur. Uncaught TypeError: Cannot destructure property ‘connectHOC’ of ‘undefined’ or ‘null’. This is because the function has no default arguments to use.

Note: For more information on this, read David Walsh’s article. Depending on what you know about the language, some learning moments may seem trivial, so it’s best to focus on things you’ve never seen before or need to learn more about.

CreateConnect itself has no role in the function body. It returns a function called connect, which I’m using here:

export default connect(null, mapDispatchToProps)(MarketContainer)
Copy the code

It takes four arguments, all optional, and the first three arguments are passed through a match function to help define their behavior based on whether they exist and their value types. Now, because the second argument provided match is one of the three imported functions connect, I have to decide which thread to follow.

If these arguments are functions, the proxy function connect used to wrap the first argument, the isPlainObject utility used to check the ordinary object, or the warning module that reveals how to set up the debugger to break all exceptions, there is a learning moment. After the match function, we have connectHOC, a function that takes our React component and connects it to Redux. It’s another function call that’s returned, wrapWithConnect which actually handles the function that connects the component to the store.

Looking at connectHOC’s implementation, I can see why it needs Connect to hide its implementation details. It is the heart of React-Redux and contains connect without exposing logic. Although I had intended to end my in-depth discussion of it at this point, I will continue, and this will be the best time to look through the references I found earlier, as some of them are quite detailed in explaining the code base.

Abstract

Reading source code is difficult at first, but like anything, it gets easier over time. The goal is not to understand every line of code, but to read it to gain perspective and new knowledge. The key is to be thoughtful about the whole process, but also curious about everything.

For example, I find the isPlainObject function interesting because it uses it if (typeof obj! = = ‘object’ | | obj = = = null) return false to ensure that a given parameter is an ordinary object. When I first read it in the implementation process, I want to know why it didn’t use the Object. The prototype. ToString. Call (opts)! == ‘[object object]’, which produces less code and distinguishes objects from object subtypes, such as Date objects. However, reading the next line, you realize that it is almost impossible for a developer to use connect to return a Date Object, for example, which is checked by Object.getProtoTypeof (obj) === NULL.

Another interesting bit is this code in isPlainObject:

while (Object.getPrototypeOf(baseProto) ! = =null) {
 baseProto = Object.getPrototypeOf(baseProto)
}
Copy the code

Some of my Google searches led me to this StackOverflow community or Redux issue to see examples of how the code handles things, such as checking the object source of the iFrame.

In addition, there are some articles that are helpful for reading the source code

  • How to Reverse Engineer A Framework, Max Koretskyi, Medium
  • How to Read Code, Aria Stewart, GitHub

[Author profile] : Marmot, Reed Science and Technology Web front-end development engineer, representative works: Feihuating small program, battery gene, YY emoticon red envelope, YY stack square live competition mini game. Good at website construction, public account development, wechat small program development, small games, public account development, focus on front-end framework, server-side rendering, SEO technology, interaction design, image rendering, data analysis and other research.

Welcome to join us: [email protected]

Visit www.talkmoney.cn to learn more