JavaScript 笔记

JavaScript 笔记
DotRedStone目录
一、JavaScript 引入方式
二、JavaScript 输出
三、数据类型
四、typeof 运算符
五、补充说明
六、字符串
七、数组
八、对象与内置对象
九、DOM 操作
十、事件处理操作
十一、定时器
十二、防抖
十三、节流
十四、Babel
十五、Let
十六、Const
十七、对象解构赋值
十八、字符串拓展
十九、字符串新增方法
二十、扩展运算符
二十一、数组新增方法
二十二、对象的拓展
二十三、函数拓展
二十四、Set 数据结构
二十五、Promise 对象
二十六、Async 函数
二十七、Class
二十八、Module
一、JavaScript 引入方式
推荐在
<body> </body>标签内引入
嵌入到 HTML
1
2
3
4<script>
// JavaScript 代码
console.log("Hello, World!");
</script>引入本地 JavaScript 文件
1
<script src="script.js"></script>
引入网络 JavaScript 文件
1
<script src="https://example.com/script.js"></script>
二、JavaScript 输出
alert()1
alert("Hello, World!");
弹出警告框
console.log()1
console.log("Hello, World!");
控制台输出
document.write()1
document.write("Hello, World!");
页面输出(不推荐页面加载后使用)
三、数据类型
基本数据类型
- Number:数字
- String:字符串
- Boolean:布尔
- Undefined:未定义
- Null:空
- Symbol:唯一值
引用数据类型
- Object:对象
- Array:数组
- Function:函数
四、typeof 运算符
判断数据类型
1 | typeof 123; // "number" |
null一般代表对象不存在,undefined一般代表变量未定义
五、补充说明
比较运算符
===和!==:严格相等/不等(不做类型转换)==和!=:宽松相等/不等(会做类型转换)
for in遍历对象
1 | const myObject = { |
六、字符串
1. 引号嵌套与转义
- 单引号/双引号等价,可互相嵌套
- 内部引号需转义
\ - 多行字符串可用
\续行
2. 属性
length1
2let str = "Hello, World!";
console.log(str.length); // 13字符串的长度
3. 方法
charAt()1
2let str = "Hello, World!";
console.log(str.charAt(0)); // H返回指定位置的字符
1
2let str = "Hello, World!";
console.log(str.charAt(-1)); // ""指定值为负数或大于长度时,返回空字符串
concat()1
2
3
4let str1 = "Hello";
let str2 = "World";
let str3 = str1.concat(", ", str2, "!"); // Hello, World!
console.log(str3);连接两个或多个字符串,并返回新的字符串
1
2
3
4let str1 = "Hello";
let str2 = "World";
let str3 = str1 + ", " + str2 + "!"; // Hello, World!
console.log(str3);加号遇到数字类型会进行运算
substring()1
2let str = "Hello, World!";
console.log(str.substring(0, 5)); // Hello返回两个指定索引之间的子字符串
1
2
3
let str = "Hello, World!";
console.log(str.substring(12, 7)); // World第二个参数小于第一个参数时,自动换位
1
2let str = "Hello, World!";
console.log(str.substring(7)); // World!忽略第二个参数时,直到结尾为止
1
2let str = "Hello, World!";
console.log(str.substring(-1)); // Hello, World!负数自动转为0
substr()1
2let str = "Hello, World!";
console.log(str.substr(0, 5)); // Hello与
substring()相似,但第二个参数代表子字符串长度1
2let str = "Hello, World!";
console.log(str.substr(7)); // World!忽略第二个参数时,直到结尾为止
1
2let str = "Hello, World!";
console.log(str.substr(-6)); // World!第一个参数负数,则倒数计算位置
1
2let str = "Hello, World!";
console.log(str.substr(4,-1)); // ""第二个参数负数,则自动转为0,即返回空字符串
indexOf()1
2let str = "Hello, World!";
console.log(str.indexOf("o")); // 4用于确定一个字符在另一个字符中出现的位置,返回值为开始匹配的位置。无法匹配则返回-1
1
2let str = "Hello, World!";
console.log(str.indexOf("o", 5)); // 8第二个参数为开始匹配的位置
trim()1
2let str = " Hello, World! ";
console.log(str.trim()); // Hello, World!去除字符串两端的空格(去除不仅是空格,还包括换行、制表符等)
1
2let str = " Hello, World! ";
console.log(str.trimStart()); // Hello, World!1
2let str = " Hello, World! ";
console.log(str.trimEnd()); // Hello, World!trimStart()去除开头空格,trimEnd()去除结尾空格split()1
2let str = "Hello, World!";
console.log(str.split(", ")); // ["Hello", "World!"]按照参数规则将字符串分割成数组
1
2let str = "Hello, World!";
console.log(str.split("o")); // ["Hell", ", W", "rld!"]1
2let str = "Hello, World!";
console.log(str.split("")); // ["H", "e", "l", "l", "o", ",", " ", "W", "o", "r", "l", "d", "!"]1
2let str = "Hello, World!";
console.log(str.split("" ,4)); // ["H", "e", "l", "l"]接受第二个参数表示限定返回数组的最大成员数
七、数组
1. 定义
1 | let arr = [1, 2, 3]; |
2. 属性
length1
2let arr = [1,2,3,4];
console.log(arr.length); // 4数组长度
3. 方法
Array.isArray()1
2let arr = [1,2,3,4];
console.log(Array.isArray(arr)); // true判断是否为数组
typeof()的局限性,数组返回object,故使用Array.isArray()来判断数组push()1
2
3let arr = [1,2,3,4];
console.log(arr.push(5)); // 5
console.log(arr); // [1,2,3,4,5]在数组末尾添加元素,并返回改变后数组的长度
pop()1
2
3let arr = [1,2,3,4];
console.log(arr.pop()); // 4
console.log(arr); // [1,2,3]删除数组末尾元素,并返回删除的元素
shift()1
2
3let arr = [1,2,3,4];
console.log(arr.shift()); // 1
console.log(arr); // [2,3,4]删除数组开头元素,并返回删除的元素
unshift()1
2
3let arr = [1,2,3,4];
console.log(arr.unshift(0)); // 5
console.log(arr); // [0,1,2,3,4]在数组开头添加元素,并返回改变后数组的长度
join()1
2let arr = [1,2,3,4];
console.log(arr.join('-')); // 1-2-3-4将数组元素连接成字符串
与字符串的split()方法互逆concat()1
2
3
4let arr1 = [1,2,3];
let arr2 = [4,5,6];
let arr3 = arr1.concat(arr2);
console.log(arr3); // [1,2,3,4,5,6]合并数组,返回新数组
1
2
3let arr4 = [1];
let arr5 = arr4.concat(2,3,4,5);
console.log(arr5); // [1,2,3,4,5]reverse()1
2let arr = [1,2,3,4];
console.log(arr.reverse()); // [4,3,2,1]反转数组
注意:该方法会改变原数组1
2
3
4
5let str = 'hello';
let arr = str.split('');
arr.reverse();
str = arr.join('');
console.log(str); // 'olleh'用于字符串反转
1
2
3let str = 'hello';
str = str.split('').reverse().join('');
console.log(str); // 'olleh'连为一串
indexOf()1
2let arr = [1,2,3,4];
console.log(arr.indexOf(2)); // 1返回指定元素在数组中的索引,如果不存在则返回-1
1
2let arr = [1,2,3,4,2];
console.log(arr.indexOf(2)); // 1只返回第一个匹配项的索引
1
2let arr = [1,2,3,4,2];
console.log(arr.indexOf(2,1)); // 4第二个参数指定开始搜索的索引
map()1
2
3
4let arr = ["Java", "C", "Python"];
arr.forEach((item, index, array) => {
console.log( `${index+1}: ${item} (total: ${array.length}`);
});用于遍历数组
八、对象与内置对象
1. 对象定义
1 | let user = { |
2. Math 对象
- `Math.abs(x)`:绝对值
- `Math.max(a, b, ...)` / `Math.min(a, b, ...)`:最大/最小值
- `Math.ceil(x)` / `Math.floor(x)` / `Math.round(x)`:向上/下/四舍五入
- `Math.random()`:0~1 随机数
Date 对象
Date.now():当前时间戳(毫秒)new Date():当前时间对象- 常用方法:
getTime(),getFullYear(),getMonth(),getDate(),getHours(),getMinutes(),getSeconds(),getDay()
九、DOM 操作
1. 节点类型
| 节点类型 | nodeType | nodeName | nodeValue | 描述 |
|---|---|---|---|---|
| 元素节点 | 1 | 大写的标签名 (如 DIV) |
null |
HTML 元素 (如 <div>) |
| 属性节点 | 2 | 属性名 (如 id) |
属性值 (如 box) |
元素的属性 (存在于元素的 attributes属性中) |
| 文本节点 | 3 | #text |
文本内容 | 元素内的文本内容 (包括换行和空格) |
| 注释节点 | 8 | #comment |
注释内容 | <!-- comment --> |
| 文档节点 | 9 | #document |
null |
整个文档的入口,即 document对象 |
| 文档类型节点 | 10 | html |
null |
<!DOCTYPE html> |
| 文档片段节点 | 11 | #document-fragment |
null |
轻量级的文档节点,用于批量操作 [citation:6] |
示例:
1 | // 获取元素节点 |
2. 查询节点
| 方法 | 返回内容 | 示例 |
|---|---|---|
getElementById(id) |
匹配 ID 的单个元素 | document.getElementById('header') |
getElementsByTagName(tag) |
匹配标签名的动态元素集合 (HTMLCollection) |
document.getElementsByTagName('p') |
getElementsByClassName(class) |
匹配类名的动态元素集合 (HTMLCollection) |
document.getElementsByClassName('active') |
querySelector(selector) |
匹配 CSS 选择器的第一个元素 | document.querySelector('.item.highlight') |
querySelectorAll(selector) |
匹配 CSS 选择器的静态元素集合 (NodeList) |
document.querySelectorAll('ul.menu li') |
3. 节点关系
| 属性 | 描述 | 示例 (假设 elem是一个元素) |
|---|---|---|
parentNode |
父节点 (可能是元素、文档或文档片段) | elem.parentNode |
parentElement |
父元素节点 | elem.parentElement |
childNodes |
所有子节点的集合 (包括文本、注释等任何类型的节点,NodeList) |
elem.childNodes |
children |
所有子元素节点的集合 (HTMLCollection) |
elem.children |
firstChild/ lastChild |
第一个/最后一个子节点 (包括任何类型的节点) | elem.firstChild(可能是文本或换行) |
firstElementChild/ lastElementChild |
第一个/最后一个子元素节点 | elem.firstElementChild |
previousSibling/ nextSibling |
前一个/后一个兄弟节点 (包括任何类型的节点) | elem.previousSibling |
previousElementSibling/ nextElementSibling |
前一个/后一个兄弟元素节点 | elem.previousElementSibling |
4. 节点操作
- 创建节点
1
2
3
4
5
6
7
8// 创建新的元素节点
const newDiv = document.createElement('div');
// 创建文本节点
const newText = document.createTextNode('Hello World');
// 创建文档片段 (用于高效批量操作)
const fragment = document.createDocumentFragment(); - 插入节点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15const parent = document.getElementById('parent');
const newNode = document.createElement('div');
const referenceNode = document.getElementById('child2');
// 作为最后一个子节点插入
parent.appendChild(newNode);
// 在 referenceNode 之前插入
parent.insertBefore(newNode, referenceNode);
// 现代方法:直接作为第一个子节点插入
parent.prepend(newNode);
// 现代方法:插入到元素之后 (非标准,但可用)
// parent.appendChild(newNode); 或 parent.insertBefore(newNode, referenceNode.nextSibling); - 修改内容
1
2
3
4
5
6
7
8
9
10const elem = document.getElementById('myElem');
// textContent: 获取或设置元素的纯文本内容,包括隐藏内容,性能较好,且能防范XSS攻击
elem.textContent = 'New text content';
// innerHTML: 获取或设置元素的HTML内容(包含标签字符串)
elem.innerHTML = '<strong>Bold</strong> text'; // 注意:这会解析HTML字符串,有安全风险
// innerText: 获取或设置元素及其后代的“渲染”文本内容(考虑CSS样式,如 visibility: hidden),但性能较差且结果可能因样式而异
// elem.innerText = 'Some text'; - 属性操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15const link = document.querySelector('a');
// 设置属性
link.setAttribute('href', 'https://www.example.com');
link.setAttribute('data-custom', 'value'); // 自定义属性
// 获取属性值
const hrefValue = link.getAttribute('href');
// 移除属性
link.removeAttribute('data-custom');
// 直接通过元素属性访问 (通常用于标准属性,如 id, href, src, value 等)
console.log(link.id); // 获取 id
link.id = 'newId'; // 设置 id - 样式操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14const elem = document.getElementById('myElem');
// 直接操作 style 属性 (修改内联样式,优先级高)
elem.style.color = 'red';
elem.style.backgroundColor = '#fff'; // 注意驼峰命名
elem.style.marginTop = '10px';
// 相较于前者,更简洁
elem.style.cssTest = "color:red;backgroudColor:#fff;marginTop:10px"
// 使用 classList 操作 CSS 类 (更推荐)g
elem.classList.add('active'); // 添加类
elem.classList.remove('hidden'); // 移除类
elem.classList.toggle('visible'); // 切换类(有则删,无则加)
elem.classList.contains('active'); // 检查是否包含某个类 - 删除节点
1
2
3
4
5
6
7
8const elemToRemove = document.getElementById('to-remove');
// 现代方法:直接调用元素自身的 remove()
elemToRemove.remove();
// 传统方法:通过父节点删除子节点
const parent = elemToRemove.parentNode;
parent.removeChild(elemToRemove); - 其他常用操作
1
2
3
4
5
6
7
8
9
10
11
12// 克隆节点
const original = document.getElementById('original');
const clone = original.cloneNode(true); // 参数 true 表示深度克隆(包括所有子节点)
// 替换节点
const oldNode = document.getElementById('old');
const newNode = document.createElement('div');
newNode.textContent = 'Replacement';
oldNode.parentNode.replaceChild(newNode, oldNode);
// 检查是否有子节点
const hasChildren = parentElement.hasChildNodes();
十、事件处理操作
1.添加事件
- HTML事件
1
2
3
4
5
6<button onclick="clickHandle()">按钮</button>
<script>
function clickHandle(){
console.log("点击了按钮");
}
</script>缺点:js和html未分离
- DOM0事件
1
2
3
4
5
6
7
8
9
10
11
12
13<button id="btn">按钮</button>
<script>
var btn = document.getElementById("btn");
btn.onclick = function(){
console.log("点击了按钮1");
}
btn.onclick = function(){
console.log("点击了按钮2");
}
//只会输出2,1被覆盖
</script>优点:js和html分离 缺点:无法同时添加多个事件
- DOM2事件
1
2
3
4
5
6
7
8
9
10
11
12
13<button id="btn">按钮</button>
<script>
var btn = document.getElementById("btn");
btn.addEventListener("click", function(){
console.log("点击了按钮1");
})
btn.addEventListener("click", function(){
console.log("点击了按钮2");
})
//1和2都会输出
</script>优点:可同时添加多个事件 缺点:麻烦
2.事件类型
鼠标
| 事件 | 解释 |
|---|---|
| click | 按下鼠标时触发 |
| dbclick | 双击鼠标时触发 |
| mousedown | 按下鼠标键是触发 |
| mouseup | 释放鼠标键时触发 |
| mousemove | 鼠标在节点内移到时触发,持续移动连续触发 |
| mouseenter | 鼠标进入节点时触发,进入子节点不触发 |
| mouseleave | 鼠标离开节点时触发,离开父节点不触发 |
| mouseover | 鼠标进入节点时触发,进入子节点再触发 |
| mouseout | 鼠标离开节点时触发,离开父节点再触发 |
| wheel | 滚动滚轮时触发 |
表单
| 事件 | 解释 |
|---|---|
| input | 输入时触发 |
| select | 选中时触发 |
| Change | 回车或失去焦点触发 |
| 方法 | 解释 |
|---|---|
| reset | 重置表单 |
| submit | 提交表单 |
3.Event 事件对象
1 | <button id="btn">按钮</button> |
属性
Event.target1
2
3
4
5
6
7
8<button id="btn">按钮</button>
<script>
var btn = document.getElementById("btn");
btn.onclick = function(event){
event.target.innerHTML = "点击后";
} //点击后button文本由 “按钮” 变 “点击后”
</script>Event.type1
2
3
4
5
6
7
8<button id="btn">按钮</button>
<script>
var btn = document.getElementById("btn");
btn.onclick = function(event){
console.log(event.type); // click
}
</script>
方法
Event.preventDefault()1
2
3
4
5
6
7
8
9<a href="www.baidu,com" id="a">百度</a>
<script>
var a = document.getElementById("a");
a.onclick = function(event){
event.preventDefault(); //阻止默认事件,此时点击并不会跳转
console.log("点击了a标签") ;
}
</script>Event.stopPropagation()1
2
3
4
5
6
7
8
9
10.root{
width: 200px;
height: 200px;
background-color: red;
}
.box{
width: 100px;
height: 100px;
background-color: blue;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16<div class = "root" id = "root">
<div class = "box" id = "box"></div>
</div>
<script>
var root = document.getElementById("root");
var box = document.getElementById("box");
root.onclick = function(){
console.log("点击了root");
}
box.onclick = function(e){
e.stopPropagation();//阻止事件冒泡,此时点击仅触发box的点击事件
console.log("点击了box");
}
</script>
4. 事件代理
基于事件冒泡的原理,通过父元素的代理,集中处理子元素的事件逻辑
1 | <ul id = "list"> |
十一、定时器
setTimeout()指定某个函数或某段代码,在多少毫秒后执行
1
2
3setTimeout(function(){
console.log("定时器");
},1000);注意:如果回调函数时对象方法,那么
setTimeout()使得方法内部的this关键字指向全局环境,而不是定义时所在的那个对象1
2
3
4
5
6
7
8
9
10var name = "a";
var user = {
name: "b",
getName: function(){
setTimeout(function(){
console.log(this.name);
},1000)
}
};
user.getName();//this指向全局作用域,此处输出a解决办法
1
2
3
4
5
6
7
8
9
10
11var name = "a";
var user = {
name: "b",
getName: function(){
var that = this;
setTimeout(function(){
console.log(that.name);
},1000)
}
};
user.getName();// b定时器可以取消
1
2var id = setTimeout(f,1000);
clearTimeout(id);setINterval()1
2
3var timer = setInterval(function(){
console.log(2);
},1000);每隔一段时间执行一次
十二、防抖
让高频触发的事件在短时间内只触发一次事件(例如滚动事件)
原理:在delay时间内若持续触发事件,则不断重置延时函数。只有在delay时间内不触发事件延时函数才能正常执行。(手机固定时间熄屏逻辑)
1 | function debounce(fn,delay){ |
十三、节流
让高频触发的事件在一定间隔触发一次,达到节约流量的效果。
原理:在valid为真时触发事件,并反转valid状态,等延时函数触发时再让valid恢复为真(搜索框联想逻辑)
1 | function throttle(fn,delay){ |
十四、Babel
1. 安装Babel
1 | npm install --save-dev @babel/core |
2. 配置文件 .babelrc
1 | { |
3. 转码规则
1 | npm install --save-dev @babel/preset-env |
4. 将规则加入
1 | { |
5. Babel命令行转码工具
1 | npm install --save-dev @babel/cli |
基本用法
1 | # 转码结果输出到标准输出 |
十五、Let
1.
var关键字:函数级作用域
2.let关键字:
1.let是块级作用域
2.let不存在变量提升
3.let不允许重复声明
十六、Const
const关键字:
1.声明之后不可改变
2.声明时必须初始化
3.块级作用域
4.不存在变量提升
5.不能重复声明
十七、对象解构赋值
1 | user = { |
十八、字符串拓展
1. 字符串Unicode表示法
1 | console.log("\u0061");// "a" |
2. 字符串遍历接口
1 | var str = "hello"; |
3. 模板字符串
1 | var href = "https://www.baidu.com"; |
十九、字符串新增方法
includes()startsWith()endWith()1
2
3
4
5
6
7
8
9
10
11let str = "Hello";
str.includes("ell");// true
str.starWith("He");// true
str.endWith("lo");// true
let s = "hello world!"
s.includes("hello", 6)// false 从索引6开始,是否包含"hello"
s.starWith("world", 6);// true 从索引6开始,是否以"world"开始
s.endWith("hello", 5);// true 到索引5结束,是否以"hello"结束repeat()1
2
3
4let x = "x";
console.log(x.repeat(3));// "xxx"
console.log(x);// "x"padStart()padEnd()1
2
3
4
5
6
7let x = "x";
x.padStart(5, "01");// "0101x"
x.padStart(4, "01");// "010x"
x.padEnd(5, "01");// "x0101"
x.padEnd(4, "01");// "x010"trimStart()trimEnd()1
2
3
4
5const s = " xxx ";
s.trim();// ”xxx“
s.trimStart();// "xxx "
s.trimEnd();// " xxx"at()1
2
3
4let s = "abcdefg";
console.log(s.at(3));// d, 输出索引为3的字符
console.log(s.at(-3));// e, 输出索引为-3的字符
二十、扩展运算符
扩展运算符(…)。将一个数组转为用逗号分隔的参数序列
1 | console.log(...[1, 2, 3]);// 1 2 3 |
可以代替apply方法
1 | let arr = [10, 20, 30, 40]; |
合并数组
1 | let arr1 = [1, 2, 3, 4]; |
二十一、数组新增方法
Array.form()用于将类数组转化为数组
常见的类数组
argumentsarguments只能使用数组的读取方式和length属性,不能使用数组方法1
2
3
4
5
6
7
8
9
10
11function add(){
console.log(arguments);// Arguments(3)[10, 20, 30, callee: f, Symbol(Symbol.iterator): f]
console.log(arguments[0]);// 10
console.log(arguments[1]);// 20
console.log(arguments[2]);// 30
console.log(Array.form(arguments));// (3) [10, 20, 30]
}
add(10, 20, 30);- 元素集合
1
2
3
4
5
6
7
8
9
10
11<body>
<h1>1</h1>
<h1>2</h1>
<h1>3</h1>
<script>
let titles = document.querySelectorAll("h1");
console.log(titles);// NodelList(3) [h1, h1, h1]
console.log(Array.form(titles));// (3) [h1, h1, h1]
</script>
</body> - 类似数组的对象
1
2
3
4
5
6
7
8let user = {
"0": xxx,
"1": 20,
"2": "man",
length: 3
}
console.log(user);// {0: 'xxx', 1: 20, 2: 'man', length: 3}
console.log(Array.form(user));// (3) ['xxx', '20', 'man']
Array.of()1
Array.of(10, 20, 30);// [10, 20, 30]
将一组值转化为数组
二十二、对象的拓展
1. 属性的简洁表示
1 | //ES5 |
2. 属性名表达式
1 | //ES5 |
3. 对象的拓展运算符
1 | let z = { a: 1, b: 2 }; |
二十三、函数拓展
1. 箭头函数
1 | // 直接声明函数 |
将匿名函数改写为箭头函数
1 | let arr = [1, 2, 3]; |
对普通函数内部的this指向函数运行时的对象,但这点对箭头函数不成立。它没有自己的this,内部的this就是定义时上层作用域的this
1 | var name = "a"; |
使用箭头函数可以避免该问题
1 | var name = "a"; |
二十四、Set 数据结构
1. 定义
类似于数组,但成员值都是唯一的,没有重复值。Set()本身是一个构造函数,用于生成Set数据结构。
1 | let s = new Set(); |
数组去重
1 | let arr = [10, 20, 30, 10, 20, 40]; |
字符串去重
1 | let str = "abcabcabb"; |
向set类型添加数据时不会发生字符转换
1 | let set = new Set(); |
2. 属性
size1
2const s = new Set([1, 2, 3, 4, 4, 4]);
console.log(s.size);// 4返回成员数
3. 方法
add()向set中添加数据
delete()删除数据
has()判断是否含有
clear()清空
二十五、Promise 对象
1. 定义
一种异步编程的解决方案
2. 用法
ES6规定,Promise是一个构造函数,用来生成Promise实例
1 | const promise = new Promise(function(resolve, reject){ |
Promise实例生成后,可以用then方法分别指定resolve状态和reject状态的回调函数
1 | promise.then(function(value){ |
二十六、Async 函数
1. 定义
ES6引入async函数,使异步操作更简单。可以将异步操作变为同步操作
2. 用法
1 | function print(){ |
使用async将上述异步改同步
1 | function timeout(ms){ |
二十七、 Class
1. 基本语法
1 | // ES5 |
class不存在提升
2. 属性与方法
1 | class Person{ |
3. 继承
1 | class Person{ |
二十八、 Module
1. 导入导出
1 | // ES6 |
2. 改名
1 | // 1.js |
3. 整体导入
1 | // hello.js |
4. 默认导出
1 | // 1.js |



