【技术】JS的ES6有哪些知识点

1.let-const块级作用域的补充

const names=["abc","cba","nba"];for(let  i=0;i<names.length;i++){ //* 这个数组的元素有三个,所以会形成3个块级作用域console.log(names[i]);
}

以上for遍历内部的实现是以下这样的:

因为数组有3个元素,所以会产生3个块级作用域。

//第一个块级作用域
{let i=0;console.log(names[i])
}
//第二个块级作用域
{把上次i++的结果赋值新定义的i //注意i++的i和let i不是同一个,js引擎会在内部做一些处理,这里为了方便让我们理解内部的实现let i=结果console.log(names[i]);
}
//第三个块级作用域
{把上次i++的结果赋值给新定义的ilet i=结果console.log(names[i]);
}

所以每个块级作用域的i都不是同一个。

那使用const定义是不是可以实现呢?

如果将上面的代码换一下:

const names=["abc","cba","nba"];for(const  i=0;i<names.length;i++){ //* 这个数组的元素有三个,所以会形成3个块级作用域console.log(names[i]);
}

同样地,因为names有三个元素,所以还是会形成三个作用域。内部实现是这样的:

//第一个块级作用域
{const i=0;console.log(names[i]);
}
//第二个块级作用域 此时在i++的时候会报错,因为const本质是值不能改变,所以就会抛出错误
{//注意i++的i和const i不是同一个,js引擎会在内部做一些处理,这里为了方便让我们理解内部的实现将i++的结果赋值给新定义的i  //这一行就开始报错const i=结果
}
1.1 for...of 遍历可迭代的数组(或对象)
const names=["abc","cba","nba"];for(const item of names){ //* 这个数组的元素有三个,所以会形成3个块级作用域console.log(item);
}

for...of是将数组或对象每个元素取出来

内部实现:因为数组有3个元素,所以还是会形成3个块级作用域

//第一个块级作用域
{const item="abc";console.log(item)
}
//第二个块级作用域
{const item="cba";console.log(item)
}
//第三个块级作用域
{const item="nba";console.log(item)
}

这里每个块级作用域的item都不是同一个

2.暂时性死区

在ES6中,我们还有一个概念称之为暂时性死区:

  • 它表达的意思是在一个代码块中,使用let、const声明的变量,在声明之前不可以访问的
  • 我们将这种现象称之为 temporal dead zone(暂时性死区,TDZ)(社区)

以下两段代码都形成了暂时性死区,在let、const声明之前,不能进行访问。

var foo="foo";if(true){console.log(foo);let foo="abc"; //* Cannot access 'foo' before initialization
}
var foo="foo";
function bar(){console.log(foo);let foo="abc";
}bar()

3.var、let、const的选择

对于var的使用:

  • var有其自身的特殊性:作用域提升、在window对象上添加属性、没有块级作用域,这些都是历史遗留问题
  • 其实这是javascript设计之初的一种语言缺陷
  • 目前市场上也在利用这种缺陷出一系列的面试题,来考察大家对JavaScript语言本身以及底层的理解
  • 但是在实际工作中,我们可以使用最新的规范来编写,也就是不再使用var来定义变量了。

对于let、const来说

  • 对于let、const,是目前开发中推荐使用的
  • 我们优先推荐使用const,这样可以保证数据的安全性不会被随意的篡改
  • 只有当我们明确知道一个变量后续会需要被重新赋值时这个时候再使用let
  • 这种在很多其他语言里面也都是一种约定俗成的规范,尽量我们也遵守这种规范。

4.字符串模板基本使用

在ES6之前,如果我们想要使用字符串和动态的变量(标识符)拼接在一起,是非常麻烦和丑陋的(ugly)

ES6允许我们使用字符串模板来嵌入JS的变量或表达式来进行拼接:

  • 首先,我们会使用``符号来编写字符串,称之为 模板字符串
  • 其次,在模板字符串中,我们可以通过${expresion}来嵌入动态的内容

// * 在ES6之前拼接字符串和动态的变量在一起,是非常麻烦的
var name="wjy";
var age=18;
var height=1.6
console.log("我的名字是:"+name+" 年龄是:"+age+" 身高:"+height);

在ES6中提供了模板字符串 ``

如果需要引用动态变量:${变量名}

// *在ES6当中,提供了一个模板字符串 `` 引用动态变量是:${变量名}
const name="wjy";
const age=18;
const height=1.66
console.log(`我的名字是${name} 年龄是:${age} 身高:${height}`)

5.标签模板字符串

模板字符串还有另外一种用法:标签模板字符串 (Tagged Template Literals)

普通JavaScript的函数调用

function foo(m,n){console.log(m,n);
}
// * 函数调用最普通的方式
foo(20,39)

如果我们使用标签模板字符串,并且在调用的时候插入其他的变量:

  • 模板字符串被拆分了
  • 第一个元素是数组,是被模板字符串拆分的字符串组合
  • 后面的元素是一个个模板字符串传入的内容

function foo(m,n){console.log(m,n);
}
// * 函数调用最普通的方式
foo(20,39)
// * 另外调用函数的方式:标签模板字符串foo``;//[ '' ] undefined
foo`hello World` //[ 'hello World' ] undefined
const name="wjy";
const age=20;
// * 第一个参数依然是模板字符串的完整字符串,只是被切成了多块,放到了数组中   第二个参数是 模板字符串中,第一个${expression}的expression的值
foo`Hello${age}Wo${name}rld`;//[ 'Hello', 'Wo', 'rld' ] wjy

6.函数的默认参数

在ES5的时候,可以给参数设置值,使用的是 逻辑或:如果前面为真,则返回前面的表达式的值,如果前面为false则将后面的表达式的值返回。

但是存在缺陷:

  • 写起来比较麻烦,阅读性差
  • 存在缺陷:如果传入的值是0或者是"",但还是设置"aaa"或"bbb"

function foo(m,n){// * 如果没有给函数传参:那么m,n会是undefined,如果对m、n进行操作时,很容易产生错误// * ES5之前是怎么给参数默认值 逻辑或/*** 缺点:* 1.写起来很麻烦 ,并且代码的阅读性比较差* 2.这种写起来是有bug 如果传入的是 0 "" ,但是会被设置 为"aaa"或"bbb"* */m=m|| "aaa";n=n||"bbb"console.log(m,n);
}
foo();
foo(100);
foo(100,200)

但在ES6中提供了给函数的参数设置默认值,直接参数后面使用="值"

function foo(m="aaa",n="bbb"){console.log(m,n);
}foo();//aaa bbb
foo(100);//100 bbb
foo(100,200);//100 200

上面的代码,转化为ES5是这样的:

"use strict";function foo() {var m =arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "aaa";var n =arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "bbb";console.log(m, n);
}foo(); //aaa bbbfoo(100); //100 bbbfoo(100, 200); //100 200
6.1 函数的默认值

// * 可以传基本数据类型
function foo(m="aaa",n="bbb"){console.log(m,n);
}foo();//aaa bbb
foo(100);//100 bbb
foo(100,200);//100 200
6.7 函数默认值的补充
  1. 默认值也可以和解构一起使用

    function printInfo({name,age}={name:"wjy",age:18}){console.log(name,age);
    }
    printInfo()// * 另外一个写法
    function printInfo({name="wjy",age=20}={}){console.log(name,age);
    }printInfo()
    
  2. 另外参数的默认值我们通常会放到最后(在很多语言中,如果不放到最后其实会报错的)

    • 但是Javascript允许不将其放到最后,但是意味着还是会按照顺序来匹配
  3. 另外默认值会改变函数的length的个数,默认值以及后面的参数都不计算在length之内的

// * 有默认值的函数的length属性
console.log(bar.length); //2function baz(x=20,y,z){}
console.log(baz.length);//0

7.函数的剩余参数

ES6中引用了rest parameter,可以将不定数量的参数放入到一个数组中:

如果最后一个参数是以...为前缀,那么它会将剩余的参数放到该参数中,并且作为一个数组

那么arguments和剩余参数有什么区别?

  • 剩余参数只包含没有对应形参的实参,而arguments包含传递给函数的所有实参
  • arguments对象不是一个真正的数组,而剩余参数是一个真正的数组,可以进行数组的所有操作。
  • arguments是早期的ECMAScript中为了方便去获取所有的参数提供的一个数据结构,而剩余参数是ES6提供的,并且希望以此替代arguments

剩余参数必须是 函数的参数的最后一个位置,否则会报错。

function foo(m,n,...args){console.log(m,n);//10 20console.log(args); //[ 30, 40, 50, 60, 70 ]
}foo(10,20,30,40,50,60,70)

function bar(...args,m,n){ //*Rest parameter must be last formal parameterconsole.log(args);console.log(m);console.log(n);
}
bar(1,2,3,4)

8.函数箭头函数的补充

  • 箭头函数是没有显式原型的,所以不能作为构造函数
  • 箭头函数没有this,箭头函数的this会去上层作用域查找,如果还没有找到,会继续往上查找。直到全局作用域中
  • 箭头函数没有arguments

var bar=()=>{}
console.log(bar.prototype);//undefined
console.log(new bar());//* bar is not a constructor

9.展开语法(Spread syntax)

  • 可以在函数调用/数组构造时,将数组表达式或者string在语法层面展开
  • 还可以在构造字面量对象时,将对象表达式按key-value的方式展开

const names=["abc","wjy","nba"];// * 1.函数调用时
function foo(x,y,z){console.log(x,y,z);
}
foo.apply(null,names);//这种方式也可以,但是阅读性非常差
foo(...names)
let str="wjy";
foo(...str)// * 2.构造数组时
const newNames=[...names]//*  3. ES2018 (ES9)构造 字面量对象
let info={name:"wjy",age:20,height:160
}
let newInfo={...info,...names}; //* 数组展开在对象中,key是对应的索引值
console.log(newInfo);// * 展开运算符其实是一个浅拷贝
9.1 展开运算符的浅拷贝

const info={name:"wjy",friend:{name:"kobe"}
}
// * 浅拷贝的是拷贝的对象的第一层属性的值,如果拷贝的对象的属性的值引用类型,其实在拷贝的对象中对应的属性的引用的是同一片内存空间
const newInfo={...info}
newInfo.friend.name="hyz"
console.log(info);

10.数值的表示

在ES6中规范了二进制和八进制的写法:

  • 二进制:以0b开头
  • 八进制:以0O开头
  • 十六进制:以0x开头

let num1=100;//默认是10进制
let num2=0b100;//二进制
let num3=0O100;//八进制
let num4=0x100;//十六进制console.log(num1,num2,num3,num4);//100 4 64 256// * 大的数值(在ES2021 ES12中),允许使用下划线进行连接
// const num=10000000000;//这种可读性非常差
const num=10_000_000_000;
console.log(num);

11.Symbol的基本使用

Symbol是ES6新增的一个基本的数据类型,翻译为符号。

那么为什么需要Symbol呢?

  • 在ES6之前,对象的属性都是字符串形式,那么很容易造成属性名的冲突
  • 比如原来有一个对象,我们希望在其中添加一个新的属性和值,但是在我们不确定它原来内部有什么内容的情况下,很容易造成冲突,从而覆盖它内部的某个属性
  • 比如我们前面实现讲apply、call、bind实现时,我们给其中添加一个fn属性,那么如果它内部原来有一个fn属性了呢?
  • 如果在开发中我们使用了混入,那么混入中出现了同名的属性,必然有一个会被覆盖掉。

Symbol就是为了解决上面的问题,用来生成一个独一无二的值

  • Symbol的值是通过Symbol函数来生成的,生成后可以作为属性名
  • 也就是在ES6中,对象的属性名就可以使用字符串,也可以使用Symbol值

Symbol即使多次创建值,它们也是不同的:Symbol函数每次创建出来的值都是独一无二的

我们也可以在创建Symbol值的时候传入一个描述description:这个是ES2019(ES10)新增的特性

11.1 Symbol作为属性名

// * 3.Symbol作为key
// * 写法1
const obj2={[s1]:"abc",[s2]:"wjy"
}
console.log(obj2);// * 新增:ES2019 ES10新增可以向Symbol传入一个description
obj2[s3]="hyz"
console.log(obj2);// * 新增
Object.defineProperty(obj2,Symbol("s4"),{value:"s4",configurable:true,enumerable:true,writable:true
})// * 获取:只能通过[]获取,不能通过.语法获取
console.log(obj2[s1]);
console.log(obj2.s1);//* undefined 这样是获取不到的,因为通过.获取的时候,会根据后面的名字去对象找对象的属性名为这个的值
// * 4.使用Symbol作为key,在遍历/Object.keys是获取不到Symbol属性值的
// * 需要通过Object.getOwnPropertySymbols来获取所有的Symbol的key
console.log(Object.keys(obj2));//[]
console.log(Object.getOwnPropertyNames(obj2));//[]
console.log(Object.getOwnPropertySymbols(obj2));//[ Symbol(), Symbol(), Symbol(hyz), Symbol(s4) ]let sKeys=Object.getOwnPropertySymbols(obj2)for(const item of sKeys ){console.log(obj2[item]);
}
11.2 相同的key生成相同的Symbol

如果想根据相同的key创建相同的Symbol可以使用Symbol.for(key)

可以通过Symbol.keyFor获取对应的key

// * 5. Symbol.for(key) :如果想要创建一样的Symbol值:通过相同的key创建相同的Symbol
const sa=Symbol.for("aaa");
const sb=Symbol.for("aaa");
console.log(sa==sb);//true// * 获取key
const key=Symbol.keyFor(sa);
console.log(key);

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

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

相关文章

数据库-MySQL 实战项目——书店图书进销存管理系统数据库设计与实现(附源码)

一、前言 该项目非常适合MySQL入门学习的小伙伴&#xff0c;博主提供了源码、数据和一些查询语句&#xff0c;供大家学习和参考&#xff0c;代码和表设计有什么不恰当还请各位大佬多多指点。 所需环境 MySQL可视化工具&#xff1a;navicat&#xff1b; 数据库&#xff1a;MySq…

数据结构之线性表的实现

顺序存储实现&#xff08;数组&#xff09; 顺序存储的线性表通常使用数组来实现。在数组中&#xff0c;元素在内存中是连续存放的&#xff0c;通过数组下标可以访问任意位置的元素。 链式存储实现&#xff08;链表&#xff09; 链式存储的线性表使用链表来实现。链表中的元…

C++ --> 类和对象(三)

欢迎来到我的Blog&#xff0c;点击关注哦&#x1f495; 前言 前面已经对类和对象有一定的了解&#xff0c;接下来再次深入的了解一下。 一、深入理解构造函数 构造函数体赋值&#xff1a; 虽然上述构造函数调用之后&#xff0c;对象中已经有了一个初始值&#xff0c;但是不能…

[笔记] SEW的振动分析工具DUV40A

1.便携式振动分析仪 DUV40A 文档编号&#xff1a;26871998/EN SEW是一家国际化的大型的机械设备供应商。产品线涵盖电机&#xff0c;减速机&#xff0c;变频器等全系列动力设备。DUV40A是他自己设计的一款振动分析工具。 我们先看一下它的软硬件参数&#xff1a; 内置两路传…

防火墙综合实验之NAT和智能选路

目录 前言&#xff1a; 一、实验题目 二、实验操作 需求一 需求二 需求三 需求四、需求五 需求六 需求七 ​编辑 需求八 需求九 需求十 需求十一 三、需求测试 前言&#xff1a; 本篇文章是延续上一篇文章&#xff0c;简单来说就是防火墙实验的完善和延续&#…

CV07_深度学习模块之间的缝合教学(2)--维度转换

教学&#xff08;1&#xff09;&#xff1a;链接 1.1 预备知识 问题&#xff1a;假如说我们使用的模型张量是三维的&#xff0c;但是我们要缝合的模块是四维的&#xff0c;应该怎么办&#xff1f; 方法&#xff1a;pytorch中常用的函数&#xff1a;(1)view函数&#xff08;2…

新华三H3CNE网络工程师认证—DHCP使用场景

网络服务与应用当中的技术有DHCP、Telnet和FTP。DHCP是计算机当中常用来获取地址的。比如日常使用中&#xff0c;计算机并没有接入IP&#xff0c;IP通过DHCP技术从上端服务去获取的。手动配置网络参数会出现多种问题。 文章目录 一、手动配置网络参数的问题1、参数多、理解难2、…

【零基础】学JS之APIS第四天

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 非常期待和您一起在这个小…

喰星云·数字化餐饮服务系统 多处 SQL注入漏洞复现

0x01 产品简介 喰星云数字化餐饮服务系统是一款专为餐饮企业设计的综合性管理软件,旨在通过信息化手段提升餐饮企业的运营效率、降低运营成本,并实现数据驱动的决策管理。该系统包括供应链管理、财务管理、巡店管理、人力资源管理等多个模块,可全面覆盖餐饮企业的日常运营需…

Zynq7000系列FPGA中的DDR内存控制器

DDR内存控制器是一个高度集成的组件&#xff0c;支持多种DDR内存类型&#xff08;DDR2、DDR3、DDR3L、LPDDR2&#xff09;&#xff0c;并通过精心设计的架构来优化内存访问效率。 DDR内存控制器架构 AXI内存端口接口&#xff08;DDRI&#xff09;&#xff1a;该部分负责处理与…

C/C++指针智能指针二

C/C指针&智能指针二 文章目录 C/C指针&智能指针二1.智能指针简介2.独占智能指针unique_ptr1.基本概念2.使用方法1.初始化 3.使用技巧 3.共享智能指针1.基本概念2.使用方法3.注意事项 4.智能指针删除器1.如何使用删除器2.应用场景 5.弱智能指针weak_ptr1.基本概念2.使用…

雷赛运动控制卡编程(2)限位设定与回原方式、脉冲模式设置

一、限位开关及急停开关的设置 限位开关的设置 //设置限位开关// dmc_set_el_modeushort _cardNo0;ushort _axisNo 0;ushort _enable 1; // 正负限位使能 ushort _elLogic 0; // 正负限位 低电平 有效ushort _model 0;// 正负限位停止方式为立即停止LTDMC.dmc_set_el_m…

构建实用的NLP应用程序:重塑人类与计算机的协同工作方式

文章目录 一、NLP技术的核心价值二、构建实用NLP应用程序的关键步骤三、NLP应用程序在协同工作中的创新应用《赠ChatGPT中文范例的自然语言处理入门书》编辑推荐内容简介作者简介精彩书评目录前言/序言获取方式 在数字化时代&#xff0c;自然语言处理&#xff08;NLP&#xff0…

手机数据恢复:适用于 Android 的 4 大数据恢复应用程序

没有人希望丢失设备上的重要数据。如果发生这种情况&#xff0c;请不要惊慌。以下是可帮助您恢复丢失或删除的数据的 Android 数据恢复应用程序列表。 有多种方法可以恢复已删除或丢失的 Android 数据&#xff0c;最简单、最快捷的方法是使用第三方恢复应用程序。这些应用程序会…

Transformer模型:Postion Embedding实现

前言 这是对上一篇WordEmbedding的续篇PositionEmbedding。 视频链接&#xff1a;19、Transformer模型Encoder原理精讲及其PyTorch逐行实现_哔哩哔哩_bilibili 上一篇链接&#xff1a;Transformer模型&#xff1a;WordEmbedding实现-CSDN博客 正文 先回顾一下原论文中对Posit…

[Windows] 号称最快免费小巧的远程桌面 AnyDesk v8.0.11单文件版

描述 对于经常在互联网上进行操作的学生&#xff0c;白领等&#xff01; 一款好用的软件总是能得心应手&#xff0c;事半功倍。 今天给大家带了一款高科技软件 虽然 QQ 拥有远程协助功能&#xff0c;但很多时候连接并不够流畅&#xff0c;而且被控电脑那方也必须要有人操作才行…

电脑关机被阻止

1. winR输入regedit进入注册表 2. 选择HKEY_USERS-》.DEFAULT-》Control Panel-》Desktop 3. 右键DeskTop新建字符串值&#xff0c;命名为AutoEndTasks&#xff0c;数值设置为1

C++中链表的底层迭代器实现

大家都知道在C的学习中迭代器是必不可少的&#xff0c;今天我们学习的是C中的链表的底层迭代器的实现&#xff0c;首先我们应该先知道链表的底层迭代器和顺序表的底层迭代器在实现上有什么区别&#xff0c;为什么顺序表的底层迭代器更加容易实现&#xff0c;而链表的底层迭代器…

不会编程怎么办?量化交易不会编程可以使用吗?

量化交易使用计算机模型程序代替人工进行交易&#xff0c;一般需要投资者自己编写程序建模&#xff0c;然后回测无误之后再进行实盘交易&#xff0c;那么不会编程的投资者能使用量化软件进行量化交易吗&#xff1f; 不会编程使用量化软件有两种方法 一种是请人代写代码&#x…

Java软件设计模式-单例设计模式

目录 1.软件设计模式的概念 2.设计模式分类 2.1 创建型模式 2.2 结构型模式 2.3 行为型模式 3.单例设计模式 3.1 单例模式的结构 3.2 单例模式的实现 3.2.1 饿汉式-方式1&#xff08;静态变量方式&#xff09; 3.2.2 懒汉式-方式1&#xff08;线程不安全&#xff09; 3.…