call和apply重寫

經常能使用到call和apply的情況下進行內部實現

<script>
            //ES6版
            Function.prototype.newCall = function (obj) {
                //判斷參數傳入的值是否爲null或者undefined
                obj = obj ? Object(obj) : window;
                //this指向設置爲調用對象
                obj.func = this;  
                //截取參數數組中除了元對象外的參數列表
                let args = [...arguments].slice(1);
                //當前保存有this指向和參數內容的變量
                let res = obj.func(...args);
                //刪除該函數
                delete obj.func
                //返回上下文
                return res;
            }
            //ES5
            Function.prototype.newCall = function (obj) {
                obj = obj ? Object(obj) : window; 
                obj.func = this;
                var args = [];
                //爲取代擴展運算符使用手動分割數組爲參數列表
                for (var i = 1, len = arguments.length; i < len; i++) {
                    args.push('arguments[' + i + ']');
                }
                //args 會自動調用 args.toString() 方法
                var result = eval('context.func(' + args + ')');
                delete obj.func
                return result; 
            }

            //ES6版
            Function.prototype.newApply = function (context, arr) {
                //判斷參數傳入的值是否爲null或者undefined
                context = context ? Object(context) : window;
                //this指向設置爲調用對象
                context.fn = this;
                //當前保存有this指向和參數內容的變量
                let result;
                // 判斷是否存在第二個參數
                if (!arr) {
                    result = context.fn();
                } else {
                    //數組參數合併爲一個參數列表
                    result = context.fn(...arr);
                }
                //刪除該函數
                delete context.fn
                //返回上下文
                return result;
            }

            //ES5
            Function.prototype.newApply = function (context, arr) {
                context = context ? Object(context) : window;
                context.fn = this;
                var result;
                // 判斷是否存在第二個參數
                if (!arr) {
                    result = context.fn();
                } else {
                    //更改傳參方法
                    var args = [];
                    for (var i = 0, len = arr.length; i < len; i++) {
                        args.push('arr[' + i + ']');
                    }
                    result = eval('context.fn(' + args + ')');
                }
                delete context.fn
                return result;
            }
        </script>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章