一、let
1、变量声明
let a;
let b,c,d
let f = 521, g = 'iloveyou', h = []
2、注意事项
块儿级作用域 全局,函数,eval
{
大括号里面就是块儿级作用域
}
比如if else while for
{
let girl = '张翼飞'
}
console.log('girl')
//输出结果为undefind,若用var的话则会输出’张翼飞‘
不存在变量提升
console.log(song)
let song = '恋爱达人'
不影响作用域链
{
let a = 'zyf'
{
console.log(a)
}
}
//输出结果为'zyf'
第2点和第4点看起来有点冲突,其实不然,因为,第2点是外面调里面的,第4点是里面调用外面的
3、练习
<body>
<div class="wrap">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<script>
const btn = document.getElementsByClassName('item')
console.log(btn);
for(var i = 0;i<btn.length;i++){
btn[i].onclick=function(){
btn[i].style.background = 'blue'
}
}
</script>
</body>
结果:
这是因为
{
var i = 0
btn[i].onclick=function(){
btn[i].style.background = 'blue'
}
}
{
var i = 1
…
}
{
var i = 2
…
}
{
var i = 3
}
先执行循环,循环三次,开辟三个作用域
再次点击时i = 3,三个作用域的i都为3,而btn[3]为undefind,所以此时没反应
而如果将var改为let
{
let i = 0
btn[i].onclick=function(){
btn[i].style.background = 'blue'
}
}
{
let i = 1
…
}
{
let i = 2
…
}
{
let i = 3
…
}
他们的作用域是不会互相影响的,所以点击每一个块级元素都会进行背景颜色渲染
二、const
对于数组和对象的元素修改,不算作对常量的修改,不会报错
const Team = ['zyf','ls'];
Team.push('pp')
这个不会报错,因为它的地址没有发生改变
三、对象的简化写法
// ES6允许在大括号里面,直接写入变量和函数,作为对象的属性和方法
// 这样的书写更加简洁
let name = '尚硅谷';
let change = function(){
console.log('我爱你');
}
const school = {
name,
change,
improve(){
console.log('你好');
}
}
console.log(school);
输出结果为:
四、箭头函数
1、this始终指向函数声明所在作用域的this的值,就是比如
const a = ()=>{
console.log(this.name)
}
window.name = 'shangguigu';
a()
输出的值是'shangguigu',这是因为a是定义在window的作用域里的
2、this是静态的
function getName(){
console.log(this.name);
}
const getName2=()=>{
console.log(this,name);
}
window.name = '尚硅谷';
const school = {
name:'张翼飞'
}
getName.call(school); // 输出结果为张翼飞
getName2.call(school);//输出结果为尚硅谷
箭头函数里面this指向的值一旦固定,就无法改变
3、案例
<div id="ad"></div>
<script>
let ad = document.getElementById('ad');
ad.addEventListener("click",function(){
setTimeout(function(){
console.log(this);
this.style.background = 'pink'
},2000)
})
</script>
// 输出的是window,且点击块级元素没反应
<script>
let ad = document.getElementById('ad');
ad.addEventListener("click",()=>{
setTimeout(()=>{
console.log(this);
this.style.background = 'pink'
},2000)
})
</script>
// 输出的是div节点,且点击块级元素会改变背景颜色
五、函数参数
1、函数参数的默认值
//ES6允许给函数参数赋值初始值
//1、形参初始值 具有默认值的参数,一般位置要靠后(潜规则)
function add(a, b, c = 10){
return a + b + c;
}
let result = add(1, 2);
console.log(result); //输出13
function connection({name='zyf',age,sex}){
console.log(name); //zyf
console.log(age); //20
console.log(sex); //男
}
connection({age:20,sex:'男'})
</script>
2、rest参数
function fn(...args){
console.log(args); //一个长度为5的数组
}
fn(1,2,2,3,4)
//rest参数必须要写到最后面,rest参数不写到后面会报错
六、Symbol
1、Symbol的声明定义
Symbol相当于唯一表示标识,即使里面的值相同,进行对比,也会返回false
let hd = Symbol('zyf');
let edu = Symbol('zyf');
console.log(hd = edu);
//输出false
打印Symbol里面的值
let cms = Symbol('hdcms');
console.log(cms.description);
//输出结果为:hdcms
Symbol的for用法
let cms = Symbol.for('hdcms');
let zyf = Symbol.for('hdcms');
consloe.log(cms===zyf);
//输出true
console.log(Symbol.keyFor(cms))
//输出结果为:hdcms
这是因为Symbol.for有缓存,所以当zyf的定义和cms一样时,用的是cms的值
2、Symbol的应用场景
let user1 = {
name:'李四',
}
let user2 = {
name:'李四',
}
let grade = {
[user1.name]:{js: 100, css: 89},
[user2.name]:{js: 55, css: 55}
}
console.log(grade[user1.key]);
//输出结果为:{js: 100, css: 89}
console.log(grade[user2.key]);
//输出结果为:{js: 55, css: 55}
不用Symbol打印的都是一样的值
let user1 = {
name:'李四',
key:Symbol()
}
let user2 = {
name:'李四',
key:Symbol()
}
let grade = {
[user1.name]:{js: 100, css: 89},
[user2.name]:{js: 55, css: 55}
}
console.log(grade[user1.name]);
//输出结果为:{js: 100, css: 89}
console.log(grade[user2.name]);
//输出结果为:{js: 55, css: 55}
打印出了理想的结果
Symbol在缓存容器中的使用
class Person{
static data = {};
static set(name, value){
this.data[name] = value
}
static get(name){
return this.data[name]
}
}
let user1 = {
name: 'zyf',
operate: '吃饭',
key: Symbol()
}
let user2 = {
name: 'zyf',
operate: '洗澡',
key: Symbol()
}
Person.set(user1.key,user1)
Person.set(user2.key,user2)
console.log(Person.get(user1.key));
//输出结果为:{ name: 'zyf',operate: '吃饭',key: Symbol()}
console.log(Person.get(user2.key));
//输出结果为:{ name: 'zyf',operate: '洗澡',key: Symbol()}
3、Symbol对象属性保护
const obj = {
name: 'zyf',
[Symbol('name')]:'ls'
}
for(const key of Reflect.ownKeys(obj)){
//一般方法无法获取到obj的"[Symbol('name')]",所以可以用Reflect.ownKeys(obj)这种方法
console.log(key);
}
七、迭代器
八、生成器
1、生成器函数声明与调用(*符号)
function * gen(){
console.log(111);
yield '一只没有耳朵';
console.log(222);
yield '一只没有尾巴';
console.log(333);
yield '真奇怪';
console.log(444);
}
let iterator = gen();
iterator.next(); //输出111
iterator.next(); //输出222
iterator.next(); //输出333
iterator.next(); //输出444
所以此时想要进行四个部分空间内容的打印的话,可以用里面的next()–相当于指针
生成器遍历
function * gen(){
yield '一只没有耳朵';
yield '一只没有尾巴';
yield '真奇怪';
}
let iterator = gen();
for(let v of gen()){
console.log(v);
}
九、集合
1、集合介绍与API
let s = new Set();
let s2 = new Set(['zyf','zyf','ls','pp'])
console.log(s2) //{'zyf','ls','pp'},会进行去重的操作
s2.size //元素个数
s2.add('lz') //添加新的元素
s2.delete('zyf')//删除元素
s2.has('糟心事') //检测
s2.clear() //清空
2、示例
const arr1 = [1,1,2,2,3,4];
const arr2 = [1,2,6,6,7,8];
//数组去重
console.log([...new Set(arr1)]); //[1, 2, 3, 4]
//交集
console.log([...new Set(arr1)].filter((item)=> new Set(arr2).has(item))) //[1, 2]
//并集
console.log([...new Set([...arr1,...arr2])]) //[1, 2, 3, 4, 6, 7, 8]
//差集
console.log([...new Set(arr1)].filter((item)=> !new Set(arr2).has(item))) //[3, 4]
//Number.parseInt Number.parseFloat字符串转数组
console.log(Number.parseInt('5211569你好')); //5211569
console.log(Number.parseFloat('3.14569你好11')); //3.14569
//Number.isInteger 判断一个数是否为整数
console.log(Number.isInteger(5)); //true
console.log(Number.isInteger(2.5)); //false
//Math.trunc将数字的效数部分抹掉
console.log(Math.trunc(3.5)); //3
//Math.sign判断一个数列到底为整数 负数 还是零
console.log(Math.sign(100)); //1
console.log(Math.sign(0)); //0
console.log(Math.sign(-20000)); //-1
//对象合并
const obj1 = {
name:'zyf',
age:18
}
const obj2 = {
name:'ls',
sex:'male'
}
console.log(Object.assign(obj1,obj2)) //{name:'ls', age:18, sex:'male'}
await是拿到resolve和reject里面的值的
const p = new Promise((resolve, reject)=>{
resolve('111111')
})
//await要与async配合使用,async里面没有await可以,但是使用await时,必须要在async函数里面使用
async function main(){
try{
const result = await p;
console.log(result); //当p函数里面为resolve时,这里进行输出
}catch(e){
lconsole.log(e) //当p函数里面为reject时,这里进行输出
}
}
const fs = require('fs');
const fn = (urlLoad)=>new Promise((resolve,reject)=>{
fs.readFile(urlLoad,(err,data)=>{
if(err) reject(err);
resolve(data)
})
})
async function asy (){
const fn3 = await fn('./1.md')
const fn4 = await fn('./2.md')
console.log(fn3.toString());
console.log(fn4.toString());
}
asy() //分别输出1.md,2.md的内容
Promise永远的神
let b = 1;
function fn(){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve((()=>{return '11111'})())
},2000)
})
}
async function main(){
b = await fn();
//输出'11111',会先执行完fn里面的resolve,reject函数,再执行先的console.log(b)语 句
console.log(b);
}
main()
let b = 1;
function fn(){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
b = 2
},2000)
resolve(6666666)
})
};
async function main(){
b = await fn();
console.log(b); //输出6666666,并且会立马执行,不会等待2秒钟,拿到resolve的值就会立马执行吓一条语句
}
main()
const school = {
name:'尚硅谷',
cities:['北京','上海','深圳'],
xueke:['前端','java','大数据','运维']
}
//对象属性的描述对象
console.log(Object.keys(school));
//获取对象所有的值
console.log(Object.values(school));
//entries
console.log(Object.entries(school));
打印结果为
//将二维数组转为对象
const result1 = [['name','zyf'],['sex','male']];
console.log(Object.fromEntries(result1)); //{name: 'zyf', sex: 'male'}
const m = new Map();
m.set('name','ls');
console.log(Object.fromEntries(m)); //{name: 'ls'}
trimStart和trimEnd分别清楚字符串左边和右边的空白字符串
//数组方法扩展flat,flat后面括号里的值默认为1
const arr1 = [1,2,3,[4,5]];
console.log(arr1.flat()); //[1, 2, 3, 4, 5]
const arr2 = [1,2,[3,4,[5,6]]]
console.log(arr2.flat(2)); //[1, 2, 3, 4, 5, 6]
初版订阅与发布
<script>
const shopObj = {}
shopObj.list = []
shopObj.listen = function(fn){
shopObj.list.push(fn)
}
shopObj.trigger = function(){
let fn
for(let i = 0;fn = this.list[i];i++){
fn(...arguments)
}
}
shopObj.listen(function(color,size){
console.log(`颜色是${color}`);
console.log(`尺寸是${size}`);
})
shopObj.listen(function(color,size){
console.log(`再次颜色是${color}`);
console.log(`再次尺寸是${size}`);
})
shopObj.trigger('red',42)
shopObj.trigger('black',40)
</script>
foreach是干事用的(执行业务逻辑),map是返回数组拿数据的
十、一些常用的方法
1、数组扁平化
const deps = {
'采购部':[1,2,3],
'人事部':[5,8,12],
'行政部':[5,14,79],
'运输部':[3,64,105],
}
// 原本写法:
let member = [];
for (let item in deps){
const value = deps[item];
if(Array.isArray(value)){
member = [...member,...value]
} }
member = [...new Set(member)]
// 现如今写法
let member = Object.values(deps).flat(Infinity);
// 其中使用`Infinity`作为`flat`的参数,使得无需知道被扁平化的数组的维度。
2、关于输入框非空的判断
// 原本写法
if(value !== null && value !== undefined && value !== ''){
//...
}
//现如今写法
if((value??'') !== ''){
//...
}
3、列表搜索
列表搜索尽量用find,少用filter