掌握 JavaScript ES6+:现代编程技巧与模块化实践
这篇文章我们将深入探讨 JavaScript 的最新特性,包括 ES6 及其后续版本中引入的一系列现代 JavaScript 编程技巧。文章将从变量声明的新方式开始,介绍 let 和 const 关键字的使用,以及它们如何帮助我们更好地管理变量作用域和常量。接着,我们将学习模板字符串的便利性,它使得字符串拼接变得更加直观和简洁。
文章还将涵盖函数的参数默认值,这是提高函数灵活性和代码可读性的有力工具。紧接着,我们将探索箭头函数的简洁语法。此外,ES6 中的对象和数组的简化初始化方式,以及解构赋值的高效用法,也将在我们的讲解之中。
最后,我们将讨论 JavaScript 模块化编程的基础知识,包括如何使用 export 和 import 关键字来组织和重用代码。通过这些内容的学习,读者将能够掌握现代 JavaScript 编程的核心概念和技巧,为开发更高效、更可维护的代码打下坚实的基础。
如果你觉得此专栏对你有帮助的话 , 还可以订阅一下此专栏
https://blog.csdn.net/m0_53117341/category_12778663.html
一 . 变量声明 let
在 ES 6 之前 , 使用的是 var 关键字声明变量 . 无论声明在哪些位置 , 都会被视为声明在函数的最顶部 (相当于全局变量) .
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
<script>
function test(bool) {
if (bool) {
var str = 'Hello World';
}
// 在外部也可以访问到 str
console.log('在 str 作用域外部也可以获取到 str 的值: ' + str);
}
test(true);
</script>
</html>
那 ES 6 推出了 let 定义变量的方式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
<script>
function test(bool) {
if (bool) {
// 使用 let 定义的是局部变量
let str = 'Hello World';
}
// 局部变量在外部访问不到 str
console.log('在 str 作用域外部也可以获取到 str 的值: ' + str);
}
test(true);
</script>
</html>
二 . 声明常量 const
常量是不能被更改引用的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
<script>
// 定义常量
const username = 'Jack';
// 不允许更改常量引用
username = 'Kun';
console.log(username);
</script>
</html>
三 . 模板字符串
比如我们之前拼接字符串 , 是通过 + 的方式拼接的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
// 之前拼接字符串
let username = 'Jack';
// 通过 + 拼接字符串
console.log('当前用户姓名为 : ' + username);
</script>
</html>
那在 ES6 中 , 引入了模板字符串的方式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
let username = 'Jack';
// 模板字符串: 使用反引号,可以直接打印变量的值
// 在反引号中使用 ${变量名} 来获取值进行字符串的拼接
console.log(`姓名为 : ${username}`);
</script>
</html>
那这样的话 , 拼接字符串更加直白 , 避免由于加号或者引号导致代码变得特别不直观 .
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
let username = 'Jack';
let password = '123456';
let tel = '13555555555';
// 模板字符串: 使用反引号,可以直接打印变量的值
// 在反引号中使用 ${变量名} 来获取值进行字符串的拼接
console.log(`姓名为 : ${username}, 密码为 : ${password}, 电话号为: ${tel}`);
</script>
</html>
四 . 函数的参数默认值
我们之前介绍过 , 如果调用函数的时候没有传递实参 , 那么就会使用默认值 undefined
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
function show(username) {
console.log(username);
}
// 如果调用函数的时候没有传递实参 , 那么就会使用默认值 undefined
show();
</script>
</html>
那 ES6 为了避免这种情况 , 就推出了函数的参数默认值
如果调用的时候没有传递参数 , 那么就使用设置的默认值 Jack 即可 .
如果调用的时候传递了参数 , 那么就使用我们传递的参数即可 .
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
function show(username = 'Jack') {
console.log(username);
}
// 如果调用的时候没有传递参数 , 那么就使用设置的默认值 Jack 即可 .
show();
// 如果调用的时候传递了参数 , 那么就使用我们传递的参数即可 .
show('Rose');
</script>
</html>
五 . 箭头函数
我们之前定义函数 , 是这样定义的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
<script>
// 原始的创建函数的方式
let add1 = function (a,b) {
return a + b;
}
console.log(add1(100,200));
</script>
</html>
那在 ES6 中 , 引入了箭头函数 , 他可以更加简洁的进行函数的创建
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
// 箭头函数
// 格式: (参数名1,参数名2,参数名3,...)=>{函数体}
let add2 = (a,b) => {
return a + b;
}
console.log(add2(100,200));
</script>
</html>
如果函数体只有一句话 , 那就可以省略大括号和 return 关键字
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 箭头函数
// 格式: (参数名1,参数名2,参数名3,...)=>{函数体}
// 如果函数体只有一句话, 则可以省略大括号和 return 关键字
let add3 = (a,b) => a + b;
console.log(add3(100,200));
</script>
</body>
</html>
六 . 对象初始化
我们在 ES5 的时候 , 返回一个 JSON 对象是这样返回的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
// es5 的写法
function people(username,age) {
// 将 JSON 对象返回给调用者
return {
// 冒号左边的 username 是 JSON 对象的 key, 冒号右边的 username 是函数形参
// 比如: username: 'Jack'
username: username,
age: age
}
}
// 打印返回的 JSON 对象
console.log(people('Jack',18));
</script>
</html>
那在 ES6 标准中 , 如果 key 的名字和变量参数名一致 , 则可以进行简化
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
// es6 的写法
function people(username,age) {
// 将 JSON 对象返回给调用者
return {
// 如果 key 的名字和变量参数名一致 , 则可以进行简化
username,
age
}
}
// 打印返回的 JSON 对象
console.log(people('Jack',18));
</script>
</html>
但是如果我们 key 的名字和变量的参数名不一致 , 就会报错
七 . 解构
7.1 接收 JSON 对象
之前我们获取 JSON 格式中的字段 , 可以这样获取
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
<script>
// 目标: 从 JSON 对象中取值
// es5 的写法
const people = {
username: 'Mark',
age: 20
};
let username = people.username;
let age = people.age;
console.log(username + " , " + age);
</script>
</html>
那在 ES6 中 , 获取的方法如下 :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
<script>
// 目标: 从 JSON 对象中取值
const people = {
username: 'Mark',
age: 20
};
// es6 的写法
// 等号左侧大括号中的 username 接收的值就是等号右边的 people 对象中的 username 的值
const {username,age} = people;
console.log(username + " , " + age);
</script>
</html>
那我修改一下 , 左边部分不叫 username , 叫 name 还能获取成功吗 ?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
<script>
// 目标: 从 JSON 对象中取值
const people = {
username: 'Mark',
age: 20
};
// es6 的写法
// 等号左侧大括号中的 username 接收的值就是等号右边的 people 对象中的 username 的值
const {name,age} = people;
console.log(username + " , " + age);
</script>
</html>
此时就会获取失败 . 这里的等号左边的标识符必须和等号右边的 people 对象中的 key 保持一致
那反正我们左侧都已经接收到了 username 和 age 这两个属性 , 那我们调换一下顺序如何呢 ?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
<script>
// 目标: 从 JSON 对象中取值
const people = {
username: 'Mark',
age: 20
};
// es6 的写法
// 等号左侧大括号中的 username 接收的值就是等号右边的 people 对象中的 username 的值
// 调换顺序也是可以正常接收的
const {age,username} = people;
console.log(username + " , " + age);
</script>
</html>
也是能够获取到的 , 这就代表前后书写顺序无关 , 只要有对应的标识符即可
我们也可以只接收一个字段
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
<script>
// 目标: 从 JSON 对象中取值
const people = {
username: 'Mark',
age: 20
};
// es6 的写法
// 等号左侧大括号中的 username 接收的值就是等号右边的 people 对象中的 username 的值
// 也可以只接收一个字段
const {age} = people;
console.log(age);
</script>
</html>
7.2 接收数组
在 ES5 中 , 我们需要通过数组名以及对应的索引才能够获取到数组中的数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
// 目标: 从数组中取值
let arr = ['red','blue','green','orange','black'];
// 通过数组名和索引获取元素
console.log(arr[0]);
</script>
</html>
那在 ES 6 中的写法如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
// 目标: 从数组中取值
let color = ['red','blue','green','orange','black'];
// ES6 写法
// 将 color 数组的元素值赋值给等号左边的标识符
// 标识符随便定义, 根据顺序依次赋值
const [first,second,third,fourth,fifth] = color;
console.log(first);
console.log(second);
console.log(third);
console.log(fourth);
console.log(fifth);
</script>
</html>
八 . 延展操作符
我们目前有一个需求 : 扩展对象的值 , 那我们就可以通过延展操作符来实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
// 目标: 扩展对象的值
// 原来的对象
const peopleOld = {username: 'Tom',age: 18};
// 我们可以重新生成一个对象, 并且给予之前的对象扩展
// ... 实际上就表示 {username: 'Tom',age: 18}
const peopleNew = {...peopleOld,address: '上海'};
console.log(peopleOld);
console.log(peopleNew);
</script>
</html>
数组同样是可以扩展的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
// 目标: 扩展数组的值
// 原来的数组
const colorOld = ['red','yellow'];
// 我们可以重新生成一个数组, 并且给予之前的数组扩展
// ... 实际上就表示 ['red','yellow']
// colorOld 是旧的数组名
const colorNew = [...colorOld,'black'];
console.log(colorOld);
console.log(colorNew);
</script>
</html>
那也可以把要追加的元素放到前面 / 后面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
// 目标: 扩展数组的值
// 原来的数组
const colorOld = ['red','yellow'];
// 我们可以重新生成一个数组, 并且给予之前的数组扩展
// ... 实际上就表示 ['red','yellow']
// colorOld 是旧的数组名
const colorNew = ['black',...colorOld,'blue'];// 也可以将要追加的元素放到前面 / 后面
console.log(colorOld);
console.log(colorNew);
</script>
</html>
九 . 导入和导出
模块功能主要由两个部分构成 : export 和 import .
我们可以演示一下导入和导出是怎么做的
9.1 方式一
首先 , 我们创建一个 lib.js 文件 , 我们可以把这个文件理解成底层源码文件
然后在这个 js 文件中定义两个文件
接下来 , 我们需要通过 export 来将这个模块导出
模块在 JS 中 , 指的就是文件 . 那当前模块指的就是当前文件
let add = function() {
console.log('add...');
}
let remove = function() {
console.log('remove...');
}
// 导出当前模块
export {add,remove}
然后再创建一个 other.js 文件 , 将上面的模块进行导入
// 导入模块
import {add,remove} from './lib.js';
// 调用方法
add();
remove();
最后我们在我们的页面中引入 other.js 即可
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<!-- 需要添加 type="module" 模块信息 -->
<script type="module" src="js/other.js">
</script>
</html>
此时我们刷新页面 , 发现报错了
那这个错误是跨域问题 , 跨域问题的解决办法也有很多 , 在这里先给大家介绍一种 : 安装 Live Server 插件
此时右键 , 通过 Live Server 查看
此时就没有问题了
9.2 方式二
lib.js :
export default {
add() {
console.log('add...');
},
remove() {
console.log('remove...');
}
}
other.js :
import jsApi from './lib.js' // 使用这种方式, 必须要使用 export default {} 导出
jsApi.add()
jsApi.remove()
demo.html :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<!-- 需要添加 type="module" 模块信息 -->
<script type="module" src="js/other.js">
</script>
</html>
不知道你对 JavaScript ES6+ 的新语法学习如何 , 如果对你有帮助的话 , 还请一键三连~