10个常考的前端手写题,你全都会吗?
前言
📫 大家好,我是南木元元,热爱技术和分享,欢迎大家交流,一起学习进步!
🍅 个人主页:南木元元
今天来分享一下10个常见的JavaScript手写功能。
目录
1.实现new
2.call、apply、bind
实现call
实现apply
实现bind
3.防抖和节流
防抖
节流
4.实现instanceof
5.实现Ajax
6.深拷贝和浅拷贝
浅拷贝
深拷贝
7.函数柯里化
参数定长的柯里化
参数不定长的柯里化
8.数组扁平化
9.数组去重
10.手写类型判断函数
结语
1.实现new
(1)首先创建一个新的空对象。
(2)设置原型,将对象的原型设置为函数的prototype对象。
(3)让函数的this指向这个对象,执行构造函数的代码。
(4)判断函数的返回值类型,如果是值类型,返回创建的对象。如果是引用类型,就返回这个引用类型的对象。
function myNew(constructor, ...args) {// 如果不是一个函数,就报错if (typeof constructor !== "function") {throw "myNew function the first param must be a function";}// 基于原型链 创建一个新对象,继承构造函数constructor的原型对象上的属性let newObj = Object.create(constructor.prototype);// 将newObj作为this,执行 constructor ,传入参数let res = constructor.apply(newObj, args);// 判断函数的执行结果是否是对象,typeof null 也是'object'所以要排除nulllet isObject = typeof res === "newObject" && res !== null;// 判断函数的执行结果是否是函数let isFunction = typeof res === "function";// 如果函数的执行结果是一个对象或函数, 则返回执行的结果, 否则, 返回新创建的对象return isObject || isFunction ? res : newObj;
}// 用法
function Person(name, age) {this.name = name;this.age = age;// 如果构造函数内部,return 一个引用类型的对象,则整个构造函数失效,而是返回这个引用类型的对象
}
Person.prototype.say = function() {console.log(this.age);
};
let p1 = myNew(Person, "poety", 18);
console.log(p1.name); //poety
console.log(p1); //Person {name: 'poety', age: 18}
p1.say(); //18
测试结果:
2.call、apply、bind
实现call
思路:接受传入的context上下文,如果不传默认为window,将被调用的方法设置为上下文的属性,使用上下文对象来调用这个方法,删除新增属性,返回结果。
//写在函数的原型上
Function.prototype.myCall = function (context) {// 如果要调用的方法不是一个函数,则报错if (typeof this !== "function") {throw new Error("Type error");}// 判断 context 是否传入,如果没有传就设置为 windowcontext = context || window;// 获取参数,[...arguments]把类数组转为数组let args = [...arguments].slice(1);let result = null;// 将被调用的方法设置为context的属性,this即为要调用的方法context.fn = this;// 执行要被调用的方法result = context.fn(...args);// 删除手动增加的属性方法delete context.fn;// 将执行结果返回return result;
};//测试
function f(a,b){console.log(a+b)console.log(this.name)
}
let obj={name:1
}
f.myCall(obj,1,2) // 3,1
测试结果:
实现apply
除了传参方式是数组,其它与call没区别。
Function.prototype.myApply = function (context) {if (typeof this !== "function") {throw new Error("Type error");}let result = null;context = context || window;// 与上面代码相比,我们使用 Symbol 来保证属性唯一,也就是保证不会重写用户自己原来定义在 context 中的同名属性const fnSymbol = Symbol();context[fnSymbol] = this;// 执行要被调用的方法,处理参数和 call 有区别,判断是否传了参数数组if (arguments[1]) {//传了参数数组result = context[fnSymbol](...arguments[1]);} else {//没传参数数组result = context[fnSymbol]();}delete context[fnSymbol];return result;
};//测试
function f(a,b){console.log(a,b)console.log(this.name)
}
let obj={name:'张三'
}
f.myApply(obj,[1,2]) //1 2,张三
测试结果:
实现bind
bind返回的是一个函数,需要判断函数作为构造函数的情况,当作为构造函数时,this 指向实例,不会被任何方式改变 this,所以要忽略传入的context上下文。
bind可以分开传递参数,所以需要将参数拼接。
如果绑定的是构造函数,还需要继承构造函数原型上的属性和方法,保证不丢失。
Function.prototype.myBind = function (context) {// 判断调用对象是否为函数if (typeof this !== "function") {throw new Error("Type error");}// 获取参数const args = [...arguments].slice(1);const fn = this; // 保存this的值,代表调用bind的函数//返回一个函数,此函数可以被作为构造函数调用,也可以作为普通函数调用const Fn = function () {// 根据调用方式,传入不同绑定值// 当作为构造函数时,this 指向实例,不会被任何方式改变 this,要忽略传入的context上下文return fn.apply(this instanceof Fn ? this : context,// bind可以分开传递参数(如f.bind(obj, 1)(2)),所以需要将参数拼接,这里使用apply,参数拼接成一个数组args.concat(...arguments)//当前的这个 arguments 是指 Fn 的参数,也可以用剩余参数的方式);};//对于构造函数,要保证原函数的原型对象上的属性不能丢失Fn.prototype = Object.create(fn.prototype);return Fn;
};// 1.先测试作为构造函数调用
function Person(name, age) {console.log(name);console.log(age);console.log(this); //构造函数this指向实例对象
}
// 构造函数原型的方法
Person.prototype.say = function () {console.log("say");
};
var obj = {name: "cc",age: 18,
};
var bindFun = Person.myBind(obj, "cxx");
var a = new bindFun(10);
// cxx
// 10
// Person {}
a.say(); // say// 2.再测试作为普通函数调用
function normalFun(name, age) {console.log(name);console.log(age);console.log(this); // 普通函数this指向绑定bind的第一个参数 也就是例子中的obj
}
var obj = {name: "aa",age: 18,
};
var bindNormalFun = normalFun.myBind(obj, "cc");
bindNormalFun(12);
// cc
// 12
// { name: 'aa', age: 18 }
测试结果:
3.防抖和节流
防抖
防抖是指在事件被触发 n 秒后再执行回调,如果在这 n 秒内事件又被触发,则重新计时。可以使用在一些点击请求的事件上,避免因为用户的多次点击向后端发送多次请求。
//fn是需要防抖的函数,delay是等待时间
function debounce(fn, delay = 500) {let timer = null;// 这里返回的函数是每次用户实际调用的防抖函数return function(...args) { //...args是es6的剩余参数语法,将多余的参数放入数组,用来代替arguments对象// 如果已经设定过定时器了就清空上一次的定时器if(timer) {clearTimeout(timer); }// 开始一个新的定时器,延迟执行用户传入的方法;注:定时器的返回值是一个数值,作为定时器的编号,可以传入clearTimeout来取消定时器timer = setTimeout(() => { //这里必须是箭头函数,不然this指向window,要让this就指向fn的调用者fn.apply(this, args); }, delay) }
}
节流
节流就是一定时间内只执行一次事件,即使重复触发,也只有一次生效。可以使用在监听滚动scroll事件上,通过事件节流来降低事件调用的频率。
- 定时器版本
function throttle(fn, delay = 500) {let timer = null;return function(...args) {// 当前有任务了,直接返回if(timer) {return;}timer = setTimeout(() => {fn.apply(this, args);//执行完后,需重置定时器,不然timer一直有值,无法开启下一个定时器timer = null; }, delay)}
}
- 时间戳版本
// 节流
function throttle(fn, delay = 500) {let prev = Date.now();// 上一次执行该函数的时间return function(...args) {let now = Date.now();//返回从UTC到当前时间的毫秒数// 如果差值大于等于设置的等待时间就执行函数if (now - prev >= delay) {fn.apply(this, args);prev = Date.now();}};
}
详细可以去看我的这篇文章——前端性能优化之防抖&节流
4.实现instanceof
instanceof用于检测构造函数的prototype
属性是否出现在某个实例对象的原型链上。
function myInstanceof(instance, constructor) {//如果不是对象,或者是null,直接返回falseif (typeof instance !== "object" || instance === null) {return false;}// 获取对象的原型let proto = Object.getPrototypeOf(instance);// 获取构造函数的 prototype 对象let prototype = constructor.prototype;// 判断构造函数的 prototype对象是否在对象的原型链上while (true) {// 到达原型链终点null,说明没找到if (!proto) {return false;}if (proto === prototype) {return true;}// 如果没有找到,就继续从其原型上找proto = Object.getPrototypeOf(proto);}
}//测试
let Fn = function () { }
let p1 = new Fn()
console.log(myInstanceof(p1, Fn));//true
console.log(myInstanceof([], Fn));//false
console.log(myInstanceof([], Array)) // true
console.log(myInstanceof(function(){}, Function)) // true
测试结果:
5.实现Ajax
(1)创建一个 XMLHttpRequest 对象。
(2)在这个对象上使用 open 方法创建一个 HTTP 请求(参数为请求方法、请求地址、是否异步和用户的认证信息)。
(3)通过send方法来向服务器发起请求(post请求可以入参数作为发送的数据体)。
(4)监听请求成功后的状态变化:根据状态码进行相应的处理。onreadystatechange设置监听函数,当对象的readyState变为4的时候,代表服务器返回的数据接收完成,这个时候可以通过判断请求的状态,如果状态是200则代表成功,404或500代表失败。
function ajax(url) {//1.创建XMLHttpRequest对象const xhr = new XMLHttpRequest();//2.使用open方法创建一个GET请求xhr.open('GET',url);//xhr.open('GET',url,true);//true代表异步,已完成事务的通知可供事件监听器使用;如果为false,send() 方法直到收到答复前不会返回//3.发送请求xhr.send(); //4.监听请求成功后的状态变化(readyState改变时触发):根据状态码(0~5)进行相应的处理xhr.onreadystatechange = function () {//readyState为4代表服务器返回的数据接收完成if (xhr.readyState == 4) { //请求的状态为200或304代表成功if(xhr.status == 200 || xhr.status == 304) {//this.response代表返回的数据handle(this.response);} else {//this.statusText代表返回的文本信息console.error(this.statusText);}}};
}
使用Promise封装AJAX:
function ajax(url) {return new Promise((resolve, reject) => {let xhr = new XMLHttpRequest()xhr.open('get', url)xhr.send() xhr.onreadystatechange = () => {if (xhr.readyState == 4) {if (xhr.status == 200 || xhr.status == 304) {resolve(this.response)} else {reject(new Error(this.statusText));}}}})
}
//使用
let url = '/data.json'
ajax(url).then(res => console.log(res)).catch(reason => console.log(reason))
6.深拷贝和浅拷贝
浅拷贝
浅拷贝是创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。
//实现浅拷贝
function shallowCopy (obj){// 只拷贝对象,基本类型或null直接返回if(typeof obj !== 'object' || obj === null) {return obj;}// 判断是新建一个数组还是对象let newObj = Array.isArray(obj) ? []: {};//for…in会遍历对象的整个原型链,如果只考虑对象本身的属性,需要搭配hasOwnPropertyfor(let key in obj ){//hasOwnProperty判断是否是对象自身属性,会忽略从原型链上继承的属性if(obj.hasOwnProperty(key)){newObj[key] = obj[key];//只拷贝对象本身的属性}}return newObj;
}//测试
var obj ={name:'张三',age:8,pal:['王五','王六','王七']
}
let obj2 = shallowCopy(obj);
obj2.name = '李四'
obj2.pal[0] = '王麻子'
console.log(obj); //{age: 8, name: "张三", pal: ['王麻子', '王六', '王七']}
console.log(obj2); //{age: 8, name: "李四", pal: ['王麻子', '王六', '王七']}
测试结果:
深拷贝
深拷贝是将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象。
function deepCopy (obj, map = new WeakMap()){// 基本类型或null直接返回if(typeof obj !== 'object' || obj === null) {return obj;}// 判断是新建一个数组还是对象let newObj = Array.isArray(obj) ? []: {};//利用map解决循环引用if (map.has(obj)) {return map.get(obj);}map.set(obj, newObj);//将当前对象作为key,克隆对象作为valuefor(let key in obj ){ if(obj.hasOwnProperty(key)){newObj[key] = deepCopy(obj[key], map); //递归}}return newObj
}// 测试
let obj1 = {name : '南木元元',arr : [1,[2,3],4],
};
let obj2=deepCopy(obj1)
obj2.name = "阿元";
obj2.arr[1] = [5,6,7] ; // 新对象跟原对象不共享内存console.log('obj1',obj1) // obj1 { name: '南木元元', arr: [ 1, [ 2, 3 ], 4 ] }
console.log('obj2',obj2) // obj2 { name: '阿元', arr: [ 1, [ 5, 6, 7 ], 4 ] }
测试结果:
7.函数柯里化
函数柯里化指的是一种将使用多个参数的一个函数转换成一系列使用一个参数的函数的技术。
作用:可以参数复用(公共的参数已经通过柯里化预置了)和延迟执行(柯里化时只是返回一个预置参数的新函数,并没有立刻执行,在满足条件后才会执行)。
参数定长的柯里化
思路:通过函数的length属性获取函数的形参个数,形参的个数就是所需参数的个数。维护一个数组,当数组的长度与函数接收参数的个数一致,再执行该函数。
// 实现函数柯里化
function curry(fn) {// 返回一个新函数return function curried(...args) {if (args.length >= fn.length) {return fn.apply(this, args); // 如果参数够了,就执行原函数,返回结果} else {//返回一个新函数,继续递归去进行柯里化,利用闭包,将当前已经传入的参数保存下来return function (...args2) {//递归调用 curried 函数return curried.apply(this, [...args, ...args2]); //新函数调用时会继续传参,拼接参数};}};
}// 测试
function sum(a, b, c) {return a + b + c;
}
var curried = curry(sum);
console.log(curried(1, 2, 3)); //6
console.log(curried(1, 2)(3)); //6
console.log(curried(1)(2, 3)); //6
console.log(curried(1)(2)(3)); //6
测试结果:
参数不定长的柯里化
题目:如何实现一个方法,使计算结果能够满足如下预期。
add(1, 2, 3) // 6
add(1) // 1
add(1)(2) // 3
add(1, 2)(3) // 6
add(1)(2)(3) // 6
add(1)(2)(3)(4) // 10
思路:利用闭包和递归,如果参数为空,则判断递归结束,求和,返回结果。
function addCurry() {// 利用闭包的特性收集所有参数值let arr = [...arguments] //返回函数return function fn() {// 如果参数为空,则判断递归结束,即传入一个()执行函数if(arguments.length === 0) { return arr.reduce((a, b) => a + b) // 求和} else {arr.push(...arguments)return fn //递归}}
}// 测试
console.log(addCurry(1)()); //1
console.log(addCurry(1)(2)()); //3
console.log(addCurry(1)(2)(3)()); //6
console.log(addCurry(1, 2)(3)()); //6
console.log(addCurry(1, 2, 3)()); //6
上述写法,总是要以空括号()结尾,于是再改进为隐式转换.toString
写法,原理:当用 Function的值做计算的时候,会调用toString做隐式转换。注意一些旧版本的浏览器隐式转换会默认执行,新版本不行了。可以利用隐式转换或者alert。
function addCurry() {let arr = [...arguments]// 利用闭包的特性收集所有参数值var fn = function() {arr.push(...arguments);return fn;//递归};// 利用 toString 隐式转换,转换的时候再返回结果fn.toString = function () {return arr.reduce(function (a, b) {return a + b;});}return fn;
}//测试
console.log(addCurry(1)(2) == 3) //true 利用隐式转换,自动调用toString方法得到柯里化的结果
//alert(addCurry(1)(2)(3))//6 alert参数只能是字符串,如果其他类型的值,会转换成字符串,会调用toString方法
console.log(addCurry(1).toString());//1 手动调用toString
console.log(addCurry(1, 2)(3).toString());//6
console.log(addCurry(1, 2)(3)(4)(5).toString());//15
测试结果:
8.数组扁平化
数组扁平化其实就是将多维数组转为一维数组。
(1)ES6中的flat
const arr = [1,[2,[3,[4,5]]],6]
// arr.flat([depth]) flat的参数代表的是需要展开几层,如果是Infinity的话,就是不管嵌套几层,全部都展开
console.log(arr.flat(Infinity)) //[1,2,3,4,5,6]
(2)递归
let arr = [1, [2, [3, 4]]];
function flatten(arr) {let result = [];for (let i = 0; i < arr.length; i++) {//如果当前元素还是一个数组if (Array.isArray(arr[i])) {result = result.concat(flatten(arr[i]));//递归拼接} else {result.push(arr[i]);}}return result;
}
console.log(flatten(arr)); // [1, 2, 3, 4]
(3)reduce函数迭代
从上面普通的递归函数中可以看出,其实就是对数组的每一项进行处理,那么其实也可以用reduce来实现数组的拼接,从而简化第一种方法的代码。
let arr = [1, [2, [3, 4]]];
function flatten(arr) {return arr.reduce((total, cur) => {return total.concat(Array.isArray(cur) ? flatten(cur) : cur);}, []); //传递初始值空数组[],就会从数组索引为 0 的元素开始执行
}
console.log(flatten(arr)); // [1, 2, 3, 4]
(4)split和toString
数组的toString
方法可以把数组直接转换成逗号分隔的字符串。如[1, [2, [3, 4]]] => "1,2,3,4"
let arr = [1, [2, [3, 4]]];
function flatten(arr) {//先把数组直接转换成逗号分隔的字符串,然后再用 split 方法把字符串重新转换为数组return arr.toString().split(",").map(Number);
}
console.log(flatten(arr)); // [ 1, 2, 3, 4 ]
9.数组去重
(1)利用Set。new一个Set,参数为需要去重的数组,Set 会自动删除重复的元素,再Array.from将 Set 转为数组返回。
const arr = [1, 2, 3, 5, 1, 5, 9, 1, 2, 8];
console.log([...new Set(arr)]); //[ 1, 2, 3, 5, 9, 8 ]
console.log(Array.from(new Set(arr))); //[ 1, 2, 3, 5, 9, 8 ]
(2)利用数组的filter() + indexOf去重。利用filter方法,返回arr.indexOf(num)等于index的值。原理就是indexOf会返回最先找到的数字的索引。
function unique(arr) {return arr.filter((item, index, array) => {return array.indexOf(item) === index;});
}
const arr = [1, 2, 3, 5, 1, 5, 9, 1, 2, 8];
console.log(unique(arr)); // [1, 2, 3, 5, 9, 8]
(3)利用map。新建一个数组和map,如果当前值在map中没有出现过,就加入数组,最后返回数组。
const unique = (arr) => {const map = new Map();const res = [];for (let item of arr) {if (!map.has(item)) {map.set(item, true);res.push(item);}}return res;
}
const arr = [1, 2, 3, 5, 1, 5, 9, 1, 2, 8];
console.log(unique(arr)); // [1, 2, 3, 5, 9, 8]
10.手写类型判断函数
思路:如果是null,直接返回String(null);基本类型和函数,直接使用typeof;
其它引用类型,使用Object.prototype.toString.call。
function getType(value) {// 判断数据是 null 的情况if (value === null) {return String(value);}// 判断数据是基本数据类型的情况和函数的情况,使用typeofif (typeof value !== "object") {return typeof value;} else {// 判断数据是引用类型的情况,设当前类型为datelet valueClass = Object.prototype.toString.call(value); //"[object Date]"type = valueClass.split(" ")[1].split(""); //[ 'D', 'a', 't', 'e', ']' ] 截取类型并转换为数组type.pop(); //[ 'D', 'a', 't', 'e' ],去掉数组最后的右括号"]"return type.join("").toLowerCase(); //[ 'D', 'a', 't', 'e' ] => "Date" => "date" 数组转小写字符串}
}// 测试
console.info(getType(null)); // null
console.info(getType(undefined)); // undefined
console.info(getType(100)); // number
console.info(getType("abc")); // string
console.info(getType(true)); // boolean
console.info(getType(Symbol())); // symbol
console.info(getType({})); // object
console.info(getType([])); // array
console.info(getType(() => {})); // function
console.info(getType(new Date())); // date
console.info(getType(new RegExp(""))); // regexp
console.info(getType(new Map())); // map
console.info(getType(new Set())); // set
console.info(getType(new WeakMap())); // weakmap
console.info(getType(new WeakSet())); // weakset
console.info(getType(new Error())); // error
console.info(getType(new Promise(() => {}))); // promise
测试结果:
结语
本文总结了前端常见的一些手写功能,你是不是全都掌握了呢,欢迎在评论区交流。
🔥如果此文对你有帮助的话,欢迎💗关注、👍点赞、⭐收藏、✍️评论,支持一下博主~
相关文章:

10个常考的前端手写题,你全都会吗?
前言 📫 大家好,我是南木元元,热爱技术和分享,欢迎大家交流,一起学习进步! 🍅 个人主页:南木元元 今天来分享一下10个常见的JavaScript手写功能。 目录 1.实现new 2.call、apply、…...

vue组件间通信
Vue组件之间通信方式有哪些 一、父子组件通讯 1、props,emit 父组件可以通过props给子组件传递变量。子组件可以通过emit派发自定义事件,使父组件可以获得事件函数传递过来的形参。 2、$parent、$children、ref 父组件可以通过 c h i l d r e n 获取…...

编程框架概述:MVC, MVP, MVVM, Flux/Redux, 和 Clean Architecture
前言 在软件开发中,选择合适的编程框架和架构模式对于构建可维护和可扩展的应用程序至关重要。初学者在面对多种架构选项时可能会感到困惑。本文将详细介绍五种流行的编程框架:MVC、MVP、MVVM、Flux/Redux和Clean Architecture。 MVC(Model-V…...

多维时序 | Matlab实现CNN-BiLSTM-Mutilhead-Attention卷积双向长短期记忆神经网络融合多头注意力机制多变量时间序列预测
多维时序 | Matlab实现CNN-BiLSTM-Mutilhead-Attention卷积双向长短期记忆神经网络融合多头注意力机制多变量时间序列预测 目录 多维时序 | Matlab实现CNN-BiLSTM-Mutilhead-Attention卷积双向长短期记忆神经网络融合多头注意力机制多变量时间序列预测效果一览基本介绍程序设计…...

np.argsort排序问题(关于位次)-含GitHub上在numpy项目下提问的回复-总结可行方案
np.argsort 与获取位相关问题 位次: 数组中的数据在其排序之后的另一个数组中的位置 [1,0,2,3] 中 0的位次是1 1的位次是2 2的位次是3 3的位次是4 这里先直接给出结论,np.argsort()返回的索引排序与实际位次在确实在某些情况下会出现一致,但后来numpy的开…...

Element中的el-input-number+SpringBoot+mysql
1、编写模板 <el-form ref"form" label-width"100px"><el-form-item label"商品id:"><el-input v-model"id" disabled></el-input></el-form-item><el-form-item label"商品名称&a…...

Jupyter Notebook五分钟基础速通
1 作用 常用于数据分析 2 安装 2.1 Anaconda 通过直接安装Anaconda,会自动安装Jupyter Notebook 2.2 命令行安装 ① 3.x版本 pip3 install --upgrade pip pip3 install jupyter ② 2.x版本 pip install --upgrade pip pip install jupyter 3 启动 cmd窗口下…...

基于SpringBoot的SSM整合案例
项目目录: 数据库表以及表结构 user表结构 user_info表结构 引入依赖 父模块依赖: <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.12.RELEASE</version>…...
[SS]语义分割_转置卷积
转置卷积(Transposed Convolution) 抽丝剥茧,带你理解转置卷积(反卷积) 目录 一、概念 1、定义 2、运算步骤 二、常见参数 一、概念 1、定义 转置卷积(Transposed Convolution)…...

面板小程序命令行工具介绍
Ray 体系提供配套的工程化解决方案。 由于多端构建的一些客观原因,在构建流程的设计上,必须将工程套件安装在项目内。 项目内的依赖至少包含以下内容: {"dependencies": {"ray-js/ray": "latest"},"de…...

DBA技术栈MongoDB: 数据增改删除
该博文主要介绍mongoDB对文档数据的增加、更新、删除操作。 1.插入数据 以下案例演示了插入单个文档、多个文档、指定_id、指定多个索引以及插入大量文档的情况。在实际使用中,根据需求选择适合的插入方式。 案例1:插入单个文档 db.visitor.insert({…...

Xcode查看APP文件目录
一、连接真机到MAC电脑上 二、打开Devices 点击window -> Devices and Simulatores 三、选中设备、选择app 四、选择下载内容 五、查看文件内容 得到的文件 右键显示包内容,获得APP内数据 六、分发证书无法下载 使用分发的证书无法下载文件内容…...

【视频媒体】深入了解直播视频流
深入了解直播视频流🎥 YouTube、TikTok live和Twitch上的直播视频是如何工作的? 直播视频流与常规流媒体不同,因为视频内容通过互联网近乎实时发送,通常只有几秒钟的延迟。 下图解释了实现这一目标背后所发生的事情。 步骤1&…...

【01】mapbox js api加载arcgis切片服务
需求: 第三方的mapbox js api加载arcgis切片服务,同时叠加在天地图上,天地图坐标系web墨卡托。 效果图: 形如这种地址去加载http://zjq2022.gis.com:8080/demo/loadmapboxtdt.html 思路: 需要制作一个和天地图比例…...

图像分割实战-系列教程15:deeplabV3+ VOC分割实战3-------网络结构1
🍁🍁🍁图像分割实战-系列教程 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 deeplab系列算法概述 deeplabV3 VOC分割实战1 deeplabV3 VOC分割实战2 deeplabV3 VOC分割实战3 dee…...

【Docker】安装nacos以及实现负载均衡
🥳🥳Welcome 的Huihuis Code World ! !🥳🥳 接下来看看由辉辉所写的关于Docker的相关操作吧 目录 🥳🥳Welcome 的Huihuis Code World ! !🥳🥳 前言 一.nacos单个部署 1.镜像拉取 …...

如何用数据赋能社媒营销决策?
在数字化时代,越来越多的商家开始意识到数据分析对于改善经营的重要性。 传统决策更多依赖过往经验、商业直觉、他人的思路模板等方法,或者依靠描述性统计、简单的数据分析。在数字时代,则通过精细化数据分析,做出更明智的营销决策…...

初识k8s(概述、原理、安装)
文章目录 概述由来主要功能 K8S架构架构图组件说明ClusterMasterNodekubectl 组件处理流程 K8S概念组成PodPod控制器ReplicationController(副本控制器)ReplicaSet (副本集)DeploymentStatefulSet (有状态副本集&#…...

【Java】Maven的基本使用
Maven的基本使用 Maven常用命令 complie:编译clean:清理test:测试package:打包install:安装 mvn complie mvn clean mvn test mvn package mvn installMaven生命周期 IDEA配置Maven Maven坐标 什么是坐标?…...

【RT-DETR有效改进】遥感旋转网络 | LSKNet动态的空间感受野网络(轻量又提点)
前言 大家好,我是Snu77,这里是RT-DETR有效涨点专栏。 本专栏的内容为根据ultralytics版本的RT-DETR进行改进,内容持续更新,每周更新文章数量3-10篇。 专栏以ResNet18、ResNet50为基础修改版本,同时修改内容也支持Re…...

【进阶之路】如何提升 Java 编程内力?
如何提升 Java 编程内力? 可能很多初学者在学完 SpringBoot 之后,做了 1-2 个项目之后,不知道该去学习什么了,其实这时候需要去学习的东西还有很多,接下来我会列举一下主要需要从哪些方面来对 Java 编程深入学习&#…...

Git一台电脑 配置多个账号
Git一台电脑 配置多个账号 Git一台电脑 配置多个账号 常用的Git版本管理有 gitee github gitlab codeup ,每个都有独立账号,经常需要在一个电脑上向多个代码仓提交后者更新代码,本文以ssh 方式为例配置 1 对应账号 公私钥生成 建议&#…...

2024年华为OD机试真题-素数之积-Java-OD统一考试(C卷)
题目描述: RSA加密算法在网络安全世界中无处不在,它利用了极大整数因数分解的困难度,数据越大,安全系数越高,给定一个32位正整数,请对其进行因数分解,找出是哪两个素数的乘积。 输入描述: 一个正整数num 0 < num <= 2147483647 输出描述: 如果成功找到,以单个空…...

汤姆·齐格弗里德《纳什均衡与博弈论》笔记(2)
第三章 纳什均衡——博弈论的基础 冯诺伊曼没有解决的问题 博弈论在其建立初始也显现出了严重的局限性。冯诺伊曼解决了二人零和博弈,但对多人博弈问题仍无法解决。如果只是鲁宾逊克鲁索和星期五玩游戏,博弈论可以很好地被应用,但它无法精确…...

QT上位机开发(动态数据采集与监控)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 上位机开发中,有一种类型的应用软件很特殊,它几乎没有什么交互操作,主要的工作就是检测和显示。如果说在此基础上有什么扩展的话,可能就是安全监控和报警。所以,这个上位机软件…...

vue2 -- 截图工具html2canvas
文章目录 🍉需求描述🍉基础功能实现🍉下载另存为本地图片功能🍉需求描述 可以将网页中的指定元素或整个页面截取为图片,以便保存或分享。 🍉基础功能实现 在 Vue 中使用 html2canvas 实现 1:安装 html2canvas 库。你可以使用 npm 安装,命令如下: npm install …...

笔记-孙子兵法-第三篇-谋攻(1)-不战而屈人之兵,上兵伐谋,韩信之死
笔记-From 《华杉讲透孙子兵法》和《兵以诈立,我读孙子》 第三篇-谋攻(1)不战而屈人之兵 《孙子兵法》第一篇讲计,第二篇讲野战,第三篇就讲攻城。 《孙子》尚谋,认为最好是“不战而屈人之兵”࿰…...

kafka参数配置参考和优化建议 —— 筑梦之路
对于Kafka的优化,可以从以下几个方面进行思考和优化: 硬件优化:使用高性能的硬件设备,包括高速磁盘、大内存和高性能网络设备,以提高Kafka集群的整体性能。 配置优化:调整Kafka的配置参数,包括…...

如何本地搭建Splunk Enterprise数据平台并实现任意浏览器公网访问
文章目录 前言1. 搭建Splunk Enterprise2. windows 安装 cpolar3. 创建Splunk Enterprise公网访问地址4. 远程访问Splunk Enterprise服务5. 固定远程地址 前言 本文主要介绍如何简单几步,结合cpolar内网穿透工具实现随时随地在任意浏览器,远程访问在本地…...

FlinkAPI开发之状态管理
案例用到的测试数据请参考文章: Flink自定义Source模拟数据流 原文链接:https://blog.csdn.net/m0_52606060/article/details/135436048 Flink中的状态 概述 有状态的算子 状态的分类 托管状态(Managed State)和原始状态&…...