前端面试笔试(三)
目录
一、数据结构算法等综合篇
二、代码输出篇
1.yield与生成器函数
2.this指向有关
3.instanceof 与Array.isArray
4.继承class cls extends Array,调用里面的sum方法
三、css、html、JavaScript篇
1.哪项不能提高dom元素操作效率?
2.contenteditable
基本功能:
使用场景:
注意:
示例:
3.关于promise的then、catch、resolve、reject
逐项解析:
一、数据结构算法等综合篇
无
二、代码输出篇
1.yield与生成器函数
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,需要:
console.log(res.return().value)
2.this指向有关
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函数中,所以change
的this
就是test
的this
- 我觉得 作用域可以分为函数作用域和全局作用域(虽然还有块级作用域,但是在这可以不考虑)
- 当点击
document
的时候触发函数执行。因为change
的this
是test
的this
也就是button
,所以这里将button
的flag
改为了true
。所以最后打印的就是true - 如果这里的函数并不是箭头函数,而是普通的函数,那么这里的
this
就会变成document
。此时打印document.flag
得到的就是true
;(谁调用this指向谁),而程序的输出结果就会变成false
3.instanceof 与Array.isArray
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方法
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
-
x
是使用new cls(3)
创建的实例。这里需要注意的是,当向Array
或其子类构造函数传递一个单独的数字参数时,它会创建一个具有该长度(但元素未定义)的数组。因此,x
是一个长度为 3 的数组,但其所有元素都是undefined
。 -
y
是使用new Array(3)
创建的普通数组实例,与x
类似,它也是一个长度为 3、元素未定义的数组。 -
z
是使用cls.of(3)
创建的实例。Array.of
方法创建一个具有可变数量参数的新数组实例,而不考虑参数的数量或类型。因此,z
是一个包含一个元素(数字 3)的数组。
由于 x
是一个长度为 3 的数组,但其所有元素都是 undefined
,undefined
在数学运算中被视为 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
提供了更灵活的事件处理机制,允许你为同一个元素添加多个事件监听器而不会覆盖之前的监听器。此外,它支持更细粒度的事件控制(如捕获和冒泡阶段)。- 然而,就单次事件绑定操作的性能而言,
addEventListener
和onxxx
(如onClick
)之间的性能差异通常很小,并且不一定直接导致DOM操作的整体效率提升。这个选项主要是关于事件管理的灵活性和兼容性,而不是直接提升DOM操作的效率。
2.contenteditable
contenteditable
是 HTML5 中的一个全局属性,它允许用户编辑元素中的内容。
基本功能:
contenteditable
属性可以被添加到 HTML 元素中,如div
、table
、p
、span
、body
等,使这些元素变得可编辑。- 当
contenteditable
属性被设置为true
时,该元素就可以被用户编辑。 - 当
contenteditable
属性被设置为false
时,该元素不能被用户编辑,这是该属性的默认值(当属性值缺失时,效果与设置为false
相同)。 contenteditable
属性还可以被设置为inherit
,此时该元素会继承其父元素的contenteditable
状态。
使用场景:
- 编辑器功能:
contenteditable
属性最常用的场景是在网页上创建一个可编辑的文本区域,使用户能够直接在网页上输入和编辑文本内容,类似于常见的文本编辑器功能。 - 富文本编辑:
contenteditable
属性还可以用于创建富文本编辑器,允许用户在文本中添加格式、图片、链接等样式和元素。 - 评论功能:网站或应用的评论框通常会使用
contenteditable
属性,使用户能够直接在评论框中输入评论内容,并实时提交到服务器。 - 笔记应用:
contenteditable
属性也适用于笔记应用或在线日记,用户可以直接在网页上输入和保存个人的笔记或日记内容。 - 在线表单:有些情况下,内容需要在表单中进行编辑,此时
contenteditable
属性可以用于在表单中添加富文本内容,如说明文字或公告等。
注意:
- 设置了
contenteditable
属性的元素必须是可以获得鼠标焦点的元素,并且在点击鼠标后要向用户提供一个插入符号,提示可编辑。 - 在使用
contenteditable
属性时,需要注意如何保存用户编辑的内容。通常可以通过监听失焦事件(如blur
事件)来获取并保存用户编辑后的内容。
示例:
<!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状态。
加油加油^_^