javascript常考算法

call、apply原理

function person(){
	console.log(this.name)
}
var egg={name:'蛋老师'}
//函数的构造函数原型对象添加newCall
Function.prototype.newCall=function(obj,...args){
	//这里this指的是person函数,因为是person调用了
	//给对象添加了一个person函数
	obj.p=this;
	obj.p(...args);//执行函数
	delete obj.p;
}
person.newCall(egg);

实现一个call或 apply

//手写apply,传入数组
Function.prototype.apply = function (context, args) {
  // 检查调用```apply```的对象是否为函数
  if (typeof this !== 'function') {
    throw new TypeError('not a function')
  }
  // 将函数作为传入的```context```对象的一个属性,调用该函数
  const fn = Symbol()
  context[fn] = this
  context[fn](...args)
  // 不要忘了调用之后删除该属性
  delete context[fn]
}
//手写call,传入多个参数
Function.prototype.call = function (context, ...args) {
  // 检查调用```apply```的对象是否为函数
  if (typeof this !== 'function') {
    throw new TypeError('not a function')
  }
  // 将函数作为传入的```context```对象的一个属性,调用该函数
  const fn = Symbol()
  context[fn] = this
  var result=context[fn](...args)
  // 不要忘了调用之后删除该属性
  delete context[fn]
  return result;
}

实现一个Function.bind

// 手写bind
		function person(a,b){
			console.log(a,b);
		}
		var egg={name:'egg'}
		Function.prototype.newBind=function(obj){
			var that=this; // this指的是person
			arr=Array.prototype.slice.call(arguments,1); //这个是传进来的参数
			o=function(){} //这个是匿名函数 判断是否使用了new
			newf=function(){
				var arr2=Array.prototype.slice.call(arguments);//第二次传递的所有参数
				arrSum=arr.concat(arr2);//两次的所有参数
				if(this instanceof o){
				   that.apply(this,arrSum)//解释一
				}else{
				   that.apply(obj,arrSum)
				}
			}
			//newf.prototype=that.prototype
			o.prototype=that.prototype; //解释二
			newf.prototype=new o; //解释二
			return newf;
		}
		var bibi=person.newBind(egg,'点赞');
		var b=new bibi('充电')

解释一:如果使用new来调用函数,发生了构造函数,那么实例(新对象)会绑定到函数调用的this,使用new时,this的绑定规则,this不是person函数而是一个实例
解释二:用原型链将其串联起来,把person的原型对象赋值给bibi这个函数的原型对象,修改bibi的原型对象,使person和bibi两者串联起来,使得bibi这个函数的实例,可以用到person原型对象的属性
解释三:创建空函数o,将空函数的原型对象修改为这里this的原型对象,把空函数o的原型对象修改为函数person的原型对象

实现new

new实现的事情
1.创建一个空对象,这个对象作为执行new构造函数后,返回的对象实例
2.将上面创建的空对象的原型(proto),指向构造函数的prototype属性。
3.将这个空对象赋值给构造函数内部的this,并执行构造函数逻辑
4.根据构造函数执行逻辑,返回第一个步创建的对象或者构造函数的显示返回值
//Object.create 新创建一个对象,参数为原型对象类型。

function Person(name){
    this.name=name
}
const person=new newFunc(Person,'lucas')
console.log(person)
function newFunc(...args){
   const consturctor=args.shift() //Person 目标构造函数
   const obj=Object.create(constructor.prototype) //obj.__prototy__=constructor.prototype
   const result=consturctor.apply(obj,args) //obj对象添加方法
   return (typeof result==="object" && result!=null)? result:obj
}

手写一个JS浅拷贝、深拷贝

//浅拷贝知识拷贝一层,拷贝引用
//深拷贝拷贝多层,每一级别的数据都会拷贝

var obj={
	id:1,
	name:'andy'
}
//浅拷贝
var o={}
for(var k in obj){
//k 是属性名  obj[k]属性值
o[k]=obj[k]
}
//es6新增浅拷贝
Object.assign(o,obj)
// 深拷贝
//封装函数
function deepCope(newObj,oldObj){
	for(var k in oldObj){
		//判读属性值属于哪种数据类型
		//1.获取属性值
		var item=oldObj[k]
		//2.判断值是否为数组
		if(item instanceof Array){
			newObj[k]=[];
			deepCope(newObj[k],item)
		}else if(item instanceof Object){
			//3.判断是否是对象
			newObj[k]={};
			deepCope(newObj[k],item)
		}else{
		//4.属于简单数据类型
			newObj[k]=item
		}
	}
}

实现一个JS函数柯里化

function uri(protocol){
	return function(hostname,pathname){
		return `${hostname}${pathname}`
	}
}
const uri_https=uri('https://')
const uri2=uri_https('www.aa.com','点赞')
const uri3=uri_https('www.aa.com','收藏')
const uri4=uri_https('www.aa.com','关注')
console.log(uri2,uri3,uri4)
--------------------------------------------------
function add (...args) {
	return args.reduce((a, b) => a + b)
}
function currying (fn) {
	let args = []
	return function _c (...newArgs) {
		if (newArgs.length) {
			args = [...args,...newArgs]
			return _c
		} else {
			return fn.apply(this, args)
		}
	}
}

let addCurry = currying(add)
// 注意调用方式的变化
console.log(addCurry(1)(2)(3)(4, 5)())
--------------------------------------------------------------
function add(){
			//let args=arguments;
			let args=Array.prototype.slice.call(arguments);
			var inner=function(){
				//arguments是对象不是数组
				args.push(...arguments)
				return inner;
			}
			inner.toString=function(){
				return args.reduce(function(prev,cur){
					return prev+cur
				})
			}
			return inner;
		}
		console.log(add(1)(2)(3))

实现一个JSON.stringify()

实现一个JSON.parse

手写jsonp

(function(window){
var jsonp=function(){
var FuncName=‘handeler’+Math.randow().toString().replace(’.’,’’);
var parameter=’?jsoncallback=’+FuncName;
var scriptEle=document.createElement(‘script’);
scriptEle.src=url+parameter;
window[FuncName]=function(data){
callback(data);
document.body.removeChild(scriptEle);
}
window.jsonp=jsonp;
}
})(window)
$(’#btn’).click(function(){
jsonp(‘https://www.samm.com/jsonp.aspx’,function(data){
var result=JSON.stringigy(data);
$("#text").val(result);
})

})
实现一个继承
手写一个Promise(中高级必考)
手写防抖(Debouncing)和节流(Throttling)
实现一个instanceOf

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

微星星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值