前端宝典二十二: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

相关文章

Java实现优雅日期处理的方案详解

《Java实现优雅日期处理的方案详解》在我们的日常工作中,需要经常处理各种格式,各种类似的的日期或者时间,下面我们就来看看如何使用java处理这样的日期问题吧,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言一、日期的坑1.1 日期格式化陷阱1.2 时区转换二、优雅方案的进阶之路2.1 线程安全重构2

Android实现两台手机屏幕共享和远程控制功能

《Android实现两台手机屏幕共享和远程控制功能》在远程协助、在线教学、技术支持等多种场景下,实时获得另一部移动设备的屏幕画面,并对其进行操作,具有极高的应用价值,本项目旨在实现两台Android手... 目录一、项目概述二、相关知识2.1 MediaProjection API2.2 Socket 网络

使用Python实现图像LBP特征提取的操作方法

《使用Python实现图像LBP特征提取的操作方法》LBP特征叫做局部二值模式,常用于纹理特征提取,并在纹理分类中具有较强的区分能力,本文给大家介绍了如何使用Python实现图像LBP特征提取的操作方... 目录一、LBP特征介绍二、LBP特征描述三、一些改进版本的LBP1.圆形LBP算子2.旋转不变的LB

Redis消息队列实现异步秒杀功能

《Redis消息队列实现异步秒杀功能》在高并发场景下,为了提高秒杀业务的性能,可将部分工作交给Redis处理,并通过异步方式执行,Redis提供了多种数据结构来实现消息队列,总结三种,本文详细介绍Re... 目录1 Redis消息队列1.1 List 结构1.2 Pub/Sub 模式1.3 Stream 结

C# Where 泛型约束的实现

《C#Where泛型约束的实现》本文主要介绍了C#Where泛型约束的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录使用的对象约束分类where T : structwhere T : classwhere T : ne

将Java程序打包成EXE文件的实现方式

《将Java程序打包成EXE文件的实现方式》:本文主要介绍将Java程序打包成EXE文件的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录如何将Java程序编程打包成EXE文件1.准备Java程序2.生成JAR包3.选择并安装打包工具4.配置Launch4

HTML5中的Microdata与历史记录管理详解

《HTML5中的Microdata与历史记录管理详解》Microdata作为HTML5新增的一个特性,它允许开发者在HTML文档中添加更多的语义信息,以便于搜索引擎和浏览器更好地理解页面内容,本文将探... 目录html5中的Mijscrodata与历史记录管理背景简介html5中的Microdata使用M

html5的响应式布局的方法示例详解

《html5的响应式布局的方法示例详解》:本文主要介绍了HTML5中使用媒体查询和Flexbox进行响应式布局的方法,简要介绍了CSSGrid布局的基础知识和如何实现自动换行的网格布局,详细内容请阅读本文,希望能对你有所帮助... 一 使用媒体查询响应式布局        使用的参数@media这是常用的

HTML5表格语法格式详解

《HTML5表格语法格式详解》在HTML语法中,表格主要通过table、tr和td3个标签构成,本文通过实例代码讲解HTML5表格语法格式,感兴趣的朋友一起看看吧... 目录一、表格1.表格语法格式2.表格属性 3.例子二、不规则表格1.跨行2.跨列3.例子一、表格在html语法中,表格主要通过< tab

MySQL索引的优化之LIKE模糊查询功能实现

《MySQL索引的优化之LIKE模糊查询功能实现》:本文主要介绍MySQL索引的优化之LIKE模糊查询功能实现,本文通过示例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录一、前缀匹配优化二、后缀匹配优化三、中间匹配优化四、覆盖索引优化五、减少查询范围六、避免通配符开头七、使用外部搜索引擎八、分