// 1、选择排序/冒泡排序
const arr = [3, 1, 4, 5, 9, 2, 6, 8, 7, 0]
/* 选择排序 */
function fn1() {
/* 选择排序 */
let temp
// 依次选择椅子
for (let p = 0
// 选中第0位 将最小的元素置换到第0位
let smallest = arr[p]
let smallestIndex = p
for (let i = p
if (arr[i] < smallest) {
smallest = arr[i]
smallestIndex = i
}
}
temp = arr[p]
arr[p] = smallest
arr[smallestIndex] = temp
}
console.log(arr)
}
// fn1()
/* 冒泡排序 */
function fn2() {
let temp
/* 外层循环由8递减为0 */
for (let j = arr.length - 2
/* 通过相邻元素元素两两冒泡 将最大元素冒泡到末尾 */
for (let i = 0
if (arr[i] > arr[i + 1]) {
temp = arr[i]
arr[i] = arr[i + 1]
arr[i + 1] = temp
}
}
}
console.log(arr)
}
// fn2()
// 2、深拷贝
function fn14(data) {
let copy
if (typeof (data) === 'function' || typeof (data) !== 'object') {
return data
} else if (Array.isArray(data)) {
copy = []
data.forEach(function (item, index) {
copy[index] = fn14(item)
})
return copy
} else {
copy = {}
for (let key in data) {
copy[key] = fn14(data[key])
}
return copy
}
}
//3、手撸函数防抖与节流
const inputHandler = function (e) {
console.log(e.target);
console.log(e.target.value);
};
ip.addEventListener(
"input",
mydebounce(inputHandler, 1000)
);
function mydebounce(fn, delay) {
let timer = null;
return function (...args) {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.apply(null, args);
timer = null;
}, delay);
};
}
//节流
const clickHandler = function (e) {
console.log("hello");
};
btn.addEventListener(
"click",
mythrottle(clickHandler, 1000)
);
function mythrottle(fn, delay) {
let timer = null;
return function (...args) {
if (!timer) {
fn.apply(null, args);
timer = setTimeout(() => {
timer = null;
}, delay);
}
};
}
节流使用时间戳
function mythrottle(fn, delay) {
let forbidden = false;
return function (...args) {
if (!forbidden) {
fn.apply(null, args);
forbidden = true;
setTimeout(() => {
forbidden = false;
}, delay);
}
};
}
// 4、使用连环异步回调实现求5的阶乘:
function fn1() {
const multiply = (a, b, callback) => {
setTimeout(() => callback(a * b), 2000);
};
const mulPromise = (a, b) => {
return new Promise(
(resolve, reject) => {
multiply(a, b, (ret) => resolve(ret));
}
);
};
mulPromise(2, 3)
.then((ret) => 6 * 4)
.then((ret) => mulPromise(ret, 5))
.then((ret) => console.log("ret=", ret));
~(async function awaitDemo() {
try {
let ret = await mulPromise(2, 3);
ret = await mulPromise(ret, 4);
ret = await mulPromise(ret, 5);
console.log(ret);
} catch (err) {
console.log("err=", err);
}
})();
}
// 5、提取URL中的查询参数
function getSearchParams(url) {
const obj = {};
const reg = /\w+=\w+/g
const arr = url.match(reg)
arr.forEach((item) => {
let [key, value] = item.split("=");
obj[key] = value
});
return obj;
}
// 6、封装ajax,实现POST一个表单
~ function () {
function getSearchParams(url = '') {
const obj = {}
url.match(/\w+=\w+/g).forEach(str => {
let [key, value] = str.split('=')
obj[key] = value
})
return obj
}
function toGetParams(obj) {
let str = ''
for (let key in obj) {
str += `&${key}=${obj[key]}`
}
return str.slice(1)
}
function ajax({
url,
method,
data,
dataType,
onSuccess,
onFail
}) {
const xhr = new XMLHttpRequest()
if (!url) {
throw new Error('没给url')
}
method = method || 'GET'
onSuccess = onSuccess || (data => console.log('default onSuccess:', data))
onFail = onFail || (err => console.log('default onFail:', err))
xhr.open(method, url)
let reqBody = null
switch (true) {
case dataType == 'form':
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
reqBody = toGetParams(data)
break
case dataType == 'json':
xhr.setRequestHeader('Content-Type', 'application/json')
reqBody = JSON.stringify(data)
break
default:
break
}
xhr.onload = () => onSuccess(xhr.responseText)
xhr.onerror = err => onFail(err)
xhr.send(reqBody)
}
function ajaxPromise(config) {
return new Promise((resolve, reject) => {
ajax({
...config,
onSuccess: data => resolve(data),
onFail: err => reject(err),
})
})
}
ajaxPromise({
url: 'http://www.httpbin.org/post',
method: 'POST',
dataType: 'form',
data: {
name: 'admin',
pwd: '123456'
},
})
.then(data => console.log(data))
.catch(err => console.log(err))
}
// 7、带有超时功能的Promise
function fn2() {
function executeWithTimeout(ajaxPromise, ms) {
return new Promise((resolve, reject) => {
let timer = setTimeout(() => {
reject("timeout");
}, ms);
ajaxPromise()
.then((data) => {
clearTimeout(timer);
resolve(data);
});
});
}
function ajaxPromise() {
return new Promise((resolve) =>
setTimeout(() => {
resolve(`来自淘宝的数据`);
}, 1000)
);
}
executeWithTimeout(ajaxPromise, 3000)
.then((data) => console.log(data))
.catch((err) => console.log(err));
}
function fn2X() {
async function executeWithTimeout(fn, ms) {
return new Promise(async (resolve, reject) => {
let timer = setTimeout(() => {
reject("timeout");
}, ms);
const data = await fn();
clearTimeout(timer);
resolve(data);
});
}
const timeout = 5000;
function rq(url) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(`来自${url}的数据`);
}, timeout);
});
}
async function fn1() {
return rq("https://www.taobao.com");
}
executeWithTimeout(fn1, 3000)
.then((value) => console.log("value=", value))
.catch((err) => console.log("err=", err));
}
// 7、一次性获取多个指定页面
function fn3() {
async function getContentByUrl(url) {
return new Promise((resolve, reject) =>
setTimeout(() => {
Math.random() > 0.5 ? resolve(`${url}的页面内容`) : reject("timeout");
}, 1000)
);
}
const urls = [
"https://www.taobao.com",
"https://www.baidu.com",
"https://web.taobao.com",
];
async function fetchDataSplited(urls = []) {
urls = urls.filter((url) => url.endsWith("taobao.com"));
const ajaxPromises = urls.map((url) => getContentByUrl(url));
const allSettledPromise = Promise.allSettled(ajaxPromises);
return allSettledPromise;
}
async function fetchData(urls = []) {
return Promise.allSettled(
urls
.filter((url) => url.endsWith("taobao.com"))
.map((url) => getContentByUrl(url))
);
}
fetchData(urls)
.then((results) => console.log(results));
}
fn3();
// 8、IP地址比大小
function fn1() {
function compare(ip1 = "", ip2 = "") {
const arr1 = ip1.split(".").map((item) => item * 1);
const arr2 = ip2.split(".").map((item) => item * 1);
for (let i = 0; i < arr1.length; i++) {
if (arr1[i] > arr2[i]) {
return 1;
}
if (arr1[i] < arr2[i]) {
return -1;
}
}
return 0;
}
console.log(compare("1.2.3.4", "1.1.3.4"));
console.log(compare("1.11.3.4", "1.2.3.4"));
console.log(compare("1.2.3.4", "1.11.3.4"));
console.log(compare("1.2.3.4", "1.2.3.4"));
}
// 9、实现闭包管理全班学生成绩
function score(name) {
const scores = {
chinese: 0,
math: 0,
coding: 0,
};
return {
set(key, value) {
scores[key] = value;
},
getAll() {
return `${name}:${JSON.stringify(scores)}`;
},
};
}
const arr1 = ["张三疯", "尼古拉斯赵四", "隔壁老王"]
const obj = {}
arr1.forEach(
name => obj[name] = scrore(name)
)
// 10、手封MyMap实现以下效果
class MyMap {
constructor() {
this.obj = {};
this.size = 0;
}
set(key, value) {
this.obj[key] = value;
this.updateSize();
}
get(key) {
return this.obj[key];
}
updateSize() {
this.size = Object.keys(this.obj).length;
}
delete(key) {
delete this.obj[key];
this.updateSize();
}
clear() {
this.obj = {};
this.size = 0;
}
has(key) {
return this.obj.hasOwnProperty(key);
}
forEach(handler) {
for (let key in this.obj) {
handler.apply(this, [this.obj[key], key, this]);
}
}
keys() {
return Object.keys(this.obj);
}
values() {
return Object.keys(this.obj).map((key) => this.obj[key]);
}
entries() {
return Object.keys(this.obj).map(
(key) => ({
key,
value: this.obj[key]
})
);
}
}
~(function () {
const map = new MyMap()
ap.setm("name", "张三")
map.set("age", 20)
map.set("gender", "男")
map.forEach(
(value, key) => console.log(key, value)
)
for (let entry of map.entries()) {
console.log(entry)
}
console.log(map.size)
console.log(map.get("name"))
console.log(map.get("age"))
console.log(map.has("name"))
console.log(map.has("myname"))
map.delete("age")
map.clear()
console.log(map.size)
})
// 11、全班人马排除空座位后抽取N名幸运观众
function fn3() {
let stus = []
for (let i = 1
stus.push(i)
}
/* 排除 */
const empties = [12, 34, 56, 78]
stus = stus.filter((s) => empties.indexOf(s) === -1)
// console.log(stus)
/* 抽人头 */
const pick = (arr, n) => {
// 幸运观众
let luckies = []
// 算法一:只要幸运观众的人头数还不满N 就一直循环
// while (luckies.length < n) {
// // 随机抽取幸运观众的序号
// let randomIndex = parseInt(Math.random() * arr.length)
// let stu = stus[randomIndex]
// // 如果幸运观众中不含stu 就将stu丢入
// !luckies.includes(stu) && luckies.push(stu)
// }
/* 算法二:只允许循环N次 每次弹出一个元素 */
for(let i=0
let randomIndex = parseInt(Math.random() * arr.length)
// [24].concat([1,2,3])
luckies = arr.splice(randomIndex,1).concat(luckies)
}
// 丢还幸运观众数组
return luckies
}
console.log(pick(stus, 5))
}
// fn3()
// 12、手撸观察者模式:实现彩票机周期性地发布【开售】【开奖】事件,玩家开售时下注,开奖时购买,一旦中奖则彩票机停止工作;
function observerDemo() {
class Observable {
constructor(name) {
this.name = name;
this.observers = [];
}
register(ob) {
this.observers.push(ob);
ob.observable = this;
}
unregister(ob) {
this.observers = this.observers.filter((o) => o !== ob);
}
emit(event) {
this.observers.forEach((ob) => ob.onEvent(event));
}
}
class Observer {
constructor(name) {
this.name = name;
}
onEvent(event) {
console.log(this.name, "响应事件", event);
}
}
class Lottery extends Observable {
constructor(name) {
super(name);
this.timer = null;
}
start() {
if (!this.timer) {
this.timer = setInterval(() => {
const code = parseInt(Math.random() * 3);
console.log(this.name, "发布开奖事件", code);
this.emit({ type: "开奖", code });
this.emit({ type: "开售" });
}, 2000);
}
}
stop() {
if (this.timer) {
clearInterval(this.timer);
console.log(this.name, "已停止");
this.timer = null;
}
}
}
class Player extends Observer {
constructor(name) {
super(name);
this.code = null;
}
buy() {
this.code = parseInt(Math.random() * 3);
console.log(this.name, "下注", this.code);
}
check(event) {
const isLucky = this.code === event.code;
console.log(this.name, isLucky ? "中奖了" : "未中奖");
isLucky && this.observable.stop();
}
onEvent(event) {
super.onEvent(event);
switch (event.type) {
case "开售":
this.buy();
break;
case "开奖":
this.check(event);
break;
default:
break;
}
console.log("");
}
}
~(function main() {
const lot = new Lottery("六合彩");
const tiger = new Player("打老虎");
const gaojin = new Player("高进");
lot.register(tiger);
lot.register(gaojin);
lot.unregister(gaojin);
lot.start();
})();
}
// 13、实现任意多个入参的函数fn的柯里化
function curryDemo() {
const curry = (fn) => {
return function cfn(...args) {
if (args.length === fn.length) {
return fn.apply(null, args);
}
return function (...b) {
args = args.concat(b);
return cfn(...args);
};
};
};
const cadd = curry(add);
console.log(cadd(1, 2, 3, 4));
console.log(cadd(1, 2)(3)(4));
}
// 14、实现任意多个函数的管道与组合
function pipeDemo() {
const pipe = (...fns) => (v => fns.reduce(
(pv,fn,index)=>fn(pv),
v
))
const compose = (...fns) => (v => fns.reverse().reduce(
(pv,fn,index)=>fn(pv),
v
))
const len = (n) => (n + "").length;
const pow = (n) => n * n;
const cubicRoot = (n) => Math.cbrt(n);
console.log(pipe(len, pow, cubicRoot)(10));
console.log(compose(len, pow, cubicRoot)(1000));
}
// 15、函数的Promise化
async function promDemo() {
function promisify(fn){
return function(...args){
return new Promise(
(resolve,reject)=>{
try {
resolve(fn.apply(null,args))
} catch (err) {
reject(err)
}
}
)
}
}
const add = (a, b, c, d) => {
if(Math.random() > 0.7) {
throw new Error("人品槽已空,请尽快充100块钱的人品")
}
return a + b + c + d
}
const pow = (a, b) => {
if(Math.random() > 0.7) {
throw new Error("人品槽已空,请尽快充100块钱的人品")
}
return Math.pow(a,b)
}
const padd = promisify(add)
const ppow = promisify(pow)
try {
let data = await padd(1,2,3,4)
console.log("data=",data)
data = await ppow(data,2)
console.log("data=",data)
} catch (err) {
console.error("err=",err)
}
}
// 16、封装MongoDB数据引擎层
async function fn3() {
function getCollection(dbName, collectionName) {
return new Promise(
(resolve, reject) => {
var MongoClient = require("mongodb").MongoClient;
var url = "mongodb://localhost:27017/";
MongoClient.connect(url, function (err, conn) {
if (err) {
resolve({
err,
collection: undefined,
conn: undefined,
});
return;
}
var dbo = conn.db(dbName);
const collection = dbo.collection(collectionName);
resolve({
err: undefined,
collection,
conn,
});
});
}
);
}
async function doCreate(dbName, collectionName, dataObj) {
const { err, collection, conn } = await getCollection(
dbName,
collectionName
);
if (err) {
return {
err,
res: undefined,
};
}
collection.insertOne(dataObj, function (err, res) {
conn.close();
return {
err,
res,
};
});
}
async function addUser(user) {
const ret = await doCreate(dbName, collectionName, user);
return ret;
}
}
Promise求阶乘
function fn1() {
const multiply = (a, b, callback) => {
setTimeout(() => callback(a * b), 2000);
};
const mulPromise = (a, b) => {
return new Promise(
(resolve, reject) => {
multiply(a, b, (ret) => resolve(ret));
}
);
};
mulPromise(2, 3)
.then((ret) => 6 * 4)
.then((ret) => mulPromise(ret, 5))
.then((ret) => console.log("ret=", ret));
~(async function awaitDemo() {
try {
let ret = await mulPromise(2, 3);
ret = await mulPromise(ret, 4);
ret = await mulPromise(ret, 5);
console.log(ret);
} catch (err) {
console.log("err=", err);
}
})();
}
函数的Promise化
function fn2() {
function add(a, b) {
return a + b;
}
function multiply(a, b, callback) {
setTimeout(() => callback(a * b), 1000);
}
function promisify(fn) {
return function pfn(...args) {
return new Promise(
(resolve, reject) => {
const ret = fn.apply(null, [...args, (...a) => resolve(a)]);
ret && resolve(ret);
}
);
};
}
const pmul = promisify(multiply);
pmul(2, 3)
.then((values) => {
console.log("value=", values);
return pmul(values[0], 4);
})
.then((values) => {
console.log("value=", values);
return pmul(values[0], 5);
})
.then((values) => console.log(values[0]));
}
- 调用一次的函数柯里化
~function fn1(){
const once = (fn)=>{
let flag = false
return function(...args){
if(!flag){
let ret = fn(...args)
flag = true
return ret
}else{
console.log('函数以调用过了!');
}
}
}
const add =(a,b)=>a+b
const addonce = once(add)
console.log(addonce(2,3));
console.log(addonce(3,3));
console.log(addonce(7,3));
}()
</script>
<!-- 高级函数,参数是函数,返回值为函数,只可以调用一次函数 -->