解锁 JavaScript ES6:函数与对象的高级扩展功能


在这里插入图片描述



个人主页:学习前端的小z

个人专栏:JavaScript 精粹

本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结,欢迎大家在评论区交流讨论!
在这里插入图片描述


ES5、ES6介绍


文章目录

  • ES6函数扩展
    • 1 默认参数
      • 1.1 之前写法
      • 1.2 ES6 写法
      • 1.3 注意点
    • 2 reset 参数
    • 3 name属性
    • 4 箭头函数
      • 4.1 this指向
      • 4.2 练习
  • ES6对象扩展
    • 1 表示方法
    • 2 属性名表达式
    • 3 属性的可枚举性和遍历
      • 3.1 可枚举性
      • 3.2 属性的遍历
    • 4 super 关键字
    • 5 对象拷贝与解构
      • 5.1 对象解构
      • 5.2 对象拷贝
      • 5.3 链判断运算符


在这里插入图片描述


ES6函数扩展

1 默认参数

javascript函数中 我们经常需要给必要参数加以默认值 防止参数为传的情况下出现错误

1.1 之前写法

function count(x,y){return x + y;
}
count(3); //因为参数y没有传递 默认值为 undefined 3+undefined返回 NaN
function count(x,y){x = x||0;y = y||0;  //如果参数y为undefined 返回0设置给yreturn x + y;
}
count(3); //3 function count(x,y){x = x??0;y = y??0;//ES2019新增 空值合并运算符?? 详见对应文档return x + y;
}
count(3); //3 

1.2 ES6 写法

ES6 的写法不仅简洁 而且易读 让其他开发者能够快速了解参数类型 是否可省等信息, 也不会对函数体代码造成过多负担 有利于后期优化重构

function count(x = 0,y = 0){return x + y;
}
count(3); //3 

1.3 注意点

// 使用默认参数 无法在函数体内重新声明同名变量
function count(x = 0,y = 0){let x; //报错  const y; //报错
}
//参数默认值不是传值的,而是每次都重新计算默认值表达式的值。也就是说,参数默认值是惰性求值的。let num = 1;
function count(x = num + 1 , y = 0){return x;
}
count() // 2num = 99;count(); // 100
//参数也可以作为默认值 但要注意顺序function fn(x = 10, y = x){console.log(x,y);
}fn(20); //20 20
fn(); // 10 10----------------------------
//错误写法 x参数调用y时 y还未定义
function fn(x = y, y = 10){console.log(x,y);
}fn(); //Cannot access 'y' before initialization
//参数默认值为变量时 如果外部作用域有对应变量 指向外部变量对应值
let  w = 10;
function fn(x = w){let w = 20;return x;
}
fn(); //10;//在() 阶段 x已经赋值 后续修改w 也无法改变x的值
let  w = 10;
function fn(x = w){w = 20;return x;
}
fn(); //10;

2 reset 参数

ES6 引入 rest 参数(形式为...变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。

//类似结构赋值 以后就不用call来使arguments可以调用数组方法了
function count(...values) {console.log(values); //[2,5,3]return values.reduce((acc,curr)=> acc + curr);
}
add(2, 5, 3) // 10
//注意 reset参数必须作为函数最后一个参数function count(...values,a) { //ERROR Rest parameter must be last formal parameterconsole.log(values); //[2,5,3]return values.reduce((acc,curr)=> acc + curr);
}

3 name属性

函数的name属性,返回该函数的函数名。

function count(){}
console.log(count.name); //"count"(new Function).name // "anonymous"function foo() {};
foo.bind({}).name // "bound foo"function foo() {};
foo.bind({}).name // "bound foo"(function(){}).bind({}).name // "bound " // "bound "(function(){}).name // ""

4 箭头函数

ES6 容许使用 “箭头” => 定义函数

function count(x,y){return x + y;
}let count = (x, y) => x + y;let getName = o => o.name; //getName({name:"海牙"})  "海牙"
//函数体可以 直接书写表达式 或()内书写表达式 或 {} 书写多行语句let count = (x,y)=>{y = 100;x = x * y;return x + y;  
}count(3,4); //400//()内可以通过,书写多个短语语句, 最后一个 "," 之后的值为返回值
let count = (x,y)=>(x = 100, y = 10, x + y);
count(3,4); //110 // 报错 会识别{}为函数体
let count = id => { id: id, name: "Kyogre" };// 不报错
let count = id => ({ id: id, name: "Kyogre" });

4.1 this指向

/*函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。*/
//箭头函数可以让setInterval里面的this,绑定定义时所在的作用域,而不是指向运行
const DATE = {time:0
}
function clock(){setInterval(()=>{this.time++; //this指向 clock作用域内的thisconsole.log(this.time);},100);
}
clock.call(DATE);---------------------------------const DATE = {time:0
}
function clock(){setInterval(function(){}{this.time++; //this通过bind绑定为clock作用域的thisconsole.log(this.time);}.bind(this),100);
}
clock.call(DATE);
*注意: `箭头函数里面根本没有自己的this,而是引用外层的this。由于箭头函数没有自己的this,所以当然也就不能用call()、apply()、bind()这些方法去改变this的指向。`
(function() {return [(() => this.x).bind({ x: 'inner' })()];
}).call({ x: 'outer' });
//['outer']//注意避免
const PERSON = {name:"kyogre",showName:()=>{return this.name;}
}PERSON.showName(); //'' showName使用箭头函数 this指向了 全局作用域//addEventListener回调函数内部this指向oBtn 如果使用了箭头函数 this指向就错了
let oBtn = document.querySelector('.btn');
oBtn.addEventListener('click', () => {this.classList.toggle('on');
});

4.2 练习

//pipeline 通道组合函数function double(x) {return x + x;
}function triple(x) {return 3 * x;
}function quarter(x) {return x / 4;
}function pipe() {var funs = Array.prototype.slice.call(arguments);return function (input) {return funs.reduce(function (acc, currFn) {return currFn(acc);}, input)}
}var result = pipe(quarter, double);-----------------------------------
const double = x => x + x;
const triple = x => 3 * x;
const quarter = x => x / 4;const pipe = (...functions) => input => functions.reduce((acc, fn) => fn(acc),input
);const result = pipe(quarter, double);
result(10); //5

ES6对象扩展

1 表示方法

ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。

const foo = 'bar';
const baz = {foo};
baz // {foo: "bar"}// 等同于
const baz = {foo: foo};//变量foo直接写在大括号里面。这时,属性名就是变量名, 属性值就是变量值。下面是另一个例子。
function f(x, y) {return {x, y};
}// 等同于function f(x, y) {return {x: x, y: y};
}f(1, 2) // Object {x: 1, y: 2}```方法简写```const o = {method() {return "Hello!";}
};// 等同于const o = {method: function() {return "Hello!";}
};

setter/getter写法

const cart = {_wheels: 4,get wheels () {return this._wheels;},set wheels (value) {if (value < this._wheels) {throw new Error('数值太小了!');}this._wheels = value;}
}

2 属性名表达式

// 方法一
obj.foo = true;// 方法二
obj['a' + 'bc'] = 123;

上面代码的方法一是直接用标识符作为属性名,方法二是用表达式作为属性名,这时要将表达式放在方括号之内。

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

ES6 允许字面量定义对象时,用方法二(表达式)作为对象的属性名,即把表达式放在方括号内。

let propKey = 'foo';let obj = {[propKey]: true,['a' + 'bc']: 123
};
let lastWord = 'last word';const a = {'first word': 'hello',[lastWord]: 'world'
};a['first word'] // "hello"
a[lastWord] // "world"
a['last word'] // "world"

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

// 报错
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"}

上面代码中,[keyA][keyB]得到的都是[object Object],所以[keyB]会把[keyA]覆盖掉,而myObject最后只有一个[object Object]属性。

3 属性的可枚举性和遍历

3.1 可枚举性

对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行为。Object.getOwnPropertyDescriptor方法可以获取该属性的描述对象。

let obj = { foo: 123 };
Object.getOwnPropertyDescriptor(obj, 'foo')
//  {
//    value: 123,
//    writable: true, //可写
//    enumerable: true, //可枚举
//    configurable: true //可配置
//  }

描述对象的enumerable属性,称为“可枚举性”,如果该属性为false,就表示某些操作会忽略当前属性。

目前,有四个操作会忽略enumerablefalse的属性。

  • for...in循环:只遍历对象自身的和继承的可枚举的属性。
  • Object.keys():返回对象自身的所有可枚举的属性的键名。
  • JSON.stringify():只串行化对象自身的可枚举的属性。
  • Object.assign(): 忽略enumerablefalse的属性,只拷贝对象自身的可枚举的属性。

这四个操作之中,前三个是 ES5 就有的,最后一个Object.assign()是 ES6 新增的。其中,只有for...in会返回继承的属性,其他三个方法都会忽略继承的属性,只处理对象自身的属性。实际上,引入“可枚举”(enumerable)这个概念的最初目的,就是让某些属性可以规避掉for...in操作,不然所有内部属性和方法都会被遍历到。比如,对象原型的toString方法,以及数组的length属性,就通过“可枚举性”,从而避免被for...in遍历到。

Object.getOwnPropertyDescriptor(Object.prototype, 'toString').enumerable
// falseObject.getOwnPropertyDescriptor([], 'length').enumerable
// false

上面代码中,toStringlength属性的enumerable都是false,因此for...in不会遍历到这两个继承自原型的属性。

另外,ES6 规定,所有 Class 的原型的方法都是不可枚举的。

Object.getOwnPropertyDescriptor(class {foo() {}}.prototype, 'foo').enumerable
// false

总的来说,操作中引入继承的属性会让问题复杂化,大多数时候,我们只关心对象自身的属性。所以,尽量不要用for...in循环,而用Object.keys()代替。

3.2 属性的遍历

ES6 一共有 5 种方法可以遍历对象的属性。

(1)for…in

for...in循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)。

(2)Object.keys(obj)

Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名。

(3)Object.getOwnPropertyNames(obj)

Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名。

(4)Object.getOwnPropertySymbols(obj)

Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有 Symbol 属性的键名。

(5)Reflect.ownKeys(obj)

Reflect.ownKeys返回一个数组,包含对象自身的(不含继承的)所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。

以上的 5 种方法遍历对象的键名,都遵守同样的属性遍历的次序规则。

  • 首先遍历所有数值键,按照数值升序排列。
  • 其次遍历所有字符串键,按照加入时间升序排列。
  • 最后遍历所有 Symbol 键,按照加入时间升序排列。
Reflect.ownKeys({ [Symbol()]:0, b:0, 10:0, 2:0, a:0 })
// ['2', '10', 'b', 'a', Symbol()]

上面代码中,Reflect.ownKeys方法返回一个数组,包含了参数对象的所有属性。这个数组的属性次序是这样的,首先是数值属性210,其次是字符串属性ba,最后是 Symbol 属性。

4 super 关键字

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

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

上面代码中,对象obj.find()方法之中,通过super.foo引用了原型对象protofoo属性。

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

// 报错
const obj = {foo: super.foo
}// 报错
const obj = {foo: () => super.foo
}// 报错
const obj = {foo: function () {return super.foo}
}

上面三种super的用法都会报错,因为对于 JavaScript 引擎来说,这里的super都没有用在对象的方法之中。第一种写法是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指向原型对象protofoo方法,但是绑定的this却还是当前对象obj,因此输出的就是world

5 对象拷贝与解构

5.1 对象解构

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

5.2 对象拷贝

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

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

// 写法一
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)
)

上面代码中,写法一的__proto__属性在非浏览器的环境不一定部署,因此推荐使用写法二和写法三。

扩展运算符可以用于合并两个对象。

5.3 链判断运算符

编程实务中,如果读取对象内部的某个属性,往往需要判断一下该对象是否存在。比如,要读取message.body.user.firstName,安全的写法是写成下面这样。

// 错误的写法
const  firstName = message.body.user.firstName;// 正确的写法
const firstName = (message&& message.body&& message.body.user&& message.body.user.firstName) || 'default';
const fooInput = myForm.querySelector('input[name=foo]')
const fooValue = fooInput ? fooInput.value : undefined-------------------------------
//链判断运算符      const firstName = message?.body?.user?.firstName || 'default';
const fooValue = myForm.querySelector('input[name=foo]')?.value

下面是判断对象方法是否存在,如果存在就立即执行的例子。

iterator.return?.()

链判断运算符有三种用法。

  • obj?.prop // 对象属性
  • obj?.[expr] // 同上
  • func?.(...args) // 函数或对象方法的调用
a?.b
// 等同于
a == null ? undefined : a.ba?.[x]
// 等同于
a == null ? undefined : a[x]a?.b()
// 等同于
a == null ? undefined : a.b()a?.()
// 等同于
a == null ? undefined : a()

使用这个运算符,有几个注意点。

(1)短路机制

?.运算符相当于一种短路机制,只要不满足条件,就不再往下执行。

a?.[++x]
// 等同于
a == null ? undefined : a[++x]

上面代码中,如果aundefinednull,那么x不会进行递增运算。也就是说,链判断运算符一旦为真,右侧的表达式就不再求值。

(2)delete 运算符

delete a?.b
// 等同于
a == null ? undefined : delete a.b

上面代码中,如果aundefinednull,会直接返回undefined,而不会进行delete运算。

(3)括号的影响

如果属性链有圆括号,链判断运算符对圆括号外部没有影响,只对圆括号内部有影响。

(a?.b).c
// 等价于
(a == null ? undefined : a.b).c

上面代码中,?.对圆括号外部没有影响,不管a对象是否存在,圆括号后面的.c总是会执行。

一般来说,使用?.运算符的场合,不应该使用圆括号。

(4)报错场合

以下写法是禁止的,会报错。

// 构造函数
new a?.()
new a?.b()// 链判断运算符的右侧有模板字符串
a?.`{b}`
a?.b`{c}`// 链判断运算符的左侧是 super
super?.()
super?.foo// 链运算符用于赋值运算符左侧
a?.b = c

(5)右侧不得为十进制数值

为了保证兼容以前的代码,允许foo?.3:0被解析成foo ? .3 : 0,因此规定如果?.后面紧跟一个十进制数字,那么?.不再被看成是一个完整的运算符,而会按照三元运算符进行处理,也就是说,那个小数点会归属于后面的十进制数字,形成一个小数。


在这里插入图片描述


JavaScript: https://developer.mozilla.org/en-US/docs/Web/JavaScript

在这里插入图片描述


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/845463.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于VGG16使用图像特征进行迁移学习的时装推荐系统

前言 系列专栏:【深度学习&#xff1a;算法项目实战】✨︎ 涉及医疗健康、财经金融、商业零售、食品饮料、运动健身、交通运输、环境科学、社交媒体以及文本和图像处理等诸多领域&#xff0c;讨论了各种复杂的深度神经网络思想&#xff0c;如卷积神经网络、循环神经网络、生成对…

解决Vscode Copilot连不上网问题

这段时间Copilot突然连不上网&#xff0c;修改vscode的proxy固然好使&#xff0c;但是还是不能从根本解决问题&#xff0c;并且会带来诸多问题&#xff0c;比如用vscode打开服务器这个proxy就失效了等等… 今天看到一种方法&#xff0c;很好的解决了我的问题。 直接修改本机的h…

【vue+ts】性能优化,defer优化白屏

代码&#xff1a; import {ref} from vueexport function useDefer(maxCount 100) {const count ref(0)let raqId:any null;function updateFrame() {count.valueif (count.value > maxCount) {return;}raqId requestAnimationFrame(updateFrame)}updateFrame();onUnmo…

【React篇】简述React-Router 的实现原理及工作方式

React Router 路由的基础实现原理分为两种&#xff0c;如果是切换 Hash 的方式&#xff0c;那么依靠浏览器 Hash 变化即可&#xff1b;如果是切换网址中的 Path&#xff0c;就要用到 HTML5 History API 中的 pushState、replaceState 等。在使用这个方式时&#xff0c;还需要在…

如何使用AES128位进行视频解密

要实现AES128位加解密&#xff0c;可以使用JavaScript的crypto-js库。以下是一个简单的示例&#xff1a; HTML代码&#xff1a; <video controlsList"nodownload" controls></video> 首先&#xff0c;需要安装crypto-js库&#xff1a; npm install cr…

数据库管理软件:Navicat Premium 17 中文激活版

Navicat Premium 是一套可创建多个连接的数据库开发工具&#xff0c;让你从单一应用程序中同时连接 MySQL、MariaDB、MongoDB、SQL Server、Oracle、PostgreSQL 和 SQLite 。它与 OceanBase 数据库及 Amazon RDS、Amazon Aurora、Amazon Redshift、Microsoft Azure、Oracle Clo…

Linux基础指令目录管理001

Linux目录管理是Linux操作系统中的一项基本而重要的任务&#xff0c;涉及到创建、删除、移动、查看和修改目录结构。 操作系统&#xff1a; CentOS Stream 操作命令&#xff1a; mkdir 创建目录 [rootlocalhost ~]# mkdir 秘密 [rootlocalhost ~]# ls -lhrt 总用量 1.2M …

万字解析线控底盘技术

文章出处&#xff1a;汽车学堂Automooc 引言 在当今这个由科技驱动的时代&#xff0c;汽车电动化、智能化已成为汽车行业的热门话题。特斯拉的自动驾驶功能、蔚来的换电模式、以及比亚迪的刀片电池技术&#xff0c;这些创新不仅引领着市场趋势&#xff0c;也推动着消费者对智…

SiC晶圆市场步入价格调整期:技术革新与产能扩张共促成本降低,加速下游应用拓展

近期硅碳&#xff08;SiC&#xff09;晶圆市场传出了降价的风声&#xff0c;似乎一场价格战即将拉开序幕。那么&#xff0c;当前SiC晶圆市场的实际情况如何呢&#xff1f; 供应链中多数企业普遍认同SiC晶圆价格确实在下滑。环球晶圆董事长徐秀兰公开表示&#xff0c;全球6英寸…

深入解读 Android Hook 技术-从原理到实践

在Android开发中&#xff0c;Hook技术是一种强大的手段&#xff0c;它允许开发者拦截和修改系统或应用的行为。通过Hook&#xff0c;我们可以在事件传递的过程中插入自定义的逻辑&#xff0c;从而实现对应用行为的监控和修改。 Android 系统有自己的事件分发机制&#xff0c;…

Leetcode2028. 找出缺失的观测数据

Every day a Leetcode 题目来源&#xff1a;2028. 找出缺失的观测数据 解法1&#xff1a;模拟 统计当前 m 个元素的总和 curSum sum(rolls)&#xff0c;总共 mn 个元素和为 total (m n) * mean。 排除 2 种情况&#xff1a; total - curSum > 6 * n&#xff1a;n 个…

链表(2)反转链表

题目描述 反转一个单链表。&#xff08;题目来源&#xff09; 思路一 其实&#xff0c;反转一个单向链表&#xff0c;我们可以看成是将链表中的每个结点的指向反向&#xff08;即从后一个结点指向前一个结点&#xff09;。 我们在考虑情况的时候&#xff0c;还是可以先考虑一般…

【基础计算机网络】应用层

一、网络应用模型 1.1 客户/服务器模型 1.1.1 工作流程 服务器处于接收请求的状态&#xff0c;客户机发出服务请求&#xff0c;并等待接收结果&#xff0c;服务器收到请求后&#xff0c;分析请求&#xff0c;进行必要的处理&#xff0c;得到结果并发送给客户机客户程序必须知…

变种水仙花

变种水仙花 题干要求&#xff1a; 变种水仙花数 - Lily Number&#xff1a;把任意的数字&#xff0c;从中间拆分成两个数字&#xff0c;比如1461 可以拆分成&#xff08;1和461&#xff09;,&#xff08;14和61&#xff09;,&#xff08;146和1),如果所有拆分后的乘积之和等于…

Ollama 本地大模型框架

该篇教程主要讲解*Ollama的安装和简单使用* Ollama&#xff1a; 在本地启动并运行大型语言模型。 主要流程目录&#xff1a; 1.安装 2.使用 2.1.下载模型 2.2.简单使用 2.3.中文模型 2.4.中文社区 3.总结 1.安装 创建一个容器 切换”高级视图“ 参考填写 ollama oll…

java家政上门系统源码,App端采用uniapp开发编写,可打包H5 、微信小程序、微信公众号、Android、IOS等。

家政上门系统是一种通过互联网或移动应用平台&#xff0c;为用户提供在线预约、下单、支付和评价家政服务的系统。该系统整合了家政服务资源&#xff0c;使用户能够便捷地找到合适的服务人员&#xff0c;同时也为家政服务人员提供了更多的工作机会。 本套家政上门系统源码&…

Golang | Leetcode Golang题解之第120题三角形最小路径和

题目&#xff1a; 题解&#xff1a; func minimumTotal(triangle [][]int) int {n : len(triangle)f : make([]int, n)f[0] triangle[0][0]for i : 1; i < n; i {f[i] f[i - 1] triangle[i][i]for j : i - 1; j > 0; j-- {f[j] min(f[j - 1], f[j]) triangle[i][j]…

旅游行业:解锁收入增长的新策略!

随着科技的飞速发展和人们生活水平的提高&#xff0c;旅游行业已成为全球范围内最具活力和潜力的行业之一。然而&#xff0c;在这个充满机遇与挑战的市场中&#xff0c;如何确保收入的持续增长&#xff0c;成为每一家旅游企业都必须面对的问题。在这个背景下&#xff0c;用友BI…

虚拟现实环境下的远程教育和智能评估系统(七)

在后端代码的基础上&#xff0c;利用vue框架设计前端界面&#xff0c;至此&#xff0c;用户界面基本成型&#xff0c;后续添加其他进阶功能&#xff1b; 另&#xff0c;前后端交互相关&#xff1a; UsersVO.java package com.roncoo.education.user.feign.interfaces.vo;impor…

Llama改进之——分组查询注意力

引言 今天介绍LLAMA2模型引入的关于注意力的改进——分组查询注意力(Grouped-query attention,GQA)1。 Transformer中的多头注意力在解码阶段来说是一个性能瓶颈。多查询注意力2通过共享单个key和value头&#xff0c;同时不减少query头来提升性能。多查询注意力可能导致质量下…