前端面试笔试(三)

目录

一、数据结构算法等综合篇

二、代码输出篇

1.yield与生成器函数

2.this指向有关

[3.instanceof 与Array.isArray](#3.instanceof 与Array.isArray)

[4.继承class cls extends Array,调用里面的sum方法](#4.继承class cls extends Array,调用里面的sum方法)

三、css、html、JavaScript篇

1.哪项不能提高dom元素操作效率?

2.contenteditable

基本功能:

使用场景:

注意:

示例:

3.关于promise的then、catch、resolve、reject

逐项解析:


一、数据结构算法等综合篇

二、代码输出篇

1.yield与生成器函数

javascript 复制代码
  function* func(){
      yield 117;
      yield 935;
      return 130;
  }
  const res=func();
  for(let item of res){
      console.log(item);
  }

输出结果为:

这段代码定义了一个生成器函数 func,并通过 for...of 循环遍历了该生成器函数返回的迭代器 res

  • function* func(){...} 定义了一个名为 func 的生成器函数。生成器函数是一种特殊的函数,可以暂停执行并在之后重新恢复执行,通过 yield 关键字实现。
  • yield 117;:当生成器函数被调用并迭代时,它会在这里暂停,并返回 117 给迭代器。
  • yield 935;:在下一次迭代时,函数会从这里继续执行,并返回 935。
  • return 130;:当生成器函数完成迭代(即没有更多的 yield 表达式可供迭代),它可以通过 return 语句返回一个值。这个值可以通过调用迭代器的 return() 方法获取,但在这个例子中并没有这样做。
  • const res = func();:调用生成器函数 func,并将返回的迭代器赋值给变量 res
  • for(let item of res){...}:使用 for...of 循环遍历迭代器 res。每次迭代,迭代器会执行生成器函数的下一个 yield 表达式,直到没有更多的 yield 表达式。
  • console.log(item);:在循环体内,打印出每次迭代得到的值。

如果要获取这个返回的130,需要:

javascript 复制代码
console.log(res.return().value)

2.this指向有关

javascript 复制代码
  function test(){
      this.flag=false;
      this.change=()=>{
          this.flag=true;
          console.log(button.flag);
      };
  }
  const button=new test()
  document.addEventListener("click",button.change)

点击了浏览器后输出为true

  • 首先button是通过new test()的方式来得到的,new返回的对象,this指向对象本身 。所以此时button.flag = false;
  • button.change 是一个箭头函数 而不是普通的函数,所以他的this要取所在词法作用域的this ,因为在test函数中,所以changethis就是testthis
  • 我觉得 作用域可以分为函数作用域全局作用域(虽然还有块级作用域,但是在这可以不考虑)
  • 当点击document的时候触发函数执行。因为change的this是testthis也就是button,所以这里将buttonflag改为了true。所以最后打印的就是true
  • 如果这里的函数并不是箭头函数,而是普通的函数,那么这里的this就会变成document。此时打印document.flag 得到的就是true;(谁调用this指向谁),而程序的输出结果就会变成false

3.instanceof 与Array.isArray

javascript 复制代码
  var iframe=document.createElement('iframe');
  document.documentElement.appendChild(iframe);
  iframe.src="javascript:var a=[];"
  var a,b;
  setTimeout(()=>{
      a=iframe.contentWindow.a;
      b=[];
      console.log(a instanceof Array,b instanceof Array);
      console.log(Array.isArray(a),Array.isArray(b));

  })

输出为:

false true

true true

上面代码创建了一个 iframe 元素,并将其附加到了文档的根元素(通常是 html 元素)上。然后,您尝试通过设置 iframe.src 为一个 javascript: URL 来在 iframe 中执行一些 JavaScript 代码。

在 iframe 中声明的变量 a 是局部的,它不会影响到外部页面的变量作用域。

  • iframe.contentWindow.a 即使是一个数组(在假设的情况下),它也是一个不同上下文(即 iframe 的全局作用域)中的数组实例,因此 a instanceof Array 在外部上下文中会返回 false
  • b 是在外部上下文中声明的数组,所以 b instanceof Array 会返回 true
  • Array.isArray() 方法不受上下文限制,它会正确地识别任何数组,因此 Array.isArray(a)Array.isArray(b) 都会返回 true(再次强调,这是在假设 iframe.contentWindow.a 实际上是一个数组的情况下)。

4.继承class cls extends Array,调用里面的sum方法

javascript 复制代码
  class cls extends Array{
      sum(){
          return this.reduce(function reducer(acc,curr){
              return acc+curr;
          },0);
      }
  }
  const x=new cls(3);
  const y=new Array(3);
  const z=cls.of(3);
  console.log(x.length,y.length,z.length);//3 3 1
  console.log(x.sum())//0
  console.log(y.sum)//undefined
  console.log(z.sum())//3
  1. x 是使用 new cls(3) 创建的实例。这里需要注意的是,当向 Array 或其子类构造函数传递一个单独的数字参数时,它会创建一个具有该长度(但元素未定义)的数组。因此,x 是一个长度为 3 的数组,但其所有元素都是 undefined

  2. y 是使用 new Array(3) 创建的普通数组实例,与 x 类似,它也是一个长度为 3、元素未定义的数组。

  3. z 是使用 cls.of(3) 创建的实例。Array.of 方法创建一个具有可变数量参数的新数组实例,而不考虑参数的数量或类型。因此,z 是一个包含一个元素(数字 3)的数组。

由于 x 是一个长度为 3 的数组,但其所有元素都是 undefinedundefined 在数学运算中被视为 NaN(Not-a-Number)。当使用 reduce 方法对包含 NaN 的数组进行求和时,结果也将是 NaN。但是,由于 NaN + 0 在这个特定的上下文中(即初始累加器值为 0,且数组元素为 undefined)实际上会导致累加器保持为 0(因为 undefined 转换为数字时是 NaN,但 NaN 在加法中的行为是特殊的,它不会改变一个有效的数字值),所以最终结果是 0。

y 是一个普通的 Array 实例,它并没有 sum 方法。因此,输出是 undefined

z 是一个包含单个元素 3 的数组。调用 z.sum() 会使用 reduce 方法计算数组中元素的和,因此结果是 3。


三、css、html、JavaScript篇

1.哪项不能提高dom元素操作效率?

A.用DocumentFragment替代多次appendChild操作

B.插入大量DOM元素时用innerHTML替代逐个构建元素

C.处理列表子元素点击事件时,使用事件代理

D.使用addEventListener替代onxxx(如onClick)进行事件绑定

逐项解析:

A。使用 DocumentFragment 可以在内存中构建一个文档片段,然后将这个片段一次性添加到 DOM 树中。这样做的好处是减少了多次的 DOM 重绘和重排,因此可以显著提高性能。

B。使用 innerHTML 可以一次性地设置元素的内部 HTML 内容,这通常比逐个创建和添加 DOM 元素要快得多,因为浏览器在内部进行了优化。

C。事件代理是一种技术,它允许你将事件监听器添加到父元素上,而不是每个子元素上。通过检查事件的目标元素,可以确定哪个子元素触发了事件。这样可以减少事件监听器的数量,从而提高性能。

D。

  • addEventListener 提供了更灵活的事件处理机制,允许你为同一个元素添加多个事件监听器而不会覆盖之前的监听器。此外,它支持更细粒度的事件控制(如捕获和冒泡阶段)。
  • 然而,就单次事件绑定操作的性能而言,addEventListeneronxxx(如 onClick)之间的性能差异通常很小,并且不一定直接导致DOM操作的整体效率提升。这个选项主要是关于事件管理的灵活性和兼容性,而不是直接提升DOM操作的效率。

2.contenteditable

contenteditable 是 HTML5 中的一个全局属性,它允许用户编辑元素中的内容。

基本功能:

  • contenteditable 属性可以被添加到 HTML 元素中,如 divtablepspanbody 等,使这些元素变得可编辑。
  • contenteditable 属性被设置为 true 时,该元素就可以被用户编辑。
  • contenteditable 属性被设置为 false 时,该元素不能被用户编辑,这是该属性的默认值(当属性值缺失时,效果与设置为 false 相同)。
  • contenteditable 属性还可以被设置为 inherit,此时该元素会继承其父元素的 contenteditable 状态。

使用场景:

  • 编辑器功能contenteditable 属性最常用的场景是在网页上创建一个可编辑的文本区域,使用户能够直接在网页上输入和编辑文本内容,类似于常见的文本编辑器功能。
  • 富文本编辑contenteditable 属性还可以用于创建富文本编辑器,允许用户在文本中添加格式、图片、链接等样式和元素。
  • 评论功能 :网站或应用的评论框通常会使用 contenteditable 属性,使用户能够直接在评论框中输入评论内容,并实时提交到服务器。
  • 笔记应用contenteditable 属性也适用于笔记应用或在线日记,用户可以直接在网页上输入和保存个人的笔记或日记内容。
  • 在线表单 :有些情况下,内容需要在表单中进行编辑,此时 contenteditable 属性可以用于在表单中添加富文本内容,如说明文字或公告等。

注意:

  • 设置了 contenteditable 属性的元素必须是可以获得鼠标焦点的元素,并且在点击鼠标后要向用户提供一个插入符号,提示可编辑。
  • 在使用 contenteditable 属性时,需要注意如何保存用户编辑的内容。通常可以通过监听失焦事件(如 blur 事件)来获取并保存用户编辑后的内容。

示例:

html 复制代码
<!DOCTYPE html>
<html>
<body>
<p contenteditable="true">这是一个可以编辑的段落。</p>
</body>
</html>

在这个示例中,<p> 元素被添加了 contenteditable="true" 属性,因此它变得可编辑。用户可以直接在网页上修改这个段落的内容。


3.关于promise的then、catch、resolve、reject

下面关于Promise说法错误的是:

A.调用then或catch方法都是异步进行的,但是执行速度比较快

B.Promise.resolve(value),Promise.reject(reason)是Promise构造器上直接提供的一组静态方法

C.resolve()和reject()都是直接生成一个进入响应状态的promise对象,其参数就是进入相应状态时传递过去的参数,可以在完成回调的参数中得到

D.Promise构造器的prototype上还有两个方法,分别是then和catch,这两个方法的参数也是回调函数,这些函数会在Promise实例进入不同状态后被调用

逐项解析:

先说错误的C,resolve()reject() 并不是直接生成Promise对象的函数,而是Promise构造函数执行时传递给executor(执行器)函数的两个参数。这两个参数是函数,用于在异步操作成功或失败时分别改变Promise的状态,并传递相应的结果值或原因。

异步操作成功时,调用resolve函数,使Promise对象的状态变为fulfilled(已完成),将结果值传递给后续通过then方法注册的回调函数。

异步操作失败时,调用reject函数,使Promise对象的状态变为rejected(已拒绝),将失败原因传递给后续通过catch方法或then方法的第二个回调函数注册的错误处理函数。

因此:resolve()和reject()并不是直接生成Promise对象的函数,而是用于改变Promise对象状态的函数,它们是Promise构造器上直接提供的一组静态方法。

A:then和catch方法都是异步微任务,会在当前栈清空后立即执行,但是执行速度相对较快,因为它们只是将回调函数添加到Promise的回调队列中,等待Promise状态改变时执行。

B:见C项解析

D:Promise构造器的prototype上的then和catch方法用于注册回调函数,会在Promise实例进入不同状态(fulfilled或rejected)后被调用。then接收两个回调函数作为参数,第一个用于处理fulfilled状态,第二个(可选的)用于处理rejected状态。catch接收一个回调函数作为参数,用于处理reject状态。


加油加油^_^

相关推荐
佚名程序员4 分钟前
【Node.js】Node.js 和浏览器之间的差异
前端·node.js
yimengsama4 分钟前
Node.js | npm下载安装及环境配置教程
前端·经验分享·笔记·webpack·npm·node.js·电脑
刘艳兵的学习博客11 分钟前
刘艳兵-DBA038-以下关于Oracle SGA和PGA的描述中,哪些是正确的?
服务器·数据库·oracle·面试·刘艳兵
Fly_hao.belief1 小时前
vue内置指令和自定义指令
前端·javascript·vue.js
聊无生1 小时前
HarmonyOS ArkUI(基于ArkTS) 常用组件
前端·华为·harmonyos
jokerest1231 小时前
web——upload-labs——第三关——后缀黑名单绕过
前端
星之卡比*1 小时前
前端知识点---this的用法 , this动态绑定(Javascript)
开发语言·前端·javascript
摇光931 小时前
[前端面试]javascript
前端·javascript·面试
chusheng18402 小时前
基于Java Web 的家乡特色菜推荐系统
java·开发语言·前端·springboot·家乡特色菜推荐系统·家乡特色菜推荐
Moment2 小时前
拍出来的照片没有感觉怎么办,那就用 NodeJs 来帮助你裁剪成电影的感觉 😙😙😙
前端·javascript·后端