手写代码
1.new的实现
a.能够访问构造函数的属性
b.能访问函数函数的原型的属性
function Person(name) { this.name = name } Person.prototype.eat = function () { console.log('Eatting') } function create() { // 1. 获取构造函数,并且删除 arguments 中的第一项 var con=[].shift.call(arguments); // 2. 创建一个空的对象并链接到构造函数的原型,使它能访问原型中的属性 var obj=Object.create(con.prototype) // 3. 使用apply改变构造函数中this的指向实现继承,使obj能访问到构造函数中的属性 var ret=con.apply(obj,arguments) // 4. 优先返回构造函数返回的对象,判断构造函数有没有返回值,是不是函数 return typeof ret === 'object'?ret:obj;
} var lindaidai = create(Person, 'LinDaiDai') console.log(lindaidai) // Person{ name: 'LinDaiDai' } lindaidai.eat() // 'Eatting'
2.call的实现
Function.prototype.call2 = function (context) { var context = context||window; context.fn=this; var args=[]; for(var i=1;i<arguments.length;i++){ args.push(`arguments[${i}]`); } var result = eval(`context.fn(${args})`) delete context.fn; return result } var foo = { value: 1 }; function bar(name, age) { console.log(name) console.log(age) console.log(this.value); } bar.call2(foo, 'kevin', 18); // kevin // 18 // 1
3.apply的实现
Function.prototype.apply2 = function (context,arr) { var context = context||window; context.fn=this; var args=[]; var result; if(arr){ for (var i = 0; i < arr.length; i++) { args.push(`arr[${i}]`); } result = eval(`context.fn(${args})`) }else{ result = context.fn(); } delete context.fn; return result } // 测试一下 var foo = { value: 1 }; function bar(name, age) { console.log(name) console.log(age) console.log(this.value); } bar.apply2(foo, ["kevin","18"]); // kevin // 18 // 1
4.bind的实现
简单的实现:
// 第一版 Function.prototype.bind2 = function (context) { var self=this; var args=[].slice.call(arguments,1); return function(){ var bindArgs = [].slice.call(arguments); return self.apply(context,args.concat(bindArgs)); } } var value = 2; var foo = { value: 1 }; function bar(name, age) { this.habit = 'shopping'; console.log(this.value); console.log(name); console.log(age); } var bindFoo = bar.bind2(foo, 'daisy'); bindFoo('10'); // 1 // daisy // 10
复杂的,包含new,this指向失效
var value = 2; var foo = { value: 1 }; function bar(name, age) { this.habit = 'shopping'; console.log(this.value); console.log(name); console.log(age); } bar.prototype.friend = 'kevin'; var bindFoo = bar.bind2(foo, 'daisy'); var obj = new bindFoo('18'); // undefined // daisy // 18 console.log(obj.habit); console.log(obj.friend); // shopping // kevin Function.prototype.bind2 = function (context) { var self = this; var args = Array.prototype.slice.call(arguments, 1); var fNOP = function () {}; var fBound = function () { var bindArgs = Array.prototype.slice.call(arguments); return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs)); } fNOP.prototype = this.prototype; fBound.prototype = new fNOP(); return fBound; }
5.防抖
/** * @description 防抖 * @param {object} fn 执行函数 * @param {number} wait 延迟时间 * @return {void} 返回无 * 使用列子(不要事件里面的function): * $(".supplierUser").click( * debounce(move, 2000) * ) */ function debounce(fn, wait = 200) { var timeout = null; return function () { if (timeout !== null) clearTimeout(timeout); timeout = setTimeout(fn, wait); } }
6.节流
/** * @description 节流 * @param {object} fn 执行函数 * @param {number} wait 延迟时间 * @return {void} 返回无 * 使用列子(不要事件里面的function): * $(".supplierUser").click( * throttle(move, 2000) * ) */ function throttle(fn, wait) { var _this, args; var last = 0; return function () { var now = +new Date(); _this = this; args = arguments; if (now - last > wait) { fn.apply(_this, args); last = now; } }; }
7.数组扁平化,去重,排序
var a1 = [4,1,1,2, [2], [[3]]]; var newA = Array.from(new Set(a1.flat(Infinity))).sort(function(a,b){return a-b;});//[1,2,3,4]