1. The fluency of the interface
A good interface is smooth and easy to understand, and it mainly reflects the following aspects:
1. Simple
To operate the css attribute of a certain element, the following is the native method:
document.querySelectorAll('#id').style.color = 'red';After packaging
function a(selector, color) {document.querySelectorAll(selector)[].style.color = color}a('#a', 'red');From a long line with dozens of letters to a simple function call, the API is simple and easy to use
2. Readability
a('#a', 'red') is a good function that helps us change an element simply and practically, but the problem is that if you use the function change for the first time, it will be more confused. No one will tell him what function a is. It is necessary to know one thing about developing the interface: people are lazy. From the perspective of the color assignment function, although less code is written, it increases memory cost. Every time you do this, you need to have a mapping relationship. a---->color. If it is a few simple ones, it doesn't matter, but usually a set of frameworks has dozens or even hundreds of APIs, and the increase in mapping costs will cause the programmer to collapse. What we need is to make the interface meaningful. Let's rewrite the a function:
function letSomeElementChangeColor(selector, color) {document.querySelectorAll(selector, color);}letSomeElementChangeColor is given linguistic meaning relative to a, and anyone will know its meaning.
3. Reduce memory costs
The function we just now is also like this. It is too long. Although letSomeElementChangeColor reduces the mapping cost, it increases the memory cost. You should know that no one, including academic masters, likes to be verbally. The APIs that natively obtain dom also have this problem document.getElementsByClassName; document.getElementsByName; document.querySelectorAll; these APIs give people the feeling that the words are too long. Although the meaning they give is very clear, this approach is based on sacrificing simplicity. So we rewrite this previous function again
function setColor(selector, color) {xxxxxxxxxxxxx}Reduce the function name without significant changes. Make it easy to read, remember and use;
4. Extended
The so-called extension means that the use of functions is executed in the order of writing like flowing water to form an execution chain:
document.getElementById('id').style.color = 'red';document.getElementById('id').style.fontSize = 'px';document.getElementById('id').style.backgourdColor = 'pink';The previous method we used was to encapsulate the two functions setFontSize, setbackgroundColor again; and then execute them setColor('id', 'red'); setFontSiez('id', '12px'); setbackgroundColor('id', 'pink'); Obviously, this approach is not lazy to go beyond the realm; the id element needs to be re-acquisitioned every time, affecting performance, and failing; every time it needs to add new methods, failing, these methods are still called every time, or failing. Below we rewritten it into an extended function. First, encapsulate the obtaining id method into an object, and then return this object in each method of the object:
function getElement(selector) {this.style = document.querySelecotrAll(selector).style;}getElement.prototype.color = function(color) {this.style.color = color;return this;}getElement.prototype.background = function(bg) {this.style.backgroundColor = color;return this;}getElement.prototype.fontSize = function(size) {this.style.fontSize = size;return this;}//Call var el = new getElement('#id')el.color('red').background('pink').fontSize('px');Simple, smooth and easy to read later, we will talk about how to continue to optimize in the parameters. Therefore, everyone prefers to use jquery API. Although a $ symbol does not represent any practical significance, a simple symbol is beneficial to our use. It embodies the above principles: simple, easy to read, easy to remember, chain writing, and multi-parameter processing.
nightware:
document.getElementById('id').style.color = 'red';document.getElementById('id').style.fontSize = 'px';document.getElementById('id').style.backgourdColor = 'pink';dream:
$('id').css({color:'red', fontSize:'12px', backgroundColor:'pink'})2. Consistency
1. Interface consistency
The relevant interfaces maintain a consistent style. A complete set of APIs will greatly reduce the developer's adaptability to new tools if it conveys a sense of familiarity and comfort. Naming this thing: both short and self-describe, and most importantly, maintain consistency. "There are only two headaches in the computer science community: cache failure and naming issues" - Phil Karlton Choose a word you like and use it continuously. Choose a style and then keep it.
Nightware:
setColor,
letBackGround
changefontSize
Makedisplay
dream:
setColor;
setBackground;
setFontSize
set.........
Try to maintain the code style and naming style so that people can read your code as if they were reading articles written by the same person.
3. Parameter processing
1. Type of parameter
Determine the type of parameters to provide stable guarantees for your program
//We stipulate that color accepts string type function setColor(color) {if(typeof color !== 'string') return;dosomething}2. Use json to pass parameters
There are many benefits of passing values in json. It can name parameters, ignore the specific location of parameters, give default values, etc. For example, the following bad situations:
function fn(param1, param2............paramN)
You must pass each parameter in order accordingly, otherwise your method will be executed in a different way than you expect. The correct method is the following.
function fn(json) {//Set the default value for required parameters var default = extend({param: 'default',param: 'default'......},json)}This function code will be expected to run even if you don't pass any parameters in it. Because when declaring, you will decide the default value of the parameters based on the specific business.
4. Scalability
One of the most important principles of software design: never modify the interface, it means extending it! Scalability also requires a single responsibility for the interface, and multiple responsibility interfaces are difficult to expand. Take a chestnut:
//The font and background of an element need to be changed at the same time // Nightware:function set(selector, color) {document.querySelectroAll(selector).style.color = color;document.querySelectroAll(selector).style.backgroundColor = color;}//The function cannot be expanded. If you need to change the font size again, you can only modify this function and fill in the code to change the font size after the function //Dreamfunction set(selector, color) {var el = document.querySelectroAll(selector);el.style.color = color;el.style.backgroundColor = color;return el;}//The font, background color and size need to be set function setAgain (selector, color, px) {var el = set(selector, color)el.style.fontSize = px;return el;}The above is just a simple addition of colors. The business is complex and the code is not when you write it. You must read the previous code and modify it. Obviously, it does not conform to the open-closed principle. The modified function returns the element object, so that the next time you need to change, you will get the return value again for processing.
2. The use of this
Scalability also includes flexible use of this, call and apply methods:
function saysBonjour() {alert(this.a)}obj.a = ;obj.say = sayBonjour;obj.say();///orsayBonjour.call||apply(obj);//5. Handling errors
1. Foresee errors
You can use typeof or try...catch to detect. typeof forces the detection object to not throw errors, and is especially useful for undefined variables.
2. Throw an error
Most developers do not want to make mistakes and need to find the corresponding code themselves. The best way is to output it directly in the console to tell the user what happened. We can use the browser's output api: console.log/warn/error. You can also leave some way out for your program: try...catch.
function error (a) {if(typeof a !== 'string') {console.error('param a must be type of string')}}function error() {try {// some code excucete here maybe throw wrong }catch(ex) {console.wran(ex);}}6. Foresight
The predictable odor program interface provides robustness, and to ensure smooth execution of your code, it must take into account abnormal expectations. Let's look at the difference between unforeseen code and foreseeable code using the previous setColor
//nighwarefunction set(selector, color) {document.getElementById(selector).style.color = color;}//dreamzepto.init = function(selector, context) {var dom// If nothing given, return an empty Zepto collectionif (!selector) return zepto.Z()// Optimize for string selectorselse if (typeof selector == 'string') {selector = selector.trim()// If it's a html fragment, create nodes from it// Note: In both Chrome and Firefox , DOM error // is thrown if the fragment doesn't begin with <if (selector[] == '<' && fragmentRE.test(selector))dom = zepto.fragment(selector, RegExp.$, context), selector = null// If there's a context, create a collection on that context first, and select// nodes from thereelse if (context !== undefined) return $(context).find(selector)// If it's a CSS selector, use it to select nodes.else dom = zepto.qsa(document, selector)}// If a function is given, call it when the DOM is readyelse if (isFunction(selector)) return $(document).ready(selector)// If a Zepto collection is given, just return itelse if (zepto.isZ(selector)) return selectorelse {// normalize array if an array of nodes is given (isArray(selector)) dom = compact(selector)// Wrap DOM nodes.else if (isObject(selector))dom = [selector], selector = null// If it's a html fragment, create nodes from itelse if (fragmentRE.test(selector))dom = zepto.fragment(selector.trim(), RegExp.$, context), selector = null// If there's a context, create a collection on that context first, and select// nodes from thereelse if (context !== undefined) return $(context).find(selector)// And last but no least, if it's a CSS selector, use it to select nodes.else dom = zepto.qsa(document, selector)}// create a new Zepto collection from the nodes foundreturn zepto.Z(dom, selector)}The above is the source code of zepto. You can see that the author has done a lot of processing when foreseeing the incoming parameters. In fact, predictability provides several entrances for the program, nothing more than some logical judgments. zepto uses a lot of right and wrong judgments here, which also leads to the length of the code and is not suitable for reading. In short, predictability really requires you to write more parameters for the physical objects in the location. Change external detection to internal detection. Yes, people who use it are comfortable and happy to use it. Now! The most important thing in life is Heisen.
7. Comments and documents readability
The best interface is that we will use it without documentation, but often, once the number of interfaces is more and the business increases, it will be a bit difficult to use. Therefore, interface documents and comments need to be carefully written. The comments follow the principle of simple and conciseness, and are for those who come years later to show them:
//Annotation interface, to demonstrate PPT, use function commentary() {//If you define a variable without literal meaning, it is best to write a comment for it: a: useless variable, you can delete var a;//Write comments in key and ambiguity, just like the finishing touch: clear all data after routing to the hash interface. Return go.Navigate('hash', function(){data.clear();});}at last
It is recommended to markdown grammar writing API documents and github royal document writing syntax. Simple and fast, the code is highlighted, and you don't say much.
The above is the complete description of the JavaScript API design principles introduced to you by the editor. I hope it will be helpful to you. If you have any questions, please leave me a message and the editor will reply to you in time. Thank you very much for your support to Wulin.com website!