Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Analyze the cleanliness of JavaScript code

2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article focuses on "analyzing the cleanliness of JavaScript code". Interested friends may wish to have a look at it. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn how to analyze the cleanliness of JavaScript code.

1. Replace array subscript with named variables

/ / badconst address = "One Infinite Loop, Cupertino 95014"; const cityZipCodeRegex = / ^ [^,\] + [,\\ s] + (. +?)\ s * (\ d {5})? $/; saveCityZipCode (/ / subscript 1) 2 is not easy to understand address.match (cityZipCodeRegex) [1], address.match (cityZipCodeRegex) [2]); / / goodconst address = "One Infinite Loop, Cupertino 95014" Const cityZipCodeRegex = / ^ [^,\] + [,\\ s] + (. +?)\ s * (\ d {5})? $/; / use the array to deconstruct the better named variable const [, city, zipCode] = address.match (cityZipCodeRegex) | | []; saveCityZipCode (city, zipCode)

two。 The parameters of the function are best! hash.has (elem));}; / goodclass SuperArray extends Array {diff (comparisonArray) {const hash = new Set (comparisonArray); return this.filter (elem = >! hash.has (elem));}}

5. Replacing conditional statements with polymorphisms

/ / badif (type = = 'text') {/ / do something} else if (type = =' select') {/ / do something else}

A common way for individuals to write this kind of code is:

Const control = {text: {mapper () {}, restore () {}, name: 'this is a text field',}, select: {mapper () {}, restore () {}, name:' this is a select field',}} control [type] .mapper ()

In fact, even if it is polymorphism, you can also consider using class, something like this:

Class Field {...} class TextField extends Field {mapper () {} restore () {} name = 'this is a text field';} class SelectField extends Field {mapper () {} restore () {} name =' this i``s a select field';}

Use the getter and setter functions.

/ / badfunction makeBankAccount () {/ /... Return {balance: 0 / /...};} const account = makeBankAccount (); account.balance = 100 getter / goodfunction makeBankAccount () {/ / this one is private let balance = 0 "getter", made public via the returned object below function getBalance () {return balance;} / / a "setter", made public via the returned object below function setBalance (amount) {/ /. Validate before updating the balance balance = amount;} return {/ /... GetBalance, setBalance};} const account = makeBankAccount (); account.setBalance

You can do a lot of things in getter and setter without having to modify every .balance.

7. Prefer composition over inheritance

Try to replace inheritance with composition, and when do you use inheritance:

Your inheritance represents an "is-a" relationship and not a "has-a" relationship (Human- > Animal vs. User- > UserDetails).

You can reuse code from the base classes (Humans can move like all animals).

You want to make global changes to derived classes by changing a base class. (Change the caloric expenditure of all animals when they move).

8. SOLID

Single Responsibility Principle single responsibility principle

There should never be more than one reason for a class to change, the number of reasons for a class to be changed should be reduced as much as possible. If there are too many functions in a class, it will be impossible to estimate the impact on any module that references the class when you modify one of them.

Open/Closed Principle open and closed principle

Users can extend the function without modifying the internal implementation. For example, there is a Http module that internally determines which adaptor to use based on the environment. If users want to add adaptor, they must modify the Http module.

/ / badclass AjaxAdapter extends Adapter {constructor () {super (); this.name = "ajaxAdapter";}} class NodeAdapter extends Adapter {constructor () {super (); this.name = "nodeAdapter";}} class HttpRequester {constructor (adapter) {this.adapter = adapter } fetch (url) {if (this.adapter.name = "ajaxAdapter") {return makeAjaxCall (url) .then (response = > {/ / transform response and return});} else if (this.adapter.name = "nodeAdapter") {return makeHttpCall (url) .then (response = > {/ / transform response and return}) }} function makeAjaxCall (url) {/ / request and return promise} function makeHttpCall (url) {/ / request and return promise} / / goodclass AjaxAdapter extends Adapter {constructor () {super (); this.name = "ajaxAdapter";} request (url) {/ / request and return promise}} class NodeAdapter extends Adapter {constructor () {super (); this.name = "nodeAdapter" } request (url) {/ / request and return promise}} class HttpRequester {constructor (adapter) {this.adapter = adapter;} fetch (url) {return this.adapter.request (url) .then (response = > {/ / transform response and return});}}

Liskov Substitution Principle interior substitution principle

Parent and subclasses should be interchangeable without error.

/ / badclass Rectangle {constructor () {this.width = 0; this.height = 0;} setColor (color) {/ /...} render (area) {/ /...} setWidth (width) {this.width = width;} setHeight (height) {this.height = height;} getArea () {return this.width * this.height }} class Square extends Rectangle {setWidth (width) {this.width = width; this.height = width;} setHeight (height) {this.width = height; this.height = height;}} function renderLargeRectangles (rectangles) {rectangles.forEach (rectangle = > {rectangle.setWidth (4); rectangle.setHeight (5); const area = rectangle.getArea (); / / BAD: Returns 25 for Square. Should be 20. Rectangle.render (area);} const rectangles = [new Rectangle (), new Rectangle (), new Square ()]; renderLargeRectangles (rectangles)

The above Rectangle cannot directly replace Square, because it will lead to an error in calculating area. Consider abstracting the method of calculating area:

Class Shape {setColor (color) {/ /...} render (area) {/ /...} class Rectangle extends Shape {constructor (width, height) {super (); this.width = width; this.height = height;} getArea () {return this.width * this.height;}} class Square extends Shape {constructor (length) {super (); this.length = length } getArea () {return this.length * this.length;}} function renderLargeShapes (shapes) {shapes.forEach (shape = > {const area = shape.getArea (); shape.render (area);});} const shapes = [new Rectangle (4,5), new Rectangle (4,5), new Square (5)]; renderLargeShapes (shapes)

Interface Segregation Principle interface isolation principle

Clients should not be forced to depend upon interfaces that they do not use . For example, a functional module needs to design parameters that must be passed and optional parameters, and users should not be forced to use optional parameters.

Dependency Inversion Principle dependency injection principle

/ / badclass InventoryRequester {constructor () {this.REQ_METHODS = ["HTTP"];} requestItem (item) {/ /...}} class InventoryTracker {constructor (items) {this.items = items; / / BAD: We have created a dependency on a specific request implementation. / / We should just have requestItems depend on a request method: `request`this.requester = new InventoryRequester ();} requestItems () {this.items.forEach (item = > {this.requester.requestItem (item);});}} const inventoryTracker = new InventoryTracker (["apples", "bananas"]); inventoryTracker.requestItems ()

The above example is that InventoryRequester is instantiated internally in InventoryTracker, which means that the module of high-level needs to know the details of the low-level module (for example, instantiating InventoryRequester needs to know its construction parameters, etc., or import the module to create coupling).

/ / goodclass InventoryTracker {constructor (items, requester) {this.items = items; this.requester = requester;} requestItems () {this.items.forEach (item = > {this.requester.requestItem (item);});}} class InventoryRequesterV1 {constructor () {this.REQ_METHODS = ["HTTP"] } requestItem (item) {/ /...}} class InventoryRequesterV2 {constructor () {this.REQ_METHODS = ["WS"];} requestItem (item) {/ /...}} / / By constructing our dependencies externally and injecting them, we can easily// substitute our request module for a fancy new one that uses WebSockets.const inventoryTracker = new InventoryTracker (["apples", "bananas"], new InventoryRequesterV2 ()); inventoryTracker.requestItems ()

Pass in the instance of low-level directly, regardless of how it is instantiated, high-level only needs to rely on the abstract interface to complete the call to the submodule.

9. Annotation

Comments are an apology, not a requirement. Good code mostly documents itself. Good code is self-explanatory.

You will often encounter bug and other problems. This can be frustrating, but try to stay calm and think systematically. Remember that practice is the best way to solve problems.

At this point, I believe you have a deeper understanding of "analyzing the cleanliness of JavaScript code". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report