最新要闻
- 【环球热闻】一汽车电梯故障 200多万的法拉利秒变“大事故车”
- NVIDIA AD106、AD107小核心首次现身:“减肥”多达30%
- 全球今亮点!《狂飙》能“逆风翻盘” 一半功劳都是热搜的
- 全球微速讯:宠托师职业受青睐!上门喂宠物 几天收入数千元
- 环球微速讯:不用羡慕代驾小哥了!绿源新品TCR开售:整车超轻能跑120km
- 100%纯果蔬汁:味全每日C果汁5.5元/瓶抄底
- 私家车定速巡航失灵!时速120狂飙半小时:万幸平安无事
- 全球快报:《三体》主演于和伟:我本身就是科幻迷!
- 环球快看点丨1月新能源汽车销量榜:比亚迪“能打”两个特斯拉
- 全球快讯:iPhone 14 Plus出货跌到0台:苹果拒绝认输
- 快看:2999元 联想扬天V14/V15笔记本上架:Zen2架构锐龙5 7520U
- 国产科幻FPS大作!《边境》官宣2月6日开启新测试
- 环球焦点!网友花2499元就买到了努比亚Z50:系统零广告 性价比无敌
- 每日热门:AMD终于要解决锐龙7000装机贵的麻烦了 B650主板降价
- 每日速递:《三体》电视剧惊现360全家桶产品:竟遭周鸿祎挑刺
- 2023年安卓机皇!聊聊三星S23系列与前代有哪些不同
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
环球最资讯丨ES6 简介(一)
- ES6 简介(一)
- 一、 概述
- 1、 导读
- 2、 Babel 转码器
- 2.1 是什么
- 2.2 配置文件 .babelrc
- 2.3 命令行转码
- 2.4 babel-node
- 2.5 @babel/register
- 2.6 polyfill
- 2.7 浏览器环境
- 二、 变量
- 1、 let
- 2、 const
- 3、 ES6 声明变量
- 4、 顶层对象的属性
- 5、 globalThis 对象
- 三、 解构和赋值
- 1、 数组的解构赋值
- 1.1 语法
- 1.2 默认值
- 2、 对象的解构赋值
- 2.1 语法
- 2.2 默认值
- 3、 字符串的解构赋值
- 4、 函数参数的解构赋值
- 5、 用途
- 1、 数组的解构赋值
- 四、 字符串扩展
- 1、 字符的 Unicode 表示法
- 2、 字符串的遍历器接口
- 3、 模板字符串
- 4、 标签模板
- 5、 新增方法
- 一、 概述
ES6 简介(一)
一、 概述
1、 导读
ECMAScript 6(ES6) 目前基本成为业界标准,它的普及速度比 ES5 要快很多,主要原因是现代浏览器对 ES6 的支持相当迅速,尤其是 Chrome 和 Firefox 浏览器,已经支持 ES6 中绝大多数的特性。
【资料图】
ES6
经过持续几年的磨砺,它已成为 JS
有史以来最实质的升级,特性涵盖范围甚广, 小到受欢迎的语法糖,例如箭头函数(arrow functions)和简单的字符串插值(string interpolation),大到烧脑的新概念,例如代理(proxies)和生成器(generators);它将彻底改变程序员们编写JS代码的方式。
2、 Babel 转码器
2.1 是什么
Babel
是一个广泛使用的 ES6 转码器
,可以将 ES6 代码转为 ES5 代码,从而在老版本的浏览器执行。这意味着,你可以用 ES6 的方式编写程序,又不用担心现有环境是否支持。下面是一个例子。
// 转码前input.map(item => item + 1);// 转码后input.map(function (item) { return item + 1;});
安装 Babel :npm install --save-dev @babel/core
2.2 配置文件 .babelrc
Babel
的配置文件是.babelrc
,存放在项目的根目录下。使用 Babel 的第一步,就是配置这个文件。
该文件用来设置转码规则和插件,基本格式如下。
{ "presets": [], "plugins": []}
presets字段设定转码规则,官方提供以下的规则集,你可以根据需要安装。
# 最新转码规则npm install --save-dev @babel/preset-env# react 转码规则npm install --save-dev @babel/preset-react
然后,将这些规则加入 .babelrc。
{ "presets": [ "@babel/env", "@babel/preset-react" ], "plugins": []}
注意,以下所有 Babel 工具和模块的使用,都必须先写好 .babelrc。
2.3 命令行转码
Babel 提供命令行工具@babel/cli,用于命令行转码。 它的安装命令:npm install --save-dev @babel/cli
使用语法:
# 转码结果输出到标准输出npx babel example.js# 转码结果写入一个文件# --out-file 或 -o 参数指定输出文件npx babel example.js --out-file compiled.js# 或者npx babel example.js -o compiled.js# 整个目录转码# --out-dir 或 -d 参数指定输出目录npx babel src --out-dir lib# 或者npx babel src -d lib# -s 参数生成source map文件npx babel src -d lib -s
2.4 babel-node
@babel/node
模块的babel-node
命令,提供一个支持 ES6 的 REPL
环境。它支持 Node 的 REPL 环境的所有功能,而且可以直接运行 ES6 代码。 首先,安装这个模块:npm install --save-dev @babel/node
然后,执行 babel-node 就进入 REPL 环境。
npx babel-node# >(x => x * 2)(1)# >2
babel-node 命令可以直接运行 ES6 脚本。将上面的代码放入脚本文件 es6.js ,然后直接运行。
npx babel-node es6.js
2.5 @babel/register
@babel/register模块改写require
命令,为它加上一个钩子。此后,每当使用 require 加载 .js 、.jsx 、.es 和 .es6 后缀名的文件,就会先用 Babel 进行转码。
npm install --save-dev @babel/register
使用时,必须首先加载 @babel/register。
// index.jsrequire("@babel/register");require("./es6.js");
@babel/register只会对
require
命令加载的文件转码,而不会对当前文件转码。另外,由于它是实时转码,所以只适合在开发环境使用。
2.6 polyfill
Babel 默认只转换新的 JavaScript
句法(syntax),而不转换新的API
,比如 Iterator 、Generator 、Set 、Map 、Proxy 、Reflect 、Symbol 、Promise 等全局对象,以及一些定义在全局对象上的方法(比如 Object.assign )都不会转码。
举例来说,ES6 在 Array 对象上新增了Array.from
方法。Babel 就不会转码这个方法。如果想让这个方法运行,可以使用 core-js 和 regenerator-runtime (后者提供 generator 函数的转码),为当前环境提供一个垫片。
安装命令:npm install --save-dev core-js regenerator-runtime
然后,在脚本头部,加入如下两行代码。
import "core-js";import "regenerator-runtime/runtime";// 或者require("core-js");require("regenerator-runtime/runtime);
Babel 默认不转码的 API 非常多,详细清单可以查看 babel-plugin-transform-runtime 模块的 definitions.js 文件。
2.7 浏览器环境
Babel 也可以用于浏览器环境,使用@babel/standalone模块提供的浏览器版本,将其插入网页。
<script src="https://unpkg.com/@babel/standalone/babel.min.js" rel="external nofollow" ></script><script type="text/babel">// Your ES6 code</script>
注意,网页实时将 ES6 代码转为 ES5,对性能会有影响。生产环境需要加载已经转码完成的脚本。
Babel
提供一个REPL
在线编译器,可以在线将ES6
代码转为ES5
代码。转换后的代码,可以直接作为 ES5 代码插入网页运行。
二、 变量
1、 let
ES6
新增了let
命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。
{ let a = 10; var b = 1;}a // ReferenceError: a is not defined.b // 1
上面代码在代码块之中,分别用let和var声明了两个变量。然后在代码块之外调用这两个变量,结果let声明的变量报错,var声明的变量返回了正确的值。这表明,let
声明的变量只在它所在的代码块有效。
for循环的计数器,就很合适使用let命令。
for (let i = 0; i < 10; i++) { // ...}console.log(i);// ReferenceError: i is not defined
for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。
for (let i = 0; i < 3; i++) { let i = "abc"; console.log(i);}// abc// abc// abc
var
命令会发生“变量提升”现象,即变量可以在声明之前使用,值为undefined。这种现象多多少少是有些奇怪的,按照一般的逻辑,变量应该在声明语句之后才可以使用。
为了纠正这种现象,let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。
// var 的情况console.log(foo); // 输出undefinedvar foo = 2;// let 的情况console.log(bar); // 报错ReferenceErrorlet bar = 2;
在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。
let不允许在相同作用域内,重复声明同一个变量。
// 报错function func() { let a = 10; var a = 1;}// 报错function func() { let a = 10; let a = 1;}
同时,ES6 还可以在块级作用域声明函数:
- 允许在块级作用域内声明函数。
- 函数声明类似于 var,即会提升到全局作用域或函数作用域的头部。
- 同时,函数声明还会提升到所在的块级作用域的头部。
注意,上面三条规则只对 ES6 的浏览器实现有效,其他环境的实现不用遵守,还是将块级作用域的函数声明当作let处理。
考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。
ES6 的块级作用域必须有大括号,如果没有大括号,JavaScript 引擎就认为不存在块级作用域。
2、 const
const
声明一个只读常量。一旦声明,常量的值就不能改变。
const PI = 3.1415;PI // 3.1415PI = 3;// TypeError: Assignment to constant variable.
注意:
- const 声明的变量不得改变值,这意味着,const 一旦声明变量,就必须立即初始化,不能留到以后赋值。
- const 的作用域与 let 命令相同:只在声明所在的块级作用域内有效。
- const 命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后使用
- const 声明的常量,也与let一样不可重复声明。
本质const 实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。
const foo = {};// 为 foo 添加一个属性,可以成功foo.prop = 123;foo.prop // 123// 将 foo 指向另一个对象,就会报错foo = {}; // TypeError: "foo" is read-only
3、 ES6 声明变量
ES5只有两种声明变量的方法:var
命令和function
命令。ES6
除了添加let
和const
命令,后面章节还会提到,另外两种声明变量的方法:import命令和class命令。所以,ES6 一共有 6 种声明变量的方法。
4、 顶层对象的属性
顶层对象,在浏览器环境指的是window对象,在 Node
指的是global对象
。ES5
之中,顶层对象的属性与全局变量是等价的。
window.a = 1;a // 1a = 2;window.a // 2
顶层对象的属性与全局变量挂钩,被认为是 JavaScript 语言最大的设计败笔之一。
这样的设计带来了几个很大的问题:
- 没法在编译时就报出变量未声明的错误,只有运行时才能知道(因为全局变量可能是顶层对象的属性创造的,而属性的创造是动态的)
- 程序员很容易不知不觉地就创建了全局变量(比如打字出错
- 顶层对象的属性是到处可以读写的,这非常不利于模块化编程。另一方面,window对象有实体含义,指的是浏览器的窗口对象,顶层对象是一个有实体含义的对象,也是不合适的。
ES6 为了改变这一点:
- 为了保持兼容性,var 命令和 function 命令声明的全局变量,依旧是顶层对象的属性
- let 命令、const 命令、class 命令声明的全局变量,不属于顶层对象的属性。也就是说,从 ES6 开始,全局变量将逐步与顶层对象的属性脱钩。
var a = 1;// 如果在 Node 的 REPL 环境,可以写成 global.a// 或者采用通用方法,写成 this.awindow.a // 1let b = 1;window.b // undefined
上面代码中,全局变量 a 由 var 命令声明,所以它是顶层对象的属性;全局变量 b 由 let 命令声明,所以它不是顶层对象的属性,返回 undefined 。
5、 globalThis 对象
JavaScript 语言存在一个顶层对象,它提供全局环境
(即全局作用域),所有代码都是在这个环境中运行。但是,顶层对象在各种实现里面是不统一的。
- 浏览器里面,顶层对象是window,但 Node 和 Web Worker 没有window。
- 浏览器和 Web Worker 里面,self也指向顶层对象,但是 Node 没有self。
- Node 里面,顶层对象是global,但其他环境都不支持。
同一段代码为了能够在各种环境,都能取到顶层对象,现在一般是使用this变量,但是有局限性。
- 全局环境中,this会返回顶层对象。但是,Node 模块和 ES6 模块中,this返回的是当前模块。
- 函数里面的this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,this会指向顶层对象。但是,严格模式下,这时this会返回undefined。
- 不管是严格模式,还是普通模式,new Function("return this")(),总是会返回全局对象。但是,如果浏览器用了 CSP(Content Security Policy,内容安全策略),那么eval、new Function这些方法都可能无法使用。
综上所述,很难找到一种方法,可以在所有情况下,都取到顶层对象。下面是两种勉强可以使用的方法。
// 方法一(typeof window !== "undefined" ? window : (typeof process === "object" && typeof require === "function" && typeof global === "object") ? global : this);// 方法二var getGlobal = function () { if (typeof self !== "undefined") { return self; } if (typeof window !== "undefined") { return window; } if (typeof global !== "undefined") { return global; } throw new Error("unable to locate global object");};
ES2020 在语言标准的层面,引入 globalThis 作为顶层对象。也就是说,任何环境下,globalThis
都是存在的,都可以从它拿到顶层对象,指向全局环境下的this。
垫片库 global-this 模拟了这个提案,可以在所有环境拿到 globalThis 。ES6
新增了let
命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。
三、 解构和赋值
1、 数组的解构赋值
1.1 语法
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。
// ES5let a = 1;let b = 2;let c = 3;// ES,可以这样写let [a, b, c] = [1, 2, 3];
本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。下面是一些使用嵌套数组进行解构的例子。
let [foo, [[bar], baz]] = [1, [[2], 3]];foo // 1bar // 2baz // 3let [ , , third] = ["foo", "bar", "baz"];third // "baz"let [x, , y] = [1, 2, 3];x // 1y // 3let [head, ...tail] = [1, 2, 3, 4];head // 1tail // [2, 3, 4]let [x, y, ...z] = ["a"];x // "a"y // undefinedz // []
另一种情况是
不完全解构
,即等号左边的模式,只匹配一部分的等号右边的数组。这种情况下,解构依然可以成功。let [x, y] = [1, 2, 3];x // 1y // 2let [a, [b], d] = [1, [2, 3], 4];a // 1b // 2d // 4
对于Set
结构,也可以使用数组的解构赋值。
let [x, y, z] = new Set(["a", "b", "c"]);x // "a"
事实上,只要某种数据结构具有Iterator
接口,都可以采用数组形式的解构赋值。
function* fibs() { // Generator 函数 let a = 0; let b = 1; while (true) { yield a; [a, b] = [b, a + b]; }}let [first, second, third, fourth, fifth, sixth] = fibs();sixth // 5
1.2 默认值
解构赋值允许有默认值。
let [foo = true] = [];foo // truelet [x, y = "b"] = ["a"]; // x="a", y="b"let [x, y = "b"] = ["a", undefined]; // x="a", y="b"
注意,ES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,只有当一个数组成员严格等于undefined,默认值才会生效。
如果默认值是一个表达式,那么这个表达式是惰性求值的,即只有在用到的时候,才会求值。
function f() { console.log("aaa");}let [x = f()] = [1];
上面代码中,因为x能取到值,所以函数f根本不会执行。上面的代码其实等价于下面的代码。
let x;if ([1][0] === undefined) { x = f();} else { x = [1][0];}
默认值可以引用解构赋值的其他变量,但该变量必须已经声明。
let [x = 1, y = x] = []; // x=1; y=1let [x = 1, y = x] = [2]; // x=2; y=2let [x = 1, y = x] = [1, 2]; // x=1; y=2let [x = y, y = 1] = []; // ReferenceError: y is not defined
2、 对象的解构赋值
2.1 语法
解构不仅可以用于数组,还可以用于对象。
let { foo, bar } = { foo: "aaa", bar: "bbb" };foo // "aaa"bar // "bbb"
对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
如果解构失败,变量的值等于undefined。
对象的解构赋值,可以很方便地将现有对象的方法,赋值到某个变量。
// 将Math对象的对数、正弦、余弦三个方法,赋值到对应的变量上let { log, sin, cos } = Math;// 将console.log赋值到log变量。const { log } = console;log("hello") // hello
复杂的对象结构赋值:
const node = { loc: { start: { line: 1, column: 5 } }};let { loc, loc: { start }, loc: { start: { line }} } = node;line // 1loc // Object {start: Object}start // Object {line: 1, column: 5}
数组一样,解构也可以用于嵌套结构的对象。
2.2 默认值
对象的解构也可以指定默认值。
var {x = 3} = {};x // 3var {x, y = 5} = {x: 1};x // 1y // 5var {x: y = 3} = {};y // 3var {x: y = 3} = {x: 5};y // 5var { message: msg = "Something went wrong" } = {};msg // "Something went wrong"
默认值生效的条件是,对象的属性值严格等于undefined。
var {x = 3} = {x: undefined};x // 3var {x = 3} = {x: null};x // null
3、 字符串的解构赋值
字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。
const [a, b, c, d, e] = "hello";a // "h"b // "e"c // "l"d // "l"e // "o"
类似数组的对象都有一个
length
属性,因此还可以对这个属性解构赋值。let {length : len} = "hello";len // 5
4、 函数参数的解构赋值
函数的参数也可以使用解构赋值。
function add([x, y]){ return x + y;}add([1, 2]); // 3
上面代码中,函数add
的参数表面上是一个数组,但在传入参数的那一刻,数组参数就被解构成变量x
和y
。对于函数内部的代码来说,它们能感受到的参数就是x
和y
。
下面是另一个例子。
[[1, 2], [3, 4]].map(([a, b]) => a + b); // [ 3, 7 ]
函数参数的解构也可以使用默认值。
function move({x = 0, y = 0} = {}) { return [x, y];}move({x: 3, y: 8}); // [3, 8]move({x: 3}); // [3, 0]move({}); // [0, 0]move(); // [0, 0]
5、 用途
交换变量的值
let x = 1;let y = 2;[x, y] = [y, x];
上面代码交换变量
x
和y
的值,这样的写法不仅简洁,而且易读,语义非常清晰。从函数返回多个值
// 返回一个数组function example() { return [1, 2, 3];}let [a, b, c] = example();// 返回一个对象function example() { return { foo: 1, bar: 2 };}let { foo, bar } = example();
函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回。有了解构赋值,取出这些值就非常方便。
函数参数的定义
// 参数是一组有次序的值function f([x, y, z]) { ... }f([1, 2, 3]); // 参数是一组无次序的值function f({x, y, z}) { ... }f({z: 3, y: 2, x: 1});
提取 JSON 数据
let jsonData = { id: 42, status: "OK", data: [867, 5309]};let { id, status, data: number } = jsonData; // data: number 约等于 number = dataconsole.log(id, status, number);// 42, "OK", [867, 5309]
指定函数参数的默认值
jQuery.ajax = function (url, { async = true, beforeSend = function () {}, cache = true, complete = function () {}, crossDomain = false, global = true, // ... more config} = {}) { // ... do stuff};
遍历 Map 结构
const map = new Map();map.set("first", "hello");map.set("second", "world");for (let [key, value] of map) { console.log(key + " is " + value);}// first is hello// second is world// 获取键名for (let [key] of map) { // ...}// 获取键值for (let [,value] of map) { // ...}
任何部署了 Iterator 接口的对象,都可以用
for...of
循环遍历。Map 结构原生支持 Iterator 接口,配合变量的解构赋值,获取键名和键值就非常方便。输入模块的指定方法
const { SourceMapConsumer, SourceNode } = require("source-map");
加载模块时,往往需要指定输入哪些方法。解构赋值使得输入语句非常清晰。
四、 字符串扩展
1、 字符的 Unicode 表示法
ES6
加强了对 Unicode
的支持,允许采用 \uxxxx 形式表示一个字符,其中 xxxx 表示字符的 Unicode 码点。
"\u0061"// "a"
但是,这种表示法只限于码点在 \u0000 ~ \uFFFF 之间的字符。超出这个范围的字符,必须用两个双字节的形式表示。
"\uD842\uDFB7"// "????""\u20BB7"// " 7"
上面代码表示,如果直接在 \u 后面跟上超过 0xFFFF 的数值(比如 \u20BB7 ),JavaScript 会理解成 \u20BB+7 。由于 \u20BB 是一个不可打印字符,所以只会显示一个空格,后面跟着一个 7 。
ES6 对这一点做出了改进,只要将码点放入大括号,就能正确解读该字符。
"\u{20BB7}"// "????""\u{41}\u{42}\u{43}"// "ABC"let hello = 123;hell\u{6F} // 123"\u{1F680}" === "\uD83D\uDE80"// true
js 中表示字符串的方法:
"\z" === "z" // true"\172" === "z" // true"\x7A" === "z" // true"\u007A" === "z" // true"\u{7A}" === "z" // true
2、 字符串的遍历器接口
ES6 为字符串添加了遍历器接口,使得字符串可以被 for...of循环遍历。
for (let codePoint of "foo") { console.log(codePoint);}// "f"// "o"// "o"
3、 模板字符串
传统的 JavaScript 语言,输出模板通常是这样写的(下面使用了 jQuery 的方法)。
$("#result").append( "There are " + basket.count + " " + "items in your basket, " + "" + basket.onSale + " are on sale!");
上面这种写法相当繁琐不方便,ES6 引入了模板字符串解决这个问题。
$("#result").append(` There are ${basket.count} items in your basket, ${basket.onSale} are on sale!`);
模板字符串(template string)是增强版的字符串,用反引号标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。
// 普通字符串`In JavaScript "\n" is a line-feed.`// 多行字符串`In JavaScript this is not legal.`console.log(`string text line 1string text line 2`);// 字符串中嵌入变量let name = "Bob", time = "today";`Hello ${name}, how are you ${time}?`
上面代码中的模板字符串,都是用反引号表示。如果在模板字符串中需要使用反引号,则前面要用反斜杠转义。
var greeting = `\`Yo\` World!`;
如果使用模板字符串表示多行字符串,所有的空格和缩进都会被保留在输出之中。
$("#list").html(` - first
- second
`);
上面代码中,所有模板字符串的空格和换行,都是被保留的,比如 标签前面会有一个换行。如果你不想要这个换行,可以使用
trim
方法消除它。$("#list").html(`
`.trim());
- first
- second
大括号内部可以放入任意的 JavaScript 表达式,可以进行运算,以及引用对象属性。
var x = 1;var y = 2;`${x} + ${y} = ${x + y}`// "1 + 2 = 3"`${x} + ${y * 2} = ${x + y * 2}`// "1 + 4 = 5"var obj = {x: 1, y: 2};`${obj.x + obj.y}`// 3// 内部还可以调用函数function fn() { return "Hello World";}`foo ${fn()} bar`// foo Hello World bar
如果大括号中的值不是字符串,将按照一般的规则转为字符串。比如,大括号中是一个对象,将默认调用对象的 toString 方法。
嵌套模板字符串:
const tmpl = addrs => ` ${addrs.map(addr => ` ${addr.first} ${addr.last} `).join("")}
`;const data = [ { first: "", last: "Bond" }, { first: "Lars", last: "" },];console.log(tmpl(data));
4、 标签模板
模板字符串的功能,不仅仅是上面这些。它可以紧跟在一个函数名后面,该函数将被调用来处理这个模板字符串。这被称为“标签模板”功能(tagged template)。
alert`123`// 等同于alert(123)
标签模板其实不是模板,而是函数调用的一种特殊形式。“标签”指的就是函数,紧跟在后面的模板字符串就是它的参数。
let a = 2;console.log`123 ${a} asd`;
但是,如果模板字符里面有变量,就不是简单的调用了,而是会将模板字符串先处理成多个参数,再调用函数。
var a = 5;var b = 10;tag`Hello ${ a + b } world ${ a * b }`;// 等同于tag(["Hello ", " world ", ""], 15, 50);function tag(stringArr, value1, value2){ // ...}// 等同于function tag(stringArr, ...values){ // ...}
如:
let total = 30;let msg = passthru`The total is ${total} (${total*1.05} with tax)`;function passthru(literals) { // 除了使用默认的 arguments 来接收不定长参数 也可以使用 ...values 来接收不定长参数 let result = ""; let i = 0; console.log(literals) // 其为一个数组 while (i < literals.length) { result += literals[i++]; if (i < arguments.length) { result += arguments[i]; } } return result;}console.log(msg) // "The total is 30 (31.5 with tax)"
5、 新增方法
传统上,JavaScript 只有 indexOf 方法,可以用来确定一个字符串是否包含在另一个字符串中。ES6 又提供了三种新方法。
- includes():返回布尔值,表示是否找到了参数字符串。
- startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。
- endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。
let s = "Hello world!";s.startsWith("Hello") // trues.endsWith("!") // trues.includes("o") // true
如果使用第二个参数 n 时, endsWith 的行为与其他两个方法有所不同。它针对前 n 个字符,而其他两个方法针对从第 n 个位置直到字符串结束。
实例方法:repeat()
repeat
方法返回一个新字符串
,表示将原字符串重复 n 次。"x".repeat(3) // "xxx""hello".repeat(2) // "hellohello""na".repeat(0) // ""
实例方法:padStart()
,padEnd()
ES2017
引入了字符串补全长度的功能。如果某个字符串不够指定长度,会在头部或尾部补全。 padStart()
用于头部补全, padEnd()
用于尾部补全。
"x".padStart(5, "ab") // "ababx""x".padStart(4, "ab") // "abax""x".padEnd(5, "ab") // "xabab""x".padEnd(4, "ab") // "xaba"
如果原字符串的长度,等于或大于最大长度,则字符串补全不生效,返回原字符串。
如果省略第二个参数,默认使用空格补全长度。
实例方法:trimStart()
,trimEnd()
ES2019 对字符串实例新增了 trimStart()
和 trimEnd()
这两个方法。它们的行为与trim()
一致, trimStart()
消除字符串头部的空格,trimEnd()
消除尾部的空格。它们返回的都是新字符串,不会修改原始字符串。
const s = " abc ";s.trim() // "abc"s.trimStart() // "abc "s.trimEnd() // " abc"
环球最资讯丨ES6 简介(一)
【环球热闻】一汽车电梯故障 200多万的法拉利秒变“大事故车”
NVIDIA AD106、AD107小核心首次现身:“减肥”多达30%
全球今亮点!《狂飙》能“逆风翻盘” 一半功劳都是热搜的
全球微速讯:宠托师职业受青睐!上门喂宠物 几天收入数千元
环球微速讯:不用羡慕代驾小哥了!绿源新品TCR开售:整车超轻能跑120km
100%纯果蔬汁:味全每日C果汁5.5元/瓶抄底
私家车定速巡航失灵!时速120狂飙半小时:万幸平安无事
全球快报:《三体》主演于和伟:我本身就是科幻迷!
环球快看点丨1月新能源汽车销量榜:比亚迪“能打”两个特斯拉
全球快讯:iPhone 14 Plus出货跌到0台:苹果拒绝认输
一文搞懂工作流审批(Java+activiti)快速开发+自定义工作流
天天热推荐:HEU_KMS_Activator_v27.0.2全能系统数字许可激活工具
快看:2999元 联想扬天V14/V15笔记本上架:Zen2架构锐龙5 7520U
国产科幻FPS大作!《边境》官宣2月6日开启新测试
环球焦点!网友花2499元就买到了努比亚Z50:系统零广告 性价比无敌
每日热门:AMD终于要解决锐龙7000装机贵的麻烦了 B650主板降价
每日速递:《三体》电视剧惊现360全家桶产品:竟遭周鸿祎挑刺
天天热讯:大神教你显卡和CPU怎么搭配才合适
Python借助企业微信群机器人推送消息和文件
【天天聚看点】【验证码逆向专栏】某验“初代”滑块验证码逆向分析
快资讯丨阿里二面: BigKey、HotKey 问题严重,该如何 预防和解决
Pandas练习
2023年安卓机皇!聊聊三星S23系列与前代有哪些不同
当前观点:高颜值+顶级做工!铭瑄RTX 4080 iCraft OC16G瑷珈显卡评测:三风扇稳压71℃
全球讯息:奥迪E-Tron撞车 电池包撞飞后起火!官方:不清楚是安全功能还是隐患
天天观热点:投屏480p、禁HDMI被吐槽割韭菜!爱奇艺利润将暴增 外资力挺
全球微速讯:《森林之子》PC配置需求公布 1080Ti显卡就能爽玩
看点:微信对话生成器,生成微信聊天记录,聊天记录生成器
环球快看:跳表java实现(可直接运行)
热消息:[概率论与数理统计]笔记:5.5 单正态总体的参数假设检验
依赖注入(DI注入)
当前动态:Wine 8.1版本正式发布:首次默认启用“Windows 10”前缀
为博眼球太奇葩 四川男子用扳手代替方向盘开车拍视频:结果被扣4分
今日热闻!苹果刚发布的2299元新品HomePod 2仅支持老掉牙Wi-Fi 4:原因不服不行
“聪明的”ChatGPT 是否拥有生命?
天天热议:速度是根本!威刚UE800 U盘评测:真正跑满1GB/s
世界新动态:【算法训练营day38】动态规划理论基础 LeetCode509. 斐波那契数 LeetCode70. 爬楼梯 LeetCode746. 使用最小花
报道:韩国刷新世界最低生育率纪录:无人店铺数量持续增长 人工智能需求强
苹果营收4年来首降 库克:裁员是最后手段
低于20万会买吗?特斯拉新款Model 3外形曝光:续航、动力大增
天天热讯:今晚油价或迎年内第二次上调:预计每升上涨0.17元
播报:奔驰销售吐槽:向每位进店客户推荐买新能源 直到客户崩溃或打我
Webpack解析与讲解
全球焦点!微软回应Xbox 360商店关闭:只是搞错了
全球最新:每逢佳节胖三斤 专家提醒:节后运动“甩膘”要注意三点
天天快资讯丨el表达式注入漏洞
环球快报:13倍浓缩:日本隅田川胶囊咖啡1.16元/杯史低
充会员才解封?爱奇艺回应一号三用被封:技术故障 跳转错误页面
《卧龙》天柱山介绍公开:红晶小姐姐美如画!
天天热点!对Intel穷追猛打!AMD Zen4c 128核心上半年杀来
突然暴雷!世界第一辆量产太阳能汽车 黄了
讯息:操作系统的体系结构
天天热头条丨2023年新势力首月销量成绩单:理想最显眼 零跑暴跌
全球新资讯:蔚来大降价超10万?总裁回应:没有 展车最多2.4万优惠
【全球报资讯】比尔·盖茨盛赞ChatGPT:称其“不亚于互联网诞生”
环球视点!女子拍抖音私闯已关闭自然保护区 或处5000元以下罚款
一个手机号搞定!微信正式支持注册小号:生活、工作能分开吗?
世界语言的分布是什么?世界语言难度排行
三星手机怎么截屏图片?三星手机如何防盗?
韩国游戏公司有哪些?韩国游戏公司排名
穿越火线什么时候出的?穿越火线怎么安装?
饱和石灰水是什么意思?饱和石灰水变浑浊的原因是什么?
诺基亚5000刚出来是多少钱?诺基亚5000手机参数
宽带连接怎么创建?宽带连接怎么设置到桌面上?
一次JSF上线问题引发的MsgPack深入理解,保证对你有收获
全球快看点丨springboot实战——总结
全球观点:(笔记)【NTP系列:05】NTP时间同步失败:Windows(W32Time)作为NTP时钟源服务端,Linux作为客户端
[概率论与数理统计]笔记:5.4 假设检验概述
西门子手机怎么样?西门子手机哪年进入中国?
联想y470双显卡驱动怎么装?联想y470双显卡怎么切换?
dota2怎么改成国服?DOTA2配置要求是什么?
世界新动态:传奇大佬、联想PC全球第一的功臣蒋凡可·兰奇去世 享年69岁
不叫003 极氪第三款车型ZEEKR X官图发布:20万买不
世界观焦点:智商碾压 新养的边牧把养5年金毛拐跑丢弃
当前滚动:办公党等到了!小米笔记本12.4二合一发布:2.5K触屏 2999元
荣耀Magic5通过3C认证:1/1.1英寸主摄、标配66W充电头
世界关注:非常强大的gsap动画
2023年值得收藏的开源或免费的web应用防火墙
keycloak~JWT各字段说明及扩展字段的方法
苹果业绩暴雷:iPhone卖不动了!库克感谢国人支持 要降价刺激销量?
《巫师3:狩猎》4.01版更新上线:光追性能更强 帧率又高了
美国新造车告急:造一辆亏23万 CEO深感抱歉
极氪009被吐槽像灵车、棺材 车主亲身评测:死人躺并不舒适
比亚迪又一大杀器 全新海鸥出街被拍:超个性涂装上身
快看:iPhone 12/13/14灵魂设计师离职 苹果直接取消工业设计总监职位
动态焦点:男孩为网游充值4万 家长控诉腾讯监控不力未尽义务:该不该退钱?
全球微动态丨国内油价今晚调整 或迎兔年“第一涨”:加满一箱预计多花8.5元
环球滚动:20个小猫身上笑死人的奇葩花纹:只有你想不到!
萌萌哒的兔子竟是“头号杀手”!澳大利亚曾研制病毒专杀兔兔
全球新资讯:澳大利亚搞丢一枚剧毒放射性胶囊 相关单位仅被罚款1000块:下不为例?
专家称年轻人工资低可能是能力不够引争议:企业点赞 打铁还应自身硬
世界今热点:触控体验碾压iPhone 14 Pro Max!一加Ace 2做到了
火箭弹电子版领取处>>(密码博主昵称 全部小写)
天天观点:Pandas分析泰坦尼克号生还比例
天天新资讯:图卷积的演变-从谱图卷积到GCN
.NET Core 3.1 通过 Web Service 读写 Salesforce 数据
【全球新要闻】打开它 游戏性能飙升46%!NVIDIA为啥不要呢?
每日资讯:麦当劳赢了:世界第一美食APP
即时看!地球最稀有矿石就一个标本!已知6000多种矿石就它特殊