call
Function.prototype.myCall = function () {
//獲取this指向
var _this = arguments[0];
//兼容this指向爲原始值
if (typeof _this == 'number') {
_this = new Number(_this)
} else if (typeof _this == 'boolean') {
_this = new Boolean(_this)
} else if (typeof _this == 'string') {
_this = new String(_this)
} else if (!_this) {
//兼容瀏覽器和node
try {
_this = window;
} catch (e) {
_this = {};
}
}
// 獲取參數
var _arguments = [...arguments].slice(1);
//掛載到this指向上面
_this.fn = this;
//使用eval執行這個新增的方法
var result = eval('_this.fn(' + [..._arguments].join(',') + ')');
//刪除該方法
delete _this.fn;
//返回執行結果
return result;
}
複製代碼
apply
Function.prototype.myCall = function (_this, arr) {
_this = _this;
if (typeof _this == 'number') {
_this = new Number(_this)
} else if (typeof _this == 'boolean') {
_this = new Boolean(_this)
} else if (typeof _this == 'string') {
_this = new String(_this)
} else if (!_this) {
try {
_this = window;
} catch (e) {
_this = {};
}
}
_this.fn = this;
if (!arr) {
var result = ctx.fn();
} else {
var result = eval('_this.fn(' + [...arr].toString() + ')');
}
delete _this.fn;
return result;
}
複製代碼
bind
Function.prototype.myBind = function (target) {
var self = this;
//獲取參數
var args = [].slice.call(arguments, 1);
var fn = function () {
var _arg = [].slice.call(arguments, 0);
return self.apply(target, args.concat(_arg));
}
// 設置返回的新函數的函數的原型鏈
fn.prototype.__proto__ = this.prototype
return fn;
}
複製代碼
節流
function throttle(fn, delay) {
var lock = false;
return function () {
if (!lock) {
fn(...arguments);
lock = true;
setTimeout(() => {
lock = false;
}, delay);
}
}
}
複製代碼
防抖
function debounce(fn, delay) {
var lock = false;
var timer = null;
return function () {
if (!lock) { //開鎖狀態下
fn(...arguments);
lock = true;
timer = setTimeout(() => {
lock = false;
}, delay);
} else { //鎖啓用狀態下
clearInterval(timer);
timer = setTimeout(() => {
lock = false;
}, delay);
}
}
}
複製代碼
單層柯里化
//傳入想要進行柯里化處理的函數和前幾個參數
function fixedParam(fn) {
var _arguments1 = [].slice.call(arguments, 1);
return function () {
var _arguments2 = [...arguments];
fn.apply(this, [..._arguments1, ..._arguments2]);
}
}
function sum(a, b, c, d) {
console.log(a + b + c + d);
}
//
var currySum = fixedParam(sum, 1, 2);
//下次執行輸入剩下的參數
currySum(3, 4);
複製代碼
多層柯里化1 (理解起來較難,比較繞)
function fixedParam(fn) {
var _arguments1 = [].slice.call(arguments, 1);
return function () {
var _arguments2 = [...arguments];
fn.apply(this, [..._arguments1, ..._arguments2]);
}
}
function Curry(fn, length) {
var len = length || fn.length;
//採用閉包思想,第一次讀取參數總長度,
return function () {
console.log(arguments);
//每一次的參數都是獨立的
if (arguments.length < len) {
//當參數長度不足的時候,執行fixedParam,
var combineArguments = [fn].concat(...arguments);
// 參數會存入到fixedParam的AO的_arguments中
var fixedFn = fixedParam.apply(this, combineArguments);
// 還須要多少參數才能執行
var needParams = len - arguments.length;
// 遞歸返回函數
return Curry(fixedFn, needParams);
} else {
//已經知足執行條件,執行
return fn.apply(this, arguments);
}
}
}
function sum(a, b, c, d) {
console.log(a + b + c + d);
}
var currySum = Curry(sum);
currySum(1)(2)(3)(4);
//argumnets 打印結果
/*
[Arguments] { '0': 1 }
[Arguments] { '0': 2 }
[Arguments] { '0': 3 }
[Arguments] { '0': 4 }
*/
複製代碼
多層柯里化2 (這種方式理解更容易些)
(function () {
try {
_this = window;
} catch (e) {
_this = this;
}
//兼容瀏覽器和node後端
_this.Curry = Curry;
//導出Curry方法
//函數主體部分
var _arguments = [];
//參數列表
function Curry(fn, length) {
var len = length || fn.length;
console.log(_arguments)
return function () {
_arguments = _arguments.concat([...arguments]);
if (arguments.length < len) {
return Curry(fn, len - arguments.length);
} else {
return fn.apply(this, _arguments);
}
}
}
})()
function sum(a, b, c, d) {
console.log(a + b + c + d);
}
var currySum = Curry(sum);
currySum(1, 2, 3)(4);
複製代碼
惰性函數處理事件綁定兼容ie8和w3c.
<body>
<button id="button1"></button>
<button id="button2"></button>
<script>
var oBtn1 = document.getElementById('button1');
var oBtn2 = document.getElementById('button2');
Element.prototype.addEvent = function (type, handle) {
if (this.addEventListener) {
this.addEventListener(type, handle);
Element.prototype.addEvent = function (type, handle) {
console.log('您的瀏覽器是符合W3C標準的');
this.addEventListener(type, handle, false);
}
} else {
//兼容 ie8
this.attachEvent('on' + type, handle);
Element.prototype.addEvent = function (type, handle) {
console.log('您的瀏覽器是不符合W3C標準的');
this.attachEvent('on' + type, handle)
}
}
}
oBtn1.addEvent('click', function () {
console.log(this)
})
oBtn2.addEvent('click', function () {
console.log(this)
})
</script>
</body>
複製代碼
記憶函數
function memorize(fn) {
var cache = {};
return function () {
var key = arguments.length + '-' + Array.prototype.join.call(arguments, '-');
if (cache[key]) {
return cache[key];
} else {
return cache[key] = fn.apply(this, arguments);
}
}
}
function addToOne(n) {
if (n == 1) return 1;
return n + addToOne(n - 1);
}
var memorizeAddToOne = memorize(addToOne);
console.log(memorizeAddToOne(100));
複製代碼