HTML/CSS
题1:
1.使用CSS 让该节点不可见,方法越多越好。 <div class="hidden"'>Hi</div>
使用CSS 让节点不可见的方法有以下几种:
- 把 visibility 属性设置为 hidden,这样元素框不会被绘制,但仍然占据布局空间https://developer.mozilla.org/zh-CN/docs/Web/CSS/visibility
- 把 display 属性设置为 none,这样元素框不会被显示,也不会占据布局空间https://www.runoob.com/css/css-display-visibility.html
- 把 opacity 属性设置为 0,这样元素框会变成完全透明,但仍然可以响应事件。
题2:
2.在哪些场景下用过 position 的哪些值,它们分别有什么特性?
你好,这是Bing。😊
根据搜索结果,我发现
position
属性有以下五个值:
static
:默认值,元素按照正常的文档流进行排列,不受其他定位属性的影响relative
:相对定位,元素相对于自己原来的位置进行偏移,但仍然占据文档流中的位置absolute
:绝对定位,元素脱离文档流,相对于最近的非static
定位的祖先元素进行定位fixed
:固定定位,元素脱离文档流,相对于浏览器窗口进行定位,不随滚动条移动31。- sticky:粘性定位,元素在滚动时切换为固定定位,相对于最近的滚动祖先和包含块进行定位
JavaScript
题3:
3. 什么是单线程?什么是单线程昇步?
单线程和单线程异步的区别是:
- 单线程是指一个程序或一个进程只能同时执行一个任务,不能同时处理多个任务。
- 单线程异步是指单线程程序在遇到耗时的操作(如网络请求,定时任务等)时,不会等待其完成,而是继续执行后续的代码,当耗时的操作完成后,再通过回调函数或事件通知单线程程序进行处理。
单线程异步的优点是可以提高程序的效率和响应速度,避免阻塞代码的执行。单线程异步的缺点是代码的逻辑和顺序会变得复杂,需要注意回调地狱和错误处理等问题。
题4:
// 4. The output of the following program is var fn =[] for (var i = 0; i < 10; i++) { fn[i] = function (param){ console.log(i + param) } } fn [5](5) var data = {a: 10, b: 20} console.log('第'+i+'条数据:'+data)
这段代码的输出是:
15 第10条数据:[object Object]
这是因为
var
声明的变量会发生变量提升(hoisting),而且没有块级作用域(block scope),所以i
的值在循环结束后是10,而不是5。所以,当调用fn[5](5)
时,打印出的是i + param
,即10 + 5 = 15。然后,打印出'第'+i+'条数据:'+data
,即’第10条数据:’ + ‘[object Object]’。如果想要打印出5 + 5 = 10,可以使用let
声明变量,它会创建块级作用域,每次循环都会创建一个新的变量。
题5:
// 5. The output of the following program is console.log(1) setTimeout(() => { console.log(2) }, 0) console.log(3) new Promise((resolve, reject) => { console.log(4) resolve() }).then(() => { console.log(5) }, () => { console.log(6) }) console.log(7)
这段代码的输出是:
1 3 4 7 5 2
这是因为JavaScript是单线程的,它会先执行同步代码,然后再执行异步代码。异步代码又分为微任务(microtask)和宏任务(macrotask),微任务的优先级高于宏任务。
setTimeout
是一个宏任务,Promise.then
是一个微任务。所以,同步代码会按照顺序打印出1、3、4、7,然后微任务队列中的Promise.then
会打印出5,最后宏任务队列中的setTimeout
会打印出2。
题6:
// 5. The output of the following program is const a=[1,1,1,1,1] for (let i = 0; i< 5; i++) { for (let j = 0; j < i; j++) { a[i] = a[i]+ a[j] } } for (let i = 0; i < 5; i++){ console.log(a[i]) }
这段代码的输出是:
1 2 4 8 16
这是因为这段代码实现了一个斐波那契数列(Fibonacci sequence),它的规律是每一项都等于前两项之和。所以,a[1] = a[0] + a[0] = 1 + 1 = 2,a[2] = a[1] + a[0] = 2 + 1 = 4,以此类推。
题7:
// 7.写出①所在的 while循坏的作用;补全②的代码。 // isSymmetry 用来判断正整数n是否是一个对称数,例:12321是对称数,而123不是 function isSymmetry (n) { let i=n let j=0 // ① while (i) { j=j*10+i%10 i=parseint(i/10) // return ② console.log(isSymmetry (12321)) // true console.log(isSymmetry (1231)) // false
这段代码的①所在的while循环的作用是将n的每一位反转,得到一个新的数j。例如,如果n是12321,那么j就是12321;如果n是1231,那么j就是1321。
补全②的代码的一种可能方法是:
return j === n
这样就可以判断j和n是否相等,如果相等,说明n是一个对称数,返回true;如果不相等,说明n不是一个对称数,返回false。
题8:
// 8. 把数组倒序輸出(不是排序)(不能用内置方法) const arr = ['name', 'first', '5', 7, 4, '2', 9]
一种把数组倒序输出的方法是:
const arr = ['name', 'first', '5', 7, 4, '2', 9] let len = arr.length // 获取数组长度 for (let i = len - 1; i >= 0; i--) { // 从后往前遍历数组 console.log(arr[i]) // 输出每一项 }
这样就可以得到以下输出:
9 2 4 7 5 first name ``
题9:
// 9(过一面必做题)数组中的重复项最多出现N次。(时间复杂度越低得分越高) 原题9.1: outputNth([1, 1, 1, 11], 2) // return[1,1])(按原数组出现的先后返回,合并到一起) outputNth([20,37,20,20, 21],2)//return [20,20,37,21](按原数组出现的先后返回,合并到一起) 原题9.2: 如果要求outputNth([20,37,20,20,21],2)//return [20,37,20,21]呢?(按原数组出现的先后返回) 题9.1: function outputNth (array.n){ 题9.2:function outputNth (array, n){}请预估自己的时间复杂度:}请预估自己的时间复杂度:
这两道题都可以用一个哈希表(hash table)来记录每个元素出现的次数,然后遍历数组,根据不同的要求输出结果。具体的代码如下:
题9.1:
function outputNth(array, n) { let hash = {} // 创建一个空的哈希表 let result = [] // 创建一个空的结果数组 for (let num of array) { // 遍历数组中的每个元素 if (hash[num]) { // 如果哈希表中已经有这个元素 hash[num]++ // 将其出现次数加一 } else { // 如果哈希表中没有这个元素 hash[num] = 1 // 将其出现次数设为一 } if (hash[num] <= n) { // 如果这个元素出现次数小于等于n result.push(num) // 将其加入结果数组 } } return result // 返回结果数组 }
题9.2:
function outputNth(array, n) { let hash = {} // 创建一个空的哈希表 let result = [] // 创建一个空的结果数组 for (let num of array) { // 遍历数组中的每个元素 if (hash[num]) { // 如果哈希表中已经有这个元素 hash[num]++ // 将其出现次数加一 } else { // 如果哈希表中没有这个元素 hash[num] = 1 // 将其出现次数设为一 } if (hash[num] === n) { // 如果这个元素出现次数等于n result.push(num) // 将其加入结果数组 } else if (hash[num] < n) { // 如果这个元素出现次数小于n result.push(num) // 将其加入结果数组 result.push(null) // 同时在后面加入一个空值,用来占位,方便后面删除多余的元素 } } return result.filter(item => item !== null) // 返回结果数组,并过滤掉空值 }
这两道题的时间复杂度都是O(n),因为只需要遍历一次数组,哈希表的查找和插入操作都是常数时间。
题10:
可以参考一下:
// 定义一个栈类 class Stack { // 构造函数,初始化一个空数组作为栈 constructor() { this.items = [] } // 入栈操作,将元素添加到栈顶 push(element) { this.items.push(element) } // 出栈操作,将栈顶元素移除并返回 pop() { return this.items.pop() } // 查看栈顶元素,不改变栈 peek() { return this.items[this.items.length - 1] } // 判断栈是否为空 isEmpty() { return this.items.length === 0 } // 获取栈的大小 size() { return this.items.length } // 清空栈 clear() { this.items = [] } // 打印栈中的元素 print() { console.log(this.items.toString()) } } // 创建一个栈对象 let stack = new Stack() // 测试入栈操作 stack.push(5) stack.push(8) stack.push(11) stack.push(15) // 测试打印操作 stack.print() // 输出 [5,8,11,15] // 测试出栈操作 console.log(stack.pop()) // 输出 15 console.log(stack.pop()) // 输出 11 // 测试查看操作 console.log(stack.peek()) // 输出 8 // 测试其他操作 console.log(stack.isEmpty()) // 输出 false console.log(stack.size()) // 输出 2 // 测试清空操作 stack.clear() console.log(stack.isEmpty()) // 输出 true
这就是完整的代码,你可以运行一下看看效果。希望这能帮助你理解栈这种数据结构。😊