【JavaScript框架封裝】使用Prototype給Array,String,Function物件的方法擴充

向善的燈發表於2018-07-15
版權宣告:本文為博主原創文章,未經博主允許不得轉載。更多學習資料請訪問我愛科技論壇:www.52tech.tech https://blog.csdn.net/m0_37981569/article/details/81055991
/*
* @Author: 我愛科技論壇
* @Time: 20180705
* @Desc: 實現一個類似於JQuery功能的框架
* V 1.0: 實現了基礎框架、事件框架、CSS框架、屬性框架、內容框架、動畫框架的搭建
* V 2.0:實現了框架的進一步優化,具有良好的擴充套件性, 可以支援鏈式訪問
* V 3.0:種子模組:名稱空間、物件擴充套件、陣列化、型別的判定、domReady,無衝突處理
* V 4.0: 資料型別的檢測、正規表示式的基本用法,資料繫結的知識(模板的使用)
* */

/**
 * 用於給js中內建的物件進行擴充方法
 */
(function () {
    // 為了使得下面定義的擴充函式執行,祥和裡需要呼叫一下
    stringExtend()
    arrayExtend()
    functionExtend()


    // String物件方法的擴充
    function stringExtend() {
        // str = `name: @(name), age:@(age)`
        // data = {name : `xiugang`, age : 18}
        /**
         * 實現一個簡單的資料繫結
         * @param str
         * @param data
         * @return {*}
         */
        String.prototype.formateString = function (data) {
            return this.replace(/@((w+))/g, function (match, key) {
                // 注意這裡找到的值必須返回出去(如果是undefined,就是沒有資料)
                // 注意:判斷一個值的型別是不是undefined,可以通過typeof判斷
                console.log(typeof data[key] === `undefined`);
                return data[key] === `undefined` ? `` : data[key];
            });

        }
        /**
         * 去掉座標的空格
         * @param str
         * @return {*}
         */
        String.prototype.ltrim = function () {
            return this.replace(/^s*/g, ``);

        }
        /**
         * 去掉右邊的空格
         * @param str
         * @return {*}
         */
        String.prototype.rtrim = function () {
            return this.replace(/s*$/g, ``);
        }
        /**
         * 去掉兩邊的空格
         * @param str
         * @return {*}
         */
        String.prototype.trim = function () {
            return this.replace(/(^s*)|(s*$)/g, ``);
        }

        // red===>Red
        /**
         * 將第一個字母小寫,其他字母大寫
         * @param str
         * @return {*}
         */
        String.prototype.camelCase = function () {
            // .*?是非貪婪的匹配,點可以匹配任意字元,星號是前邊的字元有0-n個均匹配,問號是則是0-1;
            // (^w{1}): 用於匹配第一個首字母
            // (.*):用於匹配任意個的前面的字元

            // - param 1: 匹配到的字串
            // - param 2: 匹配的的子字串
            // - param 3: 匹配的子字串
            // - param 4: 匹配到的字串在字串中的位置
            // - param 5: 原始字串

            return this.replace(/(^w{1})(.*)/g, function (match, g1, g2) {
                return g1.toUpperCase() + g2.toLowerCase();
            });
        }
        /**
         * 將一個字串的下劃線轉換為中劃線
         * @param str
         * @return {*}
         */
        String.prototype.dashString = function () {
            // 這裡面的this實際上指向的就是我們自己定義的一個變數字串
            return this.replace(/\_/g, `-`);
        }

        /**
         * 檢測一個字串是不是為空
         * @return {boolean}
         */
        String.prototype.isEmpty = function () {
            return this.length === 0;

        }
        /**
         * 判斷字串是不是包含一個字串
         * @param target
         * @return {boolean}
         */
        String.prototype.contains = function (target) {
            // 只要這個indexOf的下標不是-1的話,就說明包含這個目標字串,否則的話就是不包含
            // indexOf() 方法可返回某個指定的字串值在字串中首次出現的位置,如果沒找到的話,就返回-1
            return this.indexOf(target) !== -1;
        }
        /**
         * 對一個字串中的特殊字元進行轉義
         * @return {string}
         */
        String.prototype.escapeHTML = function () {
            /*顯示結果	描述	實體名稱	實體編號
                        空格	 	 
                        <	小於號	<	<
                        >	大於號	>	>
                        &	和號	&	&
                        "	引號	"	"
                        `	撇號 	` (IE不支援)	`
                        ¢	分	¢	¢
                        �0�5	鎊	£	£
                        �0�6	日圓	¥	¥
                        €	歐元	&euro
            * **/


            // 先進行字串分割, 得到一個陣列
            var strArr = this.split(``);
            for (var pos = 0, l = strArr.length, tmp; pos < l; pos++) {
                // 拿到陣列中的每一個元素
                tmp = strArr[pos];
                // 對字串中的每一個元素進行判斷, 如果是特殊字元的話就進行處理
                switch (tmp) {
                    // pos始終為1, 表示要替換的項是1項
                    case `<`:
                        replaceArr(strArr, pos, `<`);
                        break;
                    case `>`:
                        replaceArr(strArr, pos, `>`);
                        break;
                    case ```:
                        replaceArr(strArr, pos, ```);
                        break;
                    case `"`:
                        replaceArr(strArr, pos, `"`);
                        break;
                    case `&`:
                        replaceArr(strArr, pos, `&`);
                        break;
                    default:
                        ;
                }
            }
            // join() 方法用於把陣列中的所有元素放入一個字串。
            return strArr.join(``);

            // 專門用於替換掉陣列中的元素
            /**
             * 替換陣列中指定的項
             * @param arr
             * @param pos
             * @param item
             * @return {*}
             */
            function replaceArr(arr, pos, item) {
                // Splice: splice主要用來對JS中的陣列進行操作,包括刪除,新增,替換等,原來的陣列會被改變
                // 刪除資料:array.splice(index,num),返回值為刪除內容,array為結果值。index為起始項,num為刪除元素的的個數。
                // 插入資料:array.splice(index,0,insertValue),index要插入的位置,insertValue要插入的項
                // 替換資料:array.splice(index,num,insertValue),index起始位置,num要被替換的項數,insertValue要替換的值
                return arr.splice(pos, 1, item);
            }

        }
        /**
         * 忽略HTML中的一些內建的特殊字元
         * @return {string}
         */
        String.prototype.escapeHTML = function () {
            return this.replace(/$/g, `&`)
                .replace(/</g, `<`)
                .replace(/>/g, `>`)
                .replace(/`/g, ```)
                .replace(/"/g, `"`);
        }
        /**
         * 對字串進行反轉義
         * @return {string}
         */
        String.prototype.unescapeHTML = function () {
            return this.replace(/&/, `&`)
                .replace(/</g, `<`)
                .replace(/>/g, `>`)
                .replace(/`/g, ```)
                .replace(/"/g, `"`)
                .replace(/&#(d+)/g, function ($0, $1) {
                    return String.fromCharCode(parseInt($1, 10));
                });
        }
        /**
         * 把一個字串進行反轉操作
         * @return {string}
         */
        String.prototype.reverse = function () {
            // 1. 先獲得我需要的字串,然後進行分割處理
            var arr = this.toString().split(``);
            // 2. 對我分割後得到的陣列元素進行逆序處理
            arr = arr.reverse();
            // 3.把陣列中的元素變為一個字串
            return arr.join();
            //return (this.toString()).split(``).reverse().join();
        }


    }

    // Array物件方法的擴充
    function arrayExtend() {
        /**
         * 將一個陣列元素清空
         * @return {Array}
         */
        Array.prototype.clear = function () {
            this.length = 0;
            return this;
        }
        /**
         * 計算一個陣列的長度
         * @return {*}
         */
        Array.prototype.size = function () {
            return this.length;
        }
        /**
         * 返回陣列裡面的第一個元素
         * @return {*}
         */
        Array.prototype.first = function () {
            return this[0];
        }
        /**
         * 返回陣列的最後一個元素
         * @return {*}
         */
        Array.prototype.last = function () {
            return this[this.length - 1]
        }


        function cacl(arr, callback) {
            // 變數的初始化(治理在使用的時候進行初始化)
            var ret;
            for (var i = 0, len = arr.length; i < len; i++) {
                ret = callback(arr[i], ret);
            }
            return ret;
        }

        /**
         * 對陣列的所有元素進行求和
         * @return {*}
         */
        Array.prototype.sum = function () {
            // 1. 一般的方法
            /*var ret = 0;
            for (var i = 0, len = this.length; i < len; i++){
                ret = ret + this[i];
            }
            return ret;*/

            // 2.使用上面的計算類
            /**
             * @param:item 陣列的每一項
             * @param:sum 陣列求和的結果
             */
            return cacl(this, function (item, sum) {
                // 如果剛開始沒有初始化的話,就直接使用第一項作為sum(ret)的初始值
                if (typeof sum === `undefined`) {
                    return item;
                } else {
                    return sum += item;
                }
            })

        }
        /**
         * 找出陣列中的最大值
         * @return {*}
         */
        Array.prototype.max = function () {
            // 1. 一般的方式求出最大值
            /*var ret = 0;
            for (var i = 0, len = this.length; i < len; i++){
                if (ret < this[i]){
                    ret = this[i];
                }
            }
            return ret;*/

            // 2. 第二種方式
            return cacl(this, function (item, max) {
                if (typeof max === `undefined`) {
                    return item;
                } else {
                    if (max < item) {
                        return item;
                    } else {
                        return max;
                    }
                }
            })
        }
        /**
         * 找出一個陣列中的最小值
         * @return {*}
         */
        Array.prototype.min = function () {
            return cacl(this, function (item, min) {
                if (typeof min === `undefined`) {
                    return item;
                } else {
                    // 只要每一項的值都不比最小值小的話
                    if (!(min < item)) {
                        return item;
                    } else {
                        return min;
                    }
                }
            })
        }

        /**
         * 求出一個陣列中所有元素的平均值
         * @return {*}
         */
        Array.prototype.avg = function () {
            // 1. 先對陣列中的元素個陣列進行判斷一下,防止計算出現無窮的情況
            if (this.length === 0) {
                return;
            }
            var sum = this.sum();
            return sum / this.length;
            /*return cacl(this, function (item, avg) {
                // 1. 先求和(進入到這個函式裡面, this指向的是window物件,此時window物件是沒有sum方法的,故執行錯誤)
                //var sum = this.sum();
                // 2.求出平均值
                if (typeof avg === `undefined`){
                    return item;
                } else{
                    avg = sum / (this.length);
                }
                return avg;
            })*/
        }


        // 去除陣列中的重複項
        /*
        * 實現思路: 遍歷原始陣列中的每一項元素,讓每次遍歷的這一個元素和後面的每一個元素進行比較
        * 【只要相同的話就直接跳過繼續向下尋找】
        * */
        Array.prototype.unique = function () {
            var a = [],
                len = this.length;
            for (var i = 0; i < len; i++) {
                for (var j = i + 1; j < len; j++) {
                    if (this[i] === this[j]) {
                        // 如果找到了相鄰的兩個元素是相同的,i直接向後移動一位
                        // 然後j開始從i的位置繼續向後尋找元素
                        j = ++i;
                    }
                }
                a.push(this[i]);
            }
            ;
            return a;
        }
        /**
         * 去除陣列中的重複項
         * 【實現思路】:先對陣列進行排序,然後比較相鄰的元素是否相同
         * @return {Array}
         */
        Array.prototype.unique = function () {
            var tmp = [],
                len = this.length;
            // 1.先對原始的陣列進行排序
            this.sort();
            // 2.比較相鄰的元素
            for (var i = 0; i < len; i++) {
                // 只要相鄰的元素相同,就直接跳過
                if (this[i] === this[i + 1]) {
                    continue;
                }

                // 由於tmp.length初始的位置一直是0, 新增一個元素之後變為1,因此下標和長度每次相差1, 實現了實時插入資料的功能
                tmp[tmp.length] = this[i];
            }
            return tmp;
        }

        /**
         * 實現兩個陣列的並集,然後去除重複元素
         * @param target
         * @return {*}
         */
        Array.prototype.union = function (target) {
            // concat() 方法用於連線兩個或多個陣列。
            // 連線陣列之後然後去除陣列中的重複項
            return this.concat(target).union();
        }

        /**
         * 求出兩個陣列的交集
         * @param target
         * @return {Array|*[]}
         */
        Array.prototype.intersect = function (target) {
            // 1.先去除原始陣列和目標陣列中的重複元素
            var originArr = this.unique(),
                targetArr = target.unique();
            // filter()的作用是返回某一陣列中滿足條件的元素,該方法返回的是一個新的陣列
            // 2.開始使用條件過濾
            /**
             * @param element(必選):當前元素的值
             @param index(可選): 當前元素的索引
             @param array(可選):當前元素所屬的陣列
             */
            return originArr.filter(function (element, index, array) {
                // filter函式預設會把所有的返回false的元素去掉
                for (var i = 0, len = targetArr.length; i < len; i++) {
                    if (element === targetArr[i]) {
                        // 只要是返回滿足true的所有條件,基本上都會被過濾掉
                        return true;
                    }
                    //return false;
                }
                // 只有找到相同的元素的時候返回的是true,其他情況都是返回的是false
                return false;
            });

        }

        /**
         * 找出兩個陣列中的不同元素
         * @param target
         * @return {Array|*[]}
         */
        Array.prototype.diff = function (target) {
            // 1. 獲取原始陣列和目標陣列,去除重複項
            var orignArr = this.unique(),
                targetArr = target.unique();
            // 2. 開始使用filter函式過濾條件
            return orignArr.filter(function (element, index, array) {
                for (var i = 0, len = targetArr.length; i < len; i++) {
                    // 只要元素相等的話,就全部過濾掉
                    if (element === targetArr[i]) {
                        return false;
                    }
                }
                return true;
            });
        }

        /**
         * 對陣列的每一項遍歷的時候設定一個回撥函式(沒有返回結果)
         * @param fn
         * @param ctx
         */
        Array.prototype.forEach = function (fn, ctx) {
            var i = 0,
                len = this.length;
            for (; i < len; i++) {
                // element, index, array
                // call 的第一個引數也就是this的指向, 其他參數列示需要傳遞給回撥函式的的引數
                fn.call(ctx || null, this[i], i, this);
            }
        }
    }

    /**
     *
     * 對陣列的每一項執行回撥,返回由回撥函式的結果組成的陣列
     * @param fn
     * @param ctx
     * @return {Array}
     */
    Array.prototype.map = function (fn, ctx) {
        // 初始化變數
        var ret = [],
            i = 0,
            len = this.length;
        // 遍歷陣列的每一項元素, 返回由回撥函式的結果組成的陣列
        for (; i < len; i++) {
            // 呼叫回撥函式, 返回指向結果
            res = fn.call(ctx || null, this[i], i, this);
            // 將每一項執行的結果放入到一個新的陣列裡面
            ret.push(res);
        }
        return ret;
    }
    /**
     * 對陣列的每一項執行回撥函式, 返回回撥函式執行結果為true的陣列集合
     * @param fn
     * @param ctx
     */
    Array.prototype.filter = function (fn, ctx) {
        var ret = [],
            i = 0,
            len = this.length;
        // 遍歷每一項,把執行結果為true的所有元素集合存起來
        for (; i < len; i++) {
            // 注意這裡的這種運算方式只會返回所有的回撥函式返回true的計算結果集
            fn.call(ctx || null, this[i], i, this) && ret.push(this[i]);
        }
        return ret;
    }

    /**
     * 對陣列的【每一項】執行回撥函式,必須每一項回撥函式返回true, 就返回true
     * @param fn
     * @param ctx
     */
    Array.prototype.every = function (fn, ctx) {
        var i = 0,
            len = this.length;
        // 遍歷陣列中所有的元素, 只要有一個函式回撥函式為false就返回false,只要所有的都是true才會返回true
        for (; i < len; i++) {
            // 如:a預設是undefined,!a是true,!!a則是false,所以b的值是false,而不再是undefined。這樣寫可以方便後續判斷使用。
            // 所以,!!(a)的作用是將a強制轉換為布林型(boolean)。
            // 如果a = null, !!(a) 的結果就是假, 可以直接把一個弱型別強制轉換為一個新的型別
            // 下面的程式碼就是強制將一個函式轉換為bool的型別
            if(!!fn.call(ctx || null, this[i], i, this) === false)
                return false;

            // 上面的程式碼等價於
            /*if (fn.call(ctx || null, this[i], i, this)) {
                return true;
            }*/
        }
        return true;
    }
    /**
     * 對陣列中的每一項執行回撥函式,只要有一項為true的話,就是true,否則就是false
     * @param fn
     * @param ctx
     */
    Array.prototype.some = function (fn, ctx) {
        var i = 0,
            len = this.length;
        // 迴圈遍歷每一項,只要有一項為true,就是true
        for (; i < len; i++) {
            /*
            * // 強制轉換為Boolean 用 !!
            var bool = !!"c";
            console.log(typeof bool); // boolean

            // 強制轉換為Number 用 +
            var num = +"1234";
            console.log(typeof num); // number

            // 強制轉換為String 用 ""+
            var str = ""+ 1234;
            console.log(typeof str); // string
            * */
            if(!!fn.call(ctx || null, this[i], i, this) === true)
                return true;
        }
        return false;
    }

    /**
     * 從左向右執行回撥函式(第二個元素開始)
     * 其中包含了上一次回撥的返回值
     * @param callback
     */
    Array.prototype.reduce = function (callback) {
        var i = 0,
            len = this.length,
            callbackRet = this[0];          // 這個變數儲存著上一次回到的函式的返回結果, 預設儲存的是第一個元素
        for (; i < len; i++) {
            // this的指向,element, index, 陣列物件本身
            // callbackRet 裡面儲存了陣列上一次計算的處理結果
            callbackRet = callback.call(null, callbackRet, this[i], i, this);
        }
        return callbackRet;
    }

    /**
     * 從右向左處理每一項元素,倒數第二項開始執行
     * @param callback
     */
    Array.prototype.reduceRight = function (callback) {
        var len = this.length,
            i = this[len - 2],
            callbackRet = this[len - 1];        // 儲存著最後一項

        // 從倒數第二項開始向前遍歷陣列的每一項
        for (; i >= 0; i--) {
            //this指向, prev, element, index, arr
            callbackRet = callback.call(null, callbackRet, this[i], i, this);
        }
        return callbackRet;
    }


    /**
     * 返回目標值target在陣列中第一次出現的位置, 搜尋預設會從左向右執行
     * @param target
     * @param start
     */
    Array.prototype.indexOf = function (target, start) {

        /*
        * 其實是一種利用符號進行的型別轉換,轉換成數字型別
        ~~true == 1
        ~~false == 0
        ~~"" == 0
        ~~[] == 0
        ~~undefined ==0
        ~~!undefined == 1
        ~~null == 0
        ~~!null == 1
        * */
        var len = this.length,
            start = ~~start;        // 如果start不傳過來,這裡就是undefined,指向後面的就會儲存,這裡使用了~~把其他型別強制轉換為數字型別
        if (start < 0) {
            // 如果指定搜尋的起始位置小於0的話, 預設就從0的位置開始向後搜尋
            start = 0;
        }
        // 從使用者指定的起始位置開始向後搜尋
        for (; start < len; start++) {
            if (this[start] === target) {
                return start;
            }
        }
        // 如果沒找到的話,就返回-1
        return -1;
    }


    /**
     * 返回指定的目標值在陣列中最後一次出現的位置
     * @param target
     * @param start
     */
    Array.prototype.lastIndexOf = function (target, start) {
        // 這裡相當於是typeof start ==== `undefined`
        if (start === void 0) {
            start = this.length;
        } else if (start < 0) {
            start = 0;
        }

        // 開始從陣列的最後面向前遍歷
        for (; start >= 0; start--) {
            // 找到目標元素target在陣列中最後一次出現的位置(從後向前找)
            if (this[start] === target) {
                return start;
            }
        }
        return -1;
    }

    /**
     * 陣列去重方法加強版本
     * 侷限性:只適用於陣列中存放的是單一的資料型別,如果是多種資料型別並存的話,就會去重失敗
     * [`ff`, 1, `1`]
     */
    Array.prototype.enhanceUnique = function () {
        var ret = [],
            tempMap = {},
            i = 0,
            len = this.length,
            temp;

        // 遍歷陣列的每一項
        for (; i < len; i++) {
            temp = this[i];
            // 只要這個tempMap中沒有這一項的話,就直接放入到陣列中去
            if (tempMap[temp] === void 0) {
                ret.push(temp);
                // {}資料的儲存格式為{1 : true, 2 : false, 3 : false}
                tempMap[temp] = true;
            }
        }
        return ret;
    }


    /**
     * 刪除陣列中的指定元素, 通過arguments偽陣列的方式來接受傳遞過來的引數
     * 經過測試,只能刪除陣列中重複的多餘的元素
     * @return {Array}
     */
    Array.prototype.without = function () {
        // slice(start, end) 方法可從已有的陣列中返回選定的元素。
        // 如果slice()這個函式沒有指定結束的位置的話,預設是會返回陣列中的start之後的所有元素
        // 1. 獲取使用者傳過來的引數, 去掉陣列中重複的元素
        //var args = [].slice.call(arguments).unique();
        /*
        * Array.prototype.slice.call({
         0:"likeke",
         1:12,
         2:true,
         length:3
        });
        * */
        //1. 由於arguments實際上是一個偽陣列,不能直接使用陣列裡面的方法
        // 因此先要把arguments轉換為陣列
        var arr = Array.prototype.slice.call(arguments) || [].slice.call(arguments);
        // 2. 把陣列中的重複元素去重
        var args = arr.unique(),
            len = this.length,
            aLength = args.length,
            i = 0,
            j = 0;


        // 遍歷原始的陣列(由於後面每次刪除掉一個元素之後,這裡的this.length的長度就是已經都改變了, 因此每次在執行完畢之後都要重新計算一下length)
        for (; i < len; i++) {
            for (; j < aLength; j++) {
                if (this[i] === args[j]) {
                    // 只要刪除的陣列在我的這個裡面,就直接去掉
                    // i 為起始的值,1為要刪除的項, 也就是刪除i位置的元素
                    // splice  返回的是刪除的元素, this內容是已經修改過之後的項
                    this.splice(i, 1);

                    // 為了避免刪除陣列的元素之後的陣列長度的變化,這裡需要重新計算一下陣列的新的長度
                    // len = this.length;
                }

            }
            // 將j下標復位,以便下一次迴圈(注意是在每一次j迴圈完畢之後然後再把j初始化到原始的狀態)
            j = 0;
        }
        return this;
    }


    /**
     * 去掉陣列中的目標元素
     */
    Array.prototype.enhanceWithout = function () {
        // 用於去除陣列中指定的的多餘的元素
        var ret = [],
            len = this.length,
            args = ([]).slice.call(arguments),
            argsLength = args.length,
            i = 0,
            j = 0;

        for (; i < len; i++){
            for(; j < argsLength; j++){
                if (args[j] !== this[i]){
                    ret.push(this[i]);
                }
            }
            // 由於這裡的j使用的是區域性變數,因此這裡需要進行處理
            j = 0;
        }
        return ret;
    }


    /**
     * 實現一個陣列的扁平化(可以解決陣列裡面存放陣列的問題)【遞迴處理呼叫】
     * [[], [], [], [[], [], []]]
     * @return {Array}
     */
    Array.prototype.flatten = function () {
        // 實現一個flatten函式,將一個巢狀多層的陣列 array(陣列) (巢狀可以是任何層數)轉換為只有一層的陣列
        // 陣列中元素僅基本型別的元素或陣列,
        var ret = [],
            len = this.length,      // 注意當下一次執行遞迴呼叫之後,這裡的this指向的是tmp
            i = 0,
            tmp;

        for (; i < len; i++) {
            // 注意這裡先取出來陣列中的每一項元素
            tmp = this[i];
            // 判斷一下陣列裡面存放的還是不是陣列型別(陣列裡面的每一項)
            if (({}).toString.call(tmp) === `[object Array]` || Object.prototype.toString.call(tmp) === `[object Array]`) {
                // 繼續遞迴呼叫(遞迴呼叫的時候需要把結果存起來哦)
                // 1. 對當前陣列裡面的陣列進行扁平化處理, tmp.flatten()得到的就是一個普通的陣列型別
                // 2. 由於ret是一個陣列型別,使用concat之後可以把兩個陣列裡面的元素連結起來
                // 下一次執行遞迴的時候上面的this就是指向了這裡的tmp陣列
                ret = ret.concat(tmp.flatten())
                //tmp.flatten();
            } else {
                // 如果不是陣列型別的話,就直接放入到我的新陣列裡面
                ret.push(tmp);
            }
        }
        return ret;
    }


    /**
     * 刪除陣列中的指定位置的項
     * @param pos
     * @return {Array}
     */
    Array.prototype.removeAt = function (pos) {
        // 移出陣列中指定位置的項
        // slice() 函式呼叫的執行結果返回的是刪除掉的項, 這個this就是修改之後的項
        this.splice(pos, 1);
        return this;
    }

    /*
    【經驗話語1】
      直接用等號 (==) 判斷時,變數必須要宣告(包括不用var 的隱式宣告),否則出錯。
      不管變數有沒有宣告,都可用typeof 判斷,注意typeof 返回結果為字串,所以是與"undefined"做比較。
      所以,判斷型別最好用typeof ,因為當判斷的變數是在其他js 檔案中定義的全域性變數時,
      執行此判斷時,定義該變數所在的js 檔案可能還未載入完成,用== 判斷就會報錯:is not defined
    【經驗話語2】

    注意slice()和splice() 這兩者的區別
    * */


    /**
     * 檢測陣列中是不是包含某一項
     * @param target
     * @return {boolean}
     */
    Array.prototype.contains = function (target) {
        // 可以呼叫自己之前申明好的some方法,陣列中只要有一項,就會返回true
        return this.some(function (element, index, self) {
            // 呼叫this.some()方法實際上會返回遍歷陣列元素的每一項
            return element === target;
        })
    }

    /**
     * 隨機返回陣列中的某一項(把陣列中的任意一項返回)
     * @param n
     * @return {*}
     */
    Array.prototype.random = function (n) {
        //Math.floor():向下取整。Math.floor(1.8) -> 1
        //Math.ceil():向上取整。Math.ceil(1.1) -> 2
        //v = Math.random() * n:會產生一個 0 < v < nv的數
        //v2 = Math.floor(Math.random() * n):v2為一個大於等於0,小於n的整數
        var index = (Math.floor(Math.random()) * n);
        return this[index] || this[this.length-1];
    }


    // Function物件方法的擴充
    function functionExtend(func) {
        Function.prototype.before = function () {
            // 一般來說加下劃線的變數為私有變數,這是常規都比較遵守的一種程式碼規範。
            var __self = this;      // 私有的屬性用下劃線
            return function () {
                // 重新把我需要傳遞的引數傳遞過去, 如果目標函式返回的是false, 就是false
                if (func.apply(this, arguments) === false){
                    return false;
                }
                // 否則就把我的自己的引數傳遞過去
                return __self.apply(this, arguments);
            }
        }


        /**
         * AOP 切面程式設計的函式擴充
         * @param func
         * @return {Function}
         */
        Function.prototype.after = function (func) {
            var __self = this;
            return function () {
                var ret = __self.apply(this, arguments);        // //返回一個函式,相當於一個代理函式,也就是說,這裡包含了原函式和新函式,原函式指的是myFunc,新函式指的是fn
                if (ret === false){
                    return false;
                }
                func.apply(this, arguments);
                return ret;
            }
        }

    }
})();



相關文章