Function.prototype.call = function(context,...args){ var context = context || window; context.fn = this; var result = eval(`context.fn(...args)`); delete context.fn; return result; }
call的实质就是调用函数时候改变函数中this的指向,利用对象中函数调用时候 this指向这个对象的特性我们给函数加上fn属性,指向函数本身,然后调用这个函数。指向就变成了fn前面的context也就是call的第一个参数;
Function.prototype.apply = function (context, args) { let context = context || window; context.fn = this; let result = eval('context.fn(...args)'); delete context.fn return result; }
apply同理 只是参数改变成为了数组
bind
-
对于普通函数,绑定this指向
-
对于构造函数,要保证原函数的原型对象上的属性不能丢失
Function.prototype.bind = function (context, ...args) { // 异常处理 if (typeof this !== "function") { throw new Error("Function.prototype.bind - what is trying to be bound is not callable"); } // 保存this的值,它代表调用 bind 的函数 var self = this; var fNOP = function () {}; var fbound = function () { self.apply(this instanceof self ? this : context, args.concat(Array.prototype.slice.call(arguments))); } fNOP.prototype = this.prototype; fbound.prototype = new fNOP(); return fbound; }
instanceOf
用法是a instanceOf A 原理是通过 a 的原型链和A的原型来判断a是否是A的实例
1 function instance_of(L, R){ 2 const baseType = ['string', 'number','boolean','undefined','symbol']; 3 if(baseType.includes(typeof L)) return false 4 5 let RP = R.prototype; // 取R的原型 6 L = L.__proto__; // 取L的原型链 7 while(true){ 8 if(L === null){ 9 return false; 10 } 11 if(L === RP){ 12 return true; 13 } 14 L = L.__proto__; // 没找到继续造 15 16 } 17 }
flat : 利用递归,依次遍历
Array.prototype.myFlat2 = function(arr){ let newArr=[]; (function flatArr(arr){ arr.forEach((item,idx) => { if(typeof item != 'object'){ newArr.push(item) }else{ flatArr(arr[idx]) } }) })(arr) return newArr; } let a = [1,[1,2,3],[[1,23],[12,11]]]; console.log(Array.prototype.myFlat2(a));
filter
filter() 方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。 Array.prototype.filter = function(fn){ var _this; if (typeof fn !== "function") { throw "参数必须为函数"; } //get array going to be iterated let arr = this; if (!Array.isArray(arr)) { throw "只能对数组使用forEach方法"; } if (arguments.length > 1) { _this = thisArg; } let result = []; for (let index = 0; index < arr.length; index++) { let invokedReturn = fn.call(_this, arr[index], index, arr); if (invokedReturn) { result.push(arr[index]); } } return result; }
new: js高级程序设计第四版中对于new的描述如下
1. 在内存中创建一个新对象;
2. 这个新对象内部的[[prototype]]特性被复制为构造函数的prototype属性
3. 构造函数内部的this被赋值为这个新对象
4. 执行构造函数内部代码
5. 如果构造函数返回非空对象,则返回该对象,否则返回刚创建的实例
function myNew(ctor, ...args){ if(typeof ctor !='function'){ throw 'newOperator function the first param must be a function'; } let obj = new Object(); obj.__proto__ = Object.create(ctor.prototype); // 关键步骤1 let res = ctor.call(obj, ...args)// 关键步骤2
if(result !== null && /^(object|function)$/.test(typeof res)){ return result } }
防抖
节流
深浅拷贝
数组乱序
数组去重
八种继承及各种继承之间的特点
lazyman
jsonp的实现
函数的柯里化