手写call
Function.prototype.myCall = function (context: any, ...args: any[]) {
if (typeof this !== 'function') {
return;
}
if (context === null || context === undefined) {
context = window
} else {
context = Object(context)
}
const fn = Symbol('myCall');
contextObj[fn] = this;
const result = contextObj[fn](...args);
delete contextObj[fn];
return result;
};
const test = {
name: "xxx",
hello: function () {
console.log(`hello,${this.name}!`);
},
add: function (a, b) {
return a + b;
},
};
const obj = { name: "world" };
test.hello.myCall(obj);
test.hello.call(obj);
console.log(test.add.myCall(null, 1, 2));
console.log(test.add.call(null, 1, 2));
手写apply
Function.prototype.myApply = function (context: any, argsArr: any[]) {
if (typeof this !== 'function') {
return;
}
if (!argsArr || !Array.isArray(argsArr)) {
return;
}
if (context === null || context === undefined) {
context = window
} else {
context = Object(context)
}
const fn = Symbol('myApply');
contextObj[fn] = this;
const result = contextObj[fn](...argsArr);
delete contextObj[fn];
return result;
};
const test = {
name: "xxx",
hello: function () {
console.log(`hello,${this.name}!`);
},
};
const obj = { name: "world" };
test.hello.myApply(obj);
test.hello.apply(obj);
const arr = [2,3,6,5,1,7,9,5,0]
console.log(Math.max.myApply(null,arr));
console.log(Math.max.apply(null,arr));
手写bind
Function.prototype.myBind = function (context, ...args) {
if (typeof this !== 'function') {
throw 'fn must be a function';
}
const conttextObj = context || globalThis;
const _this = this;
return function fn(...arguments) {
if (this instanceof fn) {
return new _this(...args, ...arguments);
}
return _this.apply(conttextObj, [...args, ...arguments]);
};
};
Function.prototype.myBind = function (context, ...args) {
if (typeof this !== 'function') {
throw 'fn must be a function';
}
const conttextObj = context || globalThis;
const fn = Symbol('myBind');
conttextObj[fn] = this;
return function fn(...arguments) {
if (this instanceof fn) {
return new conttextObj[fn](...args, ...arguments);
}
return conttextObj[fn](...args, ...arguments);
};
};
const test = {
name: "xxx",
hello: function (a,b,c) {
console.log(`hello,${this.name}!`,a+b+c);
},
};
const obj = { name: "world" };
let hello1 = test.hello.myBind(obj,1);
let hello2 = test.hello.bind(obj,1);
hello1(2,3)
hello2(2,3)
console.log(new hello1(2,3));
console.log(new hello2(2,3));
手写new
function myNew(fn, ...args) {
if (typeof fn !== 'function') {
throw 'fn must be a function';
}
const obj = Object.create(fn.prototype);
const result = fn.apply(obj, args);
return result && typeof result === 'object' ? result : obj;
}
function myNew(fn, ...args) {
if (typeof fn !== 'function') {
throw 'fn must be a function';
}
const obj = Object.create(null);
Object.setPrototypeOf(obj, fn.prototype);
const result = fn.apply(obj, args);
return result && typeof result === 'object' ? result : obj;
}
function myNew(fn, ...args) {
if (typeof fn !== 'function') {
throw 'fn must be a function';
}
const obj = {};
obj.__proto__ = fn.prototype;
const result = fn.apply(obj, args);
return result instanceof Object ? result : obj;
}
手写instanceof
function myInstanceof(obj, ctor) {
let proto = Object.getPrototypeOf(obj);
const ctorProto = ctor.prototype;
while (true) {
if (!proto) {
return false;
}
if (proto === ctorProto) {
return true;
}
proto = Object.getPrototypeOf(proto);
}
}
简单的双向绑定
const input = document.getElementById('input')
const span = document.getElementById('span')
let obj = {}
input.onchange = function inputChange(e) {
obj.text = e.target.value
}
Object.defineProperty(obj, 'text', {
configurable: true,
enumerable: true,
get() {
return obj.text
},
set(newVal) {
span.innerText = newVal
}
})
const input = document.getElementById('input')
const p = document.getElementById('p')
const obj = {}
const newObj = new Proxy(obj, {
get: function(target, key, receiver) {
console.log(`getting ${key}!`)
return Reflect.get(target, key, receiver)
},
set: function(target, key, value, receiver) {
console.log(target, key, value, receiver)
if (key === 'text') {
input.value = value
p.innerHTML = value
}
return Reflect.set(target, key, value, receiver)
},
})
input.addEventListener('keyup', function(e) {
newObj.text = e.target.value
})
手写Object.create
function create(obj) {
function F() {}
F.prototype = obj;
return new F();
}
请求并发控制
function concurrentReq(urls, limit) {
return new Promise((resolve, reject) => {
let num = 0;
let task = urls;
let results = [];
function goNext() {
if (task.length === 0 && num === 0 ) {
resolve(results);
return;
}
while (num < limit && task.length > 0) {
let url = task.shift();
num = num + 1
axios.get(url)
.then((res) => {
num = num - 1
results.push(res.data);
goNext();
})
.catch((err) => {
num = num - 1
console.error(`此接口:${url}请求失败,报错信息:${err}`);
goNext();
})
}
}
goNext();
});
}
let urls = [
'http://ashuai.work/api/getIdName?id=1',
'http://ashuai.work/api/getIdName?id=2',
'http://ashuai.work/api/getIdName?id=3',
'http://ashuai.work/api/getIdName?id=4',
'http://ashuai.work/api/getIdName?id=5',
'http://ashuai.work/api/getIdName?id=6',
'http://ashuai.work/api/getIdName?id=7',
'http://ashuai.work/api/getIdName?id=8',
'http://ashuai.work/api/getIdName?id=9',
'http://ashuai.work/api/getIdName?id=10',
'http://ashuai.work/api/getIdName?id=11',
'http://ashuai.work/api/getIdName?id=12',
'http://ashuai.work/api/getIdName?id=13',
'http://ashuai.work/api/getIdName?id=14',
'http://ashuai.work/api/getIdName?id=15',
'http://ashuai.work/api/getIdName?id=16',
'http://ashuai.work/api/getIdName?id=17',
'http://ashuai.work/api/getIdName?id=18',
]
let limit = 3;
concurrentReq(urls, limit)
.then((results) => {
console.log('所有请求执行结果:', results);
})
.catch((error) => {
console.error('请求执行出错:', error);
});
使用Promise封装Ajax请求
function getJSON(url) {
let promise = new Promise(function(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.response);
} else {
reject(new Error(this.statusText));
}
};
xhr.onerror = function() {
reject(new Error(this.statusText));
};
xhr.responseType = "json";
xhr.setRequestHeader("Accept", "application/json");
xhr.send(null);
});
return promise;
}
手写判断类型函数
function getType(value) {
if (typeof value !== 'object') {
return typeof value;
}
return Object.prototype.toString.call(value).slice(8, -1).toLocaleLowerCase();
}
解析URL为对象
function parseParam(url) {
const paramsStr = /.+\?(.+)$/.exec(url)[1];
const paramsArr = paramsStr.split('&');
let paramsObj = {};
paramsArr.forEach(param => {
if (/=/.test(param)) {
let [key, val] = param.split('=');
val = decodeURIComponent(val);
val = /^\d+$/.test(val) ? parseFloat(val) : val;
if (paramsObj.hasOwnProperty(key)) {
paramsObj[key] = [].concat(paramsObj[key], val);
} else {
paramsObj[key] = val;
}
} else {
paramsObj[param] = true;
}
})
return paramsObj;
}
Promise实现图片加载
function loadImage(url) {
return new Promise((resolve, reject) => {
let img = new Image()
img.onload = () => {
resolve(img)
}
img.onerror = (error) => {
reject(error)
}
img.src = url
})
}
// 使用方式
loadImage('https://example.com/path/to/image.jpg')
.then(img => {
document.body.appendChild(img)
console.log('图片加载成功')
})
.catch(error => {
console.error('图片加载失败', error)
})