第五届字节跳动青训营寒假 —— 前端专场
第五届字节跳动青训营寒假 —— 前端专场
文章目录
青训营 - 前端练习题
每日一练
DAY 1
选择题 1:
下列哪些是 HTML5 的新特性?
A. 语义标签
B. Canvas 绘图
C. <audio>元素
D. 增强型表单
【答案】ABCD
选择题 2:
下面可以继承的属性有哪些?
A. font-size
B. background
C. color
D. cursor
【答案】ACD
【解析】
-
css不可以继承的属性:display、margin、padding、border、background、width、min-width、max-width、height、min-height、max-height、overflow、position、top、bottom、left、right、z-index、float、clear、table-layout、vertical-align、page-bread-before、page-bread-after、unicode-bidi
-
所有元素都可以继承:visibility、cursor
-
子元素可以继承:letter-spacing(字符间距)、word-spacing(单词间距)、white-space(如何处理元素内的空白)、line-height(设置行高,内联元素不可以继承,设置为行内块元素可以继承)、color、font、font-size、font-family、font-style、font-weight、font-variant(大写字母)、text-decoration(文本下划线、中划线)、text-transform(首字母大写、转大写)、direction(rtl-文本方向从右向左)、text-indent(首行缩进)、text-align(文本对齐)
-
列表元素(li)可继承:list-style、list-style-type、list-style-position、list-style-image
-
表格元素可继承:border-collapse
DAY 2
选择题 1:
对于一条100M的宽带,理论下载速度上限是多少?
A. 12.5MB/s
B. 100MB/s
C. 10MB/s
D. 10Mb/s
【答案】A
【解析】1Byte = 8bit,因此理论下载速度上限是:100Mb/s ÷ 8 = 12.5MB/s
选择题 2:
关于 for of 和 for in 的描述,正确的是?
A. for in 可以循环普通对象
B. for of 可以循环普通对象
C. 都不可以循环数组
D. 都可以循环数组
【答案】AD
【解析】使用 for…of 遍历必须在原型上拥有 [Symbol.iterator] 接口才行,而一般用 for…in 遍历对象,Array 在一定程度上也属于对象,因此可以遍历,只不过 key 值为数组的下标值
DAY 3
选择题 1:
关于事件冒泡描述正确的是?
A. 从目标元素向 document 冒泡
B. 从 document 向目标元素冒泡
C. 从 document 向目标元素冒泡,再从目标元素向 document 冒泡
D. 以上都不是
【答案】A
选择题 2:
以下哪些 script 标签属性会使脚本有可能在 DOMContentLoaded 事件之后加载?
A. <script async>
B. <script defer>
C. <script type="module">
D. <script type="module" async>
【答案】AD
DAY 4
选择题 1:
以下哪些是 CSS 块级元素的特性?
A. 宽度默认由其中的内容决定
B. 高度默认由其中的内容决定
C. 可以被分拆到多行
D. 可以通过 height 属性指定高度
【答案】BD
【解析】块级元素默认情况独占一行,C 选项的可以被分拆到多行不知道啥意思
选择题 2:
以下关于跨域说法错误的是?
A. http://example.com/a.html 和 https://example.com/b.htm 是相同的域名,属于同源
B. 跨域资源共享规范中规定了除了 GET 之外的 HTTP 请求,或者搭配某些 MINE 类型的 POST 请求,浏览器都需要先发一个 OPTIONS 请求。
C. CSS 中通过 @font-face 使用字体也会有跨域问题
D. Cookie,LocalStorage 和 IndexedDB 都会受到同源策略的限制
【答案】A
【解析】A 选项,同源策略:协议、域名、端口号相同;B 选项,是简单请求和复杂请求的区别;C 选项,Web fonts 仍然受到同域限制 (字体文件必须和调用它的网页同一域);D 选项,正如大多数的 web 储存解决方案一样,localStorage 和 IndexedDB 也遵守同源策略,因此当你在某个域名下操作储存数据的时候,你不能操作其他域名下的数据
DAY 5
选择题 1:
下列哪些可以实现浏览器存储数据?
A. cookie
B. localStorage
C. session
D. sessionStorage
【答案】ABD
选择题 2:
对以下代码说法正确的是?
let arr = [1,2,3,4,5];
let arr2 = [1, , 3];
A. 执行 arr.length = 3,此时数组为 [1,2,3]
B. 执行 arr[10] = 11,此时 arr.length 为 6
C. 执行 delete arr[2],此时 arr.length 为 4,数组为 [1,2,4,5]
D. arr2.length 的长度为 2
【答案】A
【解析】B 选项,执行 arr[10] = 11,此时 arr.length 为 11;C 选项,执行 delete arr[2],此时 arr.length 为 5,数组为 [ 1, 2, <1 empty item>, 4, 5 ];D 选项,arr2.length 的长度为 3
DAY 6
选择题 1:
在 css 选择器当中,优先级排序正确的是?
A. id选择器>标签选择器>类选择器
B. 标签选择器>类选择器>id选择器
C. 类选择器>标签选择器>id选择器
D. id选择器>类选择器>标签选择器
【答案】D
选择题 2:
如以下代码所示,给 body 绑定两个事件后,调用 document.body.click() 输出的结果是?
document.body.addEventListener('click', () => {
Promise.resolve().then(() => console.log(1))
console.log(2);
}, false);
document.body.addEventListener('click', () => {
Promise.resolve().then(() => console.log(3))
console.log(4);
}, false);
A. 2, 4, 1, 3
B. 2, 1, 4, 3
C. 1, 2, 3, 4
D. 1, 3, 2, 4
【答案】A
【解析】addEventListener 的事件不会被覆盖,都会被按顺序执行,然后就是事件循环了,上面的代码相当于:
Promise.resolve().then(() => console.log(1))
console.log(2);
Promise.resolve().then(() => console.log(3))
console.log(4);
因此很容易看出来选 A
附加一道事件循环的题:
//请写出输出内容
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console.log('async2');
}
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0)
async1();
new Promise(function(resolve) {
console.log('promise1');
resolve();
}).then(function() {
console.log('promise2');
});
console.log('script end');
【答案】
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout
【解析】await 相当于把之后的代码放入微任务队列中
DAY 7
选择题 1:
浮动会导致页面的非正常显示,以下几种清除浮动的方法,哪个是不推荐使用的?
A. 在浮动元素末尾添加一个空的标签例如 <div style=”clear:both”></div>
B. 通过设置父元素overflow值为hidden;
C. 给父元素添加clearfix类
D. 父元素也设置浮动
【答案】D
选择题 2:
以下代码的运行结果是?
var f = function () {
console.log('1');
}
function f() {
console.log('2');
}
f();
A. undefined
B. 报错
C. 2
D. 1
【答案】D
【解析】js 预解析,上面的代码相当于:
var f;
function f() {
console.log('2');
}
f = function () {
console.log('1');
}
f();
DAY 8
选择题 1:
下列说法正确的有哪些?
A. visibility:hidden 表示所占据的空间位置仍然存在,仅为视觉上的完全透明
B. display:none 不为被隐藏的对象保留其物理空间
C. visibility:hidden 与display:none 两者没有本质上的区别
D. visibility:hidden 回流与重绘
【答案】AB
【解析】具体的对比参数如下:
display:none | visibility:hidden | opacity:0 | |
---|---|---|---|
页面中 | 不存在 | 存在 | 存在 |
重绘 | 会 | 会 | 不一定 |
回流 | 会 | 不会 | 不会 |
自身绑定事件 | 不触发 | 不触发 | 可触发 |
transition | 不支持 | 支持 | 支持 |
子元素复原 | 不能 | 能 | 不能 |
被遮挡元素触发事件 | 不影响 | 不影响 | 影响 |
选择题 2:
若主机甲与主机已已建立一条 TCP 链接,最大段长(MSS)为 1KB,往返时间(RTT)为 2 ms,则在不出现拥塞的前提下,拥塞窗口从 8KB 增长到 32KB 所需的最长时间是?
A. 4ms
B. 8ms
C. 24ms
D. 48ms
【答案】D
【解析】TCP 的拥塞控制包括:慢开始、拥塞避免、快重传、快恢复。这里是考察慢开始➕拥塞避免,因为当指数增长到 ssthresh 时会变成拥塞避免算法,即每个 RTT 后每次增长 1 个 MSS,题目问到最长时间,如果当 8KB 到 32KB为线性增长那时间肯定是最长的,所以所需的最长时间是:(32 - 8) * 2ms = 48ms
DAY 9
选择题 1:
以下对HTML标签的使用,哪些是符合语义的?
A. 使用 table 展示表格数据
B. 使用 span 表示按钮
C. 使用 article 展示文章内容
D. 使用 p 标签展示文章标题
【答案】AC
选择题 2:
包过滤防火墙对数据包的过滤依据不包括哪些?
A. 源IP地址
B. 源端口号
C. MAC 地址
D. 目的 IP 地址
【答案】C
【解析】包过滤是在 IP 层实现的,包过滤根据数据包的源 IP 地址、目的 IP 地址、协议类型(TCP 包、UDP 包、ICMP 包)、源端口、目的端口等包头信息及数据包传输方向等信息来判断是否允许数据包通过
编程题
前端编程题
342. 4的幂
/**
* @param {number} n
* @return {boolean}
*/
function isPowerOfFour(n) {
n = +n;
return (n & (n - 1)) === 0 && n % 3 === 1;
};
125. 验证回文串
/**
* @param {string} s
* @return {boolean}
*/
function isPalindrome(s) {
s = s.toLowerCase().match(/[0-9a-zA-Z]+/g)?.join('');
if (s === undefined) return true;
let left = 0, right = s.length - 1;
while (left <= right) {
if (s[left++] !== s[right--]) return false;
}
return true;
};
5. 最长回文子串
/**
* @param {string} s
* @return {string}
*/
function longestPalindrome(s) {
const len = s.length;
let idx = null;
for (let i = 0; i < len; i++) {
let { len: len1, idx: idx1 } = expand(i, i);
let { len: len2, idx: idx2 } = expand(i, i + 1);
const temp = len1 >= len2 ? idx1 : idx2;
idx = calcLen(temp) > calcLen(idx) ? temp : idx;
}
return s.substring(idx[0], idx[1] + 1);
function expand(left, right) {
while (left >= 0 && right < len && s[left] === s[right]) {
left--;
right++;
}
return {
len: right - left - 1,
idx: [left + 1, right - 1]
}
}
function calcLen(list) {
if (list === null) return -1;
return list[1] - list[0] + 1;
}
};
后端编程题
题目1
题目
实现一个 36 进制的加法 0-9 a-z。
示例
输入:“abbbb”,“1”
输出:“abbbc”
/**
* @param {string} num1
* @param {string} num2
* @return {string}
*/
const map = new Map(new Array(36).fill().map((item, index) => [index.toString(36), index]));
const map_reverse = new Map(new Array(36).fill().map((item, index) => [index, index.toString(36)]));
function add36Base(num1, num2) {
let carry = 0, p1 = num1.length - 1, p2 = num2.length - 1, result = "";
while (p1 >= 0 || p2 >= 0) {
let sum = (map.get(num1[p1]) ?? 0) + (map.get(num2[p2]) ?? 0) + carry;
carry = Math.floor(sum / 36);
result = map_reverse.get(sum % 36) + result;
p1--;
p2--;
}
return (carry ? carry : '') + result;
}
题目2
题目
抖音电影票业务支持电影院选座,需要在用户买票时自动推荐座位,如果一个用户买了多张票,则需要推荐相邻(上下相邻、左右相邻都可)的座位。现在使用一个二维数组来表示电影院的座位,数组中 0 表示未被选座,1 表示已被选座或者为障碍物,请实现一个方法求出给定影院中最大可推荐的相邻座位个数。
示例
输入:
[1,0,0,1,0,0,0]
[1,0,0,0,0,1,1]
[0,0,0,1,0,0,0]
[1,1,0,1,1,0,0]
输出:18
function maxAreaOfRecommendSeats(grid) {
const row = grid.length, column = grid[0].length, map = genMap(row, column);
let result = 0, cnt = 0;
for (let i = 0; i < row; i++) {
for (let j = 0; j < column; j++) {
if (grid[i][j] === 0 || map[i][j]) continue;
walk(i, j);
result = Math.max(result, cnt);
cnt = 0;
}
}
return result;
function walk(i, j) {
if (!ifExit(i, j) || grid[i][j] === 0 || map[i][j]) return;
map[i][j] = true;
cnt++;
walk(i + 1, j);
walk(i - 1, j);
walk(i, j + 1);
walk(i, j - 1);
}
function ifExit(i, j) {
return (grid[i] ?? false) && (grid[i][j] ?? false) && true;
}
function genMap(row, column) {
const result = [];
for (let i = 0; i < row; i++) {
result.push(new Array(column).fill(false));
}
return result;
}
}
题目3
热身题
/**
* @param {string} s
* @return {string[]}
*/
function restoreIpAddresses(s) {
const result = [], path = [], len = s.length;
recursion(0);
return result;
function recursion(start) {
if (len - 1 - path.at(-1) > (4 - path.length) * 3 || !ifIPValid(path)) return;
path.length === 4 && result.push(sliceIP(path).join('.'));
for (let i = start; i < len; i++) {
path.push(i);
recursion(i + 1);
path.pop();
}
}
function ifIPValid(idx) {
return sliceIP(idx).every(item => {
if (item.startsWith("0")) return item.length === 1;
return item <= 255;
})
}
function sliceIP(idx) {
return idx.reduce((pre, curr, index) =>
(pre.push(s.slice((idx[index - 1] + 1 || 0), curr + 1)), pre), []);
}
}
题目
有效 IP 地址正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 ‘.’ 分隔。
例如:“0.1.2.201” 和 “192.168.1.1” 是有效 IP 地址,但是 “0.011.255.245”、“192.168.1.312” 和 “192.168@1.1” 是无效 IP 地址。
给定一个字符串 s,非数字的字符可替换为任意不包含在本字符串的数字,同样的字符只能替换为同样的数字,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 s 中插入 ‘.’ 来形成。你不能重新排序或删除 s 中的任何数字,你可以按任何顺序返回答案。
示例 1
输入:20212118136
输出:
20.212.118.136
202.12.118.136
202.121.18.136
202.121.181.36
示例 2
输入:11a2b22a037
输出:114.252.240.37
/**
* @param {string} s
* @return {string[]}
*/
function restoreIpAddressesWithLetters(s) {
const list = [...new Set(s.match(/[a-zA-Z]/g))], letterVal = new Map(), result = [];
recursion(0);
return result;
function recursion(index) {
if (letterVal.size === list.length) {
[...letterVal].forEach(item => s = s.replaceAll(item[0], item[1]));
result.push(...restoreIpAddresses(s));
return;
}
for (let i = 0; i <= 9; i++) {
letterVal.set(list[index], i);
recursion(index + 1);
letterVal.delete(list[index]);
}
}
}
写在最后
如果喜欢可以收藏这个专栏,后续会发布更多的资料,记得点赞➕关注 🌟