当前位置: 首页 > news >正文

es6特性-第一部分

let

let关键字主要用来进行变量的声明。有以下注意的点:

  • 变量名不能重复声明,防止变量被污染。var关键字可以

    let star ='罗志祥';
    let star ='小猪'; //执行后报错
    
  • let声明的变量只能在块级作用域(if、函数、for…)内有效。但不影响作用域链。

    {let girl = "周扬青';
    }
    console.log(girl); //报错{let school ='尚硅谷';function fn(){console.log(school);}fn();//这块不会报任何错误
    }
    
  • 不存在变量提升。必须使用let先声明变量,然后在使用。

    console.log(song);
    let song ="恋爱达人'; //报错
    

以后声明变量都使用let关键字。

const

const使用这个关键字用来声明常量。有以下注意事项:

  • const声明的常量声明时必须赋值,否则报错。

  • const声明的常量的值不能修改。

  • 一般常量名使用大写(潜规则)

  • 块儿级作用域

  • 对于数组和对象的元素修改,不算做对常量的修改,不会报错。

    因为数组和对象的修改是对数组元素或者对象属性做修改,而数组和对象本身的地址不会发生变化。

//声明常量
const SCHOOL =‘尚硅谷';
const A; //报错:常量声明时必须赋值
const a = 100; //一般常量名大写
SCHOOL = 'ATGUIGU '; //报错:常量的值不能修改
{const PLAYER =UZI';
}
console.log(PLAYER); //报错:块儿级作用域const TEAM = ['UZI','MXLG','Ming','Letme'];
TEAM.push('Meiko');//正常

变量的解构赋值

ES6允许按照一定模式从数组和对象中提取值,对变量进行赋值,这种的被称为解构赋值。

//数组解构赋值
const F4 = ['宋小宝', '小沈阳', '刘能', '赵四'];
let [song, xiao, liu, zhao] = F4; //注意:数组要对应的中括号
console.log(song);
console.log(xiao);
console.log(liu);
console.log(zhao);
//对象解构赋值
let wukong = {name: "悟空",age: 18,jineng: function () {console.log('72变');}
}
let { name, age, jineng } = wukong;  //注意:对象要对应的大括号
console.log(name);
console.log(age);
console.log(jineng);
jineng();

模板字符串

之前字符串的声明方式是单引号’'或者双引号""。ES6引入新的声明字符串的方式``(反引号)

//1.声明
let str =`我也是一个字符串哦!`;
console.log(str, typeof str);
//2.内容中可以直接出现换行符.单引号和双引号不允许。
let str = `<ul><li>沈腾</li><li>玛丽</li><li>魏翔</li><li>艾伦</li></ul>`;
//3.变量拼接
let lovest = '沈腾';
let out = `${lovest}是我心目中最搞笑的演员!`; //注意这里必须是$(变量名)这种格式。
console.log(out);

简化对象写法

ES6允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。

let name ="尚硅谷';
let change = function(){console.log('我们可以改变你!!");
}
//完整写法
const school = { name:name,change:change,improve:function(){console.log("我们可以提高你的技能");}
}
//es6中简化写法                
const school = { name,change,improve(){console.log("我们可以提高你的技能");}
}
//如果对象中的值对应的是字符串,而不是变量,那必须使用完整写法
const student = { name:"light", //这里如果不加引号,就会找light变量age:18,
}

箭头函数

ES6 允许使用=>定义函数。省略function关键字。

//声明一个函数
let fn = () => {//...
}
let fn1 = (a, b) => {return a + b;
}
console.log(fn1(1, 2));
箭头函数注意事项
  • this是静态的,this始终指向函数声明时所在作用域下的 this的值。即使使用call方法调用。

    function getName(){console.log(this.name);
    }
    let getName2 = ()=>{console.1og(this.name);
    }
    window.name ='尚硅谷';
    const school = {name:"ATGUIGU"
    }
    //直接调用
    getName(); //尚硅谷
    getName2();//尚硅谷
    //call方法调用
    getName.call(school); //ATGUIGU
    getName2.call(school);//尚硅谷 this对象始终指向window对象
    
  • 不能作为构造实例化对象,否则会报错

  • 不能使用arguments 变量,否则会报错

箭头函数简写
  • 当形参有且只有一个的时候,可以省略小括号。

    let add = n => {return n + n;
    }
    console.log(add(9)); //18
    
  • 当代码体只有一条语句的时候,此时花括号和return必须省略而且语句的执行结果就是函数的返回值。

    let pow = n => n*n;
    console.log(pow(8));
    
总结

箭头函数适合与this 无关的回调。比如:定时器,数组的方法回调等。

箭头函数不适合与this有关的回调。比如:事件回调,对象的方法等。

函数参数的默认值

ES6允许给函数参数赋值初始值。

  • 形参初始值具有默认值的参数,一般位置要靠后(潜规则)。

  • 函数参数赋值初始值可以与解构赋值结合使用

    //函数参数解构赋值
    function connect({ host, username, passwd, other = 'no' }) {console.log(host, username, passwd, other); //baidu.com root 123456 no
    }
    connect({host: 'baidu.com',username: 'root',passwd: '123456'
    });
    

rest参数

ES6引入rest参数,用于获取函数的实参,用来代替arguments。

//ES5获取实参的方式
function date(){console.log(arguments); //打印出来是个对象
}
date('白芷','阿娇','思慧');
//rest参数
function date(...args){console.log(args); //打印出来是个数组
}
date('阿娇',"柏芝",'思慧");

rest参数是将参数以数组的方式存储,然后传入函数中。这样我们就可以通过数组api对rest参数进行处理。

注意:如果函数中有多个形参,rest参数必须放在最后,否则会报错。

function at(a, b, c, ...args) {console.log(a, b, c, args);
}
at(1, 2, 3, 4, 5, 6, 7, 8); //1 2 3 [4, 5, 6, 7, 8]

扩展运算符

...扩展运算符能将『数组』转换为逗号分隔的『参数序列

const tfboys = ['王俊凯', '易烊千玺', '王源'];
function chunwan() {console.log(arguments);
}
chunwan(tfboys); //对象
chunwan(...tfboys); //直接取数组
扩展运算符应用
  1. 数组的合并
const kuaizi = ['王太利', '肖央'];
const fhcq = ['玲花', '曾毅'];
//es5
var zuixuanxiaopingguo = kuaizi.concat(fhcq);
console.log(zuixuanxiaopingguo);// ['王太利', '肖央', '玲花', '曾毅']
//扩展运算符
//原理: 1.扩展运算符先把数组转化成逗号分隔的参数序列
//       ...kuaizi => '王太利', '肖央'  ...fhcq => '玲花', '曾毅' 
// 2.组合数组
// zuixuanxiaopingguo = [...kuaizi, ...fhcq] => ['王太利', '肖央', '玲花', '曾毅']
zuixuanxiaopingguo = [...kuaizi, ...fhcq];
console.log(zuixuanxiaopingguo);// ['王太利', '肖央', '玲花', '曾毅']
  1. 数组克隆
const sanzhihua = ['E', 'G', 'M'];
const sanyecao = [...sanzhihua];
console.log(zuixuanxiaopingguo);//['E', 'G', 'M']
  1. 将伪数组转为真正的数组
const divs = document.querySelectorAll('div');
console.log(divs); //对象
const divArr = [...divs];
console.log(divArr); //转化为数组

Symbol

ES6引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是JavaScript语言的第七种数据类型,是一种类似于字符串的数据类型。Symbol的初衷:解决对象的属性名冲突

Symbol的创建
//创建Symbol
let s = Symbol();
console.log(s, typeof s); //Symbol() "symbol"
let s2 = Symbol("张三"); //这块构造函数里面的字符串只是对Symbol数据的描述
let s3 = Symbol("张三");
//symbol.for创建
let s4 = Symbol.for("张三");
let s5 = Symbol.for("张三');

Symbol值通过Symbol函数生成。这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的Symbol类型。凡是属性名属于Symbol类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。

Symbol特点
  1. Symbol 的值是唯一的(es内部实现唯一性),用来解决命名冲突的问题。

  2. Symbol值不能与其他数据进行运算

  3. Symbol定义的对象属性不能使用for...in循环遍历,但是可以使Reflect.ownKeys来获取对象的所有键名

Symbol的使用场景

在企业开发中如果需要对一些第三方的插件、框架进行自定义的时候可能会因为添加了同名的属性或者方法, 将框架中原有的属性或者方法覆盖掉为了避免这种情况的发生, 框架的作者或者我们就可以使用Symbol作为属性或者方法的名称。

//第一种添加方法
let bird = {name: '麻雀',fly: function () {console.log('我要飞得很高!')},eat: function () {console.log('该吃饭了!')}}
//给对象添加扩展的属性或者方法
let addMethod = {fly: Symbol(),eat: Symbol()
}
bird[addMethod.fly] = function () {console.log('请不要飞得太高');
}
bird[addMethod.eat] = function () {console.log('请不要吃的太饱');
}
//调用
bird.eat();
bird.fly();
bird[addMethod.eat]();
bird[addMethod.fly]();
//第二种添加方法
let youxi = {name: "狼人杀",[22]: function () {console.log('sfsdfsdaf');},[Symbol('say')]: function () { //相当于私有方法,不得被调用console.log("我可以发言");},[Symbol('zibao')]: function () { //相当于私有方法,不得被调用console.log("我可以自爆");}
}
console.log(youxi);
Symbol的内置值

除了定义自己使用的 Symbol值以外,ES6还提供了11个内置的Symbol值,指向语言内部使用的方法。

其实这些值都是使用Symbol的属性,而这些Symbol的属性可以作为对象的属性来使用。
在这里插入图片描述

class Person {static [Symbol.hasInstance](param) {console.log(param);console.log('我被调用了');return false;}
}
let swk = {name: '孙悟空',
}
console.log(swk instanceof Person);

迭代器

迭代器(lterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署lterator接口,就可以完成遍历操作。

  1. ES6创造了一种新的遍历命令for...of循环,lterator接口(这里的lterator接口,其实是指对象里面的一个属性,例如:Symbol(Symbol.iterator),只要有这个属性,就可以使用for...of消费)主要供 for...of消费。
   const xiyou = ['孙悟空', '猪八戒', '唐僧', '沙僧'];for (const item of xiyou) {console.log(item);}
  1. 原生具备iterator接口的数据(可用for of遍历)

    Array、Arguments、Set、Map、String、TypedArray、NodeList。这些数据都具有Symbol(Symbol.iterator)属性

工作原理
  • 创建一个指针对象,指向当前数据结构的起始位置

    let iterator = xiyou[Symbol.iterator]();

  • 第一次调用对象的next方法,指针自动指向数据结构的第一个成员

    console.log(iterator.next()); //{value: '孙悟空', done: false}
    console.log(iterator.next()); //{value: '猪八戒', done: false}
    ...
    
  • 接下来不断调用next方法,指针一直往后移动,值到指向最后一个成员

    console.log(iterator.next()); //{value: '沙僧', done: false}
    
  • 每调用next 方法返回一个包含value和 done属性的对象

    {value: '沙僧', done: false}

迭代器主要用来自定义遍历对象

//自定义遍历对象
const ig = {name: 'ig',staff: ['theshy', 'ming', 'rookie', 'jacklove', 'ming'],[Symbol.iterator]() {let index = 0;let _this = this;return {next: function () {if (index < _this.staff.length) {index++;return { value: _this.staff[index], done: false };} else {return { value: undefined, done: true }}}};}
};
for (let v of ig) {console.log(v);
}

生成器

生成器函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同。

我们之前的异步编程是纯回调函数:nodefs、 ajax、mongodb

生成器函数声明时,需要在function 和函数名之间需要加 * yield表示程序执行到这里会交出执行权,等待结果返回。它需要在协程Generator 函数中运行。

function * gen(){yield 'xxxx';//...yield 'xxxx';
}

当执行gen()的时候,并不执行 generator 函数体,而是返回一个迭代器。迭代器具有next()方法,每次调用 next() 方法,函数就执行到yield语句的地方。next() 方法返回一个对象,其中value属性表示 yield 关键词后面表达式的值,done 属性表示是否遍历结束。generator 生成器通过nextyield的配合实现流程控制。

function* gen() {console.log(111);yield '一只没有耳朵';console.log(222);yield '一只没有尾部';console.log(333);yield '真奇怪';console.log(444);
}
let iterator = gen();
console.log(iterator.next()); //111 {value: '一只没有耳朵', done: false}
console.log(iterator.next()); //222 {value: '一只没有耳朵', done: false}
console.log(iterator.next()); //333 {value: '一只没有耳朵', done: false}
console.log(iterator.next()); //444 {value: undefined, done: true}for (const item of gen()) {console.log(item); //每次输出返回的{value: '一只没有耳朵', done: false}对象的value值并且执行yield之上的代码
}
生成器参数
function* gen1(arg) {console.log(arg);let one = yield 111;console.log(one);let two = yield 222;console.log(two);let three = yield 333;console.log(three);
}
//执行获取迭代器对象
let itor = gen1('AAA');
console.log(itor.next());//AAA {value: 111, done: false}
// next方法可以传入实参
console.log(itor.next("BBB"));//BBB {value: 222, done: false}
console.log(itor.next("CCC"));//CCC {value: 333, done: false}
console.log(itor.next("DDD"));//DDD {value: undefined, done: true}

第一次执行next函数时,可以根据生成器函数的参数接受数据。以后每次执行next所传递的参数,在函数体中都由yield语句执行。例如第二次next传递的参数由函数体中第一个yield语句执行完毕后返回,第三次次next传递的参数由函数体中第二个yield语句执行完毕后返回,…

生成器实例

要求:1s后控制台输出111, 2s后输出222,3s后输出333

我们一般的做法:

setTimeout(() => {console.log('111');setTimeout(() => {console.log('222');setTimeout(() => {console.log('333');}, 3000);}, 2000);
}, 1000);

上面的编写方式如果需要多个回调,显然这种写法肥肠臃肿,这种无尽的回调方式称之为回调地狱。

可以通过生成器函数方式规避这种写法:

function one() {setTimeout(() => {console.log('111');iterator.next();}, 1000)
}
function two() {setTimeout(() => {console.log('222');iterator.next();}, 2000)
}
function three() {setTimeout(() => {console.log('333');iterator.next();}, 3000)
}
function* gen() {yield one();yield two();yield three();
}
let iterator = gen();
iterator.next();

要求:先获取用户数据,在获取用户订单数据,然后获取商品数据。

function getUserData() {setTimeout(() => {let data = "用户数据";itor.next(data);}, 1000);
}
function getOrderData() {setTimeout(() => {let data = "订单数据";itor.next(data);}, 1000);
}
function getGoodsData() {setTimeout(() => {let data = "商品数据";itor.next(data);}, 1000);
}
function* gen1() {let user = yield getUserData();console.log(user);let order = yield getOrderData();console.log(order);let goods = yield getGoodsData();console.log(goods);
}
let itor = gen1();
itor.next();
http://www.lryc.cn/news/576999.html

相关文章:

  • Tomcat 安装使用教程
  • mybatis-plus从入门到入土(一):快速开始
  • 云端可视化耦合电磁场:麦克斯韦方程组的应用-AI云计算数值分析和代码验证
  • Spring Cloud:服务监控与追踪的高级实践
  • 为什么要安装create-vue@3.17.0
  • 2025年渗透测试面试题总结-2025年HW(护网面试) 20(题目+回答)
  • 通过交互式可视化探索波动方程-AI云计算数值分析和代码验证
  • redisson看门狗实现原理
  • ai数据分析黄金
  • RuoYi-Vue学习环境搭建
  • Vue 与react 生命周期对比
  • WSL连不上网解决方案(包含WSL虚拟交换机不正常以及WSL网络配置不正常两种解决方案)
  • wpf的Binding之UpdateSourceTrigger
  • 【惯性导航知识杂记7】舒拉 (休拉、舒勒)周期、傅科周期、地球周期
  • Boss:技能选取——随机概率
  • 【51单片机按下按键1,8位共阴极数码管输出2022-606。按下按键2,8位共阴极数码管输出606-1132。】2022-6-10
  • 现代C++ 文件系统库
  • Spring生态创新应用
  • 学习React官方文档(描述UI)
  • 【机器学习实战笔记 13】集成学习:GBDT算法
  • (七)集成学习
  • stm32hal模块驱动(1)hpdl1414驱动
  • 机器学习7——神经网络上
  • 家谱族谱生成制作小工具PC/H5小程序开源
  • 【系统分析师】高分论文:论软件过程改进
  • UR Studio仿真工具上线助力协作机器人快速部署与精准配置模拟
  • Python 数据分析与可视化 Day 11 - 特征工程基础
  • 【GESP 四级】一个程序掌握大部分知识点
  • 【算法设计与分析】(三)二分搜索技术与大整数乘法
  • 信创背景下应用软件迁移解析:从政策解读到落地实践方案