当前位置: 首页 > 工具软件 > esnext > 使用案例 >

ES6/ESNext规范学习笔记

柯星辰
2023-12-01

课程名称   ES6/ESNext规范

ES6/ESNext 规范详解
ES6/ESNext 规范详解

课程目标  

1.简单了解ECMAScript规范发展及历史 (每年6月发一版)

2.ES6及以后新增的常⽤API解析

3.简单了解一下Babel.js,写一个插件

课程要点

1.let const

for(var i=0;i<=3;i++){
setTimeout(function() {
 console.log(i)
}, 10);
}

//分别会输出什么? 为什么? 如何修改可以使其输出0,1,2,3?

for(var i = 0; i <=3; i++) { (function (i) {
setTimeout(function () {
 console.log(i);
}, 10);
})(i);
}
for(let i=0;i<=3;i++){
setTimeout(function() {
 console.log(i)
}, 10);
}

主要原因 setTimeout是异步, 在下⼀轮事件循环时,i变成4 

重点 let引⼊了块级作⽤域的概念, 创建setTimeout函数时,变量i在作⽤域内。对于循环的每个迭代,引⽤的ii的不同实例。(相当于执行4次宏任务)

2.箭头函数

最⼤的区别:箭头函数⾥的 this 是定义的时候决定的 , 普通函数⾥的 this 是使⽤的时候决定的。

(定义的时候一般是指向window)注意, 箭头函数不能被⽤作构造函数

构造函数会⼲嘛? 改变this指向到新实例出来的对象. 箭头函数会⼲嘛?this指向是定义的时候决定的.

4.模板字符串

重点是~~反斜线,变量用${}

// 编写render函数, 实现template render功能.

const year = '2021';
const month = '10';
const day = '01';
let template = '${year}-${month}-${day}';
let context = { year, month, day };
const str = render(template)({year,month,day}); //重点两个括号是高阶函数
console.log(str) // 2021-10-01
function render(template) {
return function(context) {
return template.replace(/\$\{(.*?)\}/g, (match, key) => context[key]);
} }

正则replace的中间那(.*?)是相当于match 匹配的值 key 所以匹配的是year /month/day

5.数组的解构 (数组是按顺序,对象是按属性名)

// 基础类型解构
let [a, b, c] = [1, 2, 3]
console.log(a, b, c) // 1, 2, 3
// 对象数组解构
let [a, b, c] = [{name: '1'}, {name: '2'}, {name: '3'}]
console.log(a, b, c) // {name: '1'}, {name: '2'}, {name: '3'}
// ...解构
let [head, ...tail] = [1, 2, 3, 4]
console.log(head, tail) // 1, [2, 3, 4]

// 嵌套解构
let [a, [b], d] = [1, [2, 3], 4]
console.log(a, b, d) // 1, 2, 4
// 解构不成功为undefined
let [a, b, c] = [1]
console.log(a, b, c) // 1, undefined, undefined
// 解构默认赋值
let [a = 1, b = 2] = [3]
console.log(a, b) // 3, 2


// 对象属性解构
let { f1, f2 } = { f1: 'test1', f2: 'test2' }
console.log(f1, f2) // test1, test2
// 可以不按照顺序,这是数组解构和对象解构的区别之⼀
let { f2, f1 } = { f1: 'test1', f2: 'test2' }
console.log(f1, f2) // test1, test2
// 解构对象重命名
let { f1: rename, f2 } = { f1: 'test1', f2: 'test2' }
console.log(rename, f2) // test1, test2
// 嵌套解构
let { f1: {f11}} = { f1: { f11: 'test11', f12: 'test12' } }
console.log(f11) // test11
// 默认值
let { f1 = 'test1', f2: rename = 'test2' } = { f1: 'current1', f2: 'current2'}
console.log(f1, rename) // current1, current2

重点是:结构的原理 (针对可迭代对象的Iterator接⼝,通过遍历器按顺序获取对应的值进⾏赋值.

6.关于class 类 

(实例属性就是new后接受值的实例,可调用的是constructor()中的方法和属性 class本身即Test可使用static中的属性,等同于test.xxx和test.prototype.xxx)

class Test {
 _name = '';
constructor() {
this.name = 'lubai'; }
static getFormatName() {
return `${this.name} - xixi`; }
get name() {
return this._name; }
set name(val) {
 console.log('name setter');
this._name = val; } }
console.log(new Test().name)
console.log(Test.getFormatName())
 

属性大都放在constructor中 因为它是基本类型,而function 大都放在外面因为是引用类型,new的时候引用同一个地址的方法就行,不需要重复创建

class Person {
    constructor(name,sex){  //写在这里new的时候会多次生成浪费内存
        this.name = name;  //this指向实例
        this.sex = sex;
        this.say = ()=>{};
    }
    speak(){}
}
const zs = new Person('张三','男');
zs.say();
zs.speak();
//等同下面的 构造函数
function Person (name,sex){
    this.name = name;  //this指向实例
    this.sex = sex;
    this.say = function (){};
}
Person.prototype.speak = function (){};
const ls = new Person('李四',女);
ls.say();
ls.speak();

两种定义形式

声明的形式.   //最常用

class Person {}

表达式形式

const Person = class {};

实例属性和类的属性和方法

//实例属性
class Person {
    //下面的也是实例属性和方法
    name = '王五';
    getName = function (){
        return this.name;
    }
    constructor (sex){
        this.sex = sex; //this指向实例
    }
}

//静态方法  (也就是类的方法)
class Person {
    static speak(){
        this.age = 16; //this指向类
    }
}
Person.speak();
//静态属性 (类的属性)(目前静态属性 还不能使用关键字static)
class Person{};
Person.version = '1.1'; //或者用静态function来return出来

私有的属性和方法

1.以_开头的表示私有

2.将私有的属性和方法移除类

 

 

 

 

 

 

 

 

补充知识点

 类似资料: