theme: 常用api的原生实现
Function.prototype.apply()实现
Function.prototype.myapply = function(context=window,args){
if(typeof this!== function){
throw this+'is not a function'
}
const _this = context;
let fn = Symbol('fn');
_this.fn = this;
const res = _this.fn(...args);
delete _this.fn;
return res;
}
Function.prototype.call()
Function.prototype.mycall = function(context = window,...args){
if(typeof this !== 'function'){
throw this + 'is not a function';
}
const _this = context;
const fn =Symbol('fn');
_this.fn = this;
const res = _this.fn(...arg);
delete _this.fn;
return res;
}
Function.prototype.bind()
Function.prototype.mybind = function(context = window,args){
if(typeof this!== function){
throw this+"is not a function";
}
const _this = context;
let self = this;
return function F(){
if(this instanceof F){ //考虑new的情况
return new self(...args,...arguments);
}
return self.apply(_this,[...args,...arguments])
}
}
实现函数柯里化
功能性版:
实现add(1)(2)(3)(4)=10 add(1,2)(3)(4)=10
function add(){
let arg = [...arguments]; //存储第一次传进来的参数
return fn(){
arg.push(...arguments) //后续传入的参数加入数组
return fn; //返回fn调用toString方法
}
fn.toString = function(){ //重写toString方法
return arg.reduce((sum,cur)=>sum+cur);
}
return fn;
}
getOwnPropertyNames()
function getOwnNames(o){
if(o!==Object(o)){
throw TypeError('Object.getOwnPropertyNames calles on non-object')
})
let result=[];
for(i in o){
if(Object.prototype.hasOwnProperty.call(o,i)){
result.push(i);
}
}
return result;
}
原理:Object.getOwnPropertyNames()取得对象自身的可枚举属性,不包括原型对象。for-in取得对象和原型对象的可枚举属性,使用hasOwnProperty过滤掉原型对象的属性
instanceof
function instance_of(L,R){
let o = R.prototype;
let p = L.__proto__;
while(true){
if(p===null) return false;
if(p===o) return true;
p=p.__proto__;
}
}
原理:
let arr=[];
arr instanceof Array; true
arr instanceof Objec; true
arr instanceof Function false
固定右边构造函数的原型,在左边对象的__proto__层层寻找,直到__proto__值等于构造函数原型或者指向null
new
function myNew(){
let obj = new Object();
let Constructor = Array.prototype.shift.call(arguments);
obj.__proto__ = Constructor.prototype;
let res = Constructor.apply(obj,arguments); //shift改变了arguments,此时arguments是传入的构造函数参数列表
return typeof res === 'object'?res:obj;
}
Object.create()实现
function myCreate(o){
function F(){};
F.prototype=o;
return new F();
}
原理:以传入对象为构造函数的原型,创建一个新的对象
Object.is()
Object.defineProperty{Object,'is',{
value:function(x,y){
if(x===y){ //对于+0和-0
return x!==0||1/x===x/y;
}
else{ 对于NaN !== NaN
return x!==x&&y!==y;
}
},
configure:true,
enumberable:false,
writable:true
}}
原理:Object.is()用来严格比较俩个参数是否相等,和===极度相似。唯一区别:
- +0===-0 true,Object.is(+0,-0) false
- NaN === NaN false ,Object.is(NaN,NaN) true
解决的问题:js缺乏一种运算,在所有环境中,只要俩个值是一样的,他们就应该相等,比如NaN。ES6提出"Same-value equality"算法解决这个问题。
核心代码原理:
Array.isArray()
Array.myIsArray = function(o){
return Object.prototype.toString.call(Object(o))==='[object Array]'; //Object()的作用:确保call绑定的对象是 对象类型,而不是基本数据
}