Create a weapon in hand, efficient completion of front-end business code.

preface

As the front end of the battle in the business, if you want to work less overtime, you have to think of ways to improve work efficiency. A little point in here, in the process of business development, we often repeat use date format, url parameter object, browser type, throttling function of function, these tools function, basically use in every project, to avoid the trouble of repeatedly copying and pasting from project to project, we can be unified encapsulation, published to NPM, To improve development efficiency.

Here, the author has encapsulated and published his own Arsenal outils, if you are interested in this project, welcome star this project. Of course, you can also encapsulate your own Arsenal based on this project.

Summary of Common functions

Here is a taxonomy of the utility functions used many times in the previous project.

1.Array

1.1 arrayEqual

/** ** @desc Check whether two arrays are equal * @param {Array} arr1 * @param {Array} arr2 * @return {Boolean} */
function arrayEqual(arr1, arr2) {
    if (arr1 === arr2) return true;
    if(arr1.length ! = arr2.length)return false;
    for (var i = 0; i < arr1.length; ++i) {
        if(arr1[i] ! == arr2[i])return false;
    }
    return true;
}Copy the code

2.Class

2.1 addClass

/** ** @desc add class * @param {HTMLElement} ele * @param {String} CLS */

var hasClass = require('./hasClass');

function addClass(ele, cls) {
    if(! hasClass(ele, cls)) { ele.className +=' '+ cls; }}Copy the code

2.2 hasClass

/** ** @desc Determine whether the element has a class * @param {HTMLElement} ele * @param {String} CLS * @return {Boolean} */
function hasClass(ele, cls) {
    return (new RegExp('(\\s|^)' + cls + '(\\s|$)')).test(ele.className);
}Copy the code

2.3 removeClass

/** ** @desc remove class * @param {HTMLElement} ele * @param {String} CLS */

var hasClass = require('./hasClass');

function removeClass(ele, cls) {
    if (hasClass(ele, cls)) {
        var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)');
        ele.className = ele.className.replace(reg, ' '); }}Copy the code

3.Cookie

3.1 getCookie

/** ** @desc reads cookies based on name * @param {String} name * @return {String} */
function getCookie(name) {
    var arr = document.cookie.replace(/\s/g."").split('; ');
    for (var i = 0; i < arr.length; i++) {
        var tempArr = arr[i].split('=');
        if (tempArr[0] == name) {
            return decodeURIComponent(tempArr[1]); }}return ' ';
}Copy the code

3.2 removeCookie

var setCookie = require('./setCookie');
/** ** @desc Delete cookie * @param {String} name */
function removeCookie(name) {
    // The cookie will be deleted immediately if the setting is expired
    setCookie(name, '1'.- 1);
}Copy the code

3.3 setCookie

/** ** @desc Set Cookie * @param {String} name * @param {String} value * @param {Number} days */
function setCookie(name, value, days) {
    var date = new Date(a); date.setDate(date.getDate() + days);document.cookie = name + '=' + value + '; expires=' + date;
}Copy the code

4.Device

4.1 getExplore

/** ** @desc Obtain the browser type and version * @return {String} */
function getExplore() {
    var sys = {},
        ua = navigator.userAgent.toLowerCase(),
        s;
    (s = ua.match(/rv:([\d.]+)\) like gecko/))? sys.ie = s[1]:
        (s = ua.match(/msie ([\d\.]+)/))? sys.ie = s[1] :
        (s = ua.match(/edge\/([\d\.]+)/))? sys.edge = s[1] :
        (s = ua.match(/firefox\/([\d\.]+)/))? sys.firefox = s[1] :
        (s = ua.match(/ (? :opera|opr).([\d\.]+)/))? sys.opera = s[1] :
        (s = ua.match(/chrome\/([\d\.]+)/))? sys.chrome = s[1] :
        (s = ua.match(/version\/([\d\.]+).*safari/))? sys.safari = s[1] : 0;
    // Make a judgment based on the relationship
    if (sys.ie) return ('IE: ' + sys.ie)
    if (sys.edge) return ('EDGE: ' + sys.edge)
    if (sys.firefox) return ('Firefox: ' + sys.firefox)
    if (sys.chrome) return ('Chrome: ' + sys.chrome)
    if (sys.opera) return ('Opera: ' + sys.opera)
    if (sys.safari) return ('Safari: ' + sys.safari)
    return 'Unkonwn'
}Copy the code

4.2 getOS

/** ** @desc Obtain the operating system type * @return {String} */
function getOS() {
    var userAgent = 'navigator' in window && 'userAgent' in navigator && navigator.userAgent.toLowerCase() || ' ';
    var vendor = 'navigator' in window && 'vendor' in navigator && navigator.vendor.toLowerCase() || ' ';
    var appVersion = 'navigator' in window && 'appVersion' in navigator && navigator.appVersion.toLowerCase() || ' ';

    if (/mac/i.test(appVersion)) return 'MacOSX'
    if (/win/i.test(appVersion)) return 'windows'
    if (/linux/i.test(appVersion)) return 'linux'
    if (/iphone/i.test(userAgent) || /ipad/i.test(userAgent) || /ipod/i.test(userAgent)) 'ios'
    if (/android/i.test(userAgent)) return 'android'
    if (/win/i.test(appVersion) && /phone/i.test(userAgent)) return 'windowsPhone'
}Copy the code

5.Dom

5.1 getScrollTop

/** ** @desc gets the distance from the top of the scroll bar */
function getScrollTop() {
    return (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;
}Copy the code

5.2 offset

@param {HTMLElement} ele * @returns {{left: number, top: number} } */
function offset(ele) {
    var pos = {
        left: 0.top: 0
    };
    while (ele) {
        pos.left += ele.offsetLeft;
        pos.top += ele.offsetTop;
        ele = ele.offsetParent;
    };
    return pos;
}Copy the code

5.3 scrollTo

var getScrollTop = require('./getScrollTop');
var setScrollTop = require('./setScrollTop');
var requestAnimFrame = (function () {
    return window.requestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        function (callback) {
            window.setTimeout(callback, 1000 / 60); }; }) ();/** ** @desc Within ${duration}, scroll smoothly to ${to} * @param {Number} to * @param {Number} duration */
function scrollTo(to, duration) {
    if (duration < 0) {
        setScrollTop(to);
        return
    }
    var diff = to - getScrollTop();
    if (diff === 0) return
    var step = diff / duration * 10;
    requestAnimationFrame(
        function () {
            if (Math.abs(step) > Math.abs(diff)) {
                setScrollTop(getScrollTop() + diff);
                return;
            }
            setScrollTop(getScrollTop() + step);
            if (diff > 0 && getScrollTop() >= to || diff < 0 && getScrollTop() <= to) {
                return;
            }
            scrollTo(to, duration - 16);
        });
}Copy the code

5.4 setScrollTop

/** ** @desc Sets the distance between the scroll bar and the top */
function setScrollTop(value) {
    window.scrollTo(0, value);
    return value;
}Copy the code

6.Keycode

6.1 getKeyName

var keyCodeMap = {
    8: 'Backspace'.9: 'Tab'.13: 'Enter'.16: 'Shift'.17: 'Ctrl'.18: 'Alt'.19: 'Pause'.20: 'Caps Lock'.27: 'Escape'.32: 'Space'.33: 'Page Up'.34: 'Page Down'.35: 'End'.36: 'Home'.37: 'Left'.38: 'Up'.39: 'Right'.40: 'Down'.42: 'Print Screen'.45: 'Insert'.46: 'Delete'.48: '0'.49: '1'.50: '2'.51: '3'.52: '4'.53: '5'.54: '6'.55: '7'.56: '8'.57: '9'.65: 'A'.66: 'B'.67: 'C'.68: 'D'.69: 'E'.70: 'F'.71: 'G'.72: 'H'.73: 'I'.74: 'J'.75: 'K'.76: 'L'.77: 'M'.78: 'N'.79: 'O'.80: 'P'.81: 'Q'.82: 'R'.83: 'S'.84: 'T'.85: 'U'.86: 'V'.87: 'W'.88: 'X'.89: 'Y'.90: 'Z'.91: 'Windows'.93: 'Right Click'.96: 'Numpad 0'.97: 'Numpad 1'.98: 'Numpad 2'.99: 'Numpad 3'.100: 'Numpad 4'.101: 'Numpad 5'.102: 'Numpad 6'.103: 'Numpad 7'.104: 'Numpad 8'.105: 'Numpad 9'.106: 'Numpad *'.107: 'Numpad +'.109: 'Numpad -'.110: 'Numpad .'.111: 'Numpad /'.112: 'F1'.113: 'F2'.114: 'F3'.115: 'F4'.116: 'F5'.117: 'F6'.118: 'F7'.119: 'F8'.120: 'F9'.121: 'F10'.122: 'F11'.123: 'F12'.144: 'Num Lock'.145: 'Scroll Lock'.182: 'My Computer'.183: 'My Calculator'.186: '; '.187: '='.188: ', '.189: The '-'.190: '. '.191: '/'.192: '`.219: '['.220: '\ \'.221: '] '.222: '\' '
};
@param {Number} keycode * @return {String} */
function getKeyName(keycode) {
    if (keyCodeMap[keycode]) {
        return keyCodeMap[keycode];
    } else {
        console.log('Unknow Key(Key Code:' + keycode + ') ');
        return ' '; }};Copy the code

7.Object

7.1 deepClone

/** * @desc Deep copy. Common types are supported * @param {Any} values */
function deepClone(values) {
    var copy;

    // Handle the 3 simple types, and null or undefined
    if (null == values || "object"! =typeof values) return values;

    // Handle Date
    if (values instanceof Date) {
        copy = new Date(a); copy.setTime(values.getTime());return copy;
    }

    // Handle Array
    if (values instanceof Array) {
        copy = [];
        for (var i = 0, len = values.length; i < len; i++) {
            copy[i] = deepClone(values[i]);
        }
        return copy;
    }

    // Handle Object
    if (values instanceof Object) {
        copy = {};
        for (var attr in values) {
            if (values.hasOwnProperty(attr)) copy[attr] = deepClone(values[attr]);
        }
        return copy;
    }

    throw new Error("Unable to copy values! Its type isn't supported.");
}Copy the code

7.2 isEmptyObject

/** ** @desc Check whether 'obj' is empty * @param {Object} obj * @return {Boolean} */
function isEmptyObject(obj) {
    if(! obj ||typeofobj ! = ='object' || Array.isArray(obj))
        return false
    return !Object.keys(obj).length
}Copy the code

8.Random

8.1 randomColor

/** ** @desc Randomly generated color * @return {String} */
function randomColor() {
    return The '#' + ('00000' + (Math.random() * 0x1000000 << 0).toString(16)).slice(- 6);
}Copy the code

8.2 randomNum

/** ** @desc Generates a specified range of random numbers * @param {Number} min * @param {Number} Max * @return {Number} */
function randomNum(min, max) {
    return Math.floor(min + Math.random() * (max - min));
}Copy the code

9.Regexp

9.1 isEmail

/** ** @desc Check whether it is an email address * @param {String} STR * @return {Boolean} */
function isEmail(str) {
    return /\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(str);
}Copy the code

9.2 isIdCard

/ * * * * @ desc determine whether for id Number * @ param {String | Number} STR * @ return {Boolean} * /
function isIdCard(str) {
    return /^(^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$)|(^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])((\d {4})|\d{3}[Xx])$)$/.test(str)
}Copy the code

9.3 isPhoneNum

/ * * * * @ desc determine whether for mobile phone Number * @ param {String | Number} STR * @ return {Boolean} * /
function isPhoneNum(str) {
    return / ^ (0 | 86 | 17951)? (13 15 [012356789] [0-9] | | 17 [678] 18 [0-9] | | 14 [57]) [0-9] {8} $/.test(str)
}Copy the code

9.4 isUrl

/** ** @desc Check whether it is a URL * @param {String} STR * @return {Boolean} */
function isUrl(str) {
    return / [- a - zA - Z0-9 @ : %. _ \ + ~ # =] {2256} \. [a-z] {2, 6} \ b ([9 - a - zA - Z0 - @ : % _ \ +. ~ #? & / / =] *)/I.test(str);
}Copy the code

10.String

10.1 digitUppercase

/** ** @desc Capitalized * @param {Number} n * @return {String} */
function digitUppercase(n) {
    var fraction = ['Angle'.'points'];
    var digit = [
        'zero'.'one'.'. '.'叁'.'boss'.'wu'.'land'.'pure'.'捌'.'nine'
    ];
    var unit = [
        ['元'.'万'.'亿'],
        [' '.'pick up'.'or'.'仟']].var head = n < 0 ? 'less' : ' ';
    n = Math.abs(n);
    var s = ' ';
    for (var i = 0; i < fraction.length; i++) {
        s += (digit[Math.floor(n * 10 * Math.pow(10, i)) % 10] + fraction[i]).replace(Zero /. /.' ');
    }
    s = s || 'the whole';
    n = Math.floor(n);
    for (var i = 0; i < unit[0].length && n > 0; i++) {
        var p = ' ';
        for (var j = 0; j < unit[1].length && n > 0; j++) {
            p = digit[n % 10] + unit[1][j] + p;
            n = Math.floor(n / 10);
        }
        s = p.replace(/ (zero). * $/ zero.' ').replace($/ / ^.'zero') + unit[0][i] + s;
    }
    return head + s.replace(/ (zero). * zero yuan /.'元')
        .replace(/ (zero). +/g.'zero')
        .replace(Whole $/ / ^.'zero integer');
};Copy the code

11.Support

11.1 isSupportWebP

/** ** @desc Check whether the browser supports webP images. * @return {Boolean} */
function isSupportWebP() {
    return!!!!! [].map &&document.createElement('canvas').toDataURL('image/webp').indexOf('data:image/webp') = =0;
}Copy the code

12.Time

12.1 formatPassTime

/** * @desc Format ${startTime} elapsed time * @param {Date} startTime * @return {String} */
function formatPassTime(startTime) {
    var currentTime = Date.parse(new Date()),
        time = currentTime - startTime,
        day = parseInt(time / (1000 * 60 * 60 * 24)),
        hour = parseInt(time / (1000 * 60 * 60)),
        min = parseInt(time / (1000 * 60)),
        month = parseInt(day / 30),
        year = parseInt(month / 12);
    if (year) return year + "Years ago"
    if (month) return month + "A month ago."
    if (day) return day + "Days ago"
    if (hour) return hour + "Hours ago"
    if (min) return min + "Minutes ago."
    else return 'just'
}Copy the code

12.2 formatRemainTime

/** ** @desc format the remaining time from ${endTime} * @param {Date} endTime * @return {String} */
function formatRemainTime(endTime) {
    var startDate = new Date(a);// Start time
    var endDate = new Date(endTime); // End time
    var t = endDate.getTime() - startDate.getTime(); / / time
    var d = 0,
        h = 0,
        m = 0,
        s = 0;
    if (t >= 0) {
        d = Math.floor(t / 1000 / 3600 / 24);
        h = Math.floor(t / 1000 / 60 / 60 % 24);
        m = Math.floor(t / 1000 / 60 % 60);
        s = Math.floor(t / 1000 % 60);
    }
    return d + "Day" + h + "Hour" + m + "Minutes" + s + "Seconds";
}Copy the code

13.Url

13.1 parseQueryString

/** ** @desc URL parameter to Object * @param {String} URL default: window.location.href * @return {Object} */
function parseQueryString(url) {
    url = url == null ? window.location.href : url
    var search = url.substring(url.lastIndexOf('? ') + 1)
    if(! search) {return{}}return JSON.parse('{"' + decodeURIComponent(search).replace(/"/g.'\ \ "').replace(/&/g.'",").replace(/=/g.'" : "') + '"}')}Copy the code

13.2 stringfyQueryString

/** ** @desc Object serialization * @param {Object} obj * @return {String} */
function stringfyQueryString(obj) {
    if(! obj)return ' ';
    var pairs = [];

    for (var key in obj) {
        var value = obj[key];

        if (value instanceof Array) {
            for (var i = 0; i < value.length; ++i) {
                pairs.push(encodeURIComponent(key + '[' + i + '] ') + '=' + encodeURIComponent(value[i]));
            }
            continue;
        }

        pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]));
    }

    return pairs.join('&');
}Copy the code

14.Function

14.1 throttle

/** * @desc function throttling. * * @param {Number} delay 0 or more milliseconds. For event callbacks, a delay of about 100 or 250 milliseconds (or more) is most useful. * @param {Boolean} noTrailing Is optional. The default value is false. * If noTrailing is true, every 'delay' millisecond 'callback' will be executed when the throttling function is called. * If noTrailing is false or not passed, 'callback' will execute again after the last call to the throttling function. The throttling Function is not called, the internal counter is reset) * @param {Function} callback delays the execution of the Function after milliseconds. The 'this' context and all arguments are passed as-is, and' callback 'is called when the throttling function is performed. * @param {Boolean} debounceMode If 'debounceMode' is true, 'clear' after 'delay' ms. * If debounceMode is false, 'callback' is executed after 'delay' ms. * * @return {Function} New throttling Function */
function throttle(delay, noTrailing, callback, debounceMode) {

    // After wrapper has stopped being called, this timeout ensures that
    // `callback` is executed at the proper times in `throttle` and `end`
    // debounce modes.
    var timeoutID;

    // Keep track of the last time `callback` was executed.
    var lastExec = 0;

    // `noTrailing` defaults to falsy.
    if (typeofnoTrailing ! = ='boolean') {
        debounceMode = callback;
        callback = noTrailing;
        noTrailing = undefined;
    }

    // The `wrapper` function encapsulates all of the throttling / debouncing
    // functionality and when executed will limit the rate at which `callback`
    // is executed.
    function wrapper() {

        var self = this;
        var elapsed = Number(new Date()) - lastExec;
        var args = arguments;

        // Execute `callback` and update the `lastExec` timestamp.
        function exec() {
            lastExec = Number(new Date());
            callback.apply(self, args);
        }

        // If `debounceMode` is true (at begin) this is used to clear the flag
        // to allow future `callback` executions.
        function clear() {
            timeoutID = undefined;
        }

        if(debounceMode && ! timeoutID) {// Since `wrapper` is being called for the first time and
            // `debounceMode` is true (at begin), execute `callback`.
            exec();
        }

        // Clear any existing timeout.
        if (timeoutID) {
            clearTimeout(timeoutID);
        }

        if (debounceMode === undefined && elapsed > delay) {
            // In throttle mode, if `delay` time has been exceeded, execute
            // `callback`.
            exec();

        } else if(noTrailing ! = =true) {
            // In trailing throttle mode, since `delay` time has not been
            // exceeded, schedule `callback` to execute `delay` ms after most
            // recent execution.
            //
            // If `debounceMode` is true (at begin), schedule `clear` to execute
            // after `delay` ms.
            //
            // If `debounceMode` is false (at end), schedule `callback` to
            // execute after `delay` ms.
            timeoutID = setTimeout(debounceMode ? clear : exec, debounceMode === undefined? delay - elapsed : delay); }}// Return the wrapper function.
    return wrapper;

};Copy the code

14.2 debounce

/** * @desc * Unlike throttle, debounce guarantees the number of milliseconds in which a function will not be fired again and will only be executed once, either on the first call to return's anti-shock function or after a specified millisecond delay. * @example Application scenario: such as online editing automatic storage anti-shake. * @param {Number} delay 0 or more milliseconds. For event callbacks, a delay of about 100 or 250 milliseconds (or more) is most useful. * @param {Boolean} atBegin This parameter is optional. The default value is false. * If 'atBegin' is false or not passed in, the callback is delayed for a specified millisecond after the first call to return's stabilization function. If 'atBegin' is true, the callback will execute the Function that * @param {Function} callback is delayed for milliseconds after the first call to return's stabilization Function. The 'this' context and all arguments are passed as is. * When the jitter function is performed,' callback 'is called. * * @return {Function} new anti-shake Function. * /
var throttle = require('./throttle');
function debounce(delay, atBegin, callback) {
    return callback === undefined ? throttle(delay, atBegin, false) : throttle(delay, callback, atBegin ! = =false);
};Copy the code

encapsulation

In addition to the above commonly used functions for packaging, the most important is to support the introduction of reasonable, here we use WebPack unified packaging into UMD general module specification, support webPack, RequireJS, SeaJS and other module loaders, or directly through the

But this is still not satisfactory. Because it would be wasteful to import the entire library, we can’t use all the functions. So, support import on demand

1. Directory structure description

│. Babelrc │. Gitignore │. Travis. Yml │ LICENSE │ package.json │ READMEsetCookie.js // copy the function module to the root path, easy to load on demandsetScrolltop.js │ stringfyQueryString.js │... │... │ ├─min │ ├─script │ Build.js │ Test scripts │ ├─script │ Build.js │ build.js │ build.js │ build.js │ build.js │ build.js │ build.js │ build.js │ build.js ├─ SRC // │ │ ├─ SRC // │ │ ├─array │ │ ├─class │ │ ├─cookie │ │ │ ├ ─ device │ │ │ ├ ─ dom │ │ │ ├ ─ keycode │ │ │ ├ ─ object │ │ │ ├ ─ the random │ │ │ ├ ─ regexp │ │ │ ├ ─ string │ │ │ ├ ─ support │ │ ├─ ├─ │ ├─ ├─test// Test case directory │ array.test.js │ class.test.js │ cookie.test.js │ device.test.js │ dom.test.js │ index. HTML │ keycode.test.js │ │ object.test.js │ random.test.js │ regexp.test.js │ string.test.js │ support.test.js │ time.test.js │ url.test ├ ─_lib // Mocha.css mocha.js power-assert.jsCopy the code

2. Build scripts

The first step is to build the full compressed package, delete the previous outils.min.js in the min directory, and then package and save the new compressed package in the min directory through webpack:

. .// Delete the old full compression package
    rm(path.resolve(rootPath, 'min'.`${pkg.name}.min.js`), err => {
        if (err) throw (err)
        webpack(config, function (err, stats) {
            if (err) throw (err)
            building.stop()
            process.stdout.write(stats.toString({
                colors: true.modules: false.children: false.chunks: false.chunkModules: false
            }) + '\n\n')
            resolve()
            console.log(chalk.cyan(' Build complete.\n'))})})... .Copy the code

Step 2: Copy the function module to the root directory. First delete the previous function module in the root directory, and then copy all js files in the directory below SRC to the root directory. The purpose of this is to copy the root path and require(‘outils/< method name >’) when importing it.

// Replace the module file. .// Delete the previous function module in the root directory
    rm('*.js', err => {
        if (err) throw (err)
        let folderList = fs.readdirSync(path.resolve(rootPath, 'src'))
        folderList.forEach((item, index) = > {
            // copy all 'js' files from' SRC 'to the root directory
            copy(`src/${item}/*.js`, rootPath, function (err, files) {
                if (err) throw err;
                if (index === folderList.length - 1) {
                    console.log(chalk.cyan(' Copy complete.\n')) copying.stop() } }) }) }) ...... .Copy the code

3. Write test cases

As the saying goes, it’s not a good programmer not to write a test case front end. Then you can’t be a wuss, just a wuss.

However, due to time constraints, this project temporarily started a KOA static server through test.js in the project to load the test page of Mocha web page, so that the author can test the function locally when writing the project. However, Travis – CI will be used in conjunction with Github for a continuous build that will be published automatically to NPM. Use Karma, Mocha, and Power-Assert for unit testing. Use Coverage. This section will be updated later.

Power-assert (value, [message]) is a powerful assertion library. Remember to assert(value, [message]) and you’ll never have to worry about remembering the assert library API again.

All test cases of this project are in the test directory, you can make certain reference.

Update: Unit testing, using Karma, Mocha, power-Assert, testing Coverage, and integrating Travis – CI with Github for persistent builds, You can refer to the Travis configuration file.travis. Yml of this project and the karma configuration file karmap.conf.js.

release

Start by hosting it on Github, or you can fork the project and add your own functions. Take the author’s project as an example:

1. Add your own functions

In the SRC directory, create a new category directory or select a category and add the function module file to the subfolder (it is recommended to save a small function as a JS file).

/** ** @desc Determines whether NaN * @param {Any} value * @return {Boolean} */
function isNaN(value) {    
    returnvalue ! == value; }; modules.export =isNaNCopy the code

Then remember to expose the isNaN function in the SRC /index.js file

Unit testing

Create a new test case in the test file

describe('#isNaN()'.function () {
    it(`outils.isNaN(NaN) should return true`.function () {
        assert(outils.isNaN(NaN))
    })
    it(`outils.isNaN('value') should return false`.function () {
        assert.notEqual(outils.isNaN(NaN))})})Copy the code

And then remembertest/index.htmlTo introduce the test case scripts you created earlier.

3. Test and pack

Run the NPM run test to see if all the test cases pass. If there are no problems, execute the NPM Run build and commit to your personal Github repository.

4. Release tonpm

Log in to www.npmjs.com, modify the package.json file name, version, author, etc., and publish. Note: When sending packets to NPM, the image source must be switched to www.npmjs.com. An error may occur if a third-party image source such as CNPM is used.

use

1. The browser

Download outils.min.js directly from the min directory and import it with the

  <script src="outils.min.js"></script>
  <script>
      var OS = outils.getOS()
  </script>Copy the code

Note: The repository code will be updated continuously. If you need a different version of the incremental compression package or source code, please go to github Release page to download the corresponding version of the code.

2.Webpack, RequireJS, SeaJS and other module loaders

Install outils using NPM first.

$ npm install --save-dev outilsCopy the code
// complete introduction
const outils = require('outils')
const OS = outils.getOS()Copy the code

Recommended usage

// require('outils/< method name >')
const getOS = require('outils/getOS')
const OS = getOS()Copy the code

Of course, if your development environment has Babel compiling ES6 syntax, you can also use it like this:

import getOS from 'outils/getOS'
/ / or
import { getOS } from "outils";Copy the code

conclusion

This is just a simple wrapper, published to NPM, save the next time to copy and paste, or go straight to Ole time. If the author’s library, you do not use the functions, or you have better suggestions, welcome to this project Github Issues exchange, if you feel good, welcome to star this project.

Of course, a better idea would be to fork the project, or simply create your own project, adding desired, commonly used, unmemorable functions, or even abstractable functionality into a handy, familiar library. This will build your Arsenal and instantly improve your individual combat capabilities.

He that will do his work well must first sharpen his tools. With this tool belonging to their own, the hope of overtime will become extravagant. O ha ha ~ O (studying studying)