# var 与 let 的区别
# let 自带块级作用域 {} 代表块
if (5 > 3) {
var num1 = 10;
let num2 = 10;
}
console.log(num1); //10
console.log(num2); //出错
# let 不存在变量声明提升
console.log(a); // undefined
var a = 10;
console.log(a); // 出错
let a = 10;
# let 不允许重复声明
var a = 0;
var a = 10;
console.log(a); //10
let a = 0;
let a = 10;
console.log(a); //出错
# let 不会成为 window 对象的属性
# 变量的解构赋值
# 数组的解构赋值
let arr = [131, 182, 156];
//let num1 = arr[0];
//let num2 = arr[1];
//let num3 = arr[2];
let [num1, num2, num3] = arr;
console.log(num1, num2, num3); // 131 182 156
# 对象的解构赋值
// let {username} = {username:小黑}
let obj = {
username: "小黑",
userage: 20,
sex: "女",
};
//let username = obj.username;
//let userage = obj.userage;
// 可以换名也可以设置默认值
let { userage: age, username, sex = "男" } = obj;
console.log(username, age, sex); //小黑 20 女
// 如果上边没有 sex 属性则结果为男
// 将 newPost对象中的属性全拿过来,同时加了id属性
addPost(newPost) {
this.postList.push({ ...newPost, id: shortid() });
}
# 字符串的解构赋值
let str = "hello";
let [a, b, c, d, e] = str;
console.log(a, b, c, d, e); // h e l l o
# 函数参数的解构赋值
var obj = {
username: "大白",
};
/* function say(obj) {
const str = "我叫" + obj.username;
console.log(str); // 我叫大白
} */
function say({ username }) {
// 函数的形参相当于在函数内部声明变量,函数的实参相当于对这个形参变量赋值
// let {username} = obj;
const str = "我叫" + username;
console.log(str); // 我叫大白
}
say(obj);
# 字符串扩展
# 模板字符串 (高级字符串拼接)
let goods = {
name: "iphone12",
price: 10000,
};
let htmlStr = `<div><h4>商品名${goods.name}</h4><span>商品价格${goods.price}</span></div>`;
console.log(htmlStr);
# padEnd padStart 填充
let str = "hello";
let newStr = str.padEnd(8, "a"); //往后填充,省略第二个参数默认用空格填
console.log(str); //hello
console.log(newStr); // helloaaa
# 数组扩展
# flat flatMap 数组的扁平化处理
数组的成员有时还是数组,用于将嵌套的数组 “拉平”,变成一维的数组。该两个方法返回一个新数组,对原数据没有影响。
let arr = [1, 2, [3, 4, [5, 6, [7, 8]]]];
console.log(arr.flat()); //默认只拉一层[1, 2, 3, 4, Array(3)]
console.log(arr.flat(2)); //[1, 2, 3, 4, 5, 6, Array(2)]
console.log(arr.flat(Infinity)); //不管有多少层嵌套,都要转成一维数组[1, 2, 3, 4, 5, 6, 7, 8]
let arr1 = [1, 2];
/* let newArr1 = arr1.map(function (ele) {
return [ele, ele * 2];
});
console.log(newArr1); //[[1,2],[2,4]] */
let newArr1 = arr1.flatMap(function (ele) {
return [ele, ele * 2];
});
console.log(newArr1); //[1, 2, 2, 4];
// flatMap相当于是先进行了一次Map操作,再进行一次flat操作
# fill 根据指定的数据对数组进行初始化,会修改原数组
let arr2 = [1, 2, 3];
// 原来的被修改了
console.log(arr2.fill("")); //["","",""]
console.log(arr2.fill(7, 1, 2)); //[1, 7, 3],因为会改变原数组,所以结果是没有上边那条输出语句
// 从第一个开始,到第二个之前结束 [1-2)
# 对象扩展
# 属性的简捷表示法
let name = "大白";
let age = 10;
/* let obj1 = {
name: name,
age: age,
say: function () {
console.log(this.name);
},
}; */
let obj1 = {
// 创建对象的时候,如果属性值所代表的变量名和属性名相同的话可以省略
name,
age,
say() {
console.log(this.name);
},
};
console.log(obj1); //{name: "大白", age: 10, say: ƒ}
# 扩展运算符 …
用于复制拷贝
# 数组的扩展
let arr = [1, 2, 3, 4, 5];
let arr1 = arr;
arr1.push(6);
//因为是内置对象,所以拷贝的是地址
console.log(arr); //[1, 2, 3, 4, 5, 6]
console.log(arr1); //[1, 2, 3, 4, 5, 6]
console.log(arr1 === arr); //true
let arr = [1, 2, 3, 4, 5];
let arr1 = [...arr];
arr1.push(6);
console.log(arr); //[1, 2, 3, 4, 5]
console.log(arr1); //[1, 2, 3, 4, 5, 6]
console.log(arr1 === arr); //false
# 对象的扩展
let obj = {
a: 10,
b: 20,
};
let obj1 = { ...obj };
obj1.a = 100;
console.log(obj); //10 20
console.log(obj1); // 100 20
let goodsArr = [
{
name: "手机",
price: 1000,
id: 1,
},
{
name: "平板",
price: 2000,
id: 2,
},
{
name: "笔记本",
price: 3000,
id: 3,
},
];
let newArr = [...goodsArr]; //只把最外边的拷贝了(只拷贝了数组),里边的地址没有拷贝
newArr[1].price = 2500;
console.log(newArr[1]); //2500
console.log(goodsArr[1]); //2500
# 函数的扩展
# 函数参数的默认值
function add(x = 10, y = 20) {
return x + y;
}
let res = add(2);
console.log(res); //22
# …rest 参数
function fun(a, ...rest) {
// rest 叫剩余参数,剩余参数必须写在后面
console.log(rest); //(3) [2, 3, 4]
}
fun(1, 2, 3, 4);
# 箭头函数
let add = (x, y = 20) => x + y;
let res = add(10);
console.log(res); //30
//箭头函数,不能使用 function 创建,只能存储到变量中
//箭头左侧是参数部分用()包裹,没有参的时候直接写(),
//当只有一个参数的时候可以省略()直接写参数,右侧是执行部分,
//用{}包裹,当只有return的时候可以省略{},直接写返回值
// 当函数只返回对象的时候,可以直接({})
// let add = (x, y = 20) => ({})
let arr = [1, 3124, 145, 123, 1225, 6, 7];
// let newArr = arr.filter(function (ele) {
// return ele < 10;
// });
let newArr = arr.filter((ele) => ele < 10);
console.log(newArr);
# 箭头函数和普通函数的 this 指向
// 普通函数的this指向:谁调用就指向谁
let obj = {
a: 10,
fun: function () {
console.log(this); //{a: 10, fun: ƒ}
},
};
obj.fun();
// 箭头函数的this指向:创建的时候就定义好了
// 对象内定义方法的时候如果方法内部使用了 this,那么这个方法就不能用箭头函数定义
let obj = {
a: 10,
fun: () => {
console.log(this);
},
};
obj.fun(); //Window
// 箭头函数一般都设置在类里面,因为外边找不到,一般都是window,
// 如果在外边涉及不到this那么箭头函数和普通函数没什么区别
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
sayPoint = () => {
console.log(this); //Point {x: 10, y: 100, sayPoint: ƒ}
};
}
let p = new Point(10, 100);
p.sayPoint();
# symbol 数据类型 (简单看)
-
简单用法
let obj = { a: 10, a: 20, }; console.log(obj); //a:20 let s1 = Symbol("foo"); let s2 = Symbol("foo"); console.log(s1); //Symbol(foo) console.log(s1 === s2); //false console.log(s1.description); //foo let x = Symbol(); let obj = {}; let a = "say"; obj[a] = function () {}; obj[x] = "hello!"; console.log(obj); //{Symbol(): "hello!", say: ƒ}
# Class 类
-
基础用法
/* function Point(x, y) { this.x = x; this.y = y; } Point.prototype.toString = function () { return `(${this.x},${this.y})`; }; var p = new Point(1, 2); */ let _color = "orange"; class Point { // 类的内部必须存在 constructor 函数,当 new 的时候 constructor 函数被触发, // 该方法默认返回实例对象(this) // 除了 constructor 函数之外的函数都相当于公有方法,函数之间什么都不用加(逗号) // 类的内容默认只能写方法,向下边这样 constructor(x, y) { this.x = x; this.y = y; console.log("constructor函数被触发"); } // get 给 color 属性定义初始值 get color() { return _color; } // get 设置的值要用set来改,会在修改 get 函数的时候触发 set color(value) { // console.log(value); if (this.color !== value) { _color = value; } } toString() { return `(${this.x},${this.y})`; } // 静态函数 只有类本身可以访问,不会生成到类的实例上 static sayHello() { console.log("hello"); } } // 创建完类之后,也可以这样添加方法 Point.prototype.say = function () { console.log("我是新加方法"); }; let p = new Point(1, 2); //必须要有new p.color = "pink"; //在这里触发 set 函数 console.log(p); // constructor函数被触发 Point {x: 1, y: 2} console.log(p.toString()); //(1,2) p.say(); //我是新加方法 console.log(p.color); //pink Point.sayHello(); //静态方法只能这样访问
# Class 类的继承
-
基本用法
class Point { constructor(x, y) { this.x = x; this.y = y; } sayPoint() { console.log(`我是坐标(${this.x},${this.y})`); } } let p = new Point(100, 20); console.log(p); //Point {x: 100, y: 20} p.sayPoint(); //我是坐标(100,20) // 类的继承使用关键字extends class ColorPoint extends Point { // 继承Point内的所有内容 constructor(x, y, color) { // 当继承的类内部创建了 constructor,那么该函数内部必须使用 super 方法调用父类 super(x, y); this.color = color; } } let colorP = new ColorPoint(100, 200); console.log(colorP); //ColorPoint {x: 100, y: 200, color: "red"} colorP.sayPoint(); //我是坐标(100,20)
# Es6 模块
# 使用 webpack 编译打包 es6 模块语法
-
安装 node (去官网下载)
node 是 js 的运行环境,里边有 js 的各种插件
node -v 检查版本
npm -v 检查版本npm config set registry https://registry.npm.taobao.org // 淘宝镜像 npm config set loglevel=http // 下载的时候有显示 -
安装命令行工具 git bash
-
新建一个文件夹 (webpack-es6)
-
在文件夹内部打开命令行工具执行
npm init -y命令。该命令的作用是将这个文件夹变成 node 项目,从而让这个项目可以使用 npm 下载对应的包 (插件)。 -
项目内安装 webpack 执行
npm install webpack webpack-cli --save-dev -
在项目的根目录下新建
index.htmlsrc/index.jssrc/a.js在 a.js 内写一些 es6 模块代码 (导出变量) , index.js 内导入 a.js 模块内的导出 -
在项目根目录下打开命令行工具执行
npx webpack命令。该命令的默认作用是将项目下的 src 文件夹下的 index.js 打包并编译到某个文件夹 (dist 文件夹) 下的 main.js,然后 index.html 引入打包好之后的 js (main.js) 文件,在浏览器中查看 -
如果更改 index.js 以及 a.js 需要重新执行
npx webpack编译
# es6 模块的导入 (import) 导出 (export)
-
简单操作
-
a.js 文件
// 模块导出了一个变量 firstName(对外输出了一个变量) /* let lastName = "三"; export let firstName = "张"; export { firstName }; //export { lastName as laName }; //换名,导出的是laName //export { firstName, lastName }; //导出多个 */ let a = 10; let b = 20; let c = 30; let d = 10000; export { a, b, c }; export default d; -
b.js 文件
let add = () => a + b; let res = add(1, 2); console.log(res); //3 因为在index.js中导入了 -
index.js 文件
// 导入a.js模块导出的变量(加载这个变量) // 当导入模块的时候如果模块是js文件可省略后缀 import "./b.js"; //相当于只是让b.js执行了,但里边的内容拿不到 import { firstName } from "./a.js"; //这里也让a.js文件从上到下执行了一遍 //每一个导入都会让 from 后的文件从头到尾执行一遍,而不是只执行某一个阶段 console.log(firstName); //在html中引入main.js 文件,结果输出了 张 import * as all from "./a"; //* 代表导出的所有 as 是换名字 import x from "./a"; //默认导入 console.log(all.a); //10 console.log(all.b); //20 console.log(all.c); //30 console.log(all.default); //10000 console.log(x); -
index.html 文件
引入了 main.js 才生效<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <script src="./dist/main.js"></script> </body> </html>
-
-
es6 有独立作用域,每一个模块都是一个独立作用域,当你导出的时候,另外一个模块只允许你导入我允许导出的东西
-
命名导出 (export), 可以导出多次
-
默认导出 (export default),只能使用一次
-
1. 命名导入 (import) 导入的名称和导出的名称必须一致
- * 代表导出的所有 as 是换名字
-
2. 默认导入 (import) 导入的时候随意命名