前端宝典二十二:ES6必须掌握的功能和源码实现

本文主要是介绍前端宝典二十二:ES6必须掌握的功能和源码实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在前端宝典二十一中,我们已经一起探讨了Promise\ async\ await,并手写了Promise相关的方法all、race、allSettled、any等。
这一讲我们一起来看ES6其他重点的内容

一、let、const

let和const的出现,首先是基于var存在的问题,来解决问题的
var存在的问题:

  • 变量提升
  • 无法形成词法作用域
  • 可以随意篡改变量值、重复声明

1、let与const

  • let是声明块级作用域的局部变量,只在代码块内有效
  • const声明的是只读常量,常量必须在声明时初始化
    这样声明的好处是安全、简洁、规范

2、解决的问题

1. 循环中使用let声明变量避免问题

for (let i = 0; i < 5; i++) {setTimeout(() => {console.log(i); }) 
}

上面的代码如果用var声明循环的变量,就会打印出5个5

2. const常量防止被篡改

const PI =3.1415926;
const URL='https://editor.csdn.net/md?articleId=141468095';

3. const声明对象属性避免被修改

const uer = {name: 'frank',age: 18,gender: 'Male'
}
user.like='sports';  // { name: 'frank', age: 18, gender: 'Male', like: 'sports' }
Object.freeze(user);
user.like='music'
console.log(user); // 报错

3、底层原理

let 的底层实现过程

  1. 编译阶段
    在代码编译阶段,编译器会扫描整个函数体(或全局作用域),查找所有使用 let 定义的变量,为这些变量生成一个初始值为 undefined 的词法环境(LexicalEnvironment)并将其保存在作用域链中。

  2. 进入执行上下文
    当进入执行块级作用域(包括 for、if、while 和 switch 等语句块)后,会创建一个新的词法环境。如果执行块级作用域中包含 let 变量声明语句,这些变量将被添加到这个词法环境的环境记录中。

  3. 绑定变量值
    运行到 let 定义的变量时,JavaScript 引擎会在当前词法环境中搜索该变量。首先在当前环境记录中找到这个变量,如果不存在变量,则向包含当前环境的外部环境记录搜索变量,直到全局作用域为止。如果变量值没有被绑定,JavaScript 引擎会将其绑定为 undefined,否则继续执行其他操作。

  4. 实现块级作用域
    使用 let 定义变量时,在运行时不会在当前作用域之外创建单独的执行上下文,而是会创建子遮蔽(shadowing)新环境。在子遮蔽的词法环境中,变量的值只在最接近的块级作用域内有效。

const 的底层实现过程

const 具有与 let 相同的底层实现原理,区别在于 const 定义的变量被视为常量(在赋值之后无法更改),因此变量声明时 必须初始化。此外,应该注意的是,使用 const 声明的对象是可以修改属性的。在定义 const 对象时,对象本身是常量,而不是对象的属性。只有对象本身不能被修改,而对象包含的属性可以任意修改。

let和const有暂时性死区
有点类似webcomponent的shadowDom

二、Proxy

在 ES6 中,Proxy是一种用于创建对象代理的机制,可以拦截并自定义对目标对象的各种操作,如属性访问、赋值、函数调用等。它提供了一种强大的方式来实现面向切面编程(AOP)和元编程。

Proxy对象由两部分组成:目标对象(target)和处理程序对象(handler)。处理程序对象定义了各种捕获器(trap)方法,这些方法会在对目标对象进行特定操作时被调用。

1、代码实例

以下是一些使用 Proxy 的示例:

  1. 拦截属性访问:
const target = {name: 'John',age: 30
};const handler = {get: function(target, prop) {console.log(`Accessing property "${prop}"`);return target[prop];}
};const proxy = new Proxy(target, handler);console.log(proxy.name); // Accessing property "name", then prints "John"
  1. 拦截属性赋值:
const target = {count: 0
};const handler = {set: function(target, prop, value) {console.log(`Setting property "${prop}" to "${value}"`);target[prop] = value;return true;}
};const proxy = new Proxy(target, handler);proxy.count = 10; // Setting property "count" to "10"
console.log(proxy.count); // 10
  1. 拦截函数调用:
const target = {add: function(a, b) {return a + b;}
};const handler = {apply: function(target, thisArg, args) {console.log(`Calling function with arguments ${args}`);return target.apply(thisArg, args);}
};const proxy = new Proxy(target, handler);console.log(proxy.add(3, 4)); // Calling function with arguments [3,4], then prints 7

通过使用 Proxy,可以在不修改原始对象的情况下,对对象的行为进行灵活的控制和扩展。

三、 Reflect

在 ES6 中,Reflect 是一个内置的对象,它提供了一组与对象操作相关的静态方法,这些方法与传统的对象操作方法类似,但更加规范化和统一。Reflect 的目的是为了提供一种更加优雅和一致的方式来执行对象操作,并且可以与 Proxy 对象一起使用,实现对对象操作的拦截和自定义。

1、常见方法及示例

  1. Reflect.get(target, propertyKey[, receiver]):获取对象的属性值。

    const obj = {name: 'John',age: 30
    };
    console.log(Reflect.get(obj, 'name')); // John
    
  2. Reflect.set(target, propertyKey, value[, receiver]):设置对象的属性值。

    const obj = {name: 'John'
    };
    Reflect.set(obj, 'age', 30);
    console.log(obj); // { name: 'John', age: 30 }
    
  3. Reflect.has(target, propertyKey):检查对象是否具有某个属性。

    const obj = {name: 'John',age: 30
    };
    console.log(Reflect.has(obj, 'name')); // true
    
  4. Reflect.apply(target, thisArgument, argumentsList):以指定的 this 值和参数列表调用一个函数。

    function add(a, b) {return a + b;
    }
    console.log(Reflect.apply(add, null, [3, 4])); // 7
    
  5. Reflect.construct(target, argumentsList[, newTarget]):使用指定的构造函数和参数列表创建一个新对象。

    class Person {constructor(name, age) {this.name = name;this.age = age;}
    }
    const person = Reflect.construct(Person, ['John', 30]);
    console.log(person); // Person { name: 'John', age: 30 }
    

Reflect 的方法与传统的对象操作方法类似,但在一些情况下更加灵活和安全,特别是在与 Proxy 对象一起使用时,可以实现对对象操作的拦截和自定义。

四、class语法

JavaScript 的类最终也是一种函数,使用 class 关键字创建的类会被编译成一个函数,因此其底层原理与函数有一些相似之处。

1、js中原型继承实现继承有哪些方法?

构造器借用、寄生式继承、组合继承

2、class语法继承,最接近哪种?

寄生+组合
js引擎将class语法转化为了原型链继承的方式

3、构造函数

使用 class 关键字来定义类时,在内部会创建一个特殊的函数,称为构造函数(constructor)。构造函数用于在创建对象时初始化对象的属性,类似于传统的基于原型的代码中的构造函数。

class Person {constructor(name, age) {this.name = name;this.age = age;}
}const p = new Person("Tom", 20);
console.log(p.name, p.age); // Tom 20

class 中定义的属性和方法分别定义在这个构造函数的 prototype 属性中。并且与原型方式不同的是,类的方法(静态方法)是不可枚举的,因此无法使用 for…in 循环进行遍历。

问题:是否可枚举
判断方法:
是否可枚举,就用for…in循环遍历到属性,不能遍历就不可枚举
如何设置不可枚举:

Object.defineProperty(obj,'name',{value:'frank',enumerable: false // 不可枚举
})
for (const key in obj) {console.log(key); // 没有输出
}

4、继承

class Student extends Person {constructor(name,age,grade){super(name,age);this.grade = grade;}
}

这段代码中,子类 Student 继承了父类 Person 的构造函数方法并添加了自己的属性和方法。

5、静态方法和属性

类中的静态方法和属性可以使用 static 关键字来定义,它们不是类实例的属性,而是类本身的属性和方法。

class Person {static species = "human";static saySpecies() {console.log(`We are ${this.species}.`);}
}

这段代码中定义了一个静态方法和一个静态属性,可以通过类本身直接调用静态方法和属性。

6、也可以使用class表达式创建函数对象

const Person = class {constructor(name,age){this.name = name;this.age = age;}
}

五、@修饰器(Decorators)

ES6 修饰器是一种特殊的语法,它可以用来修改类及其成员(方法、属性、访问器等)的行为。修饰器本质上是一个函数,它接收被修饰的目标、名称和描述符作为参数,并返回一个新的描述符或直接修改目标。

修饰器可以用于实现许多功能,如日志记录、性能测量、权限控制等,它可以帮助我们在不修改原有代码的情况下增强类的功能。

1、代码实例

  1. 方法修饰器

    function logMethod(target, name, descriptor) {const originalMethod = descriptor.value;descriptor.value = function (...args) {console.log(`Calling method ${name} with arguments ${args}`);const result = originalMethod.apply(this, args);console.log(`Method ${name} returned ${result}`);return result;};return descriptor;
    }class MyClass {@logMethodmyMethod(arg1, arg2) {return arg1 + arg2;}
    }const instance = new MyClass();
    instance.myMethod(2, 3);
    

    在这个例子中,logMethod修饰器用于在方法调用前后输出日志信息。

  2. 类修饰器

    function logClass(constructor) {console.log(`Creating class ${constructor.name}`);return constructor;
    }@logClass
    class MyClass {constructor() {console.log('Constructing MyClass instance');}
    }const instance = new MyClass();
    

    这里的logClass修饰器在创建类的时候输出日志信息。

2、注意:

修饰器只可用于类和类属性方法,不可用于函数,因为存在函数提升。
修饰器是在编译时执行而不是运行时,所以修饰符是可以在编译时执行的代码,优秀哦

六、箭头函数

在箭头函数中,this关键字的作用域与它周围代码作用域相同,因而有时也被称为“词法作用域函数”。

1、基础概念与使用

箭头函数的原理是基于JavaScript中的闭包、this和参数作用域。在箭头函数中,this关键字始终指向函数所在上下文的this指针,而不是所在作用域的this指针。

2、箭头函数与普通函数的区别

  • this指向,箭头函数不能定义构造器
  • 不能new
  • 内部无arguments对象
  • this绑定方法失效,如apply、call、bind

所以,当我们需要引用所在父级的this指向时,可以用箭头函数。

这篇关于前端宝典二十二:ES6必须掌握的功能和源码实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1120727

相关文章

golang版本升级如何实现

《golang版本升级如何实现》:本文主要介绍golang版本升级如何实现问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录golanwww.chinasem.cng版本升级linux上golang版本升级删除golang旧版本安装golang最新版本总结gola

SpringBoot中SM2公钥加密、私钥解密的实现示例详解

《SpringBoot中SM2公钥加密、私钥解密的实现示例详解》本文介绍了如何在SpringBoot项目中实现SM2公钥加密和私钥解密的功能,通过使用Hutool库和BouncyCastle依赖,简化... 目录一、前言1、加密信息(示例)2、加密结果(示例)二、实现代码1、yml文件配置2、创建SM2工具

Mysql实现范围分区表(新增、删除、重组、查看)

《Mysql实现范围分区表(新增、删除、重组、查看)》MySQL分区表的四种类型(范围、哈希、列表、键值),主要介绍了范围分区的创建、查询、添加、删除及重组织操作,具有一定的参考价值,感兴趣的可以了解... 目录一、mysql分区表分类二、范围分区(Range Partitioning1、新建分区表:2、分

MySQL 定时新增分区的实现示例

《MySQL定时新增分区的实现示例》本文主要介绍了通过存储过程和定时任务实现MySQL分区的自动创建,解决大数据量下手动维护的繁琐问题,具有一定的参考价值,感兴趣的可以了解一下... mysql创建好分区之后,有时候会需要自动创建分区。比如,一些表数据量非常大,有些数据是热点数据,按照日期分区MululbU

MySQL中查找重复值的实现

《MySQL中查找重复值的实现》查找重复值是一项常见需求,比如在数据清理、数据分析、数据质量检查等场景下,我们常常需要找出表中某列或多列的重复值,具有一定的参考价值,感兴趣的可以了解一下... 目录技术背景实现步骤方法一:使用GROUP BY和HAVING子句方法二:仅返回重复值方法三:返回完整记录方法四:

IDEA中新建/切换Git分支的实现步骤

《IDEA中新建/切换Git分支的实现步骤》本文主要介绍了IDEA中新建/切换Git分支的实现步骤,通过菜单创建新分支并选择是否切换,创建后在Git详情或右键Checkout中切换分支,感兴趣的可以了... 前提:项目已被Git托管1、点击上方栏Git->NewBrancjsh...2、输入新的分支的

Python实现对阿里云OSS对象存储的操作详解

《Python实现对阿里云OSS对象存储的操作详解》这篇文章主要为大家详细介绍了Python实现对阿里云OSS对象存储的操作相关知识,包括连接,上传,下载,列举等功能,感兴趣的小伙伴可以了解下... 目录一、直接使用代码二、详细使用1. 环境准备2. 初始化配置3. bucket配置创建4. 文件上传到os

关于集合与数组转换实现方法

《关于集合与数组转换实现方法》:本文主要介绍关于集合与数组转换实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、Arrays.asList()1.1、方法作用1.2、内部实现1.3、修改元素的影响1.4、注意事项2、list.toArray()2.1、方

使用Python实现可恢复式多线程下载器

《使用Python实现可恢复式多线程下载器》在数字时代,大文件下载已成为日常操作,本文将手把手教你用Python打造专业级下载器,实现断点续传,多线程加速,速度限制等功能,感兴趣的小伙伴可以了解下... 目录一、智能续传:从崩溃边缘抢救进度二、多线程加速:榨干网络带宽三、速度控制:做网络的好邻居四、终端交互

mysql表操作与查询功能详解

《mysql表操作与查询功能详解》本文系统讲解MySQL表操作与查询,涵盖创建、修改、复制表语法,基本查询结构及WHERE、GROUPBY等子句,本文结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随... 目录01.表的操作1.1表操作概览1.2创建表1.3修改表1.4复制表02.基本查询操作2.1 SE