持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第14天,点击查看活动详情
let 关键字
let 关键字用来声明变量,使用 let 声明的变量有几个特点:
- 不允许重复声明
- 块儿级作用域
- 不存在变量提升
- 不影响作用域链
应用场景:以后声明变量使用 let 就对了
<script>
//声明变量
let a;
let b,c,d;
let e = 100;
let f = 521, g = 'iloveyou', h = [];
//1. 变量不能重复声明
// let star = 'lzx';
// let star = 'xz';
//2. 块儿级作用域 全局, 函数, eval
// if else while for
// {
// let girl = 'zyq';
// }
// console.log(girl);
//3. 不存在变量提升
// console.log(song);
// let song = 'nadr';
//4. 不影响作用域链
{
let school = 'NEFU';
function fn(){
console.log(school);
}
fn();
}
</script>
const 关键字
const 关键字用来声明常量,const 声明有以下特点
- 声明必须赋初始值
- 标识符一般为大写
- 不允许重复声明
- 值不允许修改
- 块儿级作用域
注意: 对象属性修改和数组元素变化不会出发 const 错误 应用场景:==声明对象类型使用 const,非对象类型声明选择 let==
<script>
//声明常量
const SCHOOL = 'NEFU';
//1. 一定要赋初始值
// const A;
//2. 一般常量使用大写(潜规则)
// const a = 100;
//3. 常量的值不能修改
// SCHOOL = 'NEFUER';
//4. 块儿级作用域
// {
// const PLAYER = 'UZI';
// }
// console.log(PLAYER);
//5. 对于数组和对象的元素修改, 不算做对常量的修改, 不会报错
const TEAM = ['UZI','MXLG','Ming','Letme'];
// TEAM.push('Meiko');
</script>
变量的解构赋值
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。
使用场景:频繁使用对象方法、数组元素,就可以使用解构赋值形式
数组解构使用中括号 对象解构使用大括号
例如:
//数组的解构赋值
const arr = ['zxy', 'ldh', 'lm', 'gfc'];
let [zhang, liu, li, guo] = arr;
//对象的解构赋值
const lin = {
name: 'lzy',
tags: ['cs', 'gs', '小旋风', '演员']
};
let {name, tags} = lin;
//2. 对象的解构
// const zhao = {
// name: 'zbs',
// age: '不详',
// xiaopin: function(){
// console.log("我可以演小品");
// }
// };
// let {name, age, xiaopin} = zhao;
// console.log(name);
// console.log(age);
// console.log(xiaopin);
// xiaopin();
let {xiaopin} = zhao;
xiaopin();
//复杂解构
let wangfei = {
name: 'wf',
age: 18,
songs: ['红豆', '流年', '暧昧', '传奇'],
history: [
{name: 'dw'},
{name: 'lyp'},
{name: 'xtf'}
]
};
let {songs: [one, two, three], history: [first, second, third]} =
wangfei;
模板字符串
模板字符串(template string)是增强版的字符串,用反引号(`)标识,特点:
- 字符串中可以出现换行符
- 可以使用 ${xxx} 形式输出变量
例如:
<script>
// ES6 引入新的声明字符串的方式 『``』 '' ""
//1. 声明
// let str = `我也是一个字符串哦!`;
// console.log(str, typeof str);
//2. 内容中可以直接出现换行符
let str = `<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>`;
//3. 变量拼接
let lovest = '魏翔';
let out = `${lovest}是我心目中最搞笑的演员!!`;
console.log(out);
</script>
简化对象写法
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这 样的书写更加简洁。
注意:对象简写形式简化了代码,所以以后用简写就对了
例如:
<script>
//ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。
//这样的书写更加简洁
let name = 'NEFU';
let change = function(){
console.log('我们可以改变你!!');
}
// 本来应该是
// const school = {
// name :name,
// change :change,
// improve :function(){
// console.log("我们可以提高你的技能");
// }
// }
// 现在可以简化为:
const school = {
name,
change,
improve(){
console.log("我们可以提高你的技能");
}
}
console.log(school);
</script>
箭头函数
ES6 允许使用「箭头」(=>)定义函数。 通用写法:
let fn = (arg1, arg2, arg3) => {
return arg1 + arg2 + arg3;
}
箭头函数的注意点:
- 如果形参只有一个,则小括号可以省略
- 函数体如果只有一条语句,则花括号可以省略,函数的返回值必须为该条语句的执行结果
- 箭头函数 this 指向声明时所在作用域下 this 的值(静态特性)
- 箭头函数不能作为构造函数实例化
- 不能使用 arguments
注意:箭头函数适合与 this 无关的回调. 定时器, 数组的方法回调 箭头函数不适合与 this 有关的回调. 事件回调, 对象的方法
例如:
<script>
// ES6 允许使用「箭头」(=>)定义函数。
//声明一个函数
// let fn = function(){
// }
// let fn = (a,b) => {
// return a + b;
// }
//调用函数
// let result = fn(1, 2);
// console.log(result);
//1. this 是静态的. this 始终指向函数声明时所在作用域下的 this 的值
function getName(){
console.log(this.name);
}
let getName2 = () => {
console.log(this.name);
}
//设置 window 对象的 name 属性
window.name = 'NEFU';
const school = {
name: "NF"
}
//直接调用
// getName();
// getName2();
//call 方法调用
// getName.call(school);
// getName2.call(school);
//2. 不能作为构造实例化对象
// let Person = (name, age) => {
// this.name = name;
// this.age = age;
// }
// let me = new Person('xiao',30);
// console.log(me);
//3. 不能使用 arguments 变量
// let fn = () => {
// console.log(arguments);
// }
// fn(1,2,3);
//4. 箭头函数的简写
//1) 省略小括号, 当形参有且只有一个的时候
// let add = n => {
// return n + n;
// }
// console.log(add(9));
//2) 省略花括号, 当代码体只有一条语句的时候, 此时 return 必须省略
// 而且语句的执行结果就是函数的返回值
let pow = n => n * n;
console.log(pow(8));
</script>
应用:
<body>
<div id="ad"></div>
<script>
//需求-1 点击 div 2s 后颜色变成『粉色』
//获取元素
let ad = document.getElementById('ad');
//绑定事件
ad.addEventListener("click", function(){
//原先的处理方法,得到当前作用域。
//保存 this 的值
// let _this = this;
//定时器
setTimeout(() => {
//修改背景颜色 this
// console.log(this);
// _this.style.background = 'pink';
this.style.background = 'pink';
}, 2000);
});
//需求-2 从数组中返回偶数的元素
const arr = [1,6,9,10,100,25];
// const result = arr.filter(function(item){
// if(item % 2 === 0){
// return true;
// }else{
// return false;
// }
// });
const result = arr.filter(item => item % 2 === 0);
console.log(result);
// 箭头函数适合与 this 无关的回调. 定时器, 数组的方法回调
// 箭头函数不适合与 this 有关的回调. 事件回调, 对象的方法
</script>
</body>
@[TOC]
函数参数的默认值
ES6 允许给函数参数赋值初始值 例如:
<script>
//ES6 允许给函数参数赋值初始值
//1. 形参初始值 具有默认值的参数, 一般位置要靠后(潜规则)
// function add(a,c=10,b) {
// return a + b + c;
// }
// let result = add(1,2);
// console.log(result);
//2. 与解构赋值结合
function connect({host="127.0.0.1", username,password, port}){
console.log(host)
console.log(username)
console.log(password)
console.log(port)
}
connect({
host: 'atguigu.com',
username: 'root',
password: 'root',
port: 3306
})
</script>
rest 参数
ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments 它们的区别在于:
- rest返回的是一个数组,它可以使用数组的api
- arguments返回的是一个对象
rest必须要放到形参的最后
例如:
<script>
// ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments
// ES5 获取实参的方式
// function date(){
// console.log(arguments);
// }
// date('白芷','阿娇','思慧');
// rest 参数
// function date(...args){
// console.log(args);// filter some every map
// }
// date('阿娇','柏芝','思慧');
// rest 参数必须要放到参数最后
// function fn(a,b,...args){
// console.log(a);
// console.log(b);
// console.log(args);
// }
// fn(1,2,3,4,5,6);
</script>
spread 扩展运算符
扩展运算符(spread)也是三个点(...)。它好比 rest 参数的逆运算,==将 一个数组转为用逗号分隔的参数序列==,对数组进行==解包==(rest更类似于打包)。
例如:
<script>
// 『...』 扩展运算符能将『数组』转换为逗号分隔的『参数序列』
//声明一个数组 ...
const tfboys = ['易烊千玺','王源','王俊凯'];
// => '易烊千玺','王源','王俊凯'
// 声明一个函数
function chunwan(){
console.log(arguments);
}
chunwan(...tfboys);// chunwan('易烊千玺','王源','王俊凯')
</script>
应用:
- 数组的合并
- 数组的克隆
- 伪数组转化为真正的数组
例如:
<body>
<div></div>
<div></div>
<div></div>
<script>
//1. 数组的合并 情圣 误杀 唐探
// const kuaizi = ['王太利','肖央'];
// const fenghuang = ['曾毅','玲花'];
// // const zuixuanxiaopingguo = kuaizi.concat(fenghuang);
// const zuixuanxiaopingguo = [...kuaizi, ...fenghuang];
// console.log(zuixuanxiaopingguo);
//2. 数组的克隆
// const sanzhihua = ['E','G','M'];
// const sanyecao = [...sanzhihua];// ['E','G','M']
// console.log(sanyecao);
//3. 将伪数组转为真正的数组
const divs = document.querySelectorAll('div');
const divArr = [...divs];
console.log(divArr);// arguments
</script>
</body>
Symbol
Symbol 基本使用
ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。
Symbol 特点
- Symbol 的值是唯一的,用来解决命名冲突的问题
- Symbol 值不能与其他数据进行运算
- Symbol 定义 的 对象属 性 不能 使 用 for…in 循 环遍 历 ,但 是可 以 使 用Reflect.ownKeys 来获取对象的所有键名
此处可参考js权威指南,讲得非常的详细
注: 遇到唯一性的场景时要想到 Symbol,对一个对象进行改造的时候用symbol不会造成冲突,高效且安全!
例如:
<script>
//创建Symbol
let s = Symbol();
// console.log(s, typeof s);
let s2 = Symbol('NEFU');
let s3 = Symbol('NEFU');
//Symbol.for 创建
//这里s4和s5是严格相等的
let s4 = Symbol.for('NEFU');
let s5 = Symbol.for('NEFU');
//不能与其他数据进行运算
// let result = s + 100;
// let result = s > 100;
// let result = s + s;
//
// USONB you are so niubility
// u undefined
// s string symbol
// o object
// n null number
// b boolean
</script>
截止目前的其中数据类型总结: USONB -- you are so niubility u: undefined s: string symbol o: object n: null number b: boolean
应用:用symbol创造对象属性
<script>
//向对象中添加方法 up down
let game = {
name:'俄罗斯方块',
up: function(){},
down: function(){}
};
//声明一个对象
// let methods = {
// up: Symbol(),
// down: Symbol()
// };
// game[methods.up] = function(){
// console.log("我可以改变形状");
// }
// game[methods.down] = function(){
// console.log("我可以快速下降!!");
// }
// console.log(game);
//
let youxi = {
name:"狼人杀",
[Symbol('say')]: function(){
console.log("我可以发言")
},
[Symbol('zibao')]: function(){
console.log('我可以自爆');
}
}
console.log(youxi)
</script>
因为Symbol()是一个动态的值,故不能直接作为属性名,所以此处要加一个中括号括起来。
Symbol的内置属性
除了定义自己使用的 Symbol 值以外,ES6 还提供了 11 个内置的 Symbol 值,指向语言内部使用的方法。可以称这些方法为魔术方法,因为它们会在特定的场景下自动执行。
==它的作用就是改变对象在特定场景下的表现,从而达到拓展对象功能的作用!==
- Symbol.hasInstance:当其他对象使用 instanceof 运算符,判断是否为该对象的实例时,会调用这个方法
- Symbol.isConcatSpreadable:对象的 Symbol.isConcatSpreadable 属性等于的是一个布尔值,表示该对象用于 Array.prototype.concat()时,是否可以展开。
- Symbol.species:创建衍生对象时,会使用该属性
- Symbol.match :当执行 str.match(myObject) 时,如果该属性存在,会调用它,返回该方法的返回值。
- Symbol.replace:当该对象被 str.replace(myObject)方法调用时,会返回该方法的返回值。
- Symbol.search :当该对象被 str.search (myObject)方法调用时,会返回该方法的返回值。
- Symbol.split:当该对象被 str.split(myObject)方法调用时,会返回该方法的返回值。
- Symbol.iterator:对象进行 for...of 循环时,会调用 Symbol.iterator 方法,返回该对象的默认遍历器
- Symbol.toPrimitive :该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。
- Symbol. toStringTag:在该对象上面调用 toString 方法时,返回该方法的返回值
- Symbol. unscopables:该对象指定了使用 with 关键字时,哪些属性会被with环境排除。
例如:
<script>
// class Person{
// static [Symbol.hasInstance](param){
// console.log(param);
// console.log("我被用来检测类型了");
// return false;
// }
// }
// let o = {};
// console.log(o instanceof Person);
// const arr = [1,2,3];
// const arr2 = [4,5,6];
// arr2[Symbol.isConcatSpreadable] = false;
// console.log(arr.concat(arr2));
</script>
迭代器
遍历器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提 供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。
- ES6 创造了一种新的遍历命令 for...of 循环,Iterator 接口主要供 for...of 消费
- 原生具备 iterator 接口的数据(可用 for of 遍历)
a) Array b) Arguments c) Set d) Map e) String f) TypedArray g) NodeList
- 工作原理 a) 创建一个指针对象,指向当前数据结构的起始位置 b) 第一次调用对象的 next 方法(这个方法放在对象的Symbol.iterator属性中),指针自动指向数据结构的第一个成员 c) 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员 d) 每调用 next 方法返回一个包含 value 和 done 属性的对象
注: 需要自定义遍历数据的时候,要想到迭代器。
例如:
<body>
<script>
//声明一个对象
const banji = {
name: "终极一班",
stus: [
'xiaoming',
'xiaoning',
'xiaotian',
'knight'
],
[Symbol.iterator]() {
//索引变量
let index = 0;
//因为放在了return中调用者不再是banji,则在return外取得。
let _this = this;
//Symbol.iterator:对象进行 for...of 循环时,会调用 Symbol.iterator 方法,返回该对象的默认遍历器
//返回的是迭代器(遍历器)
return {
next: function () {
if (index < _this.stus.length) {
const result = { value: _this.stus[index], done: false };
//下标自增
index++;
//返回结果
return result;
}else{
return {value: undefined, done: true};
}
}
};
}
}
//遍历这个对象
for (let v of banji) {
console.log(v);
}
</script>
</body>