Js进阶25-ES6 新增1

news/2024/7/10 22:58:05 标签: 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()写法没有<span style="color:hsl(210,75%,60%);"><span>登记机制</span></span>,所以每次调用都会返回一个<span style="color:hsl(210,75%,60%);"><span>不同的值</span></span>。</p> 

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/451194.html

相关文章

python使用pyinstaller打包运行过程中莫名的被阻塞

问题描述 使用pyinstaller打包python代码命令 python -m PyInstaller -i logo.ico -F -p ./console -n scl_runner ./main.py运行之后会有一个终端&#xff0c;可以看到终端日志输出正常&#xff0c;多次远程调用也没有问题&#xff0c;死循环测试调用10万次也没有卡死 然…

‘SelectOption‘ is declared but its value is never read.

直译过来&#xff0c;就是已经申明变量但是没有引用 哎&#xff0c;博主也是郁闷 那就改配置呗&#xff0c;来 先收藏右边这个》ts的tsconfig.json中文说明 中文如下

基于SSM的在线考试系统

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 在线考试借助于网络来…

spring boot 校运会赛事管理系统-计算机毕设 附源码87890

spring boot校运会赛事管理系统 摘 要 科技进步的飞速发展引起人们日常生活的巨大变化&#xff0c;电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流&#xff0c;人类发展的历史正进入一个新时代。在现实运…

Unity核心9——3D动画

一、3D 动画的使用 ​ 使用导入的 3D 动画&#xff1a; 将模型拖入场景中为模型对象添加 Animator 脚本为其创建 Animator Controller 动画控制器&#xff08;状态机&#xff09;将想要使用的相关动作&#xff0c;拖入 Animator Controller 动画控制器&#xff08;状态机&…

SpringBoot相关知识

SpringBoot知识 1 SpringBoot 介绍及其使用原因 Spring Boot是一个用于创建独立的、基于Java的生产级别的应用程序的框架。它旨在简化Spring应用程序的开发过程&#xff0c;减少开发人员的配置工作&#xff0c;从而提高开发效率。 原因: (1) 简化开发&#xff1a;Spring Boot…

Android 设计中心 | 助您为各种设备类型轻松打造精彩界面

作者 / Android 开发者体验部设计负责人 Adhithya Ramakumar 和 Android 高级开发者关系工程师 Rebecca Gutteridge 我们推出了 Android 设计中心&#xff0c;帮助开发者更轻松地针对各种类型的设备构建引人注目的界面。 Android 设计中心https://developer.android.google.cn/…

Unity核心7——2D动画

一、序列帧动画 &#xff08;一&#xff09;什么是序列帧动画 ​ 我们最常见的序列帧动画就是我们看的日本动画片&#xff0c;以固定时间间隔按序列切换图片&#xff0c;就是序列帧动画的本质 ​ 当固定时间间隔足够短时&#xff0c;我们肉眼就会认为图片是连续动态的&#…