1. let 关键字
let
关键字用来声明变量,使用 let
声明的变量有几个特点:
- 不允许重复声明
- 块级作用域
- 不存在变量提升
- 不影响作用域链
应用场景:以后声明变量使用let 就对了
<script type="text/javascript">
/*
let关键字就是用来声明变量的
使用let关键字声明的变量具有块级作用域
在一个大括号中 使用let关键字声明的变量才具有块级作用域 var关键字是不具备这个特点的
防止循环变量变成全局变量
使用let关键字声明的变量没有变量提升
使用let关键字声明的变量具有暂时性死区特性
*/
/* --------let关键字就是用来声明变量的-------- */
// let a = 10;
// console.log(a);
/* --------使用let关键字声明的变量具有块级作用域-------- */
// if (true) {
// let b = 20;
// console.log(b) //20
// if (true) {
// let c = 30;
// console.log(c); //30
// }
// // console.log(c);//报错,c未定义(在大括号外面找不到c这个变量)
// }
// console.log(b);//报错,b未定义(在大括号外面找不到c这个变量)
/* 在一个大括号中 使用let关键字声明的变量才具有块级作用域 var关键字是不具备这个特点的 */
// if (true) {
// let num = 100;
// var abc = 200;
// }
// console.log(abc); //200
// console.log(num);//报错
/* -------防止循环变量变成全局变量--------- */
// for (let i = 0; i < 2; i++) { }
// console.log(i);
/*-----使用let关键字声明的变量没有变量提升,要先声明再输出------*/
// console.log(a); //报错
// let a = 100;
/* -------使用let关键字声明的变量具有暂时性死区特性------- */
var num = 10
if (true) {
console.log(num);
let num = 20;
}
</script>
2. const 关键字
const
关键字用来声明常量,const
声明有以下特点:
- 声明必须赋初始值
- 标识符一般为大写
- 不允许重复声明
- 值不允许修改
- 块级作用域
注意:对象属性修改和数组元素变化不会出发 const
错误
应用场景:声明对象类型使用 const,非对象类型声明选择 let
<script type="text/javascript">
// 使用const关键字声明的常量具有块级作用域
// if (true) {
// const a = 10;
// if (true) {
// const a = 20;
// console.log(a); //20
// }
// console.log(a);//10
// }
// console.log(a);//报错
// 使用const关键字声明的常量必须赋初始值
// const PI = 3.14;
// 常量声明后值不可更改
// const PI = 3.14;
// PI = 100;
const ary = [100, 200];
ary[0] = 123;
// ary = [1, 2];//会报错,可以改变里面的某个值,但不允许给ary重新赋值
console.log(ary);//[123, 200]
</script>
let、const、var 的区别:
var | let | const |
---|---|---|
函数级作用域 | 块级作用域 | 块级作用域 |
变量提升 | 不存在变量提升 | 不存在变量提升 |
值可更改 | 值可更改 | 值不可更改 |
3. 模板字符串
模板字符串(template string)是增强版的字符串,用反引号 ` 标识,特点:
- 字符串中可以出现换行符
- 可以使用
${xxx}
形式输出变量
let name = 'jack';
console.log(`hello, ${name}`);//hello, jack
let ul = `<ul>
<li>apple</li>
<li>banana</li>
<li>peach</li>
</ul>`
应用场景:当遇到字符串与变量拼接的情况使用模板字符串。
<script type="text/javascript">
// let name = `张三`;
// let sayHello = `Hello, 我的名字叫${name}`;
// console.log(sayHello);
// let result = {
// name: "zhangsan",
// age: 20
// };
// let html = `
// <div>
// <span>${result.name}</span>
// <span>${result.age}</span>
// </div>
// `;
// console.log(html);
const fn = () => {
return '我是fn函数'
}
let html = `我是模板字符串 ${fn()}`;
console.log(html);//我是模板字符串 我是fn函数
</script>
4. 函数参数默认值设定
ES6 允许给函数参数设置默认值,当调用函数时不给实参,则使用参数默认值。
具有默认值的形参,一般要靠后。
let add = (x, y, z=3) => x + y + z;
console.log(add(1, 2)); // 6
5. rest 参数
ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments
,作用与 arguments
类似。将接收的参数序列转换为一个数组对象。
案例1:求不定个数数字的和
let add = (...args) => {
let sum = args.reduce((pre, cur) => pre + cur, 0);
return sum;
}
console.log(add(1, 2, 3, 4, 5)); // 15
应用场景:rest 参数非常适合不定个数参数函数的场景
6. 箭头函数
ES6 允许使用「箭头」=>
定义函数。
function
写法:function fn(param1, param2, …, paramN) { // 函数体 return expression; }
=>
写法:let fn = (param1, param2, …, paramN) => { // 函数体 return expression; }
箭头函数的 注意点:
- 如果形参只有一个,则小括号可以省略
- 函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果
- 箭头函数
this
始终指向声明时所在作用域下this
的值 - 箭头函数不能使用new关键字来实例化对象
- 不能使用
arguments
function函数是一个对象,但是箭头函数不是一个对象,它其实就是一个表达式
<script type="text/javascript">
// 箭头函数是用来简化函数定义语法的
// const fn = () => {
// console.log(123)
// }
// fn();
// 在箭头函数中 如果函数体中只有一句代码 并且代码的执行结果就是函数的返回值 函数体大括号可以省略
// const sum = (n1, n2) => n1 + n2;
// const result = sum(10, 20);
// console.log(result);//30
// 在箭头函数中 如果形参只有一个 形参外侧的小括号也是可以省略的
// const fn = v => {
// alert(v);
// }
// fn(20)
// 箭头函数不绑定this 箭头函数没有自己的this关键字 如果在箭头函数中使用this this关键字将指向箭头函数定义位置中的this
// 箭头函数没有this指向,箭头函数内部this值只能通过查找作用域链来确定,一旦使用箭头函数,当前就不存在作用域链
// function fn() {
// console.log(this);//指向obj
// return () => {
// console.log(this);//指向obj
// }
// }
// const obj = { name: 'zhangsan' };
// const resFn = fn.call(obj);
// resFn();
// let getObj = id => {
// return {
// id: id,
// name: '11'
// }
// }
// console.log(getObj(1));//{id: 1, name: "11"}
// let getObj = id => ({ id: id, name: '11' }) //如果没写return,数组或对象必须用小括号括起来,否则会认为它不是一个返回值
// console.log(getObj(1));//{id: 1, name: "11"}
// let fn = (function () {
// return function () {
// console.log(12);
// }
// })();
// fn();
// 上面与下面等价
let fn = (() => {
return () => {
console.log(11);
}
})();
fn();
</script>
案例1:箭头函数 this
始终指向声明时所在作用域下 this
的值,call
等方法无法改变其指向。
let obj = {
uname: 'rick',
age: 30
};
let foo = () => {
console.log(this);
}
let bar = function () {
console.log(this);
}
// foo();//window
// bar();//window
// call 对箭头函数无效
foo.call(obj); // window
bar.call(obj); // obj {...}
案例2:筛选偶数
let arr = [2, 4, 5, 10, 12, 13, 20];
let res = arr.filter(v => v % 2 === 0);
console.log(res); // [2, ,4 10, 12, 20]
案例3:点击 div两秒后变成粉色
-
方案1:使用
_this
保存div
下的this
,从而设置div
的style
属性。div.addEventListener('click', function () { let _this = this; setTimeout(function () { console.log(_this); // <div>...<div> _this.style.backgroundColor = 'pink'; }, 2000) });
-
方案2:使用
=>
箭头函数div.addEventListener('click', function () { //这里不能用箭头函数,用了this就无法指向div而是指向window了 setTimeout(() => { console.log(this); // <div>...</div> this.style.backgroundColor = 'pink'; }, 2000); });
7. 变量的解构赋值
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为 解构赋值。
应用场景:频繁使用对象方法、数组元素,就可以使用解构赋值形式。
数组的解构赋值:
const arr = ['red', 'green', 'blue'];
let [r, g, b] = arr;
对象的解构赋值:
<script type="text/javascript">
// 对象解构允许我们使用变量的名字匹配对象的属性 匹配成功 将对象属性的值赋值给变量
// let person = { name: 'lisi', age: 30, sex: '男' };
// // let { name, age, sex } = person; //完全解构
// // console.log(name)
// // console.log(age)
// // console.log(sex)
// let { name: myName } = person; //不完全解构
// console.log(myName);//lisi
const obj = {
uname: 'rick',
age: 30,
sayHi: function () {
console.log('hello');
},
sayBye() {
console.log('Bye~');
}
}
let { name, age, sayHi } = obj;
let { sayBye } = obj;
obj.sayHi();
obj.sayBye();
</script>
8. 对象功能的扩展
<script>
// es6直接写入变量和函数,作为对象的属性和方法
const name = 'lsy',
age = 18;
const person = {
name, //等价于 name:name,
age,
sayHi() {
console.log(this.name);//lsy
}
}
person.sayHi();
console.log('---------------------------');
function fn(x, y) {
return { x, y }
}
console.log(fn(12, 13));//{x: 12, y: 13}
console.log('---------------------------');
let car = {
wheel: 4,
set(newval) {
if (newval < this.wheel) {
// console.log('你的轮子掉啦');
throw new Error('你的轮子掉啦');//报错语句
}
this.wheel = newval;
},
get() {
return this.wheel;
}
}
car.set(6);
console.log(car.get());
console.log('---------------------------');
</script>
比较两个值是否严格相等 is()
console.log(NaN === NaN);//false (不严谨)
console.log(Object.is(NaN, NaN));//true
对象的合并
// 对象的合并
// Object.assign(target,obj1,obj2...)
let newObj = Object.assign({}, { a: 1 }, { b: 3 })
console.log(newObj);//{a: 1, b: 3}
9. Array 的扩展方法
9.1 扩展运算符
处理数组中的最大值:
<script>
// 剩余运算符:把多个独立的合并到一个数组中
// 扩展运算法:将一个数组分割,并将各个项作为奋力的函数传给参数
// 处理数组中的最大值,使用apply
const arr = [12, 24, 67, 89, 64];
// console.log(Math.max.apply(null, arr));//89
// es6扩展运算法更方便
console.log(Math.max(...arr));//89
</script>
实例:
<script type="text/javascript">
// 扩展运算符可以将数组拆分成以逗号分隔的参数序列
// let ary = ["a", "b", "c"];
// ...ary // "a", "b", "c"
// console.log(...ary)
// console.log("a", "b", "c")
// 扩展运算符应用于数组合并
// let ary1 = [1, 2, 3];
// let ary2 = [4, 5, 6];
// // ...ary1 // 1, 2, 3
// // ...ary1 // 4, 5, 6
// let ary3 = [...ary1, ...ary2];
// console.log(ary3)
// 合并数组的第二种方法
// let ary1 = [1, 2, 3];
// let ary2 = [4, 5, 6];
// ary1.push(...ary2);
// console.log(ary1)
// 利用扩展运算符将伪数组转换为真正的数组
var oDivs = document.getElementsByTagName('div');
console.log(oDivs)
var ary = [...oDivs];
ary.push('a');
console.log(ary);
</script>
9.2 Array.from 方法
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<script>
// 数组的方法: from() of()
// 1. from() 将伪数组转换成真正的数组
function add() {
console.log(arguments);//是一个伪数组
// // es5转换(不太好理解)
// let arr = [].slice.call(arguments);
// console.log(arr);//[1, 2, 3]
// es6写法
let arr = Array.from(arguments);
console.log(arr);//[1, 2, 3]
}
add(1, 2, 3);
let lis = document.querySelectorAll('li');
console.log(lis);//NodeList(4) [li, li, li, li].这个不是真正的数组
// from() 将伪数组转换成真正的数组
console.log(Array.from(lis));//[li, li, li, li]
// 扩展运算符将伪数组转换为真正的数组
console.log([...lis]);//[li, li, li, li]
// from() 还可以接受第二个参数,用来对某个元素进行处理
let liContents = Array.from(lis, ele => ele.textContent)
console.log(liContents);// ["1", "2", "3", "4"]
</script>
</body>
var arrayLike = {
"0": "1",
"1": "2",
"length": 2
}
var ary = Array.from(arrayLike, item => item * 2)
console.log(ary); //[2, 4]
Array.of 方法和 copyWithin 方法(不常用)
// 2. of() 将任意的数据类型,转换成数组
console.log(Array.of(3, 5, '13', [1, 2], { id: 11 }));//[3, 5, "13", Array(2), {…}]
// 3. copyWithin() 数组内部将制定位置的元素复制到其它的位置,返回当前数组
// 从索引号3位置往后的所有数值,替换从0位置往后的三个数值
console.log([1, 2, 3, 8, 9, 10].copyWithin(0, 3));//[8, 9, 10, 8, 9, 10]
console.log([1, 2, 3, 8, 9, 10].copyWithin(0, 2));//[3, 8, 9, 10, 9, 10]
console.log([1, 2, 3, 8, 9, 10].copyWithin(1, 3));//[1, 8, 9, 10, 9, 10]
9.3 find 方法
<script type="text/javascript">
var ary = [{
id: 1,
name: '张三'
}, {
id: 2,
name: '李四'
}];
let target = ary.find(item => item.id == 3);
console.log(target) //undefined
</script>
9.4 findindex 方法
<script type="text/javascript">
let ary = [10, 20, 50];
let index = ary.findIndex(item => item > 15);
console.log(index);//1
</script>
// find() 找出第一个符合条件的数组成员
var fd = [1, 2, 10, -12, -15, 40].find(n => n < 0)
console.log(fd);//-12
// fidIndex() 找出第一个符合条件的数组成员的索引号
var fdIndex = [1, 2, 10, -12, -15, 40].findIndex(n => n < 0)
console.log(fdIndex); //3
9.5 entries() keys() values()
// 5. entries() keys() values() 能返回一个遍历器 就可以使用 for...of 循环进行
// keys() 对键名遍历
for (let index of ['a', 'b'].keys()) {
console.log(index); //0 1
}
// values() 对键值遍历
for (let val of ['a', 'b'].values()) {
console.log(val); //a b
}
// entries() 对键值对遍历
for (let [index, ele] of ['a', 'b'].entries()) {
console.log(index, ele); //0 "a" 1 "b"
}
let letter = ['a', 'b', 'c'];
let it = letter.entries();
console.log(it.next().value);//[0, "a"]
console.log(it.next().value);//[1, "b"]
console.log(it.next().value);//[2, "c"]
console.log(it.next().value);//undefined
9.6 includes 方法
// 6. includes() 返回一个布尔值,表示某个数组是否包含给定的值
console.log([1, 2, 3].includes(2));//true
console.log([1, 2, 3].includes(4));//false
// 解决了之前 indexOf() 的问题
console.log([1, 2, 3].indexOf(2));//1
console.log([1, 2, 3].indexOf('2'));//-1 返回-1才能证明 '2' 不存在,
<script type="text/javascript">
let ary = ["a", "b", "c"];
let result = ary.includes('a')
console.log(result)
result = ary.includes('e')
console.log(result)
</script>
10. startsWith 方法和 endsWith 方法
- startsWith:表示参数字符串是否在元字符串的头部,返回布尔值
- endsWith:表示参数字符串是否在元字符串的尾部,返回布尔值
<script type="text/javascript">
let str = 'Hello ECMAScript 2015';
let r1 = str.startsWith('Hello');
console.log(r1);//true
let r2 = str.endsWith('2016');
console.log(r2);//false
</script>
11. repeat方法
<script type="text/javascript">
console.log("y".repeat(5)) //yyyyy
</script>
12. Symbol
12.1 Symbol 基本介绍与使用
ES6 引入了一种新的原始数据类型 Symbol
,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。
JavaScript 的七种基本数据类型:
- 值类型(基本类型):string、number、boolean、undefined、null、symbol
- 引用数据类型:object(包括了array、function)
Symbol 的特点:
- Symbol 的值是唯一的,用来解决命名冲突的问题
- Symbol 值不能与其他数据进行运算
- Symbol 定义的对象属性不能使用
for...in
循环遍历,但是可以使用Reflect.ownKeys
来获取对象的所有键名
Symbol 的创建:
- 创建一个
Symbol
:let s1 = Symbol(); console.log(s1, typeof s1); // Symbol() symbol
- 使用
Symbol.for()
方法创建,名字相同的Symbol
具有相同的实体。let s3 = Symbol.for('apple'); let s3_1 = Symbol.for('apple'); console.log(s3 === s3_1); // true
- 输出
Symbol
变量的描述,使用description
属性let s4 = Symbol('测试'); console.log(s4.description); // 测试
实例:
<script>
// 原始数据类型Symbol,它表示独一无二的值
// 最大的用途:用来定义对象的私有变量
const name1 = Symbol('name');
const name2 = Symbol('name');
console.log(name1 === name2);//false
let s1 = Symbol('s1');
console.log(s1); //Symbol(s1)
// let obj = {};
// obj[s1] = 'lsy';
let obj = {
[s1]: 'lsy' //使用变量(s1是变量)来作为对象的属性时都要加
};//简写
console.log(obj);//{Symbol(s1): "lsy"}
// 如果用symbol定义的对象中的变量,取值是一定要用 [变量名]
console.log(obj[s1]);//lsy
for (let k in obj) {
console.log(k); //没有输出
}
</script>
13. Set 数据结构
<script type="text/javascript">
// 集合:表示无重复值的有序列表
let set = new Set();
console.log(set);
// const s2 = new Set(["a", "b"]);
// console.log(s2.size);//2
// const s3 = new Set(["a", "a", "b", "b"]);
// console.log(s3.size);//2
// const ary = [...s3];
// console.log(ary);//["a", "b"] (无重复值)
// const s4 = new Set();
// // 向set结构中添加值 使用add方法
// s4.add('a').add('b');
// console.log(s4.size);//2
// // 从set结构中删除值 用到的方法是delete
// const r1 = s4.delete('c');
// console.log(s4.size);//2
// console.log(r1);//false
// // 判断某一个值是否是set数据结构中的成员 使用has
// const r2 = s4.has('d');
// console.log(r2);//false
// // 清空set数据结构中的值 使用clear方法
// s4.clear();
// console.log(s4.size);//0
// 遍历set数据结构 从中取值
const s5 = new Set(['a', 'b', 'c']);
s5.forEach(value => {
console.log(value); //a b c
})
</script>
有关 Set 中对象引用的释放:
<script>
// set中对象的引用无法被释放
// let set6 = new Set(), obj = {}
// set6.add(obj);
// // 释放当前的资源
// obj = null;
// console.log(set6);//还是存在Object,没有被释放成功
// 正确做法 ↓
let set7 = new WeakSet(), obj = {}
set7.add(obj);
// 释放当前的资源
obj = null;
console.log(set7);//成功释放了Object
// WeakSet
// 1. 不能传入非对象类型的参数
// 2. 不可迭代
// 3. 没有 forEach()
// 4. 没有 size 属性
</script>
14. Map
<script>
// Map类型是键值对的有序列表,键和值是任意类型
let map = new Map();
map.set('name', 'lsy');
map.set('age', 18)
console.log(map);//{"name" => "lsy", "age" => 18}
console.log(map.get('name'));//lsy
</script>