一些前端笔试题

157 阅读19分钟

http的标准请求方法

  1. GET:请求从服务器检索数据。GET请求应该只用于获取数据并且不产生副作用。
  2. POST:向服务器提交新的数据,通常会导致服务器上的状态变化或数据库的更新。
  3. PUT:更新服务器上的现有资源。PUT请求应该包含完整的资源表示,以便可以替换现有资源。
  4. DELETE:删除服务器上的资源。
  5. HEAD:与GET方法类似,但服务器在响应中只返回头部信息,不返回实体的主体部分。
  6. OPTIONS:用于获取目的资源所支持的通信选项。这个方法可以用来查询服务器支持哪些HTTP方法。

其中fetch不属于标准方法

如何删除localStorage特定的项

要删除localStorage中的特定项,可以使用localStorage.removeItem()方法。这个方法接受一个参数,即你想要删除的项的键名(key)。以下是如何使用这个方法的示例:

// 假设我们有一个存储在localStorage中的项,键名为'myKey'
localStorage.setItem('myKey', 'someValue');
​
// 要删除这个特定的项,我们调用removeItem方法,并传入键名'myKey'
localStorage.removeItem('myKey');

执行上述代码后,localStorage中键名为myKey的项将被删除。

此外,如果你想删除所有存储在localStorage中的项,可以使用localStorage.clear()方法:

localStorage.clear();

这将清空localStorage中的所有数据。

请注意,localStorage中的数据没有过期时间,所以如果你不显式地删除它们,浏览器会永久保存这些数据,直到用户手动清除浏览器缓存或者使用脚本进行删除。

阻止时间冒泡正确的写法

在JavaScript中,要阻止事件冒泡,你需要使用事件对象的 stopPropagation() 方法。这个方法会阻止事件继续在DOM树中向上传播,即阻止事件冒泡到父元素。

以下是阻止事件冒泡的一些正确写法:

1. 使用 stopPropagation() 方法

在事件处理函数中调用 event.stopPropagation()

element.addEventListener('click', function(event) {
    event.stopPropagation();
    // 其他代码
});

2. 使用 event_ 前缀作为参数

在事件处理函数中,将 event 作为参数,然后调用 stopPropagation()

element.onclick = function(event_) {
    event_.stopPropagation();
    // 其他代码
};

请注意,使用 event_ 或其他类似的命名前缀是为了避免与全局的 event 对象发生冲突。

3. 使用 e 作为参数

在实际开发中,通常使用单字母 e 作为事件对象的参数:

element.onclick = function(e) {
    e.stopPropagation();
    // 其他代码
};

4. 链式调用 stopPropagation()stopImmediatePropagation()

如果你想要同时阻止事件冒泡和事件的立即传播(即阻止同一元素上的其他事件监听器被调用),可以链式调用 stopImmediatePropagation()

element.addEventListener('click', function(event) {
    event.stopPropagation();
    event.stopImmediatePropagation();
    // 其他代码
});

注意事项

  • 确保在适当的时机调用 stopPropagation(),太早调用可能会影响到事件的正常处理。
  • 在使用事件委托的情况下,stopPropagation() 非常有用,因为它允许你控制事件是否应该冒泡到父元素。
  • 过度使用 stopPropagation() 可能会导致代码难以维护,因此应当谨慎使用。

如果一个函数声明三个参数只传递两个会发生什么

在JavaScript中,如果你声明了一个接受三个参数的函数,但只传递了两个参数,函数仍然会正常执行,但是未传递的参数将会有默认值 undefined

下面是一个例子:

function myFunction(param1, param2, param3) {
    console.log(param1, param2, param3);
}
​
myFunction(10, 20); // 输出: 10 20 undefined

在这个例子中,myFunction 被定义为接受三个参数,但是在调用时只传递了两个值(10 和 20)。第三个参数 param3 没有被传递,因此它的值是 undefined

这种行为是JavaScript函数的一个特性,它允许函数接受比声明时更少的参数数量。函数的参数默认是松散类型的,这意味着你可以根据需要传递更少的参数,而函数会为未提供的参数自动设置为 undefined

如果你希望在未传递参数时为参数设置特定的默认值,你可以使用默认参数值语法:

function myFunction(param1, param2, param3 = 'default value') {
    console.log(param1, param2, param3);
}
​
myFunction(10, 20); // 输出: 10 20 'default value'

在这个例子中,如果调用 myFunction 时没有传递第三个参数,param3 将会被赋予默认值 'default value'。默认参数值是在ES6(ECMAScript 2015)中引入的特性,它允许你在函数定义时为参数指定默认值。

事件冒泡描述正确的是(事件冒泡不是事件循环)

事件冒泡(Event Bubbling)是Web浏览器中事件传播的一种机制。当一个事件(如点击或鼠标移动)在一个元素上触发时,它不仅会触发该元素的事件处理程序,还会逐级向上传播到该元素的父元素,直到文档的根元素。这个过程称为事件冒泡。

以下是描述事件冒泡的一些正确方面:

  1. 自然行为:事件冒泡是DOM事件模型的自然行为之一。
  2. 向上传播:事件从最具体的元素(事件的目标元素)开始,逐级向上冒泡到文档的根元素。
  3. 捕获阶段:在事件到达目标元素之前,会先经过捕获阶段。在这个阶段,事件从根元素向下传播到目标元素的各个层次。
  4. 目标不变:在事件冒泡过程中,事件的目标(即最初触发事件的元素)保持不变。
  5. 可以被停止:事件冒泡可以通过调用事件对象的stopPropagation()方法来停止,防止事件继续向上传播。
  6. 默认行为:大多数浏览器的默认行为是允许事件冒泡,除非开发者明确停止它。
  7. 事件委托:事件冒泡是实现事件委托(Event Delegation)的基础。事件委托是一种技术,通过在父元素上设置监听器来处理子元素的事件,这可以提高性能并减少内存使用。
  8. 兼容性:事件冒泡在所有现代浏览器中都得到支持,是一种广泛使用的技术。
  9. 与事件捕获的区别:事件冒泡与事件捕获不同,事件捕获是从根元素开始,向下传播到目标元素的过程。
  10. 应用场景:事件冒泡常用于实现菜单、导航栏等组件,其中父元素的点击可以代表或影响子元素的行为。

闭包如何影响 js 的垃圾回收机制

在JavaScript中,闭包可以对垃圾回收机制产生显著的影响。垃圾回收(Garbage Collection,GC)是JavaScript运行时环境自动释放不再使用的对象所占用内存的过程。闭包由于其特殊的性质,能够持续引用变量,从而阻止垃圾回收器回收这些变量所占用的内存。以下是闭包影响垃圾回收的几个方面:

  1. 持续引用:闭包由至少两个函数组成,内层函数能够访问外层函数的变量作用域。如果外层函数执行完毕后,内层函数仍然存活(例如被赋值给一个全局变量或作为回调函数),那么外层函数的变量作用域中的变量不会被垃圾回收,因为内层函数仍然引用它们。
  2. 内存泄漏:如果开发者不小心,闭包可能导致内存泄漏。例如,如果一个闭包持续引用一个大型对象,即使这个对象不再需要,只要闭包存活,这个对象也会继续占用内存。
  3. 循环引用:在某些情况下,闭包可能会创建循环引用,即两个或多个对象互相引用,形成一个闭环。在JavaScript中,循环引用通常不会导致内存泄漏,因为垃圾回收器可以识别并处理这种情况。但是,如果循环引用中包含闭包,可能会使得垃圾回收变得更加复杂。
  4. 全局变量:如果闭包中包含了对全局变量的引用,这些全局变量也会持续存活,因为闭包本身可能被保留在内存中。
  5. 定时器和事件监听器:使用闭包设置定时器或事件监听器时,如果这些回调函数持续引用外部作用域的变量,这些变量将不会被垃圾回收,直到定时器被清除或事件监听器被移除。

为了减少闭包对垃圾回收的影响,可以采取以下措施:

  • 及时解除引用:当闭包不再需要时,确保释放其引用的外部变量。
  • 使用弱引用:在可能的情况下,使用如WeakMapWeakSet这样的数据结构,它们不会增加垃圾回收的复杂性。
  • 避免不必要的闭包:如果不需要闭包的功能,避免创建它们,以减少不必要的内存占用。
  • 清理资源:对于使用闭包的定时器和事件监听器,确保在不需要时进行清除。

有引用的情况是阻止垃圾回收

typeof [0,1] ==

在JavaScript中,typeof 操作符用来返回一个值的数据类型。当你对一个数组使用 typeof 时,它会返回字符串 "object",因为数组在JavaScript中是对象的一种类型。

所以,表达式 typeof [0,1] 的结果是:

"object"

这意味着 typeof [0,1] == 的完整表达式应该是在比较 "object" 与某个值。例如:

typeof [0,1] == "object"; // true
typeof [0,1] == "array";  // false

第一个比较操作返回 true,因为数组确实是对象。第二个比较操作返回 false,因为尽管数组是特殊的对象,typeof 不会返回 "array"。要检查一个值是否为数组,你应该使用 Array.isArray() 方法。

能改变this的函数有哪些?

在JavaScript中,this的值是在函数被调用时确定的,它指向函数执行的上下文。有一些特定的函数和方法可以改变this的指向。以下是一些常见的可以改变this指向的函数和方法:

  1. 函数调用:默认情况下,当一个函数被调用时,如果它不是作为对象的方法或者以其他方式被调用,this会指向全局对象(在浏览器中是window,在Node.js中是global)。

  2. 方法调用:当一个函数作为对象的方法被调用时,this会指向该对象。

  3. 构造函数:使用new关键字调用函数时,this会指向新创建的对象。

  4. 事件处理:在事件处理函数中,this通常指向触发事件的元素。

  5. call 方法call方法允许你调用一个函数,并将this关键字设置为调用运行时指定的任何对象。

    function sayHello() {
      console.log(`Hello, ${this.name}!`);
    }
    const person = { name: 'Kimi' };
    sayHello.call(person); // Hello, Kimi!
    
  6. apply 方法:与call类似,apply方法也允许你调用一个函数并设置this,但它接受一个参数数组。

    sayHello.apply(person); // Hello, Kimi!
    
  7. bind 方法bind方法创建一个新的函数,在bind被调用时,this被设置为提供的值,无论这个新函数在哪里被调用。

    const boundSayHello = sayHello.bind(person);
    boundSayHello(); // Hello, Kimi!
    
  8. 箭头函数:箭头函数不绑定自己的this,它会捕获其所在上下文的this值,作为自己的this值,但是你不能通过callapplybind改变箭头函数的this

  9. Function.prototype 的上下文重置Function.prototype有一个@@hasInstance方法,它在instanceof操作符中用来确定原型。虽然这不是直接改变this,但它可以影响与this相关的操作。

  10. with 语句with语句可以临时改变this的上下文,但这个语句已经被废弃,不推荐使用。

  11. eval 函数eval函数可以执行一个字符串作为代码,它可能会改变this的值,但这通常不是一个好的做法,因为eval存在安全和性能问题。

+0 === -0 1/+0=== 1/-0

在JavaScript中,+0-0 都是数值零的不同表示形式,它们在进行大多数比较时被认为是相等的。因此:

+0 === -0; // true

这意味着 +0-0 在使用严格等于(===)操作符进行比较时会被认为是相等的。

然而,当你对零进行除法运算时,结果会根据零的符号而变化。除以正零(+0)和负零(-0)会得到不同的结果,因为它们会保留被除数的符号:

1 / +0; // Infinity
1 / -0; // -Infinity

这里,1 / +0 的结果是 Infinity,因为任何非零数除以正零都等于正无穷大。而 1 / -0 的结果是 -Infinity,因为任何非零数除以负零都等于负无穷大。

在JavaScript中,无穷大(Infinity)和负无穷大(-Infinity)是不相等的:

Infinity === -Infinity; // false

因此,尽管 +0-0 在比较时被认为是相等的,但它们在数学运算中的行为是不同的。

注意

INDEFINE !==INDEFINE

相对于https//a.mucang.com:8080/不会产生跨域的地址是

跨域问题通常发生在浏览器的同源策略下,该策略出于安全考虑,限制了来自不同源(协议、域名、端口)的网页对当前网页的脚本进行交互。如果两个URL的协议、域名或端口不同,则它们被认为是不同的源。

假设给定的URL是 https://a.mucang.com:8080/,那么不会触发跨域请求的地址应该满足以下条件之一:

  1. 协议相同:请求的地址也应该是HTTPS。
  2. 域名相同:请求的地址的域名也应该是 a.mucang.com
  3. 端口相同:请求的地址的端口也应该是 8080

例如,以下地址相对于 https://a.mucang.com:8080/ 不会产生跨域问题:

  • https://a.mucang.com:8080/some/path(同源)
  • https://a.mucang.com:8080/another/resource(同源)

而以下地址会产生跨域问题:

  • http://a.mucang.com:8080/(协议不同)
  • https://b.mucang.com:8080/(域名不同)
  • https://a.mucang.com:8090/(端口不同)
  • https://a.mucang.com/(端口不同,因为默认HTTPS端口是443)

请注意,即使两个URL在技术上是同源的,服务器端的设置也必须允许跨域请求,否则浏览器仍然会阻止请求。服务器可以通过设置适当的CORS(跨源资源共享)头部来允许跨域请求。

js哪些声明方法会存在暂时性死区

在JavaScript中,暂时性死区(Temporal Dead Zone, TDZ) 是指在声明变量的代码执行之前,变量的值是未初始化的,不能被访问的时间段。这个概念主要与letconst声明有关,因为它们具有块级作用域,而var声明则没有TDZ。

以下是会存在暂时性死区的声明方法:

  1. let 声明: 使用 let 声明的变量在声明它的块级作用域内,在变量声明之前使用它会导致 ReferenceError

    if (true) {
      console.log(x); // ReferenceError: x is not defined
      let x = 5;
    }
    
  2. const 声明: 与 let 类似,const 声明的变量也存在TDZ。在声明之前访问它会导致错误。

    if (true) {
      console.log(myConst); // ReferenceError: myConst is not defined
      const myConst = 10;
    }
    
  3. class 声明: 类声明也存在TDZ,尽管它不是变量声明,但类定义在提升到其作用域的顶部,因此在类声明之前不能使用它。

    console.log(MyClass); // ReferenceError: MyClass is not defined
    class MyClass {}
    
  4. import 语句: 使用ES6模块的 import 语句时,也存在TDZ。在模块被加载并解析之前,不能访问导入的模块。

    // 假设有一个模块导出了一个名为foo的变量
    // import foo from './module.js'; // 正确的使用方式
    ​
    console.log(foo); // ReferenceError: foo is not defined
    

var 声明则没有TDZ,因为它是函数作用域或全局作用域的,并且变量在声明之前就可以访问,只是其值为 undefined

if (true) {
  console.log(x); // 输出 undefined,而不是 ReferenceError
  var x = 5;
}

TDZ是JavaScript中一个重要的概念,它帮助开发者避免在代码中使用未初始化的变量,从而减少运行时错误。

哪个方法可以将一个对象转换为bool

在JavaScript中,并没有一个直接的方法可以将一个对象转换为布尔值(truefalse)。但是,JavaScript在进行布尔上下文的检查时,会自动将对象转换为布尔值。在布尔上下文中,除了几种特殊值外,所有对象都会被转换为 true

特殊的“假值”(falsy values)包括:

  1. false
  2. 0(数字0)
  3. -0(负零)
  4. 0n(BigInt类型的0)
  5. ""(空字符串)
  6. null
  7. undefined
  8. NaN(不是一个数字)

除了这些假值,所有其他值,包括所有对象(即使是空对象 {}),在布尔上下文中都会被转换为 true

如果你想要检查一个对象是否为真值,你可以使用条件语句或者逻辑运算符,例如:

let obj = {};
​
if (obj) {
  console.log("obj is truthy"); // 这将会被执行,因为对象在布尔上下文中为true
}
​
console.log(!!obj); // true,使用双非操作符显式转换为布尔值

如果你的目的是检查一个对象是否不是 nullundefined,并且不是空对象,你可以使用以下方式:

function isObjectTruthy(obj) {
  return obj && typeof obj === 'object';
}
​
let nonEmptyObj = { key: "value" };
let emptyObj = {};
let nullObj = null;
let undefinedObj;
​
console.log(isObjectTruthy(nonEmptyObj)); // true
console.log(isObjectTruthy(emptyObj)); // true
console.log(isObjectTruthy(nullObj)); // false
console.log(isObjectTruthy(undefinedObj)); // false

在这个例子中,isObjectTruthy 函数首先检查对象是否为真值,然后检查它是否是一个对象类型。这样,nullundefined 以及非对象类型的值都会被认为不是真值。

js中哪些方法可以用于检查一个字符串是否包含另一个字符串

在JavaScript中,有几种方法可以用来检查一个字符串是否包含另一个字符串。以下是一些常用的方法:

  1. includes() 方法: includes() 方法用于判断一个字符串是否包含另一个字符串,返回一个布尔值(true 或 false)。

    let str = "Hello, world!";
    console.log(str.includes("world")); // true
    console.log(str.includes("moon")); // false
    
  2. indexOf() 方法: indexOf() 方法返回子字符串在字符串中首次出现的位置,如果没有找到则返回-1。

    let str = "Hello, world!";
    console.log(str.indexOf("world") !== -1); // true
    console.log(str.indexOf("moon") !== -1); // false
    
  3. match() 方法: match() 方法用于检索字符串中与正则表达式匹配的部分,返回匹配结果数组或null。

    let str = "Hello, world!";
    console.log(str.match(/world/)); // ["world"]
    console.log(str.match(/moon/)); // null
    
  4. search() 方法: search() 方法用于检索字符串中满足正则表达式的部分,并返回该部分的位置。如果没有找到匹配的部分,则返回-1。

    let str = "Hello, world!";
    console.log(str.search(/world/) !== -1); // true
    console.log(str.search(/moon/) !== -1); // false
    
  5. startsWith()endsWith() 方法: 这两个方法用于检查字符串是否以指定的子字符串开始或结束。它们返回布尔值。

    let str = "Hello, world!";
    console.log(str.startsWith("Hello")); // true
    console.log(str.endsWith("!")); // true
    
  6. some() 方法(对于数组): 如果你将字符串转换为数组,并使用 some() 方法来检查数组中是否有包含特定子字符串的元素,也可以实现这一功能。

    let str = "Hello, world!";
    let chars = str.split('');
    console.log(chars.some(char => char === "w")); // true
    console.log(chars.some(char => char === "z")); // false
    

使用这些方法时,需要注意它们对大小写的敏感性。如果需要进行不区分大小写的检查,可能需要先将字符串转换为统一的大小写形式。

块级元素有哪些

在HTML和CSS中,块级元素(Block-level elements)默认会开始于新的一行,并且其宽度默认填满其父元素的宽度(除非指定了宽度)。块级元素通常会对文档的布局产生较大的影响。以下是一些常见的块级元素:

  1. <address>:定义文档或文章的作者/拥有者的联系信息。
  2. <article>:表示页面独立的内容区块。
  3. <aside>:表示与页面内容略微相关的内容,如侧边栏或广告。
  4. <footer>:定义文档或文档区块的页脚。
  5. <header>:定义文档或文档区块的页眉。
  6. <nav>:表示页面的导航链接。
  7. <section>:定义文档中的一个区段。
  8. <h1><h6>:定义标题。虽然标题标签通常用于文本,但它们也是块级元素。
  9. <p>:定义段落。
  10. <div>:作为一个通用的容器,可以用来包装其他元素。
  11. <blockquote>:表示一段引用的文本。
  12. <dl>:定义定义列表(通常与 <dt><dd> 配合使用)。
  13. <dt>:定义列表中术语的列表项。
  14. <dd>:定义列表中术语的定义。
  15. <figcaption>:定义 <figure> 元素的标题。
  16. <figure>:表示自包含的内容,通常与 <figcaption> 配合使用。
  17. <form>:定义表单。
  18. <ol>:定义有序列表。
  19. <ul>:定义无序列表。
  20. <li>:定义列表项(在 <ol><ul> 中使用)。
  21. <table>:定义表格。
  22. <thead>:定义表格的头部。
  23. <tbody>:定义表格的主体。
  24. <tfoot>:定义表格的脚注。
  25. <tr>:定义表格中的行。
  26. <th>:定义表格中的表头单元格。
  27. <td>:定义表格中的单元格。

这些块级元素可以包含其他块级元素和内联元素,但通常不包含块级元素之外的块级元素。内联元素(Inline elements)则可以放在块级元素内部

哪个选择器用于相邻兄弟元素

在CSS中,用于选择相邻兄弟元素的选择器是相邻兄弟选择器(Adjacent Sibling Selector)。这个选择器由两个由加号(+)连接的简单选择器组成,它匹配紧随第一个选择器元素之后的第一个匹配第二个选择器的兄弟元素。

以下是相邻兄弟选择器的一些示例:

  1. 如果你想要选中一个<p>元素后面紧跟的<span>元素,你可以使用:
p + span {
    /* CSS样式 */
}
  1. 如果你想要选中一个<li>元素后面紧跟的<li>元素(即同一个<ul><ol>列表中的相邻列表项),你可以使用:
li + li {
    /* CSS样式 */
}

相邻兄弟选择器只匹配紧挨着的兄弟元素,如果中间有其他类型的元素,那么加号选择器将不会匹配。

html中哪一个表示引号

在HTML中,引号可以通过以下字符实体来表示:

  1. 双引号:&quot;&#34;
  2. 单引号:&apos;&#39;

例如,如果你想在HTML中表示一个包含引号的字符串,你可以这样写:

<p>He said, "Hello, world!"</p>

在上述例子中,双引号被&quot;字符实体所替换,这样浏览器就可以正确地解析并显示引号了。

代码阅读

console.log('start');
const promise1 = new Promise((res)=>{console.log(1)});
console.log("end");

代码输出:

start
1
end
var array = []
for(var i =0;i<3;i++){
    array.push(()=> i)
}
var newArray = array.map(ei=>ei())
console.log(newArray.join(""))

代码输出:

333