js基础手写第二篇
call
function mycall(context) {
// 判断它是一个对象 function
if (typeof this !== 'function') {
console.log('错误')
}
// 获取参数1 slice() 方法可从已有的数组中返回选定的元素。 1 从索引为1的地方开始截取
let args = [...arguments].slice(1)
// 定义结果值
let res = null;
// context 是否存在
context = context | window;
// 将函数作为上下文的一个属性
context.fn = this;
res = context.fn(...args)
delete context.fn
return res;
}
apply
function myApply(context) {
if (typeof this !== "function") {
console.log.log('error')
}
let res = null;
context = context | window;
context.fn = this;
if (arguments[1]) {
res = context.fn(...arguments[1]);
} else {
res = context.fn()
}
delete context.fn;
return res;
}
// 和call差不多,这里就是要注意,判断参数是否传入,并且只去一个
bind
function myBind(context) {
// 判断thi是否是函数
if (typeof this !== "function") {
console.log('error')
}
let self = this;
let args = [...arguments].slice(1);
let func = function() {
return self.apply(
this instanceof func ? this : context ,
args.concat.apply(...arguments)
)
}
// // 维护原型关系
// if (this.prototype) {
// func.prototype = this.prototype;
// }
// // 使得fBound.prototyep是func的实例,返回fBound,若作为new的构造函数,新对象的__proto__就是func的实例
// fBound.prototype = new func()
// return fBound
}
ajax
function myAjax(url) {
let xhr = new XMLHttpRequest();
xhr.open("GET",url,true);
xhr.onreadystatechange = function() {
if (this.readyState !== 4) return;
if (this.status === 200) {
handle(this.response)
// handle 是处理这个返回数据
} else {
console.log()
}
}
xhr.onerror = function() {
console.log()
}
xhr.responseType = "json";
xhr.setRequestHeader("Accept", "application/json");
xhr.send(null)
}
promise (ajax)
// 如果使用这个Promise封装
function myAjax1(url) {
return new Promise((resolve,reject) => {
let xhr = new XMLHttpRequest();
xhr.open("GET",url,true);
xhr.onreadystatechange = function () {
if (this.readyState !== 4) return;
if (this.status === 200) {
resolve(this.responseText)
} else {
reject()
}
}
xhr.onerror = function() {
reject()
}
xhr.setRequestHeader("Accept", "application/json");
xhr.send(null)
})
}
sleep
// sleep函数作用是让线程休眠,等到指定时间在重新唤起。
// 使用promise封装
function sleep2 (delay) {
return new Promise(resolve => {
setTimeout(resolve, delay)
})
}
sleep2(1000).then(() => {
console.log(2000)
})
// 不使用promise封装
function sleep(delay, callback) {
setTimeout(callback,delay)
}
sleep(100,() => {
console.log(1000)
})
shallow 浅拷贝
// Object.assign
let jing = {a:1};
let hao = {a:3,b:2};
Object.assign(jing,hao)
console.log(jing) // { a: 3, b: 2 } 会覆盖同名属性
// 扩展运算符
let obj1 = {a:1,c:3};
let obj2 = {...obj1};
console.log(obj2) // { a: 1, c: 3 }
// 数组方法 slice concat
// 手写
function shallowCopy(obj) {
if (!obj || typeof obj !== "object") return;
let newobj = Array.isArray(obj) ? [] : {};
// 指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键)。
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
newobj[key] = obj[key];
}
}
return newobj
}
deep 深拷贝
// JSON.stringify
let obj1 = {
a:0,
b: {
c:0
}
}
let obj2 = obj1;
let obj3 = Object.assign(obj1)
let obj4 = JSON.parse(JSON.stringify(obj1)); // 深拷贝 改变值也会改
obj1.a = 1;
obj1.b.c = 1;
console.log(obj1); //{ a: 1, b: { c: 1 } }
console.log(obj2); //{ a: 1, b: { c: 1 } }
console.log(obj3); //{ a: 1, b: { c: 1 } }
console.log(obj4); //{ a: 0, b: { c: 0 } }
// 手写
// 深拷贝的实现
function deepCopy(object) {
if (!object || typeof object !== "object") return;
let newObject = Array.isArray(object) ? [] : {};
for (let key in object) {
if (object.hasOwnProperty(key)) {
newObject[key] =
typeof object[key] === "object" ? deepCopy(object[key]) : object[key];
}
}
return newObject;
}
curry 柯里化
// 函数柯里化是指一种,将使用多个参数的一个函数,转化成一系列使用一个参数的函数的技术
function curry(fn,...args) {
return fn.length <= args.length
? fn(...args)
: curry.bind(null,fn,...args);
}
function curry1(fn,args) {
//获取函数需要的参数长度
let length = fn.length;
args = args | [];
return function() {
// subArgs 加入参数和arguments
let subArgs = args.slice(0);
// 拼接得到现有的所有参数
for (let i = 0;i < arguments.length;i++) {
subArgs.push(arguments[i])
}
// 判断参数是长度是否满足函数所需要的参数的长度
if (subArgs.length >= length) {
return fn.apply(this,subArgs)
} else {
// 如果不满足,递归返回柯里的函数,等待参数的传入
return curry.call(this.fn,subArgs)
}
}
}