前端实习⽣笔试_⼏道前端笔试题
今年年初,应公司要求,我作为出题⼈之⼀为实习⽣校招出的⼀份候选笔试题。因为绝⼤部分题⽬都没有选⼊最终题库 ,且现在校招已经结束(可以泄题了),为了避免我的脑⼒被⽩⽩浪费 ,现把题⽬分享出来。虽说是招实习⽣,但按照要求,题⽬平均难度 p6 ⽔平 。
单选题
1. 关于⼀个对象 obj 到底包含有多少个属性,下⾯三个 API 的检测结果可能不完全⼀致,假如将它们返回的属性个数从⼤到⼩排序的话,恒成⽴的选项是哪个?
A. Reflect.ownKeys(obj).length ≥ OwnPropertyNames(obj).length ≥ Object.keys(obj).length
B. OwnPropertyNames(obj).length ≥ Object.keys(obj).length ≥ Reflect.ownKeys(obj).length
C. Reflect.ownKeys(obj).length ≥ Object.keys(obj).length ≥ OwnPropertyNames(obj).length
D. OwnPropertyNames(obj).length ≥ Reflect.ownKeys(obj).length ≥ Object.keys(obj).length
E. Object.keys(obj).length ≥ OwnPropertyNames(obj).length ≥ Reflect.ownKeys(obj).length
F. Object.keys(obj).length ≥ Reflect.ownKeys(obj).length ≥ OwnPropertyNames(obj).length
参考答案:A
考查知识点:属性的可枚举性和 Symbol 类型属性键。Reflect.ownKeys() ⽐ OwnPropertyNames() 会多返回 Symbol 类型的属性键,OwnPropertyNames() ⽐ Object.keys() 会多返回不可枚举的字符串属性键。
2. 关于新的 DOM ⽅法 append() 和⽼的 appendChild() 的区别,下⾯说法错误的是哪个:
A. append() ⽅法可以直接追加字符串为⽂本节点,⽐如 append("text") ,appendChild() 不⾏
B. append() ⽅法可以直接追加 HTML ⽚段字符串为元素节点,⽐如 append("
test
") , appendChild() 不⾏
C. append() ⽅法⽀持追加多个参数,appendChild() 只能追加⼀个
D. append() ⽅法没有返回值,⽽ appendChild() 会返回追加进去的那个节点
E. 和 append() 同时期加⼊ DOM 规范的⽅法还有 prepend() 、before()、after() 等。
F. jQuery 中存在的 appendTo() ⽅法并没有和 append() ⼀起加⼊到 DOM 规范⾥
参考答案:B
考查知识点:对新⼀代 DOM API 的了解程度。B 为错误项,不⽀持直接追加 HTML,和 jQuery 的 append() 不⼀样。
3. 在调试页⾯中的 JavaScript 代码时,Chrome DevTools 的断点功能是必不可少的,Chrome DevTools 有很多强⼤的⾃动断点功能(即你不需要⼿动到想要加断点的那⾏代码),但下⾯有⼀个是杜撰的,请挑出它来(本题以 Chrome 当前稳定版 V72 为准):
A. 在遇到死循环代码的时候⾃动断点
B. 在每个
C. 在某个指定的 DOM ⽅法被调⽤时⾃动断点
D. 在未捕获的异常抛出时⾃动断点
E. 在匹配指定 URL 的 XHR/fetch 请求发起时⾃动断点
F. 在指定的节点被删除时⾃动断点
参考答案:A
考查知识点:页⾯调试能⼒。A 为错误项,Chrome 开发者⼯具⽬前还没有该能⼒,B 在 Sources ⾯板中右下⾓的 Event Listener Breakpoints > Script > Script First Statement,C ⽤ Console ⾯板上的 debug() 函数,⽐如 debug(alert) ,然后所有调⽤alert() 的地⽅都会⾃动中断。D 在 Sources ⾯板右上⾓的 Pause on exceptions 按钮。E 在 Sources ⾯板右下⾓的 XHR/fetch Breakpoints。
F 在 Elements ⾯板中元素上右键 -> Break on -> node removal。
4. 关于 HTTP 协议,下⾯说话错误的是哪个⼀个:
A. 看到⽹页有乱码,则很有可能是某个请求的 Content-Type 响应头丢失或者是值设置不当造成的
B. 即便是不需要发送请求体的 GET 请求,请求头区域下⽅也必须留⼀个空⾏(CRLF)
C. 服务端可以根据客户端发送的 Accept-Encoding 请求头来分别返回不同压缩格式(Gzip、Brotli)的⽂件
D. 服务端返回的 Date 响应头表⽰服务器上的系统时间,除给⼈读外没有实际⽤途
E. HTTP 是⽆状态的,⽹站是通过 Cookie 请求头来识别出两个请求是不是来⾃同⼀个浏览器的
F. Access-Control-Allow-Origin 响应头只⽀持配置单个的域名或者是 * ,不⽀持配置多个特定的域名
参考答案:Djquery在一个元素后追加标签
D 为错误选项,Date 响应头有参与缓存时长的计算,不仅仅是给⼈看看服务器时间。
5. 下⾯哪个选项不属于现代 Web 页⾯性能⽅⾯的最佳实践?
A. 使⽤ document.write()
B. 使⽤ HTTP/2
C. 使⽤ passive 的事件
D. 静态⽂件使⽤ CDN
E. 尽量使⽤更先进的图⽚格式,⽐如 WebP
F. 使⽤同步的 XHR 请求
参考答案:AF
考查知识点:知道要尽量不使⽤ document.write(),知道 passive 的事件是什么
多选题
1. 关于箭头函数,下⾯说法错误的有哪些?
A. 箭头函数没有⾃⼰的 this,⽽是会继承上层作⽤域的 this,就像其他普通的变量⼀样
B. 箭头函数还可以通过 .call()、.apply()、.bind() ⽅法来重新绑定它的 this 值
C. 箭头函数可以像普通函数⼀样使⽤ arguments 对象
D. 过度追求箭头函数的“单⾏代码”写法可能会降低代码可读性
E. 箭头函数虽然表⾯上看是匿名的,但它可以根据前⾯的变量名和属性名⾃动推断出同名的 name 属性
F. 箭头函数不可以被 new,也不会像普通函数⼀样⾃动拥有 prototype 属性
参考答案:BC
B 是箭头函数不⽀持动态改变 this 值,
C 是箭头函数同样也没有 arguments。
2. 带有 target="_blank" 的 a 标签被认为是有安全风险的,因为点击它后打开的新标签页⾯可以通过 window.opener.location = 来将来源页⾯跳转到钓鱼页⾯,不过给该 a 标签增加下⾯哪些属性就能阻⽌这⼀⾏为?
A. rel="nofollow"
B. rel="noopener"
C. rel="noreferrer"
D. rel="opener"
E. rel="external"
F. rel="parent"
参考答案:BC
noopener 是最合适的属性,不过 noreferrer 同样也包含有 noopener 的功效,noreferrer noopener 同时加是多余的。
rel="opener" 是功能恰好相反的选项,因为其实除了 Chrome,最新版的 Safari 和 Firefox 已经都为 a 链接默认采⽤ noopener 模式了,真需要 opener 属性的时候可以使⽤ rel="opener" 开启。
其它的选项都是迷惑性选项,在浏览器中实际都没有任何作⽤。
3. ES6 ⾥的 Proxy 被认为是个神器,利⽤它可以实现很多以前只有魔改 JS 引擎底层才能实现的效果,请出下⾯是利⽤ Proxy 实现了的神奇效果:
A. 原型就是⾃⼰的对象 —— PrototypeOf(obj) === obj // true
B. 任意属性都存在的对象 —— "任意名字的属性" in obj // true
C. 任意值都是它的实例的对象,甚⾄ null 和 undefined —— undefined instanceof obj // true
D. ⽤ String() 检测出来的对象类型是 haha 的对象 —— String.call(obj) === "[object haha]" // true
E. ⼀元加后的值与加 0 后的值分别恒等于两个不同的数字 —— ⽐如 +obj 始终 === 1,但 obj + 0 始终等于=== 10
F. 亦假⼜亦真的对象 —— if (obj) {alert("执⾏不到")} 但 if (obj.length) {alert("能执⾏到")}
参考答案:AB
A: obj = new Proxy({}, {getPrototypeOf(){return obj}})
B: obj = new Proxy({}, {has(){return true}})
C: obj = {[Symbol.hasInstance](){return true}}
D: obj = {[StringTag]: "haha"}
E: obj = {[Primitive](hint){return hint === "number" ? 1 : 10}}
F: document.all
C、D、E 是利⽤了 ES6 ⾥ Well-Known Symbols 的魔⼒,不是 Proxy 的。F 是唯⼀的⼤奇葩 document.all
4. ES6 中⾸次对函数的 name 属性进⾏了标准化,⽽且为了⽅便在调⽤栈⾥看到具体的函数名,ES6 ⾥还增加了函数名推断的功能。下⾯哪个选项中函数的 name 属性并不完全等于 foo ?
A. const foo = () => {}
B {foo: function(){}}
C. {*foo(){}}
D. {[Symbol("foo")](){}}
E. class C {static get foo(){}}
F. {async foo(){}}
参考答案:DE
考查知识点:对 ES6 中函数 name 属性的了解。D 中 name 属性为 [foo] ,Symbol 类型的属性键需要加中括号,E 中 name 属性为get foo,getter 和 setter 分别加 get 和 set 前缀。
5. 下⾯这些 Element 上的⽅法,有哪些是⽀持传⼊⼀个选择器作为参数的?
A. Element.prototype.querySelector()
B. Element.prototype.querySelectorAll()
C. Element.prototype.matches()
D. Element.prototype.closest()
E. ve()
F. ains()
参考答案:ABCD
考查知识点:原⽣的 remove() ⽅法和 jQuery 的不⼀样,只能删除⾃⼰,所以不⽀持传⼊选择器。contains() ⽅法也很容易被误认为⽀持选择器,⽐如 ains(".header > a") ,实际只⽀持传⼊节点。
编程题
1. JavaScript 采⽤原型继承,即⼀个对象继承⾃另外⼀个对象,另外⼀个对象再继承⾃别的对象,依
此往复。请写⼀个通⽤的 JavaScript 函数,来出某个对象⾝上的某个属性继承⾃哪个对象。
函数签名:
function findPrototypeByProperty(obj, propertyName){
// 请实现函数体}
使⽤举例:
const foo = {a: 1}
const bar = ate(foo)
bar.b = 2
const baz = ate(bar)
baz.c = 3
console.log(findPrototypeByProperty(baz, "c") === baz) // trueconsole.log(findPrototypeByProperty(b
az, "b") === bar) // trueconsole.log(findPrototypeByProperty(baz, "a") === foo) // true
参考答案:
function findPrototypeByProperty(obj, propertyName) {
do {
if (obj.hasOwnProperty(propertyName)) {
return obj
}
} while (obj = PrototypeOf(obj))
}
2. URLSearchParams() 接⼝是⽤来解析和处理 URL 参数的 API,⽬前最新的浏览器和 Node 都⽀持它。请⽤ class URLSearchParams {} 语法实现⼀个该接⼝的 polyfill,考虑到时间因素,答题者只需实现下⾯列举的要求即可:
// 构造函数⽀持传⼊ URL 参数串searchParams = new URLSearchParams("foo=1&bar=2")
// 构造函数也⽀持传⼊⼀个包含参数键值对的对象searchParams = new URLSearchParams({foo: "1", bar: "2"})
// 实例⽀持 get()、set()、has()、append() 四个⽅法console.("foo")) // "1"searchParams.set("foo", "10")
console.log(searchParams.has("bar")) // truesearchParams.append("foo", "100")
// 实例⽀持 toString() ⽅法console.String()) // "foo=10&bar=2&foo=100"
// 实例⽀持 for-of 迭代for(const [key, value] of searchParams) {
console.log([key, value])
// ["foo", "10"] // ["bar", "2"] // ["foo", "100"]}
参考答案:
考察学⽣对 URL 的认识以及对 class 语法、for-of 语法的熟悉程度,以下代码在 Chrome 74 中可⽤。
实现逻辑不需要完全依照规范,能跑通题⼲中的要求即可。
class URLSearchParams {
#searchParams = []
constructor(init) {
if (typeof init === "string") {
this.#searchParams = init.split("&").map(kv => kv.split("="))
} else {
this.#searchParams = ies(init)
}
}
get(key) {
const param = this.#searchParams.find(param => param[0] === key)
return param && param[1]
}
set(key, value) {
const param = this.#searchParams.find(param => param[0] === key)
if (param) {
param[1] = value
} else {
this.#searchParams.push([key, value])
}
}
has(key) {
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论