Js进阶25-ES6 新增(1)

news/2024/7/10 23:59:58 标签: javascript, 前端, es6

1. let 和 const

let 和 const 是 ES6 新增的2个声明符,let 用于声明变量,const 用于声明常量。

javascript">{
  var a = 10;
  let b = 20;
  const c = 30;//常量:不能被修改的量
  c = 40;    
  //Uncaught TypeError:Assignment to constant variable.(未捕获的类型错误:赋值给常量变量)
}
console.log(a); // 10
console.log(b); // b is not defined
console.log(b = c); // c is not defined

在一个大括号中用 let 和 const 声明的变量在外部不可访问了,每个大括号都是独立的作用域。

用 var 声明一个变量是存在变量提升的,这是JS中的一个缺陷所在, 但是现在的 let 不存在变量提升。

ES6 规定在某个区块中, 一旦用 let 或 const 声明一个变量,那么这个区块就变成块级作用域,用 let 或者 const 声明的变量即为该区块绑定, 该变量不受任何变量影响。 在该变量使用 let 声明前不可以用。在语法上,我们叫这种情况为:暂时性死区 (temporal dead zone,简称 TDZ)。

使用 const 声明的变量为常量,常量不可以被修改。

javascript">console.log(Math.PI); // 3.141592653589793
Math.PI = 4;
console.log(Math.PI); // 3.141592653589793
javascript">const arr = [2,3,4,5];
// arr = [3,4,4,6];
// 不能修改数组或对象的引用,但是可以通过 API 去修改内部结构
arr.push(6,7);
console.log(arr); // [2, 3, 4, 5, 6, 7]

2. 扩展运算符

扩展运算符(spread)为三个点号(…),功能是把数组或类数组对象展开成一系列用逗号隔开的值。

javascript">var arr = [1,2,3,4,5];
console.log(arr); // Array(5)
console.log(...arr); // 1 2 3 4 5 // console.log 不会显示逗号,中间其实是有逗号的
javascript">var foo = function(a, b, c) {
  console.log(a); // 1
  console.log(b); // 2
  console.log(c); // 3
}
var arr = [1, 2, 3];
// 传统写法
foo(arr[0], arr[1], arr[2]);
// 使用扩展运算符
foo(...arr);

3. 剩余运算符

剩余运算符(rest)也是三个点号(…),不过其功能与扩展运算符恰好相反,把逗号隔开的值序列组合成一个数组。

javascript">// 主要用于不定参数,所以 ES6 开始可以不再使用 arguments 对象
var bar = function(a, ...args) {
  console.log(a); // 1
  console.log(args); // [ 2, 3, 4 ]
}
bar(1, 2, 3, 4);

4. 字符串扩展

字符串的 Unicode 表示,规则为\u + 四位十六进制。

javascript">console.log("\u0061"); // a 

这种新的字符表示方式只能表示 \u0000 ~ \uffff 之间的字符,如果超出范围必须用双字节表示。

javascript">console.log("\uD842\uDFB6"); // 𠮶

如果不按照规则书写,例如 console.log("\uD842\uDFB69"),这个9是多余字符,那么则认为这段字符是 \uD842\uDFB6 + 9 所以打印结果是 ₻9。

如果想要一次性表示超出范围的字符那么我们可以使用 {} 来表示。

javascript">console.log("\u20BB9"); // ₻9
console.log("\u{20BB9}"); // 𠮹

5. 字符串模板扩展

ES6 中存在一种新的字符串, 这种字符串是以 反引号(波浪线上的那个字符 ` )括起来表示的。

通常拼接一个带有标签的字符串, 是用这样的方式:

javascript">variate + " <strong>这是一个文字" + obj.name + "</strong> " + variate 

但是有了 ES6 模板字符串一切都变得非常简单了,用 ${变量名} 括住变量让拼接变得非常容易:

javascript">`${variate} <strong>这是一个文字${obj.name}</strong>${variate} `

在字符串中使用反引号的时候我们需要进行转义:

javascript">console.log(`\`Yo\` World!`); // `Yo` World!

模板还可以调用函数:

javascript">function fn() {
  return "Hello World";
}
console.log(`foo ${fn()} bar`); // foo Hello World bar

6. for of

一种新的遍历方式,遍历数组的所有元素。

tip:可以用于遍历字符串:

javascript">var s = "abc";
for(let b of s) {
  console.log(b); // "a"  "b"  "c"
}

for of 不能用于遍历对象。

7. 箭头函数

一个常规函数如下:

javascript">const test = function (x) {
  return x + 2;
}

使用箭头函数:

javascript">const test = (x) => {
  return x + 2;
};

const 函数名 = (参数列表) => { 函数体 }。

如果箭头函数只有一个形参,那么可以省略小括号。

javascript">const test = x => {
  return x + 2;
};

如果函数体只有一条语句,那么可以省略大括号:

javascript">const foo = str => console.log(str);

如果只有一条语句,并且这条语句就是return语句,可以省略 return 关键字:</p> 

javascript">const test = x => x + 2;

箭头函数会自动绑定 this(箭头函数没有自己的this)。

缺陷:

(1) 箭头函数是不能 new 的,它的设计初衷就跟构造函数不太一样;

(2) 箭头函数如果要返回一个 JSON 对象,必须用小括号包起来。如 var test = () => ({ id: 3, val: 20 })。

javascript">document.querySelector("button").onclick = function () {
  setTimeout(() => {
    console.log(this); // <button></button>
  },1000);
};

箭头函数和普通函数的区别:

(1) 写法不一样,箭头函数更简洁;

(2) 普通函数存在变量提升;

javascript">f(); // hello
function f(){
  console.log("hello");
}

g(); //报错:Uncaught ReferenceError: g is not defined
const g = () => console.log("hello");

(3) this指向不同,箭头函数没有自己的 this,指向外层作用域的 this;

(4) 箭头函数没有自己的 arguments,箭头函数的 arguments 指向它的父级函数所在作用域的arguments;

(5) 箭头函数不能作为构造函数;

(6) 箭头函数没有new.target。

8. 解构赋值

javascript">// 对象解构
var obj = {name:"lisi", age:80, gender: "female"};
var {age, name, gender="male"} = obj;
console.log(age, name, gender); // 80 'lisi' 'female'
            
var json = [
  {name:"lisi", age:80, gender: "female"},
  {name:"liwu", age:70, gender: "male"},
  {name:"liliu", age:60, gender: "female"}
]
var [{age},{name},{gender}] = json;
// var {name} = b;
console.log(name, age, gender); // liwu 80 female


// 数组解构
let [a, b, c] = [1, 2, 3];
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3

解构赋值就是把数据结构分解,然后给变量进行赋值。

如果解构不成功,变量跟数值个数不匹配的时候,变量的值为 undefined。

数组解构用中括号([])包裹,多个变量用逗号隔开,对象解构用花括号({})包裹,多个变量用逗号隔开。</p> 

利用解构赋值能够方便的去取数组的元素,对象的属性和方法。

9. symbol 类型

symbol 类型是第6种基本数据类型。

Symbol 函数会生成一个唯一的值。可以理解为 symbol 类型跟字符串是接近的。但每次生成唯一的值,也就是每次都不相等,至于它等于多少,并不重要。这对于一些字典变量比较有用。 

javascript">var s1 = Symbol();
var s2 = Symbol();
var s3 = Symbol("abc");
var s4 = Symbol("abc");
//s1不等于s2
//s3不等于s4

在通过 Symbol 生成独一无二的值时可以设置一个标记,这个标记仅仅用于区分, 没有其它任何含义。

注意点:

(1) symbol 是基本数据类型!!!!不要加 new 哦;

(2) 后面括号可以传入一个字符串,只是一个标记,方便我们阅读,没有任何意义;

(3) 类型转化的时候不可转化为数值;

javascript">// 只能转化为字符串和布尔值
const name = Symbol('name');
console.log(String(name)); // Symbol(name)
console.log(Boolean(name)); // true
console.log(Number(name)); // 报错:Cannot convert a Symbol value to a number


(4) 不能做任何运算;

(5) Symbol 生成的值作为属性或者方法的时候,一定要保存下来,否则后续无法使用;

javascript">let name=Symbol('name');
let obj={
  // name:'lnj',
  [Symbol('name')]:'lbj'
};
console.log(obj.name);  // 访问不到,因为 [Symbol('name')] 又是一个新的值,和上面的 name 不是同一个

(6) for循环遍历对象的时候是无法遍历出 symbol 的属性和方法的,需要使用

javascript">Object.getOwnPropertySymbols。
let name=Symbol('name');
let obj={
  [name]:'lnj',
    age:12,
    teacher:'wyx'
};
for (let key in obj) {
    console.log(key);   //只能打印出 age 和 teacher
}
//这个方法可以单独取出Symbol(name)
console.log(Object.getOwnPropertySymbols(obj));

Symbol的使用场景:

(1) 作为对象的属性名

对象的属性默认是字符串,所以不加引号(‘’,"")也可以,如果需要类型为 symbol,需要使用中括号([])括起来。

不可以用点(.)来访问,因为点运算符后面总是字符串。

Symbol 值作为属性名时,该属性还是公开属性,不是私有属性。

javascript">// 后面的括号可以给 symbol 做上标记便于识别
let name = Symbol('name');
let say = Symbol('say');
let obj = {
  // 如果想使用变量作为对象属性的名称,必须加上中括号,.运算符后面跟着的都是字符串
  [name]: 'lnj',
  [say]: function () {
    console.log('say');
  }
};
obj.name = 'it666';
obj[Symbol('name')] = 'it666';
console.log(obj);

(2) 消除魔术字符串

魔术字符串:在代码之中多次出现、与代码形成强耦合的某一个具体的字符串或者数值。风格良好的代码,应该尽量消除魔术字符串,改由含义清晰的变量代替。

const gender = {
  //这样就说明man就是一个独一无二的值,不用再 man:'man'   
  man: Symbol(),
  woman: Symbol(),
};
function isMan(gender) {
  switch (gender) {
    case gender.man:
      console.log('男性');
      break;
    case gender.woman:
      console.log('女性');
      break;
    }
}
isMan(gender.man);  //男性

(3) 为对象定义一些非私有的但又希望只用于内部的方法

由于以 Symbol 值作为键名,不会被常规方法遍历得到。我们可以利用这个特性,为对象定义一些非私有的、但又希望只用于内部的方法。

注意:symbol 并不能实现真正的私有变量的效果,只是不能通过常规的遍历方法拿到 symbol 类型的属性而已。

对象的遍历方法:

(1) for (let xx in obj): xx 代表 key;

(2) for (let xx of obj):xx 代表 value;

(3) Object.keys(obj): 返回包含 key 的数组;

(4) Object.values(obj): 返回包含 value 的数组;

(5) Object.getOwnPropertyNames():返回包含 key 的数组。

上述的所有方法都是遍历不到 symbol 类型的(注意,是遍历时取不到 symbol,并不是说我们访问不到对象的 symbol 类型)。

可以遍历到 symbol 的方法:

(1) Object.getOwnPropertySymbols:返回对象中只包含 symbol 类型 key 的数组;

(2) Reflect.ownKeys:返回对象中所有类型 key 的数组(包含 symbol)。

Symbol 自带的方法:

(1) Symbol.for(str)

因为 symbol 类型的值都是独一无二的,但有时,我们希望重新使用同一个 Symbol 值,Symbol.for 方法可以做到这一点。它接受一个字符串作为参数,然后搜索有没有以该参数作为名称的 Symbol 值。如果有,就返回这个 Symbol 值,否则就新建一个以该字符串为名称的 Symbol 值,并将其注册到全局。

javascript">let s1 = Symbol.for('foo');
let s2 = Symbol.for('foo');s1 === s2 // true

(2) Symbol.keyFor()

由于 Symbol 写法没有登记机制,所以每次调用都会返回一个不同的值。

Symbol.keyFor 方法返回一个已登记的 symbol 类型值的 key。

javascript">let s1 = Symbol.for("foo");
Symbol.keyFor(s1) // "foo"

let s2 = Symbol("foo");
Symbol.keyFor(s2) // undefined

http://www.niftyadmin.cn/n/476093.html

相关文章

canvas合并多张图片成一张

效果为&#xff1a;两张图片一排 新建js文件方法&#xff0c;以便调用 const mergeImgs (list) > {return new Promise((resolve, reject) > {// 创建 canvas 节点并初始化const canvas document.createElement(canvas);if (list.length 1) {canvas.width 100; //设…

基于Python热门旅游景点数据分析系统设计与实现

博主介绍&#xff1a; ✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精彩专…

Git 分支重命名

Git 是目前最流行的版本控制系统之一&#xff0c;而分支是 Git 的核心特性之一。在开发过程中&#xff0c;我们经常需要对分支进行重命名&#xff0c;以更好地组织和管理代码库。本篇博客将介绍如何使用 Git 命令进行分支重命名操作。 步骤&#xff1a; 确定当前分支&#xff…

全志科技T3国产工业评估板规格书(四核ARM Cortex-A7,主频1.2GHz)

1 评估板简介 创龙科技TLT3-EVM是一款基于全志科技T3处理器设计的4核ARM Cortex-A7高性能低功耗国产评估板&#xff0c;每核主频高达1.2GHz&#xff0c;由核心板和评估底板组成。 评估板接口资源丰富&#xff0c;引出双路网口、双路CAN、双路USB、双路RS485等通信接口&#x…

远程桌面发生身份验证错误,要求的函数不受支持

windows10专业版&#xff1a; 解决方法&#xff1a; 使用微软官方建议修改本地组策略&#xff1a; winr弹出运行窗口&#xff0c;输入gpedit.msc,打开本地组策略 计算机配置>管理模板>系统>凭据分配>加密Oracle修正 选择启用并选择易受攻击。 windows10家庭版&a…

人工智能 ---概率问题

1) A&#xff0c;B&#xff0c;C 都是随机变量&#xff0c;且他们的值域大小都是 2。 请在下面的表格中计算以下每个概率分布表的表项数&#xff0c;以及每个表中的概率值之和是多少&#xff1f; 分布表表项数量表项值之和&#x1d443;(&#x1d434;, &#x1d435;|&#x…

docker安装nexus3搭建maven私服

搜索镜像 docker search nexus3拉取镜像 docker pull sonatype/nexus3启动镜像 docker run -d --restartalways --namenexus3 -p8081:8081 --privilegedtrue -e INSTALL4J_ADD_VM_PARAMS"-Xms512M -Xmx512M -XX:MaxDirectMemorySize512M" -v /mydata/nexus:/var/n…

用华为云低代码Astro Zero10分钟搭建 “图书馆数据可视化大屏” 应用

作者&#xff1a;福州司马懿 原文链接&#xff1a;使用Astro Zero带你从零开始&#xff0c;10分钟搭建一套 “图书馆数据可视化大屏” 应用【华为云Astro低代码体验季】-云社区-华为云 产品介绍 点击下方链接进入工具页&#xff1a;https://auth.huaweicloud.com/authui/logi…