2023--前端面试题(长期更新)

答案若是有问题的欢迎评论区留言

1.假设上下文为"let arr = [1]",结果肯定为true的表达式有?

A.arr.length === Array.prototype.length;
B.arr.push === Array.prototype.push
C.arr.proto=== Array.prototype
D. typeof Array.prototype.proto=== ‘function’
参考答案:
正确选项:B C
A. arr 是 构造函数Array的实例对象,其length属性继承于Array.prototype.length,arr.length 判断的是arr数组的长度。arr数组长度为1,Array.prototype.length 默认为0。两者不相等。arr.proto.length=== Array.prototype.length;
B. 方法本身是相等的,例如:arr.proto.push === Array.prototype.push;
arr.concat === =Array.prototype.concat.
C. arr.__proto__指向构造它的构造函数的构造器 constructor属性,Array.prototype 为构造函数Array指向本身的constructor属性。
D. Array.prototype.proto=== ‘function’, Array.prototype 为构造函数指向本身的构造器属性,其本身也是一个对象,对象的隐式原型,指向构造对象实例的构造函数,这里指向Object. 故Array.prototype.**proto为 Object。如果要指向function,**Array.proto=== ‘function’
在这里插入图片描述

2.如果把元素的样式设“width:100px;padding:10px;border:1px solid;box-sizing:border-box”,正确的描述有?

A. 元素内容区的实际宽度是 80px;
B. 元素内容区的实际宽度是 98px;
C. 元素内容区的实际宽度是 78px;
D. 元素内容区的实际宽度是 100px;
参考答案:
正确选项:C
一般在写页面的时候用这个box-sizing:border-box属性就不会再考虑边框和内边距会改变整体所占宽度,即不用再根据盒子模型再去计算,省去很多麻烦,一般在做自适应的网页设计的时候用,用这个属性网页结构才不会被破坏。

div {
  width: 100px;
  height: 100px;
  padding: 10px;
  border: 1px solid;
  background-color: aqua;
  
}

.test {
  box-sizing: border-box;
 }

3.关于箭头函数与普通函数,正确的描述有?

A. 箭头函数没有自己的this;
B. 箭头函数没有自己的作用域;
C.箭头函数不能有返回值;
D.不能对箭头函数进行new操作;
参考答案:
正确选项:** A B D**
A: 箭头函数的this继承上层函数函数作用域的this或到最后指向全局。
B: 箭头函数的作用域继承上层函数作用域或最后找到全局作用域。
C: 箭头函数写成表达式形式,隐式返回表达式结果,箭头函数可以有返回值。
D: 箭头函数没有原型,没法进行new操作。

4.以下哪些样式属性的值被修改后,肯定不会引起重排(回流)?

A.color;
B. padding;
C. margin;
D.visibillity;
参考答案:
正确选项:** A D**
二维和三维的变化都会引起回流,color,visibility 引起的是重绘。

5.跟HTTP缓存有关的HTTP头有?

A. User-Agent
B. ETag
C. Cache-Control
D.Referer

参考答案:
正确选项:** B C **
在HTTP中与网页缓存相关的HTTP头部信息分为以下三组:

  • Last-Modified和If-Modified-Since
  • ETags和If-None-Match
  • Expires和Cache-Control

User-Agent中文名为用户代理,简称 UA,
它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。
Http协议头中的Referer主要用来让服务器判断来源页面。

6.关于Vue.js 2.x,正确的描述有?

A. 在组件的created的钩子中可以访问该组件的data
B.在v-for循环中,把:key设为数组下标是比较好的做法。
C. 响应式数据是通过ES6的Proxy来实现的。
D. 在组件的created钩子中可以访问该组件的DOM元素。
参考答案:
正确选项:** A**
A. 在 created 钩子中,你能够访问 reactive data 和 events。但是模板和虚拟DOM无法访问;
B.错误,建议使用唯一标识作用唯一绑定的id值。

  • 使用v-for更新已渲染的元素列表时,默认用就地复用策略;列表数据修改的时候,他会根据key值去判断某个值是否修改,如果修改,则重新渲染这一项,否则复用之前的元素;
  • 我们在使用的使用经常会使用index(即数组的下标)来作为key,但其实这是不推荐的一种使用方法;数组如果进行增删操作会导致index全部发生变化,页面重新渲染
  • key的作用主要是为了高效的更新虚拟DOM,使用key来给每一个节点做一个唯一标识diff算法可以正确的识别此节点,找到正确的位置对此节点进行操作。

C.Vue2,Observer把对象的每个属性通过Object.defineProperty转换为带有getter和setter的属性,把一个普通的对象转换为响应式的对象。Vue3才是通过ES6的Proxy来实现,其实底层也还是Object.defineProperty。
D.A已解析。

7.下面代码的输出是什么?

[[0, 1], [2, 3]].reduce(
  (acc, cur) => {
    return acc.concat(cur)
  },
  [1, 2]
)

A:[0, 1, 2, 3, 1, 2]
B:[6, 1, 2]
C:[1, 2, 0, 1, 2, 3]
D:[1, 2, 6]
参考答案:
正确选项:** C**,
关于reduce(),[1, 2]是初始值。
初始值将会作为首次调用时第一个参数 acc 的值。

  • 在第一次执行时, acc 的值是 [1, 2], cur 的值是 [0, 1]。合并它们,结果为 [1, 2, 0, 1]。
  • 第二次执行, acc 的值是 [1, 2, 0, 1], cur 的值是 [2, 3]。合并它们,最终结果为 [1, 2, 0, 1, 2, 3]

8.下面代码输出是什么?

class Chameleon {
  static colorChange(newColor) {
    this.newColor = newColor
    return this.newColor
  }

  constructor({ newColor = 'green' } = {}) { // 对象传参的方式
    this.newColor = newColor
  }
}

const freddie = new Chameleon({ newColor: 'purple' })

console.log(freddie.colorChange('orange'));

A:orange
B:purple
C:green
D:TypeError
参考答案:
正确选项:** D**,
colorChange 是一个静态方法。静态方法被设计为只能被创建它们的构造器使用(也就是 Chameleon),并且不能传递给实例。因为 freddie 是一个实例,静态方法不能被实例使用,因此抛出了 TypeError 错误。

9.点击P标签时,会输出什么?

<div onclick="console.log('div')">
  <p onclick="console.log('p')">
    Click here!
  </p>
</div>

A:p div
B:div p
C:p
D:div
参考答案:
正确选项:A:p div
在事件传播过程中,有3个阶段:捕获目标冒泡
默认情况下,事件处理程序在冒泡阶段执行(除非将 useCapture 设置为 true),它从最深的嵌套元素向外冒泡。

9.在点击 button 时,触发的 event.target 是哪个?

<div onclick="console.log('first div')">
  <div onclick="console.log('second div')">
    <button onclick="console.log('button')">
      Click!
    </button>
  </div>
</div>

A:最外层div
B:第二层的div
C:button
D:上面三个元素
参考答案:
正确选项:C:button
js中事件是会冒泡的,所以this是可以变化的,但event.target不会变化,它永远是直接接受事件的目标DOM元素;注意这里的event.stopPropagation();这个是阻止事件冒泡的!
event.target :在事件流的目标阶段,指的是真正触发事件的那个元素
event.currentTarget:在事件流的捕获,目标及冒泡阶段,指的是绑定了事件监听的元素(可以理解为触发事件元素的父级元素)
浅谈冒泡事件和捕获事件

10.下面会输出什么?

const person = { name: 'Lydia' }

function sayHi(age) {
  console.log(`${this.name} is ${age}`)
}

sayHi.call(person, 21)
sayHi.bind(person, 21)

A:undefined is 21 Lydia is 21
B:function function
C:Lydia is 21 Lydia is 21
D:Lydia is 21 function
参考答案:
正确选项:D:Lydia is 21 function
使用这两种方法,我们都可以传递我们希望 this 关键字引用的对象。但是,.call 是立即执行的。 .bind 返回函数的副本,但带有绑定上下文!它不是立即执行的。

11.下列代码输出的是什么?

// counter.js
let counter = 10;
export default counter;

// index.js
import myCounter from './counter';
myCounter += 1;
console.log(myCounter);

A:10
B:11
C:Error
D:NaN

参考答案:
正确选项:C:Error
import命令输入的变量都是只读的,加载后不能修改接口
引入的模块是 只读 的: 你不能修改引入的模块。只有导出他们的模块才能修改其值。 当我们给myCounter增加一个值的时候会抛出一个异常: myCounter是只读的,不能被修改。
export default 用法

12.下列代码输出什么?

const person = {
	name: "Lydia Hallie",
	hobbies: ["coding"]
};

function addHobby(hobby, hobbies = person.hobbies) {
	hobbies.push(hobby);
	return hobbies;
}

addHobby("running", []);
addHobby("dancing");
addHobby("baking", person.hobbies);

console.log(person.hobbies);

A:[“coding”]
B:[“coding”, “dancing”]
C:[“coding”, “dancing”, “baking”]
D:[“coding”, “running”, “dancing”, “baking”]
参考答案:
正确选项:C:[“coding”, “dancing”, “baking”]
函数 addHobby 接受两个参数,hobby 和 hobbies,其中 hobbies 的默认值是 person 对象中的 hobbies 属性。
首先,我们调用函数 addHobby,并给 hobby 传递 “running” 以及给 hobbies 传递一个空数组。因为我们给 hobbies 传递了空数组,“running” 被添加到这个空数组,该操作不影响 person 对象中的 hobbies 属性。
然后,我们调用函数 addHobby,并给 hobby 传递 “dancing”。我们不向 hobbies 传递值,因此它获取其默认值 —— 对象 person 的属性 hobbies。我们向数组 person.hobbies push dancing。
最后,我们调用函数 addHobby,并向 hobby 传递值 “baking”,并且向 hobbies 传递 person.hobbies。我们向数组 person.hobbies push dancing。
pushing dancing 和 baking 之后,person.hobbies 的值为 [“coding”, “dancing”, “baking”]。、

13.下面那个选项将会返回 ‘6’ ?

function sumValues(x, y, z) {
	return x + y + z;
}

A:sumValues([…1, 2, 3])
B:sumValues([…[1, 2, 3]])
C:sumValues(…[1, 2, 3])
D:sumValues([1, 2, 3])
参考答案:
正确选项:C:sumValues(…[1, 2, 3])
通过展开操作符 …,我们可以 暂开 单个可迭代的元素。函数 sumValues function 接收三个参数: x, y 和 z。…[1, 2, 3] 的执行结果为 1, 2, 3,将会传递给函数 sumValues。

14.哪一个方法会返回 ‘Hello world!’ ?

const myMap = new Map()
const myFunc = () => 'greeting' 

myMap.set(myFunc, 'Hello world!')

//1
myMap.get('greeting')
//2
myMap.get(myFunc)
//3
myMap.get(() => 'greeting')

A:1
B:2
C:2 and 3
D:All of them
参考答案:
正确选项:B:2
当通过 set 方法添加一个键值对,一个传递给 set方法的参数将会是键名,第二个参数将会是值。在这个case里,键名为 函数 () => ‘greeting’,值为’Hello world’。 myMap 现在就是 { () => ‘greeting’ => ‘Hello world!’ }。 1 是错的,因为键名不是 ‘greeting’ 而是 () => ‘greeting’。 3 是错的,因为我们给get 方法传递了一个新的函数。对象受 引用 影响。函数也是对象,因此两个函数严格上并不等价,尽管他们相同:他们有两个不同的内存引用地址。

15.setInterval 方法的返回值是什么?

setInterval(() => console.log('Hi'), 1000)

A:一个唯一的id
B:该方法指定的毫秒数
C:传递的函数
D:undefined
正确选项:A:一个唯一的id
setInterval 返回一个唯一的 id。此 id 可被用于 clearInterval 函数来取消定时。
setTimeout也是如此。

console.log(setTimeout(() =>console.log('one'), 1000)); // id  1
console.log(setTimeout(() =>console.log('two'), 2000));// id 2
console.log(setTimeout(() =>console.log('three'), 3000));// id 3

16.输出什么?

let randomValue = { name: "Lydia" }
randomValue = 23

if (!typeof randomValue === "string") {
	console.log("It's not a string!")
} else {
	console.log("Yay it's a string!")
}

A:It’s not a string!
B:Yay it’s a string!
C:TypeError
D:undefined
正确选项:B:Yay it’s a string!
if 语句的条件判断 !typeof randomValue 的值是否等于 “string”。 ! 操作符将这个值转化为一个布尔值。如果值是truthy的话,返回值会是 false,如果值是falsy,返回值会是 true。在这里, typeof randomValue 的返回值是一个truthy值 “number”,意味着 !typeof randomValue 的值是一个布尔值 false。 !typeof randomValue === “string” 总是返回false,因为我们实际上是在执行 false === “string”。因为条件返回的是 false,所以 else 语句中的代码块会被运行,因此打印 Yay it’s a string! 。
Truthy、Falsy 与true、false的区别

17.下列代码输出什么?

const createMember = ({ email, address = {}}) => {
	const validEmail = /.+\@.+\..+/.test(email)
	if (!validEmail) throw new Error("Valid email pls")

	return {
		email,
		address: address ? address : null
	}
}

const member = createMember({ email: "my@email.com" })
console.log(member)

A:{ email: “my@email.com”, address: null }
B:{ email: “my@email.com” }
C:{ email: “my@email.com”, address: {} }
D:{ email: “my@email.com”, address: undefined }
参考答案:
正确选项:C:{ email: “my@email.com”, address: {} }
address 的默认值是一个空对象 {}。当我们设置 member 变量为 createMember 函数返回的对象,我们没有为address参数传值,意味着address的值为默认的空对象 {}。一个空对象是一个truthy值,意味着 address ? address : null 条件会返回 true。address的值为空对象 {}。
只有以下值才是falsy值:false , null, undefined, 空字符串, NaN, 0;

18.method 的值选择哪个时,会输出 { name: “Lydia”, age: 22 } ?

const keys = ["name", "age"]
const values = ["Lydia", 22]

const method = /* ?? */
Object[method](keys.map((_, i) => { // 下划线代表第一个参数value不使用。
	return [keys[i], values[i]]
})) // { name: "Lydia", age: 22 }

A:entries
B:values
C:fromEntries
D:forEach
参考答案:
正确选项:C:fromEntries
fromEntries 方法可以将二维数组转换为对象。在每个子数组的第一个元素是key,在每个子数组的第二个元素是value。在这个例子中,我们映射了 keys 数组,它返回了一个数组,数组的第一个元素为keys数组当前索引的值,第二个元素为values数组当前索引的值。 这样就创建了一个包含正确keys和values的子数组的数组,因此结果为{ name: “Lydia”, age: 22 }。
Object本题中有entires,values,formEntries三种方法。

19.下列异步函数输出什么?

const promise1 = Promise.resolve('First')
const promise2 = Promise.resolve('Second')
const promise3 = Promise.reject('Third')
const promise4 = Promise.resolve('Fourth')

const runPromises = async () => {
	const res1 = await Promise.all([promise1, promise2])
	const res2  = await Promise.all([promise3, promise4])
	return [res1, res2]
}

runPromises()
	.then(res => console.log(res))
	.catch(err => console.log(err))

A:[[‘First’, ‘Second’], [‘Fourth’]]
B:[[‘First’, ‘Second’], [‘Third’, ‘Fourth’]]
C:[[‘First’, ‘Second’]]
D:‘Third’
参考答案:
正确选项:D:‘Third’
Promise.all 方法可以并行式运行promise。如果其中一个promise失败了,Promise.all 方法会带上被reject的promise的值_rejects_。在这个例子中, promise3 带着 “Third” 值reject。我们在调用 runPromises 时在 runPromises 函数内部的 catch 方法去捕获任意error从而捕获到被reject的值。因为 promise3 带着 “Third” 被reject,所以只有 “Third” 打印。

const promise1 = Promise.resolve('First')
const promise2 = Promise.resolve('Second')
const promise3 = Promise.reject('Third')
const promise4 = Promise.resolve('Fourth')

const runPromises = async () => {
	const res1 = await Promise.all([promise1, promise2]) // ['First','Second']
    console.log(res1); 
	const res2  = await Promise.all([promise3, promise4]) // ['Third'] rejected之后不会再执行报错之后代码
    console.log("🚀 ~ file: test.js ~ line 10 ~ runPromises ~ res2", res2)
	
  
}

runPromises()
	.then(res => console.log(res))
	.catch(err => console.log(err))

20.下列代码打印的值是什么?

const animals = {};
let dog = { emoji: '🐶' }
let cat = { emoji: '🐈' }

animals[dog] = { ...dog, name: "Mara" }
animals[cat] = { ...cat, name: "Sara" }

console.log(animals[dog])

A:{ emoji: “🐶”, name: “Mara” }
B:{ emoji: “🐈”, name: “Sara” }
C:undefined
D:ReferenceError
参考答案:
正确选项:B:{ emoji: “🐈”, name: “Sara” }
对象的键会被转换为字符串。 因为 dog 的值是一个对象, animals[dog] 实际上意味着我们创建了一个叫做 “object Object” 的属性来代表新的对象。 animals[“object Object”] 现在等于 { emoji: “🐶”, name: “Mara”}。 cat 也是一个对象,animals[cat] 实际上意味着我们在用新的cat的属性覆盖 animals["object Object"] 的值。 打印 animals[dog],实际上是animals[“object Object”],这是因为转化dog对象为一个字符串结果 “object Object” ,所以返回结果 { emoji: “🐈”, name: “Sara” }。
普通的对象,只能键名只能是字符串,对对象之间转化为"object Object" 属性,数组之间“数组内内容”属性。

后续面试题更新在此链接

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

竹林海灵

谢谢义父

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值