当前位置: 首页 > news >正文

【07】ES6:对象的扩展

一、对象字面量语法扩展

1、属性简写

当属性名称和属性值的变量名称相同时,可以省略冒号的变量名称。

const foo = 'bar'const baz = { foo }
// 等同于
const baz = { foo: foo }baz // { foo: 'bar' }
function f(x, y) {return { x, y }
}
// 等同于
function f(x, y) {return { x: x, y: y }
}f(1, 2) // Object { x: 1, y: 2 }

2、方法简写

es6 可以省略冒号和函数关键字

// es5
const o = {method: function() {return 'Hello!'}
}// es6
const o = {method() {return 'Hello!'}
}
let birth = '2000/01/01'const Person = {name: '张三',// 等同于 birth: birthbirth,// 等同于 hello: function ()...hello() { console.log('我的名字是', this.name) }
}

CommonJS 模块输出一组变量,就非常合适使用简洁写法。

function getItem (key) {return key in ms ? ms[key] : null
}function setItem (key, value) {ms[key] = value
}function clear () {ms = {}
}module.exports = { getItem, setItem, clear }
// 等同于
module.exports = {getItem: getItem,setItem: setItem,clear: clear
}

3、计算属性名

JavaScript 定义对象的属性,有两种方法。但是,如果使用字面量方式定义对象(使用大括号),在 ES5 中只能使用方法一(标识符)定义属性。

// 方法一:标识符作为属性名
obj.foo = true// 方法二:表达式作为属性名
obj['a' + 'bc'] = 123

ES6 允许字面量定义对象时,属性名可以计算,用方括号表达式法进行计算,方括号中的值为表达式,最终结果为表达式计算的结果。

let lastWord = 'last word'const obj = {'first word': 'hello',[lastWord]: 'world',['h' + 'ello']() {return 'hi'}
}obj['first word'] // 'hello'
obj[lastWord] // 'world'
obj['last word'] // 'world'
obj.hello() // hi

注意,属性名表达式与简洁表示法,不能同时使用,会报错。

// 报错
const foo = 'bar'
const bar = 'abc'
const baz = { [foo] }// 正确
const foo = 'bar'
const baz = { [foo]: 'abc'}

注意,属性名表达式如果是一个对象,默认情况下会自动将对象转为字符串 [object Object],这一点要特别小心。

const keyA = { a: 1 }
const keyB = { b: 2 }const myObject = {[keyA]: 'valueA',[keyB]: 'valueB'
}myObject // Object {[object Object]: "valueB"}

二、super 关键字

我们知道,this 关键字总是指向函数所在的当前对象,ES6 又新增了另一个类似的关键字 super,指向当前对象的原型对象。

const proto = {foo: 'hello'
}const obj = {foo: 'world',find() {return super.foo}
}Object.setPrototypeOf(obj, proto)
obj.find() // 'hello'

注意,super 关键字表示原型对象时,只能用在对象的方法之中,用在其他地方都会报错。

// 报错:super 用在属性里面
const obj = {foo: super.foo
}// 报错:super 用在一个函数里面,然后赋值给 foo 属性
const obj = {foo: () => super.foo
}// 报错:super 用在一个函数里面,然后赋值给 foo 属性
const obj = {foo: function () {return super.foo}
}

上面三种 super 的用法都会报错,因为对于 JavaScript 引擎来说,这里的 supe r都没有用在对象的方法之中。第一种写法是 super 用在属性里面,第二种和第三种写法是 super 用在一个函数里面,然后赋值给 foo 属性。目前,只有对象方法的简写法可以让 JavaScript 引擎确认,定义的是对象的方法。

JavaScript 引擎内部,super.foo 等同于 Object.getPrototypeOf(this).foo(属性)或Object.getPrototypeOf(this).foo.call(this)(方法)。

const proto = {x: 'hello',foo() {console.log(this.x)}
}const obj = {x: 'world',foo() {super.foo()}
}Object.setPrototypeOf(obj, proto)obj.foo() // 'world'

上面代码中,super.foo 指向原型对象 proto 的 foo 方法,但是绑定的 this 却还是当前对象 obj,因此输出的就是 world 。

三、对象的扩展运算符

对象的扩展运算符(…)用于取出参数对象的所有可遍历属性,拷贝到当前对象之中。

拷贝的属性为浅拷贝。即如果一个键的值是复合类型的值(数组、对象、函数)、那么拷贝的是这个值的引用,而不是这个值的副本。

1、基本语法

对象不能直接展开,必须在 {} 中展开。

let z = { a: 3, b: 4 }
let n = { ...z } // { a: 3, b: 4 }

数组是特殊的对象,所以对象的扩展运算符也可以用于数组。

let foo = { ...['a', 'b', 'c'] }
foo // { 0: 'a', 1: 'b', 2: 'c' }

如果扩展运算符后面是一个空对象,则没有任何效果。

{ ...{}, a: 1 } // { a: 1 }

如果扩展运算符后面不是对象,则会自动将其转为对象。

// 等同于 { ...Object(1) }
{ ...1 } // {}  // 等同于 { ...Object(true) }
{ ...true } // {}// 等同于 { ...Object(undefined) }
{ ...undefined } // {}// 等同于 { ...Object(null) }
{ ...null } // {}

如果扩展运算符后面是字符串,它会自动转成一个类似数组的对象,因此返回的不是空对象。

{ ...'hello' } // { 0: 'h', 1: 'e', 2: 'l', 3: 'l', 4: '0' }

对象的扩展运算符,只会返回参数对象自身的、可枚举的属性,这一点要特别小心,尤其是用于类的实例对象时。

// m() 方法定义在 C 的原型对象上,对实例 c 进行扩展时,不会返回 c 的方法 c.m()
class C {p = 12m() {}
}let c = new C()
let clone = { ...c }clone.p // ok
clone.m() // 报错

如果想完整克隆一个对象,还拷贝对象原型的属性,可以采用下面的写法。

// 写法一:不推荐,__proto__ 属性在非浏览器的环境不一定部署。
const clone1 = {__proto__: Object.getPrototypeOf(obj)...obj
}// 写法二
const clone2 = Object.assign(Object.create(Object.getPrototypeOf(obj))obj
)// 写法三
const clone3 = Object.create(Object.getPrototypeOf(obj),Object.getOwnPropertyDescriptors(obj)
)

对象的扩展运算符等同于使用 Object.assign() 方法。

let aClone = { ...a }
// 等同于
let aClone = Object.assign({}, a)

2、用途

(1)复制对象

const a = { x: 1, y: 2 }
const c = { ...a }
console.log(c, c === a) // { x: 1, y: 2 } false 浅拷贝

(2)合并对象

const apple = {color: '红色',shape: '球形',taste: '甜'
}const pen = {color: '黑色',shape: '圆柱形',use: '写字'
}// 新对象拥有全部属性,相同属性,后者覆盖前者
{ ...apple, ...pen } // { color: '黑色', shape: '圆柱形', taste: '甜', use: '写字' }
{ ...pen, ...apple } // { color: '红色', shape: '球形', use: '写字', taste: '甜' }// 等同于
Object.assign({}, apple, pen)

(3)与解构赋值结合

对象的解构赋值用于从一个对象取值,相当于将目标对象自身的所有可遍历的(enumerable)、但尚未被读取的属性,分配到指定的对象上面。所有的键和它们的值,都会拷贝(浅拷贝)到新对象上面。

let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 }
x // 1
y // 2
z // { a: 3, b: 4 }// 浅拷贝
let obj = { a: { b: 1 } }
let { ...x } = obj
obj.a.b = 2
x.a.b // 2

由于解构赋值要求等号右边是一个对象,所以如果等号右边是 undefined 或 null,就会报错,因为它们无法转为对象。

let { ...z } = null // 运行时错误
let { ...z } = undefined // 运行时错误

扩展运算必须是最后一个参数,否则会报错。

let { ...x, y, z } = someObject // 句法错误
let { x, ...y, ...z } = someObject // 句法错误

另外,扩展运算符的解构赋值,不能复制继承自原型对象的属性。

// 对象 o3 复制了 o2,但是只复制了 o2 自身的属性,没有复制它的原型对象 o1 的属性。
let o1 = { a: 1 }
let o2 = { b: 2 }
o2.__proto__ = o1
let { ...o3 } = o2
o3 // { b: 2 }
o3.a // undefined

变量 x 是单纯的解构赋值,所以可以读取对象 o 继承的属性;变量 y 和 z 是扩展运算符的解构赋值,只能读取对象 o 自身的属性,所以变量 z 可以赋值成功,变量y取不到值。

const o = Object.create({ x: 1, y: 2 })
o.z = 3let { x, ...newObj } = o
let { y, z } = newObj
x // 1
y // undefined
z // 3// ES6 规定,变量声明语句之中,如果使用解构赋值,扩展运算符后面必须是一个变量名,而不能是一个解构赋值表达式。以下写法会报错。
let { x, ...{ y, z } } = o
// SyntaxError: ... must be followed by an identifier in declaration contexts

解构赋值的一个用处,是扩展某个函数的参数,引入其他操作。

function baseFunction({ a, b }) {// ...
}
function wrapperFunction({ x, y, ...restConfig }) {// 使用 x 和 y 参数进行操作// 其余参数传给原始函数return baseFunction(restConfig)
}

上面代码中,原始函数 baseFunction 接受 a 和 b 作为参数,函数 wrapperFunction 在 baseFunction 的基础上进行了扩展,能够接受多余的参数,并且保留原始函数的行为。

四、对象的新增方法

1、Object.is()

ES5 中比较两个值是否相等,只有两个运算符:

运算符说明
相等运算符(==)弱类型相等运算符,它比较两个值是否相等,如果两个值类型不同,会自动进行类型转换后再比较。

缺点:会自动转换数据类型。
严格相等运算符(===)严格类型相等运算符,它比较两个值的类型和值是否都相等,如果类型不同或值不同,返回 false。

缺点:NaN 不等于自身,以及 +0 等于 -0。

ES 新增的 Object.is 方法,与严格相等运算符的行为基本一致,并解决了严格相等运算符存在的问题( +0 不等于 -0、NaN 等于自身)。

Object.is('foo', 'foo')// true
// ==、===、Object.is() 在比较引用类型比较时,比较的是内存的地址,不是内容。
Object.is({}, {}) // false +0 === -0 //true
NaN === NaN // falseObject.is(+0, -0) // false
Object.is(NaN, NaN) // true

了解:ES5 可以通过下面的代码,实现 Object.is 方法。

Object.defineProperty(Object, 'is', {value: function(x, y) {if (x === y) {// 针对 +0 不等于 -0 的情况return x !== 0 || 1 / x === 1 / y}// 针对 NaN 的情况return x !== x && y !== y},configurable: true,enumerable: false,writable: true
})

2、Object.assign()

Object.assign() 方法用于对象的合并,用于将一个或多个源对象的所有属性复制到目标对象。

语法说明:

Object.assign(target, ...sources)
参数说明
target目标对象,接收复制的属性。
sources一个或多个源对象,从中复制属性到目标对象。
/* 基本用法 */
const target = { a: 1 }
const source1 = { b: 2 }
const source2 = { c: 3 }
Object.assign(target, source1, source2)
target // {a:1, b:2, c:3}/* 同名属性覆盖 */
const target = { a: { b: 'c', d: 'e' } }
const source = { a: { b: 'hello' } }
Object.assign(target, source) // { a: { b: 'hello' } }/* 返回值是目标对象(如果该参数不是对象,则会先转成对象,然后返回。)*/
const obj = { a: 1 }
Object.assign(obj) === obj // true
typeof Object.assign(2) // 'object'/* 基本数据类型作为源对象:先转换成对象,再合并*/
Object.assign({}, 'str') // { '0': 's', '1': 't', '2': 'r' }
Object.assign({}, 1) // {}
Object.assign({}, true) // {}
Object.assign({}, undefined) // {}
Object.assign({}, null) // {}/* 数组的处理:将数组视为对象 */
Object.assign([1, 2, 3], [4, 5]) // [4, 5, 3] (把数组视为属性名为 0、1、2 的对象,源数组的 0 号属性 4 覆盖了目标数组的 0 号属性 1。)/* 浅拷贝 */
const obj1 = { a: { b: 1 } }
const obj2 = Object.assign({}, obj1)
obj1.a.b = 2
obj2.a.b // 2/* 不拷贝不可枚举的属性 */
const v1 = 'abc'
const v2 = true
const v3 = 10
const obj = Object.assign({}, v1, v2, v3)
obj // { '0': 'a', '1': 'b', '2': 'c' }/* 不拷贝源对象的原型链上的属性 */
const parent = { parentProp: 'I am from the parent' }
// 定义一个子对象,并将父对象作为其原型
const child = Object.create(parent, { childProp: 'I am from the child'
})
Object.assign({}, child) // { childProp: 'I am from the child' }

注意点:

Object.assign() 只拷贝源对象的自身属性(不拷贝继承属性),也不拷贝不可枚举的属性(enumerable: false)。

如果目标对象已经具有与源对象相同的属性名,则会覆盖目标对象的属性值。

Object.assign() 是浅拷贝,复制的是引用而不是对象本身。

返回值是目标对象。

常见用途:

为对象添加属性

// 通过 Object.assign() 方法,将 x 属性和 y 属性添加到 Point 类的对象实例
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 merge = (...sources) => Object.assign({}, ...sources) // 合并后返回一个新对象

为属性指定默认值

// 默认值(由于存在浅拷贝的问题,DEFAULTS 对象和 options 对象的所有属性的值,最好都是简单类型,不要指向另一个对象。)
const DEFAULTS = {logLevel: 0,outputFormat: 'html'
}function processContent(options) {options = Object.assign({}, DEFAULTS, options) // options 对象是用户提供的参数// ...
}

3、Object.getOwnPropertyDescriptors()

语法说明:

Object.getOwnPropertyDescriptor() 方法

ES5 引入,获取单个属性的描述符,会返回某个对象属性的描述对象。

Object.getOwnPropertyDescriptors() 方法

ES 2017 引入,获取所有属性的数据描述符 ,返回指定对象所有自身属性(非继承属性)的描述对象。

// 返回一个对象,所有原对象的属性名都是该对象的属性名,对应的属性值就是该属性的描述对象。
const obj = {foo: 123,get bar() { return 'abc' }
}Object.getOwnPropertyDescriptors(obj)
/* {foo: {value: 123, // 属性的值writable: true, // 属性的值是否可被改变enumerable: true, // 属性的值是否可被枚举configurable: true // 描述符本身是否可被修改,属性是否可被删除},bar: {get: [Function: get bar], // 获取该属性的访问器函数(getter)。如果没有访问器, 该值为undefined。set: undefined, // 获取该属性的设置器函数(setter)。 如果没有设置器, 该值为undefinedenumerable: true,configurable: true}
} */

使用 ES5 的 Object.getOwnPropertyDescriptor() 方法实现 Object.getOwnPropertyDescriptors() 方法。

function getOwnPropertyDescriptors(obj) {const result = {}for (let key of Reflect.ownKeys(obj)) {result[key] = Object.getOwnPropertyDescriptor(obj, key)}return result
}

常见用途:

拷贝 get 属性和 set 属性

Object.assigns方法无法正确拷贝get属性和set属性。

const source = {set foo(value) { // 赋值函数console.log(value)}
}const target1 = {}
// Object.assign 方法总是拷贝一个属性的值,而不会拷贝它背后的赋值方法或取值方法。
Object.assign(target1, source)Object.getOwnPropertyDescriptor(target1, 'foo')
/* {value: undefined, // Object.assign 方法拷贝后属性值变为 undefinedwritable: true,enumerable: true,configurable: true
} */

Object.getOwnPropertyDescriptors() 方法配合 Object.defineProperties() 方法,就可以实现正确拷贝。

const source = {set foo(value) { // 赋值函数console.log(value)}
}const target2 = {}
// Object.defineProperties() 方法将直接在对象上定义一个或多个新的属性或修改现有属性,并返回该对象。
Object.defineProperties(target2, Object.getOwnPropertyDescriptors(source))
Object.getOwnPropertyDescriptor(target2, 'foo')
/* {get: undefined,set: [Function: set foo],enumerable: true,configurable: true
} */// 拷贝方法封装
const shallowMerge = (target, source) => Object.defineProperties(target,Object.getOwnPropertyDescriptors(source)
)

配合 Object.create() 方法,将对象属性克隆到一个新对象(浅拷贝)

/* Object.create(proto, propertiesObject)说明:以一个现有对象作为原型,创建一个新对象。参数:1. proto,新创建对象的原型对象。2. propertiesObject 可选,如果该参数被指定且不为 undefined,则该传入对象可枚举的自有属性将为新创建的对象添加具有对应属性名称的属性描述符。这些属性对应于 Object.defineProperties() 的第二个参数。返回值:根据指定的原型对象和属性创建的新对象。
*//* Object.getPrototypeOf()说明:返回指定对象的原型(即内部 [[Prototype]] 属性的值)。返回值:要返回其原型的对象。
*/
const clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj))// 或着
const shallowClone = (obj) => Object.create(Object.getPrototypeOf(obj),Object.getOwnPropertyDescriptors(obj)
)

实现一个对象继承另一个对象

// 1. __proto__写法
const obj = {__proto__: prot,foo: 123,
}// 2.  Object.create 写法
const obj = Object.create(prot)
obj.foo = 123// 3. Object.assign + Object.create 写法
const obj = Object.assign(Object.create(prot),{ foo: 123 }
)// 4. Object.create + Object.getOwnPropertyDescriptors 写法
const obj = Object.create(prot,Object.getOwnPropertyDescriptors({foo: 123})
)

4、proto 属性,Object.setPrototypeOf(),Object.getPrototypeOf()

名称说明
proto 属性用来读取或设置当前对象的原型对象(prototype)。内部属性,不推荐使用。
Object.setPrototypeOf()用来设置一个对象的原型对象(prototype),返回参数对象本身。
Object.setPrototypeOf(object, prototype)
Object.setPrototypeOf()用来读取一个对象的原型对象(prototype)。

__proto__本质上是一个内部属性,而不是一个正式的对外的 API,只是由于浏览器广泛支持,才被加入了 ES6。推荐使用 Object.setPrototypeOf()(写操作)、Object.getPrototypeOf()(读操作)、Object.create()(生成操作)代替。

// __proto__写法
const obj = {method: function() { ... }
}
obj.__proto__ = someOtherObj// Object.create 写法
var obj = Object.create(someOtherObj)
obj.method = function() { ... }// Object.setPrototypeOf 写法
Object.setPrototypeOf(obj, someOtherObj)

5、Object.keys(),Object.values(),Object.entries()

方法说明
Object.keys返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名。
Object.values返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值。
Object.entries返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组。
// 基本用法
const person = {name: 'Alex',age: 18
}
// 返回键数组
console.log(Object.keys(person)) // [ 'name', 'age' ]
// 返回值数组
console.log(Object.values(person)) // [ 'Alex', 18 ]
// 返回键值二维数组
console.log(Object.entries(person)) // [ [ 'name', 'Alex' ], [ 'age', 18 ] ]// 与数组类似方法的区别
console.log([1, 2].keys()) // Object [Array Iterator] {}
console.log([1, 2].values()) // Object [Array Iterator] {}
console.log([1, 2].entries()) // Object [Array Iterator] {}
// 数组的 keys()、values()、entries() 等方法是实例方法,返回的都是 Iterator
// 对象的 Object.keys()、Object.values()、Object.entries() 等方法是构造函数方法,返回的是数组// 应用(使用 for...of 循环遍历对象)
const person = {name: 'Alex',age: 18
}
for (const key of Object.keys(person)) {console.log(key)
}
// name
// age
for (const value of Object.values(person)) {console.log(value)
}
// Alex
// 18
for (const entries of Object.entries(person)) {console.log(entries)
}
// [ 'name', 'Alex' ]
// [ 'age', 18 ]
for (const [key, value] of Object.entries(person)) {console.log(key, value)
}
// name Alex
// age 18// Object.keys()/values()/entires() 并不能保证顺序一定是你看到的样子,这一点和 for in 是一样的
// 如果对遍历顺序有要求那么不能用 for in 以及这种方法,而要用其他方法

6、Object.hasOwn()

JavaScript 对象的属性分成两种:自身的属性和继承的属性。

对象实例有一个 hasOwnProperty() 方法,可以判断某个属性是否为原生属性。

ES2022 在 Object 对象上面新增了一个静态方法 Object.hasOwn(),也可以判断是否为自身的属性。

const foo = Object.create({ a: 123 })
foo.b = 456Object.hasOwn(foo, 'a') // false
Object.hasOwn(foo, 'b') // true

Object.hasOwn() 的一个好处是,对于不继承 Object.prototype 的对象不会报错,而 hasOwnProperty() 是会报错的。

// Object.create(null)返回的对象obj是没有原型的,不继承任何属性,
const obj = Object.create(null)obj.hasOwnProperty('foo') // 报错
Object.hasOwn(obj, 'foo') // false

相关文章:

【07】ES6:对象的扩展

一、对象字面量语法扩展 1、属性简写 当属性名称和属性值的变量名称相同时,可以省略冒号的变量名称。 const foo barconst baz { foo } // 等同于 const baz { foo: foo }baz // { foo: bar }function f(x, y) {return { x, y } } // 等同于 function f(x, y)…...

flink找不到隐式项

增加 import org.apache.flink.streaming.api.scala._ 即可...

【网络编程】-- 04 UDP

网络编程 6 UDP 6.1 初识Tomcat 服务端 自定义 STomcat S 客户端 自定义 C浏览器 B 6.2 UDP 6.2.1 udp实现发送消息 接收端: package com.duo.lesson03;import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketExceptio…...

【脚本】图片-音视频-压缩文件处理

音视频处理 一,图片操作1,转换图片格式2,多张图片合成视频 二,音频操作1,转换音频格式2,分割音频为多段3,合成多段音频 三,视频操作1,转换视频格式2,提取视频…...

跨品牌的手机要怎样相互投屏?iPhone和iPad怎么相互投屏?

选择买不同品牌的手机是基于品牌声誉、产品特点、价格和性价比等多个因素的综合考虑。每个人的需求和偏好不同,选择适合自己的手机品牌是一个个人化的决策。 一些品牌可能更加注重摄影功能,而其他品牌可能更加注重性能和速度。选择不同品牌的手机可以根据…...

图像特征提取-角点

角点特征 大多数人都玩过拼图游戏。首先拿到完整图像的碎片,然后把这些碎片以正确的方式排列起来从而重建这幅图像。如果把拼图游戏的原理写成计算机程序,那计算机就也会玩拼图游戏了。 在拼图时,我们要寻找一些唯一的特征,这些…...

N26:构建无缝体验的平台工程之路-Part 2

​ 在第一​​​​​​部分,我们介绍了 N26 团队为达成 “在 Day 1 实现轻松部署” 的目标而设定的战略规划和开发人员体验图,在这一部分,我们将带您了解该团队如何构建最简可行平台以及该平台如何运作。 01 计划构建最简可行平台 我们通…...

【Hadoop-Distcp】通过Distcp的方式进行两个HDFS集群间的数据迁移

【Hadoop-Distcp】通过Distcp的方式进行两个HDFS集群间的数据迁移 1)Distcp 工具简介及参数说明2)Shell 脚本 1)Distcp 工具简介及参数说明 【Hadoop-Distcp】工具简介及参数说明 2)Shell 脚本 应用场景: 两个实时集…...

【Linux】使用Bash和GNU Parallel并行解压缩文件

介绍 在本教程中,我们将学习如何使用Bash脚本和GNU Parallel实现高效并行解压缩多个文件。这种方法在处理大量文件时可以显著加快提取过程。 先决条件 确保系统上已安装以下内容: BashGNU Parallel 你可以使用以下命令在不同Linux系统上安装它们&am…...

T天池SQL训练营(五)-窗口函数等

–天池龙珠计划SQL训练营 5.1窗口函数 5.1.1窗口函数概念及基本的使用方法 窗口函数也称为OLAP函数。OLAP 是OnLine AnalyticalProcessing 的简称,意思是对数据库数据进行实时分析处理。 为了便于理解,称之为窗口函数。常规的SELECT语句都是对整张表进…...

道可云元宇宙每日资讯|上海市区块链关键技术攻关专项项目立项清单公布

道可云元宇宙每日简报(2023年12月11日)讯,今日元宇宙新鲜事有: 上海市2023年度区块链关键技术攻关专项项目立项清单公布 据上海市科学技术委员会近日发布通知,上海市2023年度“科技创新行动计划”区块链关键技术攻关…...

大语言模型有什么意义?亚马逊训练自己的大语言模型有什么用?

近年来,大语言模型的崭露头角引起了广泛的关注,成为科技领域的一项重要突破。而在这个领域的巅峰之上,亚马逊云科技一直致力于推动人工智能的发展。那么,作为一家全球科技巨头,亚马逊为何会如此注重大语言模型的研发与…...

RabbitMQ-学习笔记(初识 RabbitMQ)

本篇文章学习于 bilibili黑马 的视频 (狗头保命) 同步通讯 & 异步通讯 (RabbitMQ 的前置知识) 同步通讯:类似打电话,只有对方接受了你发起的请求,双方才能进行通讯, 同一时刻你只能跟一个人打视频电话。异步通讯:类似发信息&#xff0c…...

SQL Update语句

SQL Update语句 大家好,我是免费搭建查券返利机器人赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! SQL Update语句:数据库操作高招解析 数据库是我们搭建查券返利机器人的重要组成部分&…...

C语言-WIN32API介绍

Windows API 从第一个32位的Windows开始就出现了,就叫做Win32API.它是一个纯C的函数库,就和C标准库一样,使你可以写Windows应用程序过去很多Windows程序是用这个方式做出来的 main()? main()成为C语言的入口函数其实和C语言本身无关&…...

TFIDF、BM25、编辑距离、倒排索引

TFIDF TF刻画了词语t对某篇文档的重要性,IDF刻画了词语t对整个文档集的重要性...

MySQL之DML语句

文章目录 DML语句创建表添加表字段**插入数据**查询数据更新数据替换数据删除数据清除表数据删除表 DML语句 数据操作语言DML(Data Manipulation Langua) 是SQL语言的一个分类,用于对表的数据进行增,删,改&#xff0c…...

kubernetes集群常用指令

目录 1.1 基础控制指令 1.2 命令实践 1.3 备注 1.1 基础控制指令 # 查看对应资源: 状态 $ kubectl get <SOURCE_NAME> -n <NAMESPACE> -o wide ​ # 查看对应资源: 事件信息 $ kubectl describe <SOURCE_NAME> <SOURCE_NAME_RANDOM_ID> -n <NAMES…...

PyQt6 QTreeView树视图

锋哥原创的PyQt6视频教程&#xff1a; 2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili QTreeView类&#xff0c;它是树控件的基类&#xff0c;使用时&#xff0c;必须为其提供一个模型来与之配合。 QTreeView类的常用方法&#xff1a; 方法…...

链表|148. 排序链表

148. 排序链表 题目&#xff1a;给你链表的头结点 head &#xff0c;请将其按升序排列并返回排序后的链表。 题目链接&#xff1a; 148. 排序链表 时间复杂度&#xff1a;快排 O(n^2) 超出时间限制 class Solution {public ListNode sortList(ListNode head) {if(headnull)…...

如何解决5G基站高能耗问题?

安科瑞 须静燕 截至2023年10月&#xff0c;我国5G基站总数达321.5万个&#xff0c;占全国通信基站总数的28.1%。然而&#xff0c;随着5G基站数量的快速增长&#xff0c;基站的能耗问题也逐渐日益凸显&#xff0c;基站的用电给运营商带来了巨大的电费开支压力&#xff0c;降低5…...

PyTorch实现逻辑回归

最终效果 先看下最终效果&#xff1a; 这里用一条直线把二维平面上不同的点分开。 生成随机数据 #创建训练数据 x torch.rand(10,1)*10 #shape(10,1) y 2*x (5 torch.randn(10,1))#构建线性回归参数 w torch.randn((1))#随机初始化w&#xff0c;要用到自动梯度求导 b …...

什么是FPGA原型验证?

EDA工具的使用主要分为设计、验证和制造三大类。验证工作贯穿整个芯片设计流程&#xff0c;可以说芯片的验证阶段占据了整个芯片开发的大部分时间。从芯片需求定义、功能设计开发到物理实现制造&#xff0c;每个环节都需要进行大量的验证。 现如今验证方法也越来越多&#xff…...

基于VUE3+Layui从头搭建通用后台管理系统(前端篇)十四:系统设置模块相关功能实现

一、本章内容 本章使用已实现的公共组件实现系统管理中的系统设置模块相关功能,包括菜单管理、角色管理、日志管理、用户管理、系统配置、数据字典等。 1. 详细课程地址: 待发布 2. 源码下载地址: 待发布 二、界面预览 三、开发视频 3.1 B站视频地址:...

使用Visual Studio(VS)创建空项目的Win32桌面应用程序【main函数入口变WinMain】

前言 在Visual Studio中直接新建Windows桌面应用程序会有很多多余的代码生成&#xff0c;本文将提供从空项目创建Win32项目的方法&#xff0c;解决新建空项目直接使用WinMain代码编译报错的问题 例如&#xff1a;LNK2019 &#xff1a;无法解析的外部符号 参考博客&#xff1…...

基于自动化脚本批量上传依赖到nexus内网私服

前言 因为某些原因某些企业希望私服是不能连接外网的&#xff0c;所以需要某些开源依赖需要我们手动导入到nexus中&#xff0c;尽管nexus为我们提供了web页面。但是一个个手动导入显然是一个庞大的工程。 对此我们就不妨基于脚本的方式实现这一过程。 预期效果 笔者本地仓库…...

Linux中ps命令使用指南

目录 1 前言2 ps命令的含义和作用3 ps命令的基本使用4 常用选项参数5 一些常用情景5.1 查看系统中的所有进程&#xff08;标准语法&#xff09;5.2 使用 BSD 语法查看系统中的所有进程5.3 打印进程树5.4 获取线程信息5.5 获取安全信息5.6 查看以 root 用户身份&#xff08;实际…...

PHP开发语言中,网页端常用的标签

在PHP开发语言中&#xff0c;网页端常用的标签包括以下几种&#xff1a; <html>&#xff1a;用于定义整个HTML文档。<head>&#xff1a;用于定义文档的头部&#xff0c;包含元数据、样式表和脚本等。<title>&#xff1a;用于定义文档的标题&#xff0c;显示…...

Java 入门第四篇 集合

Java 入门第四篇 集合 一&#xff0c;什么是集合 在Java中&#xff0c;集合&#xff08;Collection&#xff09;是一种用于存储和操作一组对象的容器类。它提供了一系列的方法和功能&#xff0c;用于方便地管理和操作对象的集合。集合框架是Java中非常重要和常用的一部分&…...

VBA技术资料MF93:将多个Excel表插入PowerPoint不同位置

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。我的教程一共九套&#xff0c;分为初级、中级、高级三大部分。是对VBA的系统讲解&#xff0c;从简单的入门&#xff0c;到…...