ES6基础3
- 函数的扩展
- 基本用法
- 函数参数的默认值
ES6允许为函数的参数设置默认值,即直接写在参数定义的后面。
- 参数变量是默认声明的,所以不能用
let
或const
再次声明。下面代码中,参数变量x
是默认声明的,在函数体中,不能用let
或const
再次声明,否则会报错。function foo(x = 5) {let x = 1; // errorconst x = 2; // error }
- 函数参数的默认值
- 与解构赋值默认值结合使用
- 参数默认值可以与解构赋值的默认值,结合起来使用。下面代码使用了对象的解构赋值默认值,而没有使用函数参数的默认值。只有当函数
foo
的参数是一个对象时,变量x
和y
才会通过解构赋值而生成。如果函数foo
调用时参数不是对象,变量x
和y
就不会生成,从而报错。如果参数对象没有y
属性,y
的默认值5才会生效。function foo({x, y = 5}) {console.log(x, y); }foo({}) // undefined, 5 foo({x: 1}) // 1, 5 foo({x: 1, y: 2}) // 1, 2 foo() // TypeError: Cannot read property 'x' of undefined
下面两种写法都对函数的参数设定了默认值,区别是写法一函数参数的默认值是空对象,但是设置了对象解构赋值的默认值;写法二函数参数的默认值是一个有具体属性的对象,但是没有设置对象解构赋值的默认值。
// 写法一 function m1({x = 0, y = 0} = {}) {return [x, y]; }// 写法二 function m2({x, y} = { x: 0, y: 0 }) {return [x, y]; } 值。// 函数没有参数的情况 m1() // [0, 0] m2() // [0, 0]// x和y都有值的情况 m1({x: 3, y: 8}) // [3, 8] m2({x: 3, y: 8}) // [3, 8]// x有值,y无值的情况 m1({x: 3}) // [3, 0] m2({x: 3}) // [3, undefined]// x和y都无值的情况 m1({}) // [0, 0]; m2({}) // [undefined, undefined]m1({z: 3}) // [0, 0] m2({z: 3}) // [undefined, undefined]
个人理解当m1没有传入参数时,参数设置为空对象,使用对象结构值为{x = 0, y = 0};当m2没有传入参数时,使用设置的默认参数
- 参数默认值可以与解构赋值的默认值,结合起来使用。下面代码使用了对象的解构赋值默认值,而没有使用函数参数的默认值。只有当函数
- 参数默认值的位置
- 通常情况下,定义了默认值的参数,应该是函数的尾参数。因为这样比较容易看出来,到底省略了哪些参数。如果非尾部的参数设置默认值,实际上这个参数是没法省略的。
// 例一 function f(x = 1, y) {return [x, y]; }f() // [1, undefined] f(2) // [2, undefined]) f(, 1) // 报错 f(undefined, 1) // [1, 1]// 例二 function f(x, y = 5, z) {return [x, y, z]; }f() // [undefined, 5, undefined] f(1) // [1, 5, undefined] f(1, ,2) // 报错 f(1, undefined, 2) // [1, 5, 2]
- 如果传入
undefined
,将触发该参数等于默认值,null
则没有这个效果。function foo(x = 5, y = 6) {console.log(x, y); }foo(undefined, null) // 5 null
- 通常情况下,定义了默认值的参数,应该是函数的尾参数。因为这样比较容易看出来,到底省略了哪些参数。如果非尾部的参数设置默认值,实际上这个参数是没法省略的。
- 函数的length属性
- 指定了默认值以后,函数的
length
属性,将返回没有指定默认值的参数个数。也就是说,指定了默认值后,length
属性将失真。(function (a) {}).length // 1 (function (a = 5) {}).length // 0 (function (a, b, c = 5) {}).length // 2
- 因为
length
属性的含义是,该函数预期传入的参数个数。某个参数指定默认值以后,预期传入的参数个数就不包括这个参数了。同理,rest参数也不会计入length
属性。(function(...args) {}).length // 0
- 如果设置了默认值的参数不是尾参数,那么
length
属性也不再计入后面的参数了。(function (a = 0, b, c) {}).length // 0 (function (a, b = 1, c) {}).length // 1
- 指定了默认值以后,函数的
- 作用域
- 下面代码中,函数
foo
的参数x
的默认值也是x
。这时,默认值x
的作用域是函数作用域,而不是全局作用域。由于在函数作用域中,存在变量x
,但是默认值在x
赋值之前先执行了,所以这时属于暂时性死区(参见《let和const命令》一章),任何对x
的操作都会报错。var x = 1;function foo(x = x) {// ... }foo() // ReferenceError: x is not defined
- 下面代码中,函数
- 应用
- 利用参数默认值,可以指定某一个参数不得省略,如果省略就抛出一个错误。
function throwIfMissing() {throw new Error('Missing parameter'); }function foo(mustBeProvided = throwIfMissing()) {return mustBeProvided; }foo() // Error: Missing parameter
上面代码的
foo
函数,如果调用的时候没有参数,就会调用默认值throwIfMissing
函数,从而抛出一个错误。从上面代码还可以看到,参数
mustBeProvided
的默认值等于throwIfMissing
函数的运行结果(即函数名之后有一对圆括号),这表明参数的默认值不是在定义时执行,而是在运行时执行(即如果参数已经赋值,默认值中的函数就不会运行),这与python语言不一样。另外,可以将参数默认值设为
undefined
,表明这个参数是可以省略的。function foo(optional = undefined) { ··· }
- 利用参数默认值,可以指定某一个参数不得省略,如果省略就抛出一个错误。
- rest参数
- ES6引入rest参数(形式为“...变量名”),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
function add(...values) {let sum = 0;for (var val of values) {sum += val;}return sum; }add(2, 5, 3) // 10
- 注意,rest参数之后不能再有其他参数(即只能是最后一个参数),否则会报错。
// 报错 function f(a, ...b, c) {// ... }
- 函数的length属性,不包括rest参数。
(function(a) {}).length // 1 (function(...a) {}).length // 0 (function(a, ...b) {}).length // 1
- ES6引入rest参数(形式为“...变量名”),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
- 扩展运算符
- 扩展运算符(spread)是三个点(
...
)。它好比rest参数的逆运算,将一个数组转为用逗号分隔的参数序列。console.log(...[1, 2, 3]) // 1 2 3console.log(1, ...[2, 3, 4], 5) // 1 2 3 4 5[...document.querySelectorAll('div')] // [<div>, <div>, <div>]
- 该运算符主要用于函数调用。
function push(array, ...items) {array.push(...items); }function add(x, y) {return x + y; }var numbers = [4, 38]; add(...numbers) // 42
上面代码中,
array.push(...items)
和add(...numbers)
这两行,都是函数的调用,它们的都使用了扩展运算符。该运算符将一个数组,变为参数序列。 - 扩展运算符与正常的函数参数可以结合使用,非常灵活。
function f(v, w, x, y, z) { } var args = [0, 1]; f(-1, ...args, 2, ...[3]);
- 扩展运算符(spread)是三个点(
- 扩展运算符的应用
- 合并数组:扩展运算符提供了数组合并的新写法。
// ES5 [1, 2].concat(more) // ES6 [1, 2, ...more]var arr1 = ['a', 'b']; var arr2 = ['c']; var arr3 = ['d', 'e'];// ES5的合并数组 arr1.concat(arr2, arr3); // [ 'a', 'b', 'c', 'd', 'e' ]// ES6的合并数组 [...arr1, ...arr2, ...arr3] // [ 'a', 'b', 'c', 'd', 'e' ]
- 与解构赋值结合:扩展运算符可以与解构赋值结合起来,用于生成数组。
// ES5 a = list[0], rest = list.slice(1) // ES6 [a, ...rest] = list
下面是另外一些例子。
const [first, ...rest] = [1, 2, 3, 4, 5]; first // 1 rest // [2, 3, 4, 5]const [first, ...rest] = []; first // undefined rest // []:const [first, ...rest] = ["foo"]; first // "foo" rest // []
如果将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错。
const [...butLast, last] = [1, 2, 3, 4, 5]; // 报错const [first, ...middle, last] = [1, 2, 3, 4, 5]; // 报错
-
字符串
-
扩展运算符还可以将字符串转为真正的数组。
[...'hello'] // [ "h", "e", "l", "l", "o" ]
-
正确返回字符串长度的函数,可以像下面这样写。
function length(str) {return [...str].length; }
-
- 实现了Iterator接口的对象
- 任何Iterator接口的对象,都可以用扩展运算符转为真正的数组。下面是一个最特殊的例子。它不是数组,而是一个类似数组的对象。这时,扩展运算符可以将其转为真正的数组,原因就在于
NodeList
对象实现了Iterator接口。var nodeList = document.querySelectorAll('div'); var array = [...nodeList];
- 对于那些没有部署Iterator接口的类似数组的对象,扩展运算符就无法将其转为真正的数组。下面代码中,
arrayLike
是一个类似数组的对象,但是没有部署Iterator接口,扩展运算符就会报错。这时,可以改为使用Array.from
方法将arrayLike
转为真正的数组。let arrayLike = {'0': 'a','1': 'b','2': 'c',length: 3 };// TypeError: Cannot spread non-iterable object. let arr = [...arrayLike];
- 任何Iterator接口的对象,都可以用扩展运算符转为真正的数组。下面是一个最特殊的例子。它不是数组,而是一个类似数组的对象。这时,扩展运算符可以将其转为真正的数组,原因就在于
- 合并数组:扩展运算符提供了数组合并的新写法。
- Map和Set结构,Generator函数
- 扩展运算符内部调用的是数据结构的Iterator接口,因此只要具有Iterator接口的对象,都可以使用扩展运算符,比如Map结构。
let map = new Map([[1, 'one'],[2, 'two'],[3, 'three'], ]);let arr = [...map.keys()]; // [1, 2, 3]
- Generator函数运行后,返回一个遍历器对象,因此也可以使用扩展运算符。
var go = function*(){yield 1;yield 2;yield 3; };[...go()] // [1, 2, 3]
下面代码中,变量
go
是一个Generator函数,执行后返回的是一个遍历器对象,对这个遍历器对象执行扩展运算符,就会将内部遍历得到的值,转为一个数组。如果对没有
iterator
接口的对象,使用扩展运算符,将会报错。var obj = {a: 1, b: 2}; let arr = [...obj]; // TypeError: Cannot spread non-iterable object
- 扩展运算符内部调用的是数据结构的Iterator接口,因此只要具有Iterator接口的对象,都可以使用扩展运算符,比如Map结构。
- name属性
- 函数的
name
属性,返回该函数的函数名。function foo() {} foo.name // "foo" var func1 = function () {};// ES5 func1.name // ""// ES6 func1.name // "func1" const bar = function baz() {};// ES5 bar.name // "baz"// ES6 bar.name // "baz"
- 函数的
- 箭头函数
- 函数体内的
this
对象,就是定义时所在的对象,而不是使用时所在的对象
- 函数体内的
- 基本用法
- 对象的扩展
- 属性的简洁表示法
- ES6允许直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。下面代码表明,ES6允许在对象之中,直接写变量。这时,属性名为变量名, 属性值为变量的值。下面是另一个例子。
- 属性名表达式
- ES6 允许字面量定义对象时,用(表达式)作为对象的属性名,即把表达式放在方括号内。
let propKey = 'foo';let obj = {[propKey]: true,['a' + 'bc']: 123 };
- 注意,属性名表达式与简洁表示法,不能同时使用,会报错。
// 报错 var foo = 'bar'; var bar = 'abc'; var baz = { [foo] };// 正确 var foo = 'bar'; var baz = { [foo]: 'abc'};
- 注意,属性名表达式如果是一个对象,默认情况下会自动将对象转为字符串
[object Object]
,这一点要特别小心。下面代码中,[keyA]
和[keyB]
得到的都是[object Object]
,所以[keyB]
会把[keyA]
覆盖掉,而myObject
最后只有一个[object Object]
属性。const keyA = {a: 1}; const keyB = {b: 2};const myObject = {[keyA]: 'valueA',[keyB]: 'valueB' };myObject // Object {[object Object]: "valueB"}
- ES6 允许字面量定义对象时,用(表达式)作为对象的属性名,即把表达式放在方括号内。
- Object.is()
- ES5比较两个值是否相等,只有两个运算符:相等运算符(
==
)和严格相等运算符(===
)。它们都有缺点,前者会自动转换数据类型,后者的NaN
不等于自身,以及+0
等于-0
。JavaScript缺乏一种运算,在所有环境中,只要两个值是一样的,它们就应该相等。ES6提出“Same-value equality”(同值相等)算法,用来解决这个问题。Object.is
就是部署这个算法的新方法。它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。Object.is('foo', 'foo') // true Object.is({}, {}) // false//不同之处只有两个:一是+0不等于-0,二是NaN等于自身。+0 === -0 //true NaN === NaN // falseObject.is(+0, -0) // false Object.is(NaN, NaN) // true
- ES5比较两个值是否相等,只有两个运算符:相等运算符(
- Object.assign()
Object.assign
方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。Object.assign
方法的第一个参数是目标对象,后面的参数都是源对象。注意,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。如果只有一个参数,Object.assign
会直接返回该参数。如果该参数不是对象,则会先转成对象,然后返回。由于undefined
和null
无法转成对象,所以如果它们作为参数(仅限第一个参数),就会报错(其它参数无法转成对象,会直接跳过)。var target = { a: 1 };var source1 = { b: 2 }; var source2 = { c: 3 };Object.assign(target, source1, source2); target // {a:1, b:2, c:3}
- 其他类型的值(即数值、字符串和布尔值)不在首参数,也不会报错。但是,除了字符串会以数组形式,拷贝入目标对象,其他值都不会产生效果。
var v1 = 'abc'; var v2 = true; var v3 = 10;var obj = Object.assign({}, v1, v2, v3); console.log(obj); // { "0": "a", "1": "b", "2": "c" }
- 注意点:
Object.assign
方法实行的是浅拷贝,而不是深拷贝。深拷贝实现方式如下Object.assign(obj2,JSON.parse(JSON.stringify(obj1)))
- 常见用途
- 为对象添加属性
class Point {constructor(x, y) {Object.assign(this, {x, y});} }
- 为对象添加方法
Object.assign(SomeClass.prototype, {someMethod(arg1, arg2) {···},anotherMethod() {···} });// 等同于下面的写法 SomeClass.prototype.someMethod = function (arg1, arg2) {··· }; SomeClass.prototype.anotherMethod = function () {··· };
- 克隆对象
function clone(origin) {return Object.assign({}, origin); }
- 合并多个对象
const merge =(target, ...sources) => Object.assign(target, ...sources);
- 为属性指定默认值
const DEFAULTS = {logLevel: 0,outputFormat: 'html' };function processContent(options) {options = Object.assign({}, DEFAULTS, options); }
- 为对象添加属性
- 属性的可枚举性
- 对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行为。
Object.getOwnPropertyDescriptor
方法可以获取该属性的描述对象。let obj = { foo: 123 }; Object.getOwnPropertyDescriptor(obj, 'foo') // { // value: 123, // writable: true, // enumerable: true, // configurable: true // }
-
描述对象的enumerable属性,称为”可枚举性“,如果该属性为false,就表示某些操作会忽略当前属性。ES5有三个操作会忽略enumerable为false的属性。
for...in循环:只遍历对象自身的和继承的可枚举的属性
Object.keys():返回对象自身的所有可枚举的属性的键名
JSON.stringify():只串行化对象自身的可枚举的属性
ES6新增了一个操作Object.assign(),会忽略enumerable为false的属性,只拷贝对象自身的可枚举的属性。这四个操作之中,只有for...in会返回继承的属性。实际上,引入enumerable的最初目的,就是让某些属性可以规避掉for...in操作。比如,对象原型的toString方法,以及数组的length属性,就通过这种手段,不会被for...in遍历到。
Object.getOwnPropertyDescriptor(Object.prototype, 'toString').enumerable // falseObject.getOwnPropertyDescriptor([], 'length').enumerable // false
-
上面代码中,
toString
和length
属性的enumerable
都是false
,因此for...in
不会遍历到这两个继承自原型的属性。另外,ES6规定,所有Class的原型的方法都是不可枚举的。Object.getOwnPropertyDescriptor(class {foo() {}}.prototype, 'foo').enumerable // false
-
总的来说,操作中引入继承的属性会让问题复杂化,大多数时候,我们只关心对象自身的属性。所以,尽量不要用
for...in
循环,而使用Object.keys()
代替。
- 对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行为。
- __proto__属性,Object.setPrototypeOf(),Object.getPrototypeOf()
- __proto__属性
__proto__
属性(前后各两个下划线),用来读取或设置当前对象的prototype
对象。目前,所有浏览器(包括IE11)都部署了这个属性。// es6的写法 var obj = {method: function() { ... } }; obj.__proto__ = someOtherObj;// es5的写法 var obj = Object.create(someOtherObj); obj.method = function() { ... };
- 该属性没有写入ES6的正文,而是写入了附录,原因是
__proto__
前后的双下划线,说明它本质上是一个内部属性,而不是一个正式的对外的API,只是由于浏览器广泛支持,才被加入了ES6。标准明确规定,只有浏览器必须部署这个属性,其他运行环境不一定需要部署,而且新的代码最好认为这个属性是不存在的。因此,无论从语义的角度,还是从兼容性的角度,都不要使用这个属性,而是使用下面的Object.setPrototypeOf()
(写操作)、Object.getPrototypeOf()
(读操作)、Object.create()
(生成操作)代替。
- Object.setPrototypeOf()
- Object.setPrototypeOf方法的作用与__proto__相同,用来设置一个对象的prototype对象。它是ES6正式推荐的设置原型对象的方法。
// 格式 Object.setPrototypeOf(object, prototype)// 用法 var o = Object.setPrototypeOf({}, null);
- 该方法等同于下面的函数。
function (obj, proto) {obj.__proto__ = proto;return obj; }
- 下面是一个例子。
let proto = {}; let obj = { x: 10 }; Object.setPrototypeOf(obj, proto);proto.y = 20; proto.z = 40;obj.x // 10 obj.y // 20 obj.z // 40
上面代码将proto对象设为obj对象的原型,所以从obj对象可以读取proto对象的属性。
- Object.setPrototypeOf方法的作用与__proto__相同,用来设置一个对象的prototype对象。它是ES6正式推荐的设置原型对象的方法。
- Object.getPrototypeOf()
- 该方法与setPrototypeOf方法配套,用于读取一个对象的prototype对象
Object.getPrototypeOf(obj);
- 下面是一个例子。
function Rectangle() { }var rec = new Rectangle();Object.getPrototypeOf(rec) === Rectangle.prototype // trueObject.setPrototypeOf(rec, Object.prototype); Object.getPrototypeOf(rec) === Rectangle.prototype // false
- 该方法与setPrototypeOf方法配套,用于读取一个对象的prototype对象
- __proto__属性
- Object.values()
Object.values
方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值。var obj = { foo: "bar", baz: 42 }; Object.values(obj) // ["bar", 42]
- 返回数组的成员顺序,与《属性的遍历》介绍的排列规则一致。(首先遍历所有属性名为数值的属性,按照数字排序。其次遍历所有属性名为字符串的属性,按照生成时间排序。最后遍历所有属性名为Symbol值的属性,按照生成时间排序。)
var obj = { 100: 'a', 2: 'b', 7: 'c' }; Object.values(obj) // ["b", "c", "a"]
-
上面代码中,属性名为数值的属性,是按照数值大小,从小到大遍历的,因此返回的顺序是
b
、c
、a
。Object.values
只返回对象自身的可遍历属性。var obj = Object.create({}, {p: {value: 42}}); Object.values(obj) // []
-
上面代码中,
Object.create
方法的第二个参数添加的对象属性(属性p
),如果不显式声明,默认是不可遍历的。Object.values
不会返回这个属性。Object.values
会过滤属性名为Symbol值的属性。Object.values({ [Symbol()]: 123, foo: 'abc' }); // ['abc']
-
如果
Object.values
方法的参数是一个字符串,会返回各个字符组成的一个数组。Object.values('foo') // ['f', 'o', 'o']
-
上面代码中,字符串会先转成一个类似数组的对象。字符串的每个字符,就是该对象的一个属性。因此,
Object.values
返回每个属性的键值,就是各个字符组成的一个数组。如果参数不是对象,
Objec
t.values
会先将其转为对象。由于数值和布尔值的包装对象,都不会为实例添加非继承的属性。所以,Object.values
会返回空数组。Object.values(42) // [] Object.values(true) // []
- Object.entries()
Object.entries
方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组。var obj = { foo: 'bar', baz: 42 }; Object.entries(obj) // [ ["foo", "bar"], ["baz", 42] ]
-
除了返回值不一样,该方法的行为与
Object.values
基本一致。如果原对象的属性名是一个Symbol值,该属性会被省略。
- 对象的扩展运算符
- 解构赋值
- 对象的解构赋值用于从一个对象取值,相当于将所有可遍历的、但尚未被读取的属性,分配到指定的对象上面。所有的键和它们的值,都会拷贝到新对象上面。
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 }; x // 1 y // 2 z // { a: 3, b: 4 }
- 扩展运算符
- 扩展运算符(
...
)用于取出参数对象的所有可遍历属性,拷贝到当前对象之中。let z = { a: 3, b: 4 }; let n = { ...z }; n // { a: 3, b: 4 }
- 扩展运算符可以用于合并两个对象。
let ab = { ...a, ...b }; // 等同于 let ab = Object.assign({}, a, b);
- 扩展运算符(
- 对象的解构赋值用于从一个对象取值,相当于将所有可遍历的、但尚未被读取的属性,分配到指定的对象上面。所有的键和它们的值,都会拷贝到新对象上面。
- 解构赋值
- Object.getOwnPropertyDescriptors()
- ES7有一个提案,提出了
Object.getOwnPropertyDescriptors
方法,返回指定对象所有自身属性(非继承属性)的描述对象。const obj = {foo: 123,get bar() { return 'abc' } };Object.getOwnPropertyDescriptors(obj) // { foo: // { value: 123, // writable: true, // enumerable: true, // configurable: true }, // bar: // { get: [Function: bar], // set: undefined, // enumerable: true, // configurable: true } }
Object.getOwnPropertyDescriptors
方法返回一个对象,所有原对象的属性名都是该对象的属性名,对应的属性值就是该属性的描述对象。
- ES7有一个提案,提出了
- 属性的简洁表示法
相关文章:
ES6基础3
函数的扩展 基本用法 函数参数的默认值 ES6允许为函数的参数设置默认值,即直接写在参数定义的后面。 参数变量是默认声明的,所以不能用let或const再次声明。下面代码中,参数变量x是默认声明的,在函数体中,不能用let或c…...

HarmonyOS 数据持久化 关系型数据库之 初始化操作
上文 HarmonyOS 数据持久化之首选项 preferences 我们有说用户首选项 但它只能处理一些比较简单的数据类型结构 的持久化处理 如果是一些批量较大 结构较为复杂的数据结构 那么 首选项就无法满足了 我们就要选择 关系型数据库 通过 SQLite 组件实现的一种本地数据库࿰…...

伊芙丽签约实在智能,实在Agent数字员工助力品牌效能飙升
近日,国内知名时尚女装品牌伊芙丽与实在智能达成合作,引入业内领先的平台级自动化产品实在Agent数字员工——取数宝,自动获取天猫、淘宝、抖音等线上平台营销数据,开启全域化营销的“提效之旅”。 实在Agent智能体 伊芙丽集团成立…...

第十五届蓝桥杯-UART接收不定长指令的处理
学习初衷: 不仅仅为了比赛! 目录 一、问题引入 二、UART常用的三种工作模式 1.UART工作在中断模式 2.UART工作在DMA模式下 3.uart工作在接收转空闲的模式下 三、获取指令中需要的数据 四、printf函数的实现 一、问题引入 问题引入:请…...
网络 协议 UDP编程
网络:数据传输,数据共享 1.网络协议模型: OSI协议模型 应用层 实际发送的数据 表示层 发送的数据是否加密 会话层 是否建立会话连接 传输层 数据传输的方式(数据报、流式)…...

3505. 这也是一道排序题
一、题目 输入 10 7334774857 8461862436 540886577 5245195052 9194400521 5412986878 6694133363 1186771950 1405713915 7115286932 输出 -29430338967 二、思考 构造差分数组:C[i] A[i1] - A[i] 由题目条件可知:当A[i] A[i1] A[i-1] - A[i]时&am…...

【Redis】Redis的应用场景
📝个人主页:五敷有你 🔥系列专栏:Redis ⛺️稳中求进,晒太阳 Redis的应用场景: 限流 要求10s内只能访问一次 RequestMapping("xian")public String xianLiu(String sign){String sign1 …...

计算机网络—以太网接口和链路配置
目录 1.拓扑图 2.以太网交换机基础配置 3.配置手动模式的链路聚合 4.配置静态 LACP 模式的链路聚合 5.配置文件 1.拓扑图 2.以太网交换机基础配置 华为交换机接口默认开启了自协商功能,需要手动配置S1与 S2上G0/0/9和G0/0/10接口的速率。 首先修改交换机的设…...
关于做副业、做自媒体:说几句扎心的话
今天在某乎看到一个问题:想尝试自媒体,想了一个月了,都没想好怎么起步,咋整呀? 恰好昨天陪退休老妈去探店,有感而发,就来唠一唠。 一、退休老妈的副业经历 老妈去年年初开始,在某…...
精通SpringBoot单元测试
引言 单元测试是软件开发中不可或缺的一部分,它对保障代码质量和软件的可靠性起着至关重要的作用。而SpringBoot作为一个流行的Java框架,为开发高效、易于部署的微服务提供了强大的支持。 单元测试的重要性: 确保代码正确性:通过…...

HAProxy 简单介绍
一 HAProxy介绍 (一)发展历史 HAProxy是法国开发者威利塔罗(Willy Tarreau)在2000年使用C语言开发的一个开源软件,是一款具备高并发(一万以上)、高性能的TCP和HTTP负载均衡器,支持基于cookie的持久性,自动故障切换…...
SpringBoot集成Swagger3.0
一:前言 Swagger 是一个 RESTful API 的开源框架,它的主要目的是帮助开发者设计、构建、文档化和测试 Web API。Swagger 的核心思想是通过定义和描述 API 的规范、结构和交互方式,以提高 API 的可读性、可靠性和易用性,同时降…...

计算机网络-第5章 运输层(1)
主要内容:进程之间的通信与端口、UDP协议、TCP协议、可靠传输原理(停止等待协议、ARQ协议)、TCP报文首部、TCP三大题:滑动窗口、流量控制、拥塞控制机制 5.1 运输层协议概述 运输层向它上面的应用层提供通信服务,真正…...
性能优化-卡牌项目渲染优化
优化的方向 CPU 影响帧率 GPU 影响帧率 内存 超了会崩 显存 显存超了画面会异常,甚至可能导致游戏崩溃 带宽 影响耗电 分辨率 设备性能不行又要求流畅,降低目标渲染分辨率,立竿见影,但是会牺牲画质 场景 1 使用烘焙…...

STM32FreeRTOS任务通知(STM32cube高效开发)
文章目录 一、任务通知(一)任务通知概述1、任务通知可模拟队列和信号量2、任务通知优势和局限性 (二) 任务通知函数1、xTaskNotify()发送通知值不返回先前通知值的函数2、xTaskNotifyFromISR()发送通知函数ISR版本3、x…...

基于element-plus的Dialog选择控件
翻看之前工程师写的vue2的代码,很多都是复制、粘贴,也真是搞不懂,明明可以写一个控件,不就可以重复使用。很多前端总喜欢element搞一下,ant-design也搞一下,有啥意义,控件也不是自己写的&#x…...

手把手教使用静默 搭建Oracle 19c 一主一备ADG集群
一、环境搭建 主机IPora19192.168.134.239ora19std192.168.134.240 1.配置yum源 1.配置网络yum源 1.删除redhat7.0系统自带的yum软件包; rpm -qa|grep yum >oldyum.pkg 备份原信息rpm -qa|grep yum|xargs rpm -e --nodeps 不检查依赖,直接删除…...
使用协程库httpx并发请求
httpx和aiohttp都是比较常用的异步请求库,当然requests多线程或requestsgevent也是不错的选择。 一个使用httpx进行并发请求的脚本如下: import functools import sys import timeimport anyio import httpxasync def fetch(client, results, index) -…...
js的同步异步
JavaScript(JS)是一门单线程的编程语言,这意味着它一次只能处理一个任务。然而,JS 支持同步和异步操作。 同步操作是指代码按照顺序执行,每个操作必须在前一个操作完成后才能进行。这意味着当一个操作在执行时&#x…...
C# MG.CamCtrl 工业相机库(开源) 海康 大恒
C# MG.CamCtrl 相机库(开源) 海康 大恒 介绍工厂模式创建实例选取对应SN号的相机,初始化启动相机取图注销相机参数设置/获取接口 介绍 c# 相机库,含海康、大恒品牌2D相机的常用功能。 底层采用回调信号量模式封装 ,最…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...

vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
Python 高效图像帧提取与视频编码:实战指南
Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...

GraphQL 实战篇:Apollo Client 配置与缓存
GraphQL 实战篇:Apollo Client 配置与缓存 上一篇:GraphQL 入门篇:基础查询语法 依旧和上一篇的笔记一样,主实操,没啥过多的细节讲解,代码具体在: https://github.com/GoldenaArcher/graphql…...