八个针对高级职位的高级 JavaScript 面试题

JavaScript 是一种功能强大的语言,是网络的主要构建块之一。这种强大的语言也有一些怪癖。例如,您是否知道 0 === -0 的计算结果为 true,或者 Number("") 的结果为 0?

问题是,有时这些怪癖会让你摸不着头脑,甚至质疑 Brendon Eich 发明 JavaScript 的那一天。好吧,重点不在于 JavaScript 是一种糟糕的编程语言,或者像它的批评者所说的那样它是邪恶的。所有编程语言都有某种与之相关的奇怪之处,JavaScript 也不例外。

因此,在今天这篇文章中,我们将会看到一些重要的 JavaScript 面试问题的深入解释。我的目标是彻底解释这些面试问题,以便我们能够理解基本概念,并希望在面试中解决其他类似问题。

1、仔细观察 + 和 - 运算符

console.log(1 + '1' - 1);

您能猜出 JavaScript 的 + 和 - 运算符在上述情况下的行为吗?

当 JavaScript 遇到 1 + '1' 时,它会使用 + 运算符处理表达式。+ 运算符的一个有趣的属性是,当操作数之一是字符串时,它更喜欢字符串连接。在我们的例子中,“1”是一个字符串,因此 JavaScript 隐式地将数值 1 强制转换为字符串。因此,1 + '1' 变为 '1' + '1',结果是字符串 '11'。

现在,我们的等式是 '11' - 1。- 运算符的行为恰恰相反。无论操作数的类型如何,它都会优先考虑数字减法。当操作数不是数字类型时,JavaScript 会执行隐式强制转换,将其转换为数字。在本例中,“11”被转换为数值 11,并且表达式简化为 11 - 1。

把它们放在一起:

'11' - 1 = 11 - 1 = 10

2、复制数组元素

考虑以下 JavaScript 代码并尝试查找此代码中的任何问题:

function duplicate(array) {for (var i = 0; i < array.length; i++) {array.push(array[i]);}return array;
}const arr = [1, 2, 3];
const newArr = duplicate(arr);
console.log(newArr);

在此代码片段中,我们需要创建一个包含输入数组的重复元素的新数组。初步检查后,代码似乎通过复制原始数组 arr 中的每个元素来创建一个新数组 newArr。然而,重复函数本身出现了一个关键问题。

重复函数使用循环来遍历给定数组中的每个项目。但在循环内部,它使用 push() 方法在数组末尾添加一个新元素。这使得数组每次都变得更长,从而产生循环永远不会停止的问题。循环条件 (i < array.length) 始终保持为 true,因为数组不断变大。这使得循环永远持续下去,导致程序卡住。

为了解决数组长度不断增长导致无限循环的问题,可以在进入循环之前将数组的初始长度存储在变量中。

然后,您可以使用该初始长度作为循环迭代的限制。这样,循环将仅针对数组中的原始元素运行,并且不会因添加重复项而受到数组增长的影响。这是代码的修改版本:

function duplicate(array) {var initialLength = array.length; // Store the initial lengthfor (var i = 0; i < initialLength; i++) {array.push(array[i]); // Push a duplicate of each element}return array;
}const arr = [1, 2, 3];
const newArr = duplicate(arr);
console.log(newArr);

输出将显示数组末尾的重复元素,并且循环不会导致无限循环:

[1, 2, 3, 1, 2, 3]

3、原型和__proto__之间的区别

原型属性是与 JavaScript 中的构造函数相关的属性。构造函数用于在 JavaScript 中创建对象。定义构造函数时,还可以将属性和方法附加到其原型属性。

然后,从该构造函数创建的对象的所有实例都可以访问这些属性和方法。因此,prototype 属性充当在实例之间共享的方法和属性的公共存储库。

考虑以下代码片段:

// Constructor function
function Person(name) {this.name = name;
}// Adding a method to the prototype
Person.prototype.sayHello = function() {console.log(`Hello, my name is ${this.name}.`);
};// Creating instances
const person1 = new Person("Haider Wain");
const person2 = new Person("Omer Asif");// Calling the shared method
person1.sayHello();  // Output: Hello, my name is Haider Wain.
person2.sayHello();  // Output: Hello, my name is Omer Asif.

在此示例中,我们有一个名为 Person 的构造函数。通过使用 sayHello 之类的方法扩展 Person.prototype,我们将此方法添加到所有 Person 实例的原型链中。这允许 Person 的每个实例访问和利用共享方法。而不是每个实例都有自己的方法副本。

另一方面, __proto__ 属性(通常发音为“dunder proto”)存在于每个 JavaScript 对象中。在 JavaScript 中,除了原始类型之外,所有东西都可以被视为对象。这些对象中的每一个都有一个原型,用作对另一个对象的引用。__proto__ 属性只是对此原型对象的引用。当原始对象不具备属性和方法时,原型对象用作属性和方法的后备源。默认情况下,当您创建对象时,其原型设置为 Object.prototype。

当您尝试访问对象的属性或方法时,JavaScript 会遵循查找过程来查找它。这个过程涉及两个主要步骤:

对象自己的属性:JavaScript 首先检查对象本身是否直接拥有所需的属性或方法。如果在对象中找到该属性,则直接访问和使用它。

原型链查找:如果在对象本身中找不到该属性,JavaScript 将查看该对象的原型(由 __proto__ 属性引用)并在那里搜索该属性。此过程在原型链上递归地继续,直到找到属性或查找到达 Object.prototype。

如果即使在 Object.prototype 中也找不到该属性,JavaScript 将返回 undefined,表明该属性不存在。

4、范围

编写 JavaScript 代码时,理解作用域的概念很重要。范围是指代码不同部分中变量的可访问性或可见性。在继续该示例之前,如果您不熟悉提升以及 JavaScript 代码的执行方式,可以从此链接了解它。这将帮助您更详细地了解 JavaScript 代码的工作原理。

让我们仔细看看代码片段:

function foo() {console.log(a);
}function bar() {var a = 3;foo();
}var a = 5;
bar();

该代码定义了 2 个函数 foo() 和 bar() 以及一个值为 5 的变量 a。所有这些声明都发生在全局范围内。在 bar() 函数内部,声明了一个变量 a 并赋值为 3。那么当调用 thebar() 函数时,你认为它会打印 a 的值是多少?

当 JavaScript 引擎执行此代码时,声明全局变量 a 并为其赋值 5。然后,调用 bar() 函数。在 bar() 函数内部,声明了一个局部变量 a 并赋值为 3。该局部变量 a 与全局变量 a 不同。之后,从 bar() 函数内部调用 foo() 函数。

在 foo() 函数内部,console.log(a) 语句尝试记录 a 的值。由于 foo() 函数的作用域内没有定义局部变量 a,JavaScript 会查找作用域链以找到最近的名为 a 的变量。作用域链是指函数在尝试查找和使用变量时可以访问的所有不同作用域。

现在,我们来解决 JavaScript 将在哪里搜索变量 a 的问题。它会在 bar 函数的范围内查找,还是会探索全局范围?事实证明,JavaScript 将在全局范围内进行搜索,而这种行为是由称为词法范围的概念驱动的。

词法作用域是指函数或变量在代码中编写时的作用域。当我们定义 foo 函数时,它被授予访问其自己的本地作用域和全局作用域的权限。无论我们在哪里调用 foo 函数,无论是在 bar 函数内部还是将其导出到另一个模块并在那里运行,这个特征都保持一致。词法范围不是由我们调用函数的位置决定的。

这样做的结果是输出始终相同:在全局范围内找到的 a 值,在本例中为 5。

但是,如果我们在 bar 函数中定义了 foo 函数,则会出现不同的情况:

function bar() {var a = 3;function foo() {console.log(a);}foo();
}var a = 5;
bar();

在这种情况下, foo 的词法作用域将包含三个不同的作用域:它自己的局部作用域、 bar 函数的作用域和全局作用域。词法范围由编译时将代码放置在源代码中的位置决定。

当此代码运行时,foo 位于 bar 函数内。这种安排改变了范围动态。现在,当 foo 尝试访问变量 a 时,它将首先在其自己的本地范围内进行搜索。由于它在那里找不到 a,因此它将搜索范围扩大到 bar 函数的范围。你瞧,a 存在,其值为 3。因此,控制台语句将打印 3。

5、对象强制

const obj = {valueOf: () => 42,toString: () => 27
};
console.log(obj + '');

值得探索的一个有趣的方面是 JavaScript 如何处理对象到原始值(例如字符串、数字或布尔值)的转换。这是一个有趣的问题,测试您是否知道强制转换如何与对象一起使用。

在字符串连接或算术运算等场景中处理对象时,这种转换至关重要。为了实现这一点,JavaScript 依赖于两个特殊的方法:valueOf 和 toString。

valueOf 方法是 JavaScript 对象转换机制的基本部分。当在需要原始值的上下文中使用对象时,JavaScript 首先在对象中查找 valueOf 方法。

如果 valueOf 方法不存在或未返回适当的原始值,JavaScript 将回退到 toString 方法。该方法负责提供对象的字符串表示形式。

回到我们原来的代码片段:

const obj = {valueOf: () => 42,toString: () => 27
};console.log(obj + '');

当我们运行此代码时,对象 obj 被转换为原始值。在本例中,valueOf 方法返回 42,然后,由于与空字符串连接而隐式转换为字符串。因此,代码的输出将为 42。

但是,如果 valueOf 方法不存在或未返回适当的原始值,JavaScript 将回退到 toString 方法。让我们修改一下之前的例子:

const obj = {toString: () => 27
};console.log(obj + '');

这里,我们删除了 valueOf 方法,只留下 toString 方法,该方法返回数字 27。在这种情况下,JavaScript 将诉诸 toString 方法进行对象转换。

6、理解对象键

在 JavaScript 中使用对象时,了解如何在其他对象的上下文中处理和分配键非常重要。考虑以下代码片段并花一些时间猜测输出:

let a = {};
let b = { key: 'test' };
let c = { key: 'test' };a[b] = '123';
a[c] = '456';console.log(a);

乍一看,这段代码似乎应该生成一个具有两个不同键值对的对象 a。然而,由于 JavaScript 对对象键的处理方式,结果完全不同。

JavaScript 使用默认的 toString() 方法将对象键转换为字符串。但为什么?在 JavaScript 中,对象键始终是字符串(或符号),或者它们通过隐式强制转换自动转换为字符串。当您使用字符串以外的任何值(例如数字、对象或符号)作为对象中的键时,JavaScript 会在将该值用作键之前在内部将该值转换为其字符串表示形式。

因此,当我们使用对象 b 和 c 作为对象 a 中的键时,两者都会转换为相同的字符串表示形式:[object Object]。由于这种行为,第二个赋值 a[b] = '123'; 将覆盖第一个赋值 a[c] = '456';。

现在,让我们逐步分解代码:

  • let a = {};:初始化一个空对象a。
  • let b = { key: 'test' };: 创建一个对象 b,其属性键值为 'test'。
  • let c = { key: 'test' };: 定义另一个与 b 结构相同的对象 c。
  • a[b] = '123';:将对象a中键为[object Object]的属性设置为值'123'。

a[c] = '456';:将对象 a 中键 [object Object] 相同属性的值更新为 '456',替换之前的值。

两个分配都使用相同的键字符串 [object Object]。结果,第二个赋值会覆盖第一个赋值设置的值。

当我们记录对象 a 时,我们观察到以下输出:

{ '[object Object]': '456' }

7、==运算符

console.log([] == ![]);

这个有点复杂。那么,您认为输出会是什么?让我们逐步评估一下。让我们首先看看两个操作数的类型:

typeof([]) // "object"
typeof(![]) // "boolean"

对于[]来说它是一个对象,这是可以理解的。JavaScript 中的一切都是对象,包括数组和函数。但是操作数![]如何具有布尔类型呢?让我们试着理解这一点。当你使用 ! 对于原始值,会发生以下转换:

假值:如果原始值是假值(例如 false、0、null、undefined、NaN 或空字符串 ''),则应用 ! 会将其转换为 true。

真值:如果原始值是真值(任何非假值),则应用!会将其转换为 false。

在我们的例子中,[] 是一个空数组,它是 JavaScript 中的真值。由于 [] 为真,所以 ![] 变为假。所以,我们的表达式就变成了:

[] == ![]
[] == false

现在让我们继续了解 == 运算符。每当使用 == 运算符比较 2 个值时,JavaScript 就会执行抽象相等比较算法。 

该算法有以下步骤:

正如您所看到的,该算法考虑了比较值的类型并执行必要的转换。

对于我们的例子,我们将 x 表示为 [],将 y 表示为 ![]。我们检查了 x 和 y 的类型,发现 x 是对象,y 是布尔值。由于 y 是布尔值,x 是对象,因此应用抽象相等比较算法中的条件 7:

如果 Type(y) 为 Boolean,则返回 x == ToNumber(y) 的比较结果。

这意味着如果其中一种类型是布尔值,我们需要在比较之前将其转换为数字。ToNumber(y) 的值是多少?正如我们所看到的,[] 是一个真值,否定则使其为假。结果,Number(false)为0。

[] == false
[] == Number(false)
[] == 0

现在我们有了比较 [] == 0,这次条件 8 开始发挥作用:

如果 Type(x) 是 String 或 Number 并且 Type(y) 是 Object,则返回比较结果 x == ToPrimitive(y)。

基于这个条件,如果其中一个操作数是对象,我们必须将其转换为原始值。这就是 ToPrimitive 算法发挥作用的地方。我们需要将 [] x 转换为原始值。数组是 JavaScript 中的对象。正如我们之前所看到的,当将对象转换为基元时,valueOf 和 toString 方法就会发挥作用。 

在这种情况下, valueOf 返回数组本身,它不是有效的原始值。因此,我们转向 toString 进行输出。将 toString 方法应用于空数组会得到一个空字符串,这是一个有效的原语:

[] == 0
[].toString() == 0
"" == 0

将空数组转换为字符串会得到一个空字符串“”,现在我们面临比较:“”== 0。

现在,其中一个操作数是字符串类型,另一个操作数是数字类型,则条件 5 成立:

如果 Type(x) 是 String 并且 Type(y) 是 Number,则返回比较结果 ToNumber(x) == y。

因此,我们需要将空字符串“”转换为数字,即为 0。

"" == 0
ToNumber("") == 0
0 == 0

最后,两个操作数具有相同的类型并且条件 1 成立。由于两者具有相同的值,因此,最终输出为:

0 == 0 // true

到目前为止,我们在探索的最后几个问题中使用了强制转换,这是掌握 JavaScript 和在面试中解决此类问题的重要概念,这些问题往往会被问到很多。 

8、闭包

这是与闭包相关的最著名的面试问题之一:

const arr = [10, 12, 15, 21];
for (var i = 0; i < arr.length; i++) {setTimeout(function() {console.log('Index: ' + i + ', element: ' + arr[i]);}, 3000);
}

如果您知道输出,那就好了。那么,让我们尝试理解这个片段。从表面上看,这段代码片段将为我们提供以下输出:

Index: 0, element: 10
Index: 1, element: 12
Index: 2, element: 15
Index: 3, element: 21

但这里的情况并非如此。由于闭包的概念以及 JavaScript 处理变量作用域的方式,实际的输出会有所不同。当延迟 3000 毫秒后执行 setTimeout 回调时,它们都将引用同一个变量 i,循环完成后该变量的最终值为 4。结果,代码的输出将是:

Index: 4, element: undefined
Index: 4, element: undefined
Index: 4, element: undefined
Index: 4, element: undefined

出现此行为的原因是 var 关键字没有块作用域,并且 setTimeout 回调捕获对同一 i 变量的引用。当回调执行时,它们都会看到 i 的最终值,即 4,并尝试访问未定义的 arr[4]。

为了实现所需的输出,您可以使用 let 关键字为循环的每次迭代创建一个新范围,确保每个回调捕获 i 的正确值:

const arr = [10, 12, 15, 21];
for (let i = 0; i < arr.length; i++) {setTimeout(function() {console.log('Index: ' + i + ', element: ' + arr[i]);}, 3000);
}

通过此修改,您将获得预期的输出:

Index: 0, element: 10
Index: 1, element: 12
Index: 2, element: 15
Index: 3, element: 21

使用 let 在每次迭代中为 i 创建一个新的绑定,确保每个回调引用正确的值。

通常,开发人员已经熟悉涉及 let 关键字的解决方案。然而,面试有时会更进一步,挑战你在不使用 let 的情况下解决问题。在这种情况下,另一种方法是通过立即调用循环内的函数(IIFE)来创建闭包。这样,每个函数调用都有自己的 i 副本。您可以这样做:

const arr = [10, 12, 15, 21];
for (var i = 0; i < arr.length; i++) {(function(index) {setTimeout(function() {console.log('Index: ' + index + ', element: ' + arr[index]);}, 3000);})(i);
}

在此代码中,立即调用的函数 (function(index) { ... })(i); 为每次迭代创建一个新范围,捕获 i 的当前值并将其作为索引参数传递。这确保每个回调函数都有自己单独的索引值,防止与闭包相关的问题并为您提供预期的输出:

Index: 0, element: 10
Index: 1, element: 12
Index: 2, element: 15
Index: 3, element: 21

总结

以上就是我今天这篇文章想与您分享的8个关于JS的前端面试题, 我希望这篇文章对您的面试准备之旅有所帮助。 

如果您还有任何疑问,请在留言区给我们留言,我们一起交流学习进步。

最后,推荐一款应用开发神器

扯个嗓子!关于目前低代码在技术领域很活跃!

低代码是什么?一组数字技术工具平台,能基于图形化拖拽、参数化配置等更为高效的方式,实现快速构建、数据编排、连接生态、中台服务等。通过少量代码或不用代码实现数字化转型中的场景应用创新。它能缓解甚至解决庞大的市场需求与传统的开发生产力引发的供需关系矛盾问题,是数字化转型过程中降本增效趋势下的产物。

这边介绍一款好用的低代码平台——JNPF快速开发平台。近年在市场表现和产品竞争力方面表现较为突出,采的是最新主流前后分离框架(SpringBoot+Mybatis-plus+Ant-Design+Vue3。代码生成器依赖性低,灵活的扩展能力,可灵活实现二次开发。

以JNPF为代表的企业级低代码平台为了支撑更高技术要求的应用开发,从数据库建模、Web API构建到页面设计,与传统软件开发几乎没有差异,只是通过低代码可视化模式,减少了构建“增删改查”功能的重复劳动,还没有了解过低代码的伙伴可以尝试了解一下。

应用:https://www.jnpfsoft.com/?csdn

有了它,开发人员在开发过程中就可以轻松上手,充分利用传统开发模式下积累的经验。所以低代码平台对于程序员来说,有着很大帮助。

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

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

相关文章

同步推送?苹果计划本月推出 iOS17和iPadOS17,你的手机支持吗?

据报道&#xff0c;苹果公司计划在本月推出 iOS 17 和 iPadOS 17 正式版更新。与去年不同的是&#xff0c;这次更新将同时发布&#xff0c;而不是分别发布。根据彭博社的一位消息人士马克・古尔曼的说法&#xff0c;苹果公司认为 iOS 17 和 iPadOS 17 的第八个测试版已经非常接…

动态库的制作与使用及 动态库加载失败解决

加载动态库时有时会出现error while loading shared libraries&#xff1a;libcalc.so:可以通过lld命令查看动态库的依赖关系&#xff0c;发现libcalc.so时not found 原因 查找的优先级是DT_RPATH->LD_LIBRARY_PATH->/etc/ld.so.cache->/lib/,/usr/lib 找不到一个优…

文心一言api接入如何在你的项目里使用文心一言

文心一言api接入在项目里接入文心一言 一、百度文心一言API二、使用步骤1、接口2、请求参数3、请求参数示例4、接口 返回示例 三、 如何获取appKey和uid1、申请appKey:2、获取appKey和uid 四、重要说明 一、百度文心一言API 基于百度文心一言语言大模型的智能文本对话AI机器人…

java读取服务器数据包并下载至本地目录

jsch包如果没有的话&#xff0c;可评论联系我&#xff0c;我私发给你&#xff0c;或者通过https://mvnrepository.com/artifact/com.jcraft/jsch/0.1.55进行下载&#xff0c;添加至工程目录 package com.hbisdt.dqbasic.modular.util;import com.jcraft.jsch.*;import java.i…

【word技巧】如何在word文件中方框打对勾?

Word文件制作了调查问卷或者信息表之类的文件&#xff0c;总是少不了有需要打勾的选项&#xff0c;如果打印成了纸质文件打勾就简单了&#xff0c;但是在word文件中应该如何在方框中打√符号呢&#xff1f;今天分享三个方法。 方法一&#xff1a; 先输入一个大写的R&#xff…

个人信息去标识化具体实施指南

声明 本文是学习个人信息去标识化指南. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 范围 本标准描述了个人信息去标识化的目标和原则&#xff0c;提出了去标识化过程和管理措施。 本标准针对微数据提供具体的个人信息去标识化指导&#xff0c;适…

哈希的应用——布隆过滤器

文章目录 前言1. 布隆过滤器提出2. 布隆过滤器概念3. 布隆过滤器的插入多哈希函数映射减少冲突结构定义及set&#xff08;插入&#xff09;函数实现 4. 布隆过滤器的查找test&#xff08;查找&#xff09;函数实现布隆过滤器允许误判 5. 布隆过滤器的适用场景6. 如何选择布隆过…

JVM 对象的内存布局

对象头 Mark word 标记字段 用于存储对象自身的运行时数据&#xff0c;如哈希码&#xff08;HashCode&#xff09;、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等 ClassPoint 类型指针 对象指向它的类型元数据的指针&#xff0c;Java虚拟机通过这个指针 来…

延时消息队列

目录 前言 一、延时队列实用场景 二、DelayQueue DelayQueue的实现 使用延迟队列 DelayQueue实现延时任务的优缺点 三、RocketMQ 原理 四、Kafka 原理 实现 DelayMessage定义 消息发送代码 消费者代码 参考 前言 延时队列的内部是有序的&#xff0c;最重要的…

Linux之NFS服务器

目录 Linux之NFS服务器 简介 NFS背景介绍 生产应用场景 NFS工作原理 NFS工作流程图 流程 NFS的安装 安装nfs服务 安装rpc服务 启动rpcbind服务同时设置开机自启动 启动nfs服务同时设置开机自启动 NFS的配置文件 主配置文件分析 示例 案例 --- 建立NFS服务器&#…

【Python】环境的搭建

前言 要想能够进行 Python 开发, 就需要搭建好 Python 的环境. 需要安装的环境主要是两个部分: 运行环境: Python开发环境: PyCharm 一、安装 Python 1.找到官方网站 官网&#xff1a;Welcome to Python.org 2.找到下载页面 点击download中的Windows 3.选择稳定版中的Win…

【计算机网络】HTTPS

文章目录 1. HTTPS的概念2. 加密常见的加密方式对称加密非对称加密 3. HTTPS的工作过程的探究方案1 —— 只使用对称加密方案2 —— 只使用 非对称加密方案3 —— 双方都是用非对称加密方案4 —— 非对称加密对称加密中间人攻击引入证书CA认证理解数据签名 方案5 —— 非对称加…

Java守护线程的理解及应用

在Java中有两类线程&#xff0c;分别是User Thread&#xff08;用户线程&#xff09;和Daemon Thread&#xff08;守护线程&#xff09; 。 用户线程很好理解&#xff0c;我们日常开发中编写的业务逻辑代码&#xff0c;运行起来都是一个个用户线程。而守护线程相对来说则要特别…

C#__资源访问冲突和死锁问题

/// 线程的资源访问冲突&#xff1a;多个线程同时申请一个资源&#xff0c;造成读写错乱。 /// 解决方案&#xff1a;上锁&#xff0c;lock{执行的程序段}:同一时刻&#xff0c;只允许一个线程访问该程序段。 /// 死锁问题&#xff1a; /// 程序中的锁过多&#xf…

vscode debug python launch.json添加args不起作用

问题 为了带入参数调试python 程序&#xff0c;按照网上搜到的教程配置了lauch.json文件&#xff0c;文件中添加了"args": [“model” “0” “path”] {// 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。// 欲了解更多信息&#xff0c;请访问: h…

深入浅出学Verilog--基础语法

1、简介 Verilog的语法和C语言非常类似&#xff0c;相对来说还是非常好学的。和C语言一样&#xff0c;Verilog语句也是由一连串的令牌&#xff08;Token&#xff09;组成。1个令牌必须由1个或1个以上的字符&#xff08;character&#xff09;组成&#xff0c;令牌可以是&#x…

day3_C++

day3_C 思维导图用C的类完成数据结构 栈的相关操作用C的类完成数据结构 循环队列的相关操作 思维导图 用C的类完成数据结构 栈的相关操作 stack.h #ifndef STACK_H #define STACK_H#include <iostream> #include <cstring>using namespace std;typedef int datat…

2023 年全国大学生数学建模竞赛题D 题 圈养湖羊的空间利用率思路详解+Python源码(二)

昨天已经将E题第一二问的详解和思路源码都写了出来&#xff0c;大家如果想从E题下手的话推荐参考本人文章&#xff0c;个人认为E题在建模上是优于D题的&#xff0c;毕竟有给出数据而且有明确的建模思路&#xff0c;E题我直接提供了Python源码直接可以运行即可&#xff1a; 202…

STC15单片机特有的PWM寄存器和普通定时器实现PWM输出

STC15单片机特有的PWM寄存器和普通定时器实现PWM输出 🌿主要针对STC15W4型号特有的6通道15位专门的高精度PWM。 ✨STC15W4K32S4系列单片机具有6通道15位专门的高精度PWM(带死区控制)和2通道CCP(利用它的高速脉冲输出功能可实现11~16位PWM);(STC15F/L2K60S2系列单片机具有3通…

Android逆向学习(番外一)smali2java部分文件无法反编译的bug与修复方法

Android逆向学习&#xff08;番外一&#xff09;smali2java部分文件无法反编译的bug与修复方法 一、前言 昨天我和往常一样准备着android逆向&#xff08;四&#xff09;的博客&#xff0c;结果发现smali2java对某些文件无法进行逆向&#xff0c;我不知道windows会不会产生这…