JavaScript全面指南(四)
🌈个人主页:前端青山
🔥系列专栏:JavaScript篇
🔖人终将被年少不可得之物困其一生
依旧青山,本期给大家带来JavaScript篇专栏内容:JavaScript全面指南
目录
61、如何防止XSRF攻击
62、如何判断一个对象是否为数组,函数
63、JavaScript中如何使用事件处理程序?
64、解释延迟脚本在JavaScript中的作用?
65、实现一个函数clone,可以对javascript中的5种主要数据类型进行值复制。
66、decodeURI()和encodeURI()是什么?
67、解释JavaScript中的pop()方法?
68、解释什么是回调函数,并提供一个简单的例子。
69、面向对象编程与面向过程编程的区别
70、eval是做什么的?性能怎么样?安全如何?
71、函数节流、防抖
72、“use strict”的作用是什么?
73、了解ES6 的 Proxy吗?
74、深拷贝是什么?
75、解释 JavaScript 中的 null 和 undefined。
76、解释 JavaScript 中的值和类型。
77、scroll resize 使用函数节流实现不要频繁触发事件的需求
78、解释事件冒泡以及如何阻止它?
79、JavaScript 中的 let 关键字有什么用?
80、 jQuery 优点和缺点
61、如何防止XSRF攻击
一 CSRF是什么? 跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。
二、CSRF的原理
三、CSRF的防范措施
1、验证 HTTP Referer 字段
HTTP头中的Referer字段记录了该 HTTP 请求的来源地址。在通常情况下,访问一个安全受限页面的请求来自于同一个网站,而如果黑客要对其实施 CSRF 攻击,他一般只能在他自己的网站构造请求。因此,可以通过验证Referer值来防御CSRF 攻击。
2、验证码。 验证码 利用验证码将用户收到的信息与后台服务器进行比对,每次用户提交都需要用户在表单中填写一个图片上的随机字符串,不符则进行拒绝。 3、添加token验证
CSRF攻击之所以能够成功,是因为攻击者可以完全伪造用户的请求,该请求中所有的用户验证信息都存在cookie中,因此攻击者可以在不知道这些验证信息的情况下直接利用用户自己的cookie来通过安全验证。要防止CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于cookie之中。可以在HTTP请求中以参数的形式加入一个随机产生的token,并在服务器建立一个拦截器来验证这个token,如果请求中没有token或者token不正确,则认为可能是CSRF攻击而拒绝该请求。 现在业界一致的做法就是使用Anti CSRF Token来防御CSRF。
用户访问某个表单页面。 服务端生成一个Token,放在用户的Session中,或者浏览器的Cookie中。 在页面表单附带上Token参数。 用户提交请求后,服务端验证表单中的Token是否与用户Session(或Cookies)中的Token一致,一致为合法请求,不是则非法请求。
这个Token值必须是随机的,不可预测的。由于Token的存在,攻击者无法再构造一个带有合法Token的请求实施CSRF攻击。另外使用Token应注意Token的保密性,尽量把敏感操作由GET改成POST,以form或者AJAX形式提交,避免Token泄露。
4、尽量使用POST,限制GET
GET接口能够直接将请求地址暴露给攻击者,所以要防止CSRF一定最好不要用GET。当然POST并不是万无一失,攻击者只需要构造一个form表单就可以,但需要在第三方页面做,这样就增加了暴露的可能性。
62、如何判断一个对象是否为数组,函数
在js中判断数据类型通常使用typeof,但是typeof在判断数组和对象时的结果都是object。
那么,怎么才能区分对象和数组呢?
-
判断原型
var obj = {};var arr = [];console.log(arr);console.log(obj); 数组和对象的原型对象不一样,由此可以通过判断原型来判断一个对象是否为数组var obj = {};var arr = [];console.log(Object.getPrototypeOf(obj) === Object.prototype);console.log(Object.getPrototypeOf(obj) === Array.prototype); 但是这种方法虽然通过检查原型来判断是否为数组,不是特别稳定,因为原型可以人为改变的一旦原型改变就可能会失效。var obj = {};var arr = [];Object.setPrototypeOf(obj, Array.prototype);console.log(Object.getPrototypeOf(obj) === Object.prototype);//falseconsole.log(Object.getPrototypeOf(obj) === Array.prototype);//true 此时arr的原型不是Array.prototype第一个返回的结果为false,如此,不能判断是否为数组。判断构造函数创建对象和创建数组的构造函数不同可以通过此种方法判断一个对象是否为数组。var obj = {};var arr = [];console.log(Object.getPrototypeOf(obj).constructor === Object);console.log(Object.getPrototypeOf(obj).constructor === Array); 由此可见,两个输出结果并不一样,并且也符合我们的认知,通过此种方法也可以判断一个对象是否为数组。但该种方法与上一种方法的问题一样即当构造函数被修改之后就无法判断真正的数组。var obj = {};var arr = [];Object.getPrototypeOf(obj).constructor = Array;console.log(Object.getPrototypeOf(obj).constructor === Object);//falseconsole.log(Object.getPrototypeOf(obj).constructor === Array);//trueconsole.log(Object.getPrototypeOf(arr).constructor === Array);//true 由此可见,该方法的缺点与上一种方法的一样。在判断构造函数方法中除了直接判断外还可以使用 instanceof 判断一个对象是否为一个构造函数的实例var obj = {};var arr = [];console.log(obj instanceof Array);//falseconsole.log(arr instanceof Array);//true 由此可见,该方法也可以判断是否为数组。Array.isArray()通过Array.isArray()可以判断一个对象是否为数组。var obj = {};var arr = [];console.log(Array.isArray(obj));//falseconsole.log(Array.isArray(arr));//true 由此可见此种方法可行,那么当我们把其构造函数改变后还会出现和上面一样的情况吗?var obj = {};var arr = [];Object.getPrototypeOf(obj).constructor = Array;//falseconsole.log(Array.isArray(obj));//trueconsole.log(Array.isArray(arr)); 由此可见,即便将obj的构造函数改为Array也能判断出真正的数组。用Object.toString()方法判断var obj = {};var arr = [];console.log(obj.toString());//[object Object]console.log(arr.toString());// 由此可见对象是Object创建的,但是数组的toString()返回的是空。这是因为js中每个对象都有toString()方法,该方法继承自Object.toString()方法,但数组被重写了,但是我们可以使用call()来调用数组的toString的原始方法来判断。var obj = {};var arr = [];console.log(obj.toString());//[object Object]console.log(Object.prototype.toString.call(arr));//[object Array] 由此可见,也可以通过此种方法判断一个对象是否为数组。那么,如果改变构造函数是否会发生类似之前的情况呢?var obj = {};var arr = [];Object.getPrototypeOf(obj).constructor = Array;console.log(obj.toString());//[object Object]console.log(Object.prototype.toString.call(arr));//[object Array] 由此可见,此时还能正常判断并不会发生此前出现的情况。
使用场景
判断一个对象是否为数组在什么地方使用呢
在进行克隆时,需要判断对象的属性是否为数组,根据结果采取不同的操作。
总结
-
判断原型和判断构造函数的方法的结果会因为原型和构造函数的改变发生改变,并不十分稳定。
-
Array,isArray()和Object.toString()方法较为稳定,较为推荐。
-
通常在进行克隆时会用到判断一个对象是否为数组。
63、JavaScript中如何使用事件处理程序?
事件是由用户生成活动(例如单击链接或填写表单)导致的操作。需要一个事件处理程序来管理所有这些事件的正确执行。事件处理程序是对象的额外属性。此属性包括事件的名称以及事件发生时采取的操作。
64、解释延迟脚本在JavaScript中的作用?
默认情况下,在页面加载期间,HTML代码的解析将暂停,直到脚本停止执行。这意味着,如果服务器速度较慢或者脚本特别沉重,则会导致网页延迟。在使用Deferred时,脚本会延迟执行直到HTML解析器运行。这减少了网页加载时间,并且它们的显示速度更快。
65、实现一个函数clone,可以对javascript中的5种主要数据类型进行值复制。
var clone = function (type) {var o;var typeA = typeof type;switch (typeA){case 'string':o = typeA+'';break;case 'number':o = typeA-0;break;case 'undefined':break;case 'boolean':o = typeA;break;case 'object':if(type===null){o = null;}else {if(Object.prototype.toString.call(type).slice(8,-1)==='Array'){o = [];for(var i = 0;i<type.length;i++){o.push(clone(type[i]));}}else {o = {};for(var key in type){o[key] = clone(type[key]);}}}break;default:break;}return o;
}
66、decodeURI()和encodeURI()是什么?
EncodeURl()用于将URL转换为十六进制编码。而DecodeURI()用于将编码的URL转换回正常。
67、解释JavaScript中的pop()方法?
pop()方法与shift()方法类似,但不同之处在于Shift方法在数组的开头工作。此外,pop()方法将最后一个元素从给定的数组中取出并返回。然后改变被调用的数组。 例:
var cloths = [“Shirt”, “Pant”, “TShirt”];
cloths.pop();
//Now cloth becomes Shirt,Pant
68、解释什么是回调函数,并提供一个简单的例子。
回调函数是可以作为参数传递给另一个函数的函数,并在某些操作完成后执行。下面是一个简单的回调函数示例,这个函数在某些操作完成后打印消息到控制台。
function modifyArray(arr, callback) {// 对 arr 做一些操作arr.push(100);// 执行传进来的 callback 函数callback();
}
var arr = [1, 2, 3, 4, 5];
modifyArray(arr, function() {console.log("array has been modified", arr);
});
69、面向对象编程与面向过程编程的区别
面向过程考虑数据变换; 面向过程的世界是以目标问题规定的I/O为中心的
面向对象考虑功能分工; 面向对象的世界是以内部实现的可理解性为中心的
70、eval是做什么的?性能怎么样?安全如何?
eval方法是在运行时对脚bai本进行解du释执行,而普通的javascript会有一个zhi预处dao理的过程。所以会有一些性能上zhuan的损失,但是通常通过一些手段能将这些性能损失降低到非常少。不至于谈虎色变。 eval通常用在一些需要动态执行字符串,或将字符串转为javascript对象的场景,比如将json字符串转为javascript对象。 至于eval容易被XSS攻击是属于想当然的说法吧,XSS攻击就是在你的页面上嵌入html或javascript代码,我觉得与是否使用eval方法没有什么关系。
71、函数节流、防抖
函数防抖(debounce)
概念: 在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。 生活中的实例: 如果有人进电梯(触发事件),那电梯将在10秒钟后出发(执行事件监听器),这时如果又有人进电梯了(在10秒内再次触发该事件),我们又得等10秒再出发(重新计时)。
函数节流(throttle)
概念: 规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。 生活中的实例: 我们知道目前的一种说法是当 1 秒内连续播放 24 张以上的图片时,在人眼的视觉中就会形成一个连贯的动画,所以在电影的播放(以前是,现在不知道)中基本是以每秒 24 张的速度播放的,为什么不 100 张或更多是因为 24 张就可以满足人类视觉需求的时候,100 张就会显得很浪费资源。
分析图 假设,我们观察的总时间为10秒钟,规定1秒作为一次事件的最小间隔时间。 如果触发事件的频率是 0.5s/次,那么 函数防抖如图
因为始终没法等一秒钟就被再次触发了,所以最终没有一次事件是成功的。 函数节流如图
因为控制了最多一秒一次,频率为0.5s/次,所以每一秒钟就有一次事件作废。最终控制成1s/次 如果触发事件的频率是 2s/次,那么 函数防抖如图
因为2s/次已经大于了规定的最小时间,所以每计时两秒便触发一次。 函数节流如图
同样,2s/次 大于了最小时间规定,所以每一次触发都生效。 应用场景 对于函数防抖,有以下几种应用场景:
给按钮加函数防抖防止表单多次提交。 对于输入框连续输入进行AJAX验证时,用函数防抖能有效减少请求次数。 判断scroll是否滑到底部,滚动事件+函数防抖
总的来说,适合多次事件一次响应的情况
对于函数节流,有如下几个场景:
游戏中的刷新率 DOM元素拖拽 Canvas画笔功能
总的来说,适合大量事件按时间做平均分配触发。
函数防抖:
function debounce(fn, wait) {var timer = null;return function () {var context = thisvar args = argumentsif (timer) {clearTimeout(timer);timer = null;}timer = setTimeout(function () {fn.apply(context, args)}, wait)}
}
var fn = function () {console.log('boom')
}
setInterval(debounce(fn,500),1000) // 第一次在1500ms后触发,之后每1000ms触发一次 setInterval(debounce(fn,2000),1000) // 不会触发一次(我把函数防抖看出技能读条,如果读条没完成就用技能,便会失败而且重新读条)
之所以返回一个函数,因为防抖本身更像是一个函数修饰,所以就做了一次函数柯里化。里面也用到了闭包,闭包的变量是timer。
函数节流
function throttle(fn, gapTime) {let _lastTime = null;return function () {let _nowTime = + new Date()if (_nowTime - _lastTime > gapTime || !_lastTime) {fn();_lastTime = _nowTime}}
}
let fn = ()=>{console.log('boom')
}
setInterval(throttle(fn,1000),10)
如图是实现的一个简单的函数节流,结果是一秒打出一次boom
小结
函数防抖和函数节流是在时间轴上控制函数的执行次数。防抖可以类比为电梯不断上乘客,节流可以看做幻灯片限制频率播放电影。
72、“use strict”的作用是什么?
use strict 出现在 JavaScript 代码的顶部或函数的顶部,可以帮助你写出更安全的 JavaScript 代码。如果你错误地创建了全局变量,它会通过抛出错误的方式来警告你。例如,以下程序将抛出错误:
function doSomething(val) {"use strict"; x = val + 10;
}
它会抛出一个错误,因为 x 没有被定义,并使用了全局作用域中的某个值对其进行赋值,而 use strict 不允许这样做。下面的小改动修复了这个错误:
function doSomething(val) {"use strict"; var x = val + 10;
}
73、了解ES6 的 Proxy吗?
概述
-
Proxy用于修改某些操作的默认行为,等同于在语言层面上做出修改,所以属于一种“元编程”,即对编程语言进行编程。
-
Proxy可以理解成在目标对象前架设一层拦截层,外界访问该对象都必须先通过这层拦截,因此提供一种机制可以对外界的访问进行拦截或过滤。
实例的方法
1.get()
-
get方法用于拦截某个属性的读取操作。
let person = {name : '张三'
}
let proxy = new Proxy(person,{get : function(target,property){if(property in target){return target[property];}else{throw new Error('property ' + property + ' no found!')}}
})
proxy.name; //'张三'
proxy.age; //property age no found!
12345678910111213141516
以上的实例当获取对象没有的属性age时,就会抛出错误;若不通过代理,则会返回undefined;
-
get方法可以继承
let proto = new Proxy({},{get(target,propertykey,receiver){console.log('get '+ propertykey);return target[propertykey];}
});
let obj = Object.create(proto);
obj.lalala; //get lalala
123456789
-
利用Proxy对象,可以将读取属性的操作变为执行某个函数,从而实现函数的链式操作;
let pipe = (function(){return function(value){//创建函数执行栈let funcStack = [];//创建拦截器let oproxy = new Proxy({},{get: function(pipeObj,fnName){//当属性为get,返回函数栈一次执行函数后的结果if(fnName === 'get'){return funcStack.reduce(function(val,fn){return fn(val);},value)}//否则将函数置入函数执行栈中,并返回又一个拦截器else{funcStack.push(window[fnName]);return oproxy;}}});// 将拦截器返回给pipe return oproxy;}
}())
let double = n=>n*2;
let pow = n=>n*n;
pipe(2).double.pow.get; //16
1234567891011121314151617181920212223242526272829
2.set()
-
set方法用户拦截某个属性的赋值操作
let ageLimit = {set : function(obj,prop,val){if(prop === 'age'){if(!Number.isInteger(val)){throw new TypeError('the age must be a integer')}if(val > 150 || val < 0){throw new RangeError('the age must be from 0 to 150')}}obj[prop] = val;}
}let person = new Proxy({},ageLimit);
person.age = 200; //the age must be from 0 to 150;
person.age = 'abc' //the age must be a integer;
person.age = 20; //正常
person.age; // 20;
1234567891011121314151617181920
-
通过ageLimit拦截器,可以及时对用户的数据输入做数据验证,以保证数值规范;
-
有时候,我们会在对象上设置内部属性,属性名的第一个字符为下划线’_’,表示该属性不能被外部访问或使用。结合get和set方法,就可以做到防止内部属性被外部读写;
let handler = {get (target , key){invariant(key,'get');return target[key];},set (target , key , value){invatiant(key,'set');taget[key] = value;return true;}
}
function invariant(key,action){if(key[0] === '_'){throw new Error('no allowed to ' + action + ' the property');}
}
let target = {_name : '张三',_age : 20
};
let proxy = new Proxy(target,handler);
proxy._name; // no allowed to get the property
proxy._age = 12 // no allowed to set the property
1234567891011121314151617181920212223242526
3.apply()
-
apply方法拦截函数的调用、call、apply操作
-
apply方法接收三个参数:目标对象、目标对象的上下文的this、目标对象的参数数组
let target = function(){console.log('I am the target');
}
let handler = {apply : function(){console.log('I am the apply');}
}
let p = new Proxy(target,handler);
p(); //I am the apply;
12345678910111213
4.其他方法
has(target,propkey)
拦截
hasProperty()
、propkey in proxy
操作,返回一个布尔值;deleteProperty(target,propkey)
拦截
delete proxy[propkey]
操作,返回一个布尔值;ownKeys(target)
拦截
Object.getOwnPropertyNarnes(proxy)
、Object.getOwnPropertySyrnbols (proxy)
、Object.keys(proxy)
,返回一个数组。该方法返回目标对象所有自身属性的属 性名,而 Object .keys()的返回结果仅包括目标对象自身的可遍历属性;getOwnPropertyDescriptor(target,propkey)
拦截
Object.getOwnPropertyDescriptor(proxy, propKey)
,返回属性的描述对象;defineProperty(target,propkey)
拦截
Object.defineProperty(proxy, propKey, propDesc)
、Object.define Properties(proxy, propDescs)
,返回一个布尔值;preventExtensions(target)
拦截
Object . preventExtensions (proxy)
,返回一个布尔值;getPrototypeOf(target)
拦截
Object.getPrototypeOf(proxy)
,返回一个对象;isExtensible(target)
拦截
Object.isExtensible(proxy)
,返回一个布尔值;setPrototypeOf(target)
拦截
Object.setPrototypeOf(proxy,proto)
,返回一个布尔值;若对象为函数,则还有二外两种操作可以拦截(apply,construct)construct(target,args)
拦截Proxy实例作为构造函数调用的操作,比如 new proxy(…args);
74、深拷贝是什么?
变量存储类型分两类
①基本类型:直接存储在栈中的数据。(字符串、布尔值、未定义、数字、null)
②引用类型:将该对象引用地址存储在栈中,然后对象里面的数据存放在堆中。(数组、对象、函数)
这里解释一下为什么null是基本类型:有人说他用type of打印出来不是oject吗?
null只是一个空指针对象,没有数据。根据引用类型特点可以看一下是否符合。
=================
回到我们的问题上
说说深拷贝和浅拷贝还有赋值的区别,这样好理解
浅拷贝:也就是拷贝A对象里面的数据,但是不拷贝A对象里面的子对象
深拷贝:会克隆出一个对象,数据相同,但是引用地址不同(就是拷贝A对象里面的数据,而且拷贝它里面的子对象)
赋值:获得该对象的引用地址
浅拷贝和深拷贝的区别
三者的区别
下面用实例来说明
赋值特点说明:
赋值,疑惑点来自于下图。
赋值打印图
浅拷贝特点说明:
obj还是上面的
深拷贝说明:
第一种方法的缺陷在于函数不能拷贝
75、解释 JavaScript 中的 null 和 undefined。
JavaScript 中有两种底层类型:null 和 undefined。它们代表了不同的含义:
-
尚未初始化:undefined;
-
空值:null。
null和undefined是两个不同的对象, 有图为证:
76、解释 JavaScript 中的值和类型。
JavaScript提供两种数据类型: 基本数据类型和引用数据类型 基本数据类型有:
-
String
-
Number
-
Boolean
-
Null
-
Undefined
-
Symbol
引用数据类型有:
-
Object
-
Array
-
Function
77、scroll resize 使用函数节流实现不要频繁触发事件的需求
<script>function throttle(fun,delay){let timer = null;if(timer){clearTimeout(timer);}return function(){setTimeout(function(){fun();},delay);}} var firstResize = true;window.onresize = function(){if(firstResize){throttle(function(){alert(1)},30)();}firstResize = false;}</script>
78、解释事件冒泡以及如何阻止它?
事件冒泡是指嵌套最深的元素触发一个事件,然后这个事件顺着嵌套顺序在父元素上触发。
防止事件冒泡的一种方法是使用 event.cancelBubble 或 event.stopPropagation()(低于 IE 9)。
79、JavaScript 中的 let 关键字有什么用?
用let声明变量只在块级作用域起作用,适合在for循环使用,也不会出现变量提升现象。同一个代码块内,不可重复声明的相同变量,不可重复声明函数内的参数。
80、 jQuery 优点和缺点
具体而言,jQuery有如下优势:
1,提供了用css选择符来选择dom元素的api(现在已经被浏览器内置支持) 2,提供了浏览器的检测api 3,提供了兼容的功能性api 4,提供了DOM的批处理操作(批处理思想永远都不会过时) 5,提供了dom操作的链式操作 6,提供了插件机制(代码复用变得容易,也不容易过时)
缺点 现在已经很少操作DOM了 现代框架VUE中 jquery代码工程化 可维护性差vue很远
相关文章:

JavaScript全面指南(四)
🌈个人主页:前端青山 🔥系列专栏:JavaScript篇 🔖人终将被年少不可得之物困其一生 依旧青山,本期给大家带来JavaScript篇专栏内容:JavaScript全面指南 目录 61、如何防止XSRF攻击 62、如何判断一个对象是否为数组&…...

2024年诺贝尔物理学奖的创新之举
对于2024年诺贝尔物理学奖的这一创新之举,我的观点可以从以下几点展开: 跨学科融合的里程碑:将诺贝尔物理学奖颁发给机器学习与神经网络领域的研究者,标志着科学界对跨学科合作和融合的认可达到新高度。这不仅体现了理论物理与计算…...

FileLink内外网文件交换——致力企业高效安全文件共享
随着数字化转型的推进,企业之间的文件交流需求日益增加。然而,传统的文件传输方式往往无法满足速度和安全性的双重要求。FileLink作为一款专注于跨网文件交换的工具,致力于为企业提供高效、安全的文件共享解决方案。 应用场景一:项…...

使用Python在Jupyter Notebook中显示Markdown文本
使用Python在Jupyter Notebook中显示Markdown文本 引言1. 导入必要的模块2. 定义一个函数来显示Markdown文本3. 使用print_md函数显示Markdown文本4. 总结 引言 作为一名Python初级程序员,你可能已经熟悉了Jupyter Notebook这个强大的工具。Jupyter Notebook不仅支…...

G1 GAN生成MNIST手写数字图像
🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 G1 GAN生成MNIST手写数字图像 1. 生成对抗网络 (GAN) 简介 生成对抗网络 (GAN) 是一种通过“对抗性”学习生成数据的深度学习模型,通常用于生成…...

WPFDeveloper正式版发布
WPFDeveloper WPFDeveloper一个基于WPF自定义高级控件的WPF开发人员UI库,它提供了众多的自定义控件。 该项目的创建者和主要维护者是现役微软MVP 闫驚鏵: https://github.com/yanjinhuagood 该项目还有众多的维护者,详情可以访问github上的README&…...

实现鼠标经过某个元素时弹出提示框(通常称为“工具提示”或“悬浮提示”)
要实现鼠标经过某个元素时弹出提示框(通常称为“工具提示”或“悬浮提示”),你可以使用 JavaScript 结合 CSS 来创建这个效果。以下是详细步骤,包括 HTML、CSS 和 JavaScript 的代码示例。 HTML 结构 首先,创建一个简…...

【GAMES101笔记速查——Lecture 17 Materials and Appearances】
目录 1 材质和外观 1.1 自然界中,外观是光线和材质共同作用的结果 1.2 图形学中,什么是材质? 1.2.1 渲染方程严格正确,其中BRDF项决定了物体的材质 1.2.2 漫反射材质 (1)如何定义漫反射系数࿱…...

对于从vscode ssh到virtualBox的timeout记录
如题,解决方式如下: 1.把虚拟机关机退出来,在这个界面进行网络设置:选桥接网卡 2.然后再进系统,使用命令 ip addr查看如今的ip地址,应该和在本机里面看到的是一个网段 3.打开vscode,该干啥干…...

鸿蒙原生应用扬帆起航
就在2024年6月21日华为在开发者大会上发布了全新操作的系统HarmonyOS Next开发测试版,网友们把它称之为“称之为纯血鸿蒙”。因为在此之前鸿蒙系统底层式有两套基础架构的,一套是是Android的AOSP,一套是鸿蒙的Open Harmony,因为早…...

《计算机视觉》—— 表情识别
根据计算眼睛、嘴巴的变化,判断是什么表情结合以下两篇文章来理解表情识别的实现方法 基于 dilib 库的人脸检测 https://blog.csdn.net/weixin_73504499/article/details/142977202?spm1001.2014.3001.5501 基于 dlib 库的人脸关键点定位 https://blog.csdn.net/we…...

NVIDIA Aerial Omniverse
NVIDIA Aerial Omniverse 数字孪生助力打造新一代无线网络 文章目录 前言一、从链路级仿真到系统级仿真二、转变无线研发方式1. 开放且可定制的模块化平台2. 适用于 6G 标准化的 3GPP 兼容平台3. 部署前测试4. AI 和 ML 在数字孪生中的应用5. 高级物理精准的电磁求解器6. 合作伙…...

QT程序报错解决方案:Cannot queue arguments of type ‘QTextCharFormat‘ 或 ‘QTextCursor‘
项目场景: 项目场景:基于QT实现的C某程序,搭载在Linux环境中。 问题描述 执行程序时,发现log中报错如下内容: QObject::connect: Cannot queue arguments of type QTextCharFormat (Make sure QTextCharFormat is r…...

MySQL知识点_03
MySQL 命令大全 基础命令 操作命令连接到 MySQL 数据库mysql -u 用户名 -p查看所有数据库SHOW DATABASES;选择一个数据库USE 数据库名;查看所有表SHOW TABLES;查看表结构DESCRIBE 表名; 或 SHOW COLUMNS FROM 表名;创建一个新数据库CREATE DATABASE 数据库名;删除一个数据库D…...

leetcode:744. 寻找比目标字母大的最小字母(python3解法)
难度:简单 给你一个字符数组 letters,该数组按非递减顺序排序,以及一个字符 target。letters 里至少有两个不同的字符。 返回 letters 中大于 target 的最小的字符。如果不存在这样的字符,则返回 letters 的第一个字符。 示例 1&a…...

2015年-2016年 软件工程程序设计题(算法题)实战_c语言程序设计数据结构程序设计分析
文章目录 2015年1.c语言程序设计部分2.数据结构程序设计部分 2016年1.c语言程序设计部分2.数据结构程序设计部分 2015年 1.c语言程序设计部分 1.从一组数据中选择最大的和最小的输出。 void print_maxandmin(double a[],int length) //在一组数据中选择最大的或者最小的输出…...

整理一下实际开发和工作中Git工具的使用 (持续更新中)
介绍一下Git 在实际开发和工作中,Git工具的使用可以说是至关重要的,它不仅提高了团队协作的效率,还帮助开发者有效地管理代码版本。以下是对Git工具使用的扩展描述: 版本控制:Git能够跟踪代码的每一个修改记录&#x…...

Axios 的基本使用与 Fetch 的比较、在 Vue 项目中使用 Axios 的最佳实践
文章目录 1. 引言2. Axios 的基本使用2.1 安装 Axios2.2 发起 GET 请求2.3 发起 POST 请求2.4 请求拦截器2.5 设置全局配置 3. Axios 与 Fetch 的比较3.1 Axios 与 Fetch 的异同点3.2 Fetch 的基本使用3.3 使用 Fetch 处理 POST 请求 4. 讨论在 Vue 项目中使用 Axios 的最佳实践…...

Dockerfile样例
一、基础jar镜像制作 ## Dockerfile FROM registry.openanolis.cn/openanolis/anolisos:8.9 RUN mkdir /work ADD jdk17.tar.gz fonts.tar.gz /work/ RUN yum install fontconfig ttmkfdir -y && yum clean all && \chmod -R 755 /work/fonts ADD fonts.conf …...

MYSQL-多表查询
一、概述 1、定义 多表查询,也称为关联查询,指两个或更多个表一起完成查询操作。 2、前提条件 这些一起查询的表之间是有关系的(一对一、一对多),它们之间一定是有关联字段,这个关联字段可能建立了外键…...

MySQL改密码后不生效问题
MySQL修改密码后连接报密码错误 1.mysql修改密码命令: 这两种连接方式密码都必须修改 修改远程连接密码 ALTER USER ‘root’‘%’ IDENTIFIED BY ‘password’; 修改本地连接密码 ALTER USER ‘root’‘localhost’ IDENTIFIED BY ‘password’; 修改完后必须刷新…...

15分钟学Go 第1天:Go语言简介与特点
Go语言简介与特点 1. Go语言概述 Go语言(又称Golang)是由谷歌于2007年开发并在2009年正式发布的一种开源编程语言。它旨在简单、高效地进行软件开发,尤其适合于网络编程和分布式系统。 1.1 发展背景 多核处理器:随着计算机硬件…...

UDP/TCP协议
网络层只负责将数据包送达至目标主机,并不负责将数据包上交给上层的哪一个应用程序,这是传输层需要干的事,传输层通过端口来区分不同的应用程序。传输层协议主要分为UDP(用户数据报协议)和TCP(传输控制协议…...

gitee建立/取消关联仓库
目录 一、常用指令总结 二、建立关联具体操作 三、取消关联具体操作 一、常用指令总结 首先要选中要关联的文件,右击,选择Git Bash Here。 git remote -v //查看自己的文件有几个关联的仓库git init //初始化文件夹为git可远程建立链接的文件夹…...

在 Windows 环境下,Git 默认会自动处理 CRLF 和 LF 之间的转换。
在 Windows 环境下,Git 默认会自动处理 CRLF 和 LF 之间的转换。 要确保这一点并自动处理换行符差异,你可以按照以下步骤配置 1. 配置 Git 自动转换 CRLF 使用 Git Bash 或命令行执行以下命令,设置 Git 自动处理换行符: git con…...

Kibana可视化Dashboard如何基于字段是否包含某关键词进行过滤
kinana是一个功能强大、可对Elasticsearch数据进行可视化的开源工具。 我们在dashboard创建可视化时,有时需要将某个index里数据的某个字段根据是否包含某些特定关键词进行过滤,这个时候就可以用到lens里的filter功能很方便地进行操作。 如上图所示&…...

架构师之路-学渣到学霸历程-23
实战:NFS安装部署 接早上了解过了NFS的一些基本原理,咋们就看看一些实战; 尝试自己部署一下实验;然后实验成功了是我们最大的鼓励来着; 实战过程中,我们也面临了很多报错;所以每个实战的报错我…...

怎么修改编辑PDF的内容,有这4个工具就行了。
PDF 软件在现代的办公或者是学习当中的应用非常广泛,编辑PDF内容对很多人来说也是一件常有的事情。如果有了PDF 编辑软件,查看,编辑,修改,分享也会变得更加方便简单,所以今天要给大家介绍几款这样的工具。 …...

腾讯云宝塔面板前后端项目发版
后端发版 1. 打开“网站”页面,找到java项目,点击状态暂停服务 2.打开“文件”页面,进入jar包目录,删除原有的jar包,上传新jar包 3. 再回到第一步中的网站页面,找到jar项目,启动项目即可 前端发…...

C语言的结构体定义 java赋值关系运算符
1. /*#include<stdio.h> struct student { int num; //成员列表 int score; float avg; }; int main(void) { struct student Tom;//Tom结构体变量 struct student class4[50];//结构体数组 return 0; }*/ struct student { int nu…...