(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.mzph.cn/news/768169.shtml

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

相关文章

jmeter链路压测

比如登录后返回token,业务打印上传的操作需要用到token 线程组中添加登录请求,并执行 1、添加登录并执行,查看结果 2、结果树中下拉选择正则表达式,将token参数和值复制粘贴到下方,将token值改为(.*?)&#xff0…

【Nebula笔记】简介及安装

目录 一、简介 (一) 什么是图数据库 二、安装 (一) 原生安装 (二) Docker & Docker compose 1. Docker安装 Linux Window 2. 部署NebulaGraph (三) to MAC 三、Nebula Graph Studio (一) 版本兼容性 (二) 原生安装 (三) Docker compose (四) 连接Nebula Gra…

python—接口编写部分

最近准备整理一下之前学过的前端小程序知识笔记,形成合集。顺便准备学一学接口部分,希望自己能成为一个全栈嘿嘿。建议关注收藏,持续更新技术文档。 目录 前端知识技能树http请求浏览器缓存 后端知识技能树python_api:flaskflask…

Swift 从获取所有 NSObject 对象聊起:ObjC、汇编语言以及底层方法调用链(四)

概览 从上一篇博文: Swift 从获取所有 NSObject 对象聊起:ObjC、汇编语言以及底层方法调用链(三)我们学到了 Swift 中完全自己撸码实现 SwiftHook 类似功能的基本思路、提出了两个“难关”,并首先解决了其中第一道难题。 在这一篇中,我们将会继续克服各种“艰难险阻”,…

Spark spark-submit 提交应用程序

Spark spark-submit 提交应用程序 Spark支持三种集群管理方式 Standalone—Spark自带的一种集群管理方式,易于构建集群。Apache Mesos—通用的集群管理,可以在其上运行Hadoop MapReduce和一些服务应用。Hadoop YARN—Hadoop2中的资源管理器。 注意&…

STM32微控制器的中断优先级设置对系统性能有何影响?

STM32微控制器的中断优先级设置对系统性能有着显著的影响。正确配置中断优先级可以确保关键任务得到及时响应,提高系统的实时性和可靠性。相反,如果中断优先级设置不当,可能会导致系统响应延迟,甚至出现死锁等问题。本文将详细探讨…

python第三方库的安装,卸载和更新,以及在cmd下pip install安装的包在pycharm不可用问题的解决

目录 第三方库pip安装,卸载更新 1.安装: 2.卸载 3.更新 一、第三方库pip安装,卸载更新 1.安装 pip install 模块名 加镜像下载:pip install -i 镜像网址模块名 常用的是加清华镜像,如 pip install -i https://pyp…

Web前端—浏览器渲染原理

浏览器渲染原理 浏览器渲染原理渲染时间点渲染流水线1. 解析HTML—Parse HTML2. 样式计算—Recalculate Style3. 布局—Layout4. 分层—Layer5. 绘制—Paint6. 分块—Tiling7. 光栅化—Raster8. 画—Draw完整过程 面试题1. 浏览器是如何渲染页面的?2. 什么是 reflow…

每日一题 --- 两两交换链表中的节点[力扣][Go]

两两交换链表中的节点 题目:24. 两两交换链表中的节点 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。 示例 1&a…

基于Java中的SSM框架实现考研指导平台系统项目【项目源码+论文说明】

基于Java中的SSM框架实现考研指导平台系统演示 摘要 应对考研的学生,为了更好的使校园考研有一个更好的环境好好的学习,建议一个好的校园网站,是非常有必要的。提供学生的学习提供一个交流的空间。帮助同学们在学习高数、学习设计、学习统计…

Python+django+vue开发的家教信息管理系统

一直想做一款管理系统,看了很多优秀的开源项目但是发现没有合适的。 于是利用空闲休息时间开始自己写了一套管理系统。 功能介绍 平台采用B/S结构,后端采用主流的Pythondjango进行开发,前端采用主流的Vue.js进行开发。 整个平台包括前台和…

Arduino智能家居

文章目录 一、接线框图1、下载fritzing 二、Arduino IDE 下载三、实现代码 一、接线框图 1、下载fritzing https://github.com/fritzing/fritzing-app/releases打开的软件界面如下: 二、Arduino IDE 下载 官网地址 P.S. 如果upload代码过程中出现cant open de…

2024年阿里云轻量应用服务器优惠价格_2核2G_2核4G报价

阿里云轻量应用服务器2核2G和2核4G配置优惠价格表,轻量2核2G3M带宽61元一年,轻量2核4G4M带宽165元1年,均不限制月流量,阿里云活动链接 aliyunfuwuqi.com/go/aliyun 活动打开如下图: 阿里云轻量应用服务器价格 61元/年…

力扣刷题之21.合并两个有序链表

仅做学习笔记之用。 题目: 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1: 输入:l1 [1,2,4], l2 [1,3,4] 输出:[1,1,2,3,4,4]示例 2: 输入&#xf…

MySQL数据库基本操作(增删改查)与用户授权

前言 SQL(Structured Query Language,结构化查询语言)是一种用于管理关系数据库系统的语言。SQL的设计目标是提供一种简单、直观的语言,使得用户可以通过编写SQL语句来处理他们想要的数据和操作。 目录 一、结构介绍 1. 查看信…

使用Django实现信号与消息通知系统【第154篇—Django】

👽发现宝藏 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 使用Django实现信号与消息通知系统 在Web应用程序中,实现消息通知系统是至关重…

华为数通 HCIP-Datacom H12-831 题库补充

2024年 HCIP-Datacom(H12-831)最新题库,完整题库请扫描上方二维码,持续更新。 缺省情况下,PIM报文的IP协议号是以下哪一项? A:18 B:59 C:103 D:9 答案&a…

从抛硬币试验看概率论的基本内容及统计方法

一般说到概率,就喜欢拿抛硬币做例子。大多数时候,会简单认为硬币正背面的概率各为二分之一,其实事情远没有这么简单。这篇文章会以抛硬币试验为例子并贯穿全文,引出一系列概率论和数理统计的基本内容。这篇文章会涉及的有古典概型…

ubuntu20.04安装 ffmpeg 开发环境

参考:参考1 一些相关软件包,已打包整理好,如下 源码包 1、安装步骤 创建安装目录 sudo mkdir -p /usr/local/ffmpeg/lib 解压源码 tar -jxf ffmpeg-4.3.2.tar.bz2 到指定ffmpeg目录进行配置 cd ffmpeg-4.3.2/ 配置:会报错很多…

Zookeeper(八)序列化与协议

目录 一 序列化与反序列化1.1 Jute序列化工具1.1 Recor接口1.2 OutputArchive和InputArchive 二 通信协议2.1 请求部分2.1.1 请求头2.2.2 请求体2.1.3 案例分析 2.2 响应部分2.2.1 响应头2.2.2 响应内容2.2.3 案例分析 官网:Apache ZooKeeper 一 序列化与反序列化 …