(ES6)前端八股文修炼Day2

在这里插入图片描述

1. let const var 的区别

  • var:

var 是在 ES5 中引入的声明变量的关键字。
具有函数作用域,而不是块作用域,这意味着使用 var 声明的变量在函数内部是可见的。
变量可以被重复声明,而且变量的值可以在声明前使用,这可能会导致一些意外的行为。
使用 var声明的变量可以被提升(hoisted),即变量的声明会被提升到作用域的顶部。

  • let:

let 是在 ES6(ES2015)中引入的声明变量的关键字。
具有块级作用域,只在声明它的块(如 {})内部有效,不会污染外部作用域。
变量不能被重复声明,如果尝试重复声明会导致语法错误。
let 声明的变量不会被提升,不存在变量提升的情况。

  • const:

const 也是在 ES6 中引入的声明变量的关键字。
具有块级作用域,类似于 let,不能重复声明,不存在变量提升。
声明一个常量,值在声明后不能被修改。
声明时必须进行初始化,而且初始化后就不能再修改常量的值。

  • 示例比较:
var x = 10;
if (true) {var x = 20;console.log(x); // 输出: 20
}
console.log(x); // 输出: 20// 使用 let
let y = 10;
if (true) {let y = 20;console.log(y); // 输出: 20
}
console.log(y); // 输出: 10// 使用 const
const z = 10;
// z = 20; // 会导致错误,常量值无法修改

在实际开发中,推荐优先使用 const,除非变量的值需要被修改才使用 let。避免使用 var,因为它存在一些不利于代码维护和调试的特性。希望这个解释对你有帮助!如果有任何其他问题,请随时告诉我。

2.const 对象的属性可以修改吗?

在 JavaScript 中,使用 const 声明的变量是常量,这意味着变量的引用不可变,但并不意味着变量所引用的对象是不可变的。对于对象(包括数组)来说,使用 const 声明的变量可以修改对象的属性,但不能重新赋值一个新的对象给这个变量。

下面是一个示例来说明这一点:

const person = {name: 'Alice',age: 30
};// 修改对象属性是允许的
person.age = 31;
console.log(person); // 输出: { name: 'Alice', age: 31 }
// 重新赋值一个新对象会导致错误
// person = { name: 'Bob', age: 25 }; // 这行会导致错误

在上面的示例中,虽然 person 是用 const 声明的,我们仍然可以修改 person 对象的属性,如更改 age 的值。但是,尝试将一个新对象赋值给 person 会导致错误,因为常量变量的引用是不可变的。

3.new一个箭头函数的会怎么样?箭头函数与普通函数的区别?箭头函数的this指向哪⾥?

在 JavaScript 中,箭头函数和普通函数有一些重要的区别,其中包括在使用 new 关键字时的行为以及 this 的指向:

  1. 使用 new 关键字:

    • 普通函数可以使用 new 关键字来创建一个新的对象实例,这时候函数内部的 this 会指向新创建的实例。
    • 箭头函数不能用 new 关键字来创建实例,因为箭头函数没有自己的 this,它会继承外层作用域的 this
  2. 箭头函数与普通函数的区别:

    • 箭头函数没有自己的 thisargumentssupernew.target,它们都由外围最近一层非箭头函数决定。
    • 箭头函数不能用作构造函数,不能使用 new 关键字。
    • 箭头函数没有原型(prototype)属性。
  3. 箭头函数的 this 指向:

    • 箭头函数的 this 指向在函数定义时确定,取决于箭头函数外围作用域的 this
    • 普通函数的 this 则在函数被调用时才确定,取决于函数的调用方式(比如作为方法调用、函数调用、构造函数调用等)。

下面是一个示例来说明箭头函数的 this 指向和普通函数的区别:

function NormalFunction() {this.value = 42;setTimeout(function() {console.log(this.value); // 输出 undefined,普通函数的 this 指向全局对象或 undefined}, 1000);
}const ArrowFunction = () => {this.value = 42;setTimeout(() => {console.log(this.value); // 输出 42,箭头函数的 this 指向外围作用域的 this}, 1000);
};new NormalFunction(); // 输出 undefined
new ArrowFunction(); // 输出 42

在上面的示例中,setTimeout 内部的箭头函数能够访问到外围作用域的 this,而普通函数的 this 则不同,因为普通函数内部的 this 取决于调用方式。

4. 扩展运算符的作用及使用场景

扩展运算符(Spread Operator)是 ES6 中引入的一个功能强大的语法,用三个点(...)表示。它可以将一个可迭代对象(比如数组、对象等)拆分为独立的元素,或将多个参数展开为单独的参数。扩展运算符的作用和使用场景有以下几个方面:

  1. 在数组中的使用:

    • 将数组展开为独立的元素:

      const arr1 = [1, 2, 3];
      const arr2 = [4, 5, ...arr1, 6, 7];
      console.log(arr2); // 输出: [4, 5, 1, 2, 3, 6, 7]
      
    • 复制数组:

      const originalArray = [1, 2, 3];
      const copyArray = [...originalArray];
      
    • 合并数组:

      const arr1 = [1, 2];
      const arr2 = [3, 4];
      const combinedArray = [...arr1, ...arr2];
      
  2. 在函数调用中的使用:

    • 将数组作为参数传递给函数:
      const numbers = [1, 2, 3];
      function sum(a, b, c) {return a + b + c;
      }
      console.log(sum(...numbers)); // 输出: 6
      
  3. 在对象中的使用:

    • 浅拷贝对象:

      const obj1 = { a: 1, b: 2 };
      const obj2 = { ...obj1 }; // 浅拷贝 obj1 到 obj2
      
    • 合并对象:

      const obj1 = { a: 1 };
      const obj2 = { b: 2 };
      const mergedObj = { ...obj1, ...obj2 };
      
  4. 在函数参数中的使用:

    • 用于传递不定数量的参数:
      function sum(...args) {return args.reduce((acc, val) => acc + val, 0);
      }
      console.log(sum(1, 2, 3)); // 输出: 6
      

扩展运算符为 JavaScript 的数据处理提供了更灵活和方便的方式,可以简化代码并提高可读性。它在处理数组、对象、函数参数等方面都有很好的应用场景。希望这个解释对你有帮助!如果有任何其他问题,请随时告诉我。

5. Proxy

Proxy 是 ES6 中引入的一个非常强大且灵活的功能,它可以用来拦截并定义对象上的基本操作,从而可以实现各种功能,例如:

  1. 属性访问控制:通过 getset 拦截器,可以控制对对象属性的访问和赋值操作,实现属性的隐藏、验证等功能。

  2. 函数调用控制:通过 apply 拦截器,可以控制对函数的调用操作,可以在函数调用前后执行额外逻辑。

  3. 数组操作的控制:可以通过拦截数组的操作,例如 pushpopsplice 等,实现对数组的监控、验证等功能。

  4. 动态扩展属性:可以通过 get 拦截器动态生成属性,实现虚拟属性或计算属性。

  5. 数据验证:可以在 set 拦截器中对属性值进行验证,确保数据的合法性。

  6. 数据绑定:可以实现数据的双向绑定,当对象数据发生变化时自动更新相关内容。

  7. 缓存:可以利用 Proxy 实现缓存功能,避免重复计算,提高程序性能。

  8. 日志记录:可以在拦截器中记录对象操作的历史,用于调试和监控。

  9. 实现观察者模式:可以在属性访问和赋值时触发相应操作,实现观察者模式。

  10. 实现权限控制:可以根据需要拦截对象的操作,实现权限控制和安全性增强。

总的来说,Proxy 提供了一种对对象进行拦截和自定义操作的机制,可以实现很多复杂的功能和行为定制。
下面我将简要介绍 Proxy 如何实现观察者模式:

  1. 创建观察者模式的实现:

    • 首先,需要创建一个被观察者对象和一个存储观察者的数组。

    • 使用 Proxy 对被观察者对象进行封装,设置一个 observers 数组来存储观察者。

    • 通过 set 拦截器,在被观察者对象的属性发生变化时,通知所有观察者。

  2. 示例代码:

    // 创建一个被观察者对象
    const subject = new Proxy({ value: 0, observers: [] }, {set(target, key, value, receiver) {const result = Reflect.set(target, key, value, receiver);if (key === 'value') {target.observers.forEach(observer => observer());}return result;}
    });// 创建观察者
    const observer1 = () => console.log('Observer 1 updated: ', subject.value);
    const observer2 = () => console.log('Observer 2 updated: ', subject.value);// 添加观察者
    subject.observers.push(observer1, observer2);// 修改被观察者的值,触发通知
    subject.value = 1; // Observer 1 updated: 1, Observer 2 updated: 1
    

在上面的示例中,我们创建了一个简单的观察者模式,使用 Proxy 对被观察者对象进行拦截,在属性值发生变化时通知所有观察者。这样,观察者模式就得以实现。

6.提取高度嵌套对象里的指定属性

要提取高度嵌套对象里的指定属性,可以使用递归和对象解构来实现。下面是一个示例,演示如何提取高度嵌套对象中的指定属性:

// 定义一个高度嵌套的对象
const nestedObject = {level1: {level2: {level3: {key: 'value'}}}
};// 递归函数用于提取指定属性
const extractPropertyValue = (obj, property) => {for (let key in obj) {if (key === property) {return obj[key];} else if (typeof obj[key] === 'object') {return extractPropertyValue(obj[key], property);}}
};// 指定要提取的属性名
const propertyToExtract = 'key';// 提取指定属性值
const extractedValue = extractPropertyValue(nestedObject, propertyToExtract);
console.log(extractedValue); // 输出: 'value'

在上面的示例中,我们定义了一个高度嵌套的对象 nestedObject,然后编写了一个递归函数 extractPropertyValue,该函数接收一个对象和要提取的属性名,在对象中查找指定属性,并返回其值。通过调用这个函数,我们成功提取了高度嵌套对象中的指定属性值。

这种方法可以应用于任意层级的嵌套对象,通过递归地遍历对象的属性,找到目标属性并返回其值。

7.对对象与数组的解构的理解

对象和数组的解构是 JavaScript 中一种强大且方便的语法,用于快速提取数组或对象中的值并赋给变量,以便后续使用。下面我将简要介绍对象解构和数组解构的基本概念:

对象解构:
  • 基本语法: 使用花括号 {} 来指定要提取的对象属性,并将属性值赋给相应的变量。

    const person = { name: 'Alice', age: 30 };
    const { name, age } = person;
    console.log(name); // 输出: 'Alice'
    console.log(age); // 输出: 30
    
  • 给变量起别名: 可以使用冒号 : 为提取的属性值指定变量名。

    const { name: personName, age: personAge } = person;
    console.log(personName); // 输出: 'Alice'
    console.log(personAge); // 输出: 30
    
数组解构:
  • 基本语法: 使用方括号 [] 来指定要提取的数组元素,并将值赋给相应的变量。

    const numbers = [1, 2, 3];
    const [first, second, third] = numbers;
    console.log(first); // 输出: 1
    console.log(second); // 输出: 2
    
  • 忽略某些元素: 可以使用逗号 , 来跳过不需要的数组元素。

    const [,, third] = numbers;
    console.log(third); // 输出: 3
    

对象和数组解构可以简化代码,提高可读性,并且方便地从复杂的数据结构中提取所需的值。当结合递归和其他技术时,对象和数组解构可以变得非常强大。

8.Rest参数

Rest 参数是 ES6 中引入的一个新特性,用于捕获函数参数中的剩余参数,将其表示为一个数组。这样可以处理不定数量的参数,而不需要显式地定义参数个数。下面是关于 rest 参数的一些基本概念和示例:

Rest 参数的基本语法
  • 在函数定义时,使用三个点号 ... 加上一个参数名来表示 rest 参数,通常放在参数列表的最后。
function sum(...numbers) {return numbers.reduce((acc, curr) => acc + curr, 0);
}console.log(sum(1, 2, 3, 4, 5)); // 输出: 15

在这个示例中,...numbers 表示将所有传入函数的参数作为一个数组 numbers 来存储。

Rest 参数的应用场景:
  • 处理不定数量的参数: Rest 参数允许函数接受任意数量的参数,无需提前定义参数个数。
function multiply(multiplier, ...numbers) {return numbers.map(num => num * multiplier);
}console.log(multiply(2, 1, 2, 3, 4)); // 输出: [2, 4, 6, 8]
  • 替代 arguments 对象: Rest 参数可以替代传统的 arguments 对象,更直观地操作参数。
function logArguments(...args) {console.log(args);
}logArguments('a', 'b', 'c'); // 输出: ['a', 'b', 'c']

Rest 参数通常用于函数定义中,方便处理不定数量的参数,提高代码的灵活性和可读性。

9.对 rest 参数的理解ES6中模板语法与字符串处理

ES6 中的模板字符串是一种更灵活、更强大的字符串处理方式,可以在字符串中插入变量、表达式,并支持多行字符串的定义。下面我将介绍 ES6 中模板字符串的基本语法和常见用法:

模板字符串的基本语法:

  • 使用反引号 ``(通常位于键盘左上角,与波浪符号~同一个键)来定义模板字符串。
const name = 'Alice';
const greeting = `Hello, ${name}!`;
console.log(greeting); // 输出: 'Hello, Alice!'
  • 在模板字符串中,使用 ${} 来插入变量或表达式,可以是任意有效的 JavaScript 表达式。

多行字符串的定义:

  • 模板字符串可以跨越多行,而无需使用 \n 换行符。
const multiLine = `This is amulti-linestring.
`;
console.log(multiLine);
// 输出:
//     This is a
//     multi-line
//     string.

标签模板字符串:

  • 可以使用标签函数对模板字符串进行处理,这种技术称为标签模板字符串。
function customTag(strings, ...values) {console.log(strings);console.log(values);
}const value1 = 10;
const value2 = 20;
customTag`The values are: ${value1} and ${value2}`;
// 输出:
//     ["The values are: ", " and ", ""]
//     [10, 20]

模板字符串提供了一种更简洁、更直观的方式来处理字符串内容,特别是在需要插入变量或多行文本时非常有用。标签模板字符串则扩展了这一概念,允许自定义对模板字符串的处理方式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/285387.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

生成微信小程序二维码

首页 -> 统计 可以通过上面二个地方配置,生成小程序的二维码,并且在推广分析里,有详细的分析数据,

Vue3更新Package.json版本号

由于我之前已经更新过了,下面的方法提示我已经是最新的了,记录一下,过段时间在测试一下 npm install -g vue/clivue upgrade

【Hadoop大数据技术】——Hadoop高可用集群(学习笔记)

📖 前言:Hadoop设计之初,在架构设计和应用性能方面存在很多不如人意的地方,如HDFS和YARN集群的主节点只能有一个,如果主节点宕机无法使用,那么将导致HDFS或YARN集群无法使用,针对上述问题&#…

项目1-加法计算器

1.创建项目 2.导入前端代码 2.1 static包内 2.2 测试前端代码是否有误 显示成功说明无误 2.3 定义用户接口 请求路径:calc/sum 请求方式:GET/POST 接口描述:计算两个整数相加 请求参数: 参数名类型是否必须备注num1Integer是参与计算的第…

YiYi-Web项目介绍

YiYi-Web项目介绍 1. 简介2. 使用2.1 后端开发环境2.2 前端开发环境 3. 测试环境:4. 更新日志5. 打包情况6.项目截图 本项目前端是html、css、js、jQuery基础技术。 后端都是最新的SpringBoot技术,不分离版本, 是最基础的项目开发教程&#x…

【C语言】linux内核pci_alloc_irq_vectors

一、注释 代码中包含了几个关于PCI(外围组件互联)设备中断请求(IRQ)向量分配的函数,以及内联函数声明,下面是对这些函数的中文注释: static inline int pci_alloc_irq_vectors_affinity(struc…

Java安全 反序列化(3) CC1链-TransformedMap版

Java安全 反序列化(3) CC1链-TransformedMap版 本文尝试从CC1的挖掘思路出发,理解CC1的实现原理 文章目录 Java安全 反序列化(3) CC1链-TransformedMap版配置jdk版本和源代码配置前记 为什么可以利用一.CC链中的命令执行我们可以尝试一下通过InvokerTransformer.tr…

曲线生成 | 图解Reeds-Shepp曲线生成原理(附ROS C++/Python/Matlab仿真)

目录 0 专栏介绍1 什么是Reeds-Shepp曲线?2 Reeds-Shepp曲线的运动模式3 Reeds-Shepp曲线算法原理3.1 坐标变换3.2 时间翻转(time-flip)3.3 反射变换(reflect)3.4 后向变换(backwards) 4 仿真实现4.1 ROS C实现4.2 Python实现4.3 Matlab实现 0 专栏介绍 &#x1f5…

如何使用PHP和RabbitMQ实现消息队列?

前言 今天我们来做个小试验,用PHP和RabbitMQ实现消息队列功能。 前期准备,需要安装好docker、docker-compose的运行环境。 如何使用docker部署php服务_php如何使用docker发布-CSDN博客 一、安装RabbitMQ 1、创建相关目录,执行如下命令。…

吴恩达2022机器学习专项课程(一) 3.3 成本函数的公式

问题预览 模型的参数(w和b)有什么作用?不同的w和b对线性回归模型有什么影响?训练集里的y和线性回归模型预测的y(y帽)的区别是什么?成本函数的作用是什么?成本函数的公式是什么&…

neo4j所有关系只显示RELATION,而不显示具体的关系

当看r时,真正的关系在properties中的type里,而type为“RELATION” 造成这个的原因是: 在创建关系时,需要指定关系的类型,这是固定的,不能像属性那样从CSV文件的一个字段动态赋值。标准的Cypher查询语言不支…

【 Mysql8.0 忘记登录密码 可以试试 】

** Mysql8.0 忘记登录密码 可以试试 ** 2024-3-21 段子手168 1、首先停止 mysql 服务 ,WIN R 打开运行,输入 services.msc 回车打开服务,找到 mysql 服务,停止。 然后 WIN R 打开运行,输入 CMD 打开控制台终端输…

BMS均衡的相关原理及解释

1为什么要做均衡? 由于电池使用工艺和材料的本身有差异,及电池实际使用过程中所处的温度、湿度等环境的不同,电池包内部的单体电池存在SOC差异,这个SOC的差异从直观上的体现就是电池的电压不同。 另外一个重要原因是由于电池自身…

计算机网络⑧ —— IP地址

IP位于TCP/IP参考模型的第三层,也就是⽹络层 ⽹络层的主要作⽤:实现主机与主机之间的通信,也叫点对点通信 问题1:⽹络层(IP)与数据链路层(MAC)有什么关系呢? MAC的作⽤:实现直连的两个设备之间通信。IP的…

Java22已发布,支持SpringBoot3.3.0正式版

Java22已发布,支持SpringBoot3.3.0正式版 文章目录 Java22已发布,支持SpringBoot3.3.0正式版1. JDK22现已推出!2. Java22的新功能1. 语言改进1. 语言预览 2. 库文件3. 性能4. 工具 3. 资源 Java 22现已发布 下一个Java版本提高了Java应用程序…

Java安全 反序列化(4) CC1链-LazyMap版

Java安全 反序列化(4) CC1链-LazyMap版 实验环境:存在漏洞的版本 commons-collections3.1-3.2.1 jdk 8u71之后已修复不可利⽤ 文章目录 Java安全 反序列化(4) CC1链-LazyMap版一.跟踪挖掘CC1_LazyMap原理二.完整CC1_Lazy版Poc 接着上一篇文章我们通过ChainedTransFormer实现任意…

爬楼梯C语言

方法一&#xff1a;动态规划 int climbStairs(int n) {int f[100] {0};f[0] 0;f[1] 1;f[2] 2;for(int i 3;i<n;i)f[i] f[i-1] f[i-2];//可能是从i-1阶爬上第i阶&#xff0c;也有可能是从i-2阶 return f[n]; } 方法二&#xff1a;滚动数组 int climbStairs(int n){int…

Day08 Java复习8 Spring MVC概念

Day09 Java复习9 Spring MVC spring mvc 的核心组件是什么&#xff1f; DispatcherServlet 1.JAVA 和Spring 、Spring Boot 、Spring MVC的关系 你要举办一个生日派对&#xff0c;而且你希望它既特别又好玩。Java就像是举办派对的地方&#xff0c;Spring、Spring Boot和Spri…

AWTK T9 输入法实现原理

1. T9 输入法的中文字典数据 网上可以找到 T9 输入法的中文字典数据&#xff0c;但是通常有两个问题&#xff1a; 采用 GPL 协议&#xff0c;不太适合加入 AWTK。 只支持单个汉字的输入&#xff0c;不支持词组的输入。 经过考虑之后&#xff0c;决定自己生成 T9 输入法的中…

物联网应用技术中的stm32该怎么学,该从哪入手?

物联网应用技术中的stm32该怎么学&#xff0c;该从哪入手&#xff1f; STM32是只物联网中的一部分&#xff0c;单纯的学个STM32是没法满足物联网开发需求的&#xff0c;实际产品开发过程中会考虑成本等多种因素选择合适的方案&#xff0c;比如使用单片机还是stm32或是更高端的芯…