<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="text" id="ip" />
<button id="btn">点哥</button>
<input type="text" placeholder="请输入要查询的学生姓名" id="ip" />
<button id="btnSet">设置成绩</button>
<button id="btnGet">查询成绩</button>
<p id="pInfo">成绩显示区</p>
<h3 id="hMyname">{name}</h3>
<p id="pMyname">{name}</p>
<h3 id="hMyage">{age}</h3>
<p id="pMyage">{age}</p>
<p id="pGender">{gender}</p>
</body>
<script>
// 1、选择排序
const arr = [3, 4, 2, 5, 1, 6, 8, 7, 9]
function fn() {
let temp
for (let p = 0; p <= arr.length - 2; p++) {
let smallest = arr[p]
let smallestIndex = p
for (let i = p; i <= arr.length; i++) {
if (arr[i] < arr[smallestIndex]) {
smallest = arr[i]
smallestIndex = i
}
}
temp = arr[p]
arr[p] = smallest
arr[smallestIndex] = temp
}
console.log(arr);
}
//冒泡排序
(function fn() {
let temp
for (let j = arr.length - 2; j >= 0; j--) {
for (let i = 0; i <= j; i++) {
if (arr[i] > arr[i + 1]) {
temp = arr[i]
arr[i] = arr[i + 1]
arr[i + 1] = temp
}
}
}
console.log(arr);
})
// 2、深拷贝
(function fn(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] = fn(item)
})
return copy
} else {
copy = {}
for (let key in data) {
copy[key] = fn(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)
}
}
}
// 4、使用连环异步回调实现求5的阶乘:
(function fn() {
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) => mulPromise(ret, 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
}
// obj = {
// name: 'heige',
// age: 12
// }
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)
}
// try {
// ajax({
// url: 'http://www.httpbin.org/post',
// method: 'POST',
// dataType: 'form',
// data: { name: 'admin', pwd: '123456' },
// onSuccess: data => console.log(data),
// onFail: err => console.log(err)
// })
// } catch (err) {
// console.log('catch err:', err);
// }
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 fn() {
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));
}
// 8、一次性获取多个指定页面
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 fetchData(urls = []) {
return Promise.allSettled(
urls
.filter((url) => url.endsWith("taobao.com"))
.map((url) => getContentByUrl(url))
);
}
fetchData(urls)
.then((results) => console.log(results));
}
// 9、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"));
}
// 10、实现闭包管理全班学生成绩
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)
)
btnSet.onclick = function(){
let [name,key,value] = ip.value.split(":")
obj[name].set(key,value)
}
btnGet.onclick = function(){
const name = ip.value
pInfo.innerText = obj[name].getAll()
}
// 11、手封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()
map.set("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)
})
// 12、全班人马排除空座位后抽取N名幸运观众
function fn3() {
let stus = [];
for (let i = 1; i < 100; i++) {
stus.push(i);
}
const empties = [12, 34, 56, 78];
stus = stus.filter((s) => empties.indexOf(s) === -1);
const pick = (arr, n) => {
let luckies = [];
for (let i = 0; i < n; i++) {
let randomIndex = parseInt(Math.random() * arr.length);
luckies = arr.splice(randomIndex, 1).concat(luckies)
}
return luckies;
};
console.log(pick(stus, 5));
}
// fn3();
// 13、手撸观察者模式:实现彩票机周期性地发布【开售】【开奖】事件,玩家开售时下注,开奖时购买,一旦中奖则彩票机停止工作;
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();
})();
}
// observerDemo();
// 14、实现任意多个入参的函数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));
}
// curryDemo();
// 15、实现任意多个函数的管道与组合
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(compose(len, pow, cubicRoot)(1000));
}
// pipeDemo();
// 16、函数的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)
// padd(1,2,3,4).then(
// data => {
// console.log("data=",data)
// return ppow(data,2)
// }
// )
// .then(
// data => console.log("data=",data)
// )
// .catch(
// err => console.error("err=",err)
// )
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)
}
}
// promDemo()
// 17、封装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;
}
}
// fn3();
//18、异步函数的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);
}
);
};
}
/* 同步返回函数的Promise化 */
// const padd = promisify(add);
// padd(2, 3).then(
// (value) => console.log("value=", value) //5
// );
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]));
}
// fn2();
//19、 手撸数据驱动视图微框架
function defineReactive(data, keys = []) {
keys.forEach(
({
name,
listeners
}) => {
Object.defineProperty(data, name, {
get() {
console.log("get", name);
return data[`x_${name}`];
},
set(newValue) {
console.log("set", name, newValue);
data[`x_${name}`] = newValue;
listeners.forEach((dom) => (dom.innerText = newValue));
},
});
}
);
}
const data = {};
defineReactive(data, [{
name: "age",
listeners: [hMyage, pMyage]
},
{
name: "name",
listeners: [hMyname, pMyname]
},
{
name: "gender",
listeners: [pGender]
},
]);
data.name = "黑哥";
data.age = 18;
data.gender = "男";
setInterval(() => {
data.name = Date.now();
data.age = data.age + 1;
data.gender = data.gender === "男" ? "女" : "男";
}, 1000);
//20、数组APIreduce
const arr12=[1,2,3,4]
const initialValue=0
const sunWithInitial=arr12.reduce((previousValue,currentValue)=>previousValue+currentValue,initialValue)
console.log(sunWithInitial);
</script>
</html>