字节笔试23.11.2

前端笔试,题型:10个单选20分,5个多选20分,2个编程60分。(忘了挺多题了)

选择(单选and多选)

  1. 输出是什么(原型链和super)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class cls {
constructor() {
this.num1 = 117;
}
}
class son extends cls {
constructor() {
// 必须在this之前调用
super();
this.num2 = 935;
super.num3 = 130;
}
}
let obj = new son();
console.log(obj.num1); // 117
console.log(obj.num2); // 935
console.log(obj.num3); // 130
  • 以下来自:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/super

  • super 是一个关键字,并且有一些特殊的语法结构。super 不是一个指向原型对象的变量。试图读取 super 本身会导致 SyntaxError。

  • super必须在使用 this 关键字之前和构造函数返回之前被调用,它调用父类的构造函数并绑定父类的公共字段,之后派生类的构造函数可以进一步访问和修改 this

  • 设置 super 的属性,比如 super.x = 1,这会将 super 简单理解为“原型对象的引用”,实际上是在 this 上设置属性。

  1. 输出是什么(delete和Array的length)
1
2
3
4
5
6
let arr = [1,2,3];
delete arr[0];
let arr2 = [1,2,3];
arr2.length = 0;
console.log(arr1); // [empty,2,3]
console.log(arr2); // []
  • 参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/delete

  • delete一般用于删对象的属性,它与直接释放内存没有关系,内存管理是通过破坏引用间接完成的。

  • delete 只影响自身属性。如果原型链上有相同属性,删除属性之后,对象会使用原型链上的那个属性。

  • 当你删除一个数组元素时,数组的长度(length)不受影响,就算是最后一个元素也是这。

  • 参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/length

  • 数组对象会观察 length 属性,并自动将 length 值与数组的内容同步。

  • 设置 length 小于当前长度的值将会截断数组——超过新 length 的元素将被删除。

  • 设置超过当前 length 的任何数组索引(小于 232 的非负整数)将会扩展数组——length 属性增加以反映新的最高索引。

  • length 被设置为比当前长度更大的值时,数组通过添加空槽来扩展,而不是实际的 undefined 值。

  1. 具体题目不记得了,总之出现了这些东西
1
2
3
4
5
6
7
8
9
let obj = {age: 18};
obj.__proto__.name = 'John';
const {age, name} = obj;
console.log(age, name); // 18 'John'

let num1, num2;
// {num1, num2} = {num1: 117, num2: 935}; 报错
({num1, num2} = {num1: 117, num2: 935});
console.log(num1, num2); // 117 935
  • 考了js的对象解构赋值,一般的话用[]包裹,如const [num1, num2] = {...},但这里用{}的话,得加个括号让解释器不要将左边的{num1, num2}看作代码块。
  • 在 JavaScript 中,变量的作用域是由代码块决定的。也就是说,在一个代码块{}内定义的变量只在该代码块以及嵌套的子代码块中可见,而不能在外部访问。这被称为作用域链。

编程题

  1. 题目大意:给一个长度为n的数组nums,满足nums[i]都是正整数,小红可以取相邻两个数同时减1,问能不能将整个数组全部变为零。

    解法:非常简单的模拟,最左和最右的想要变成0必须靠左2和右2,以左边为例的话直接左2-左1,然后左2成为新的左1。左右一起算,O(n)就行,丑陋的代码就不粘了。

  2. 题目大意:给两个长度为n的正整数数组a[]b[],问存在多少个区间[L, R](L<=R),使得a[L] ^ a[L+1] ^ ...^ a[R] = b[L] ^ b[L+1] ^ ... ^ b[R]

    解法:先用前缀和的思想,算个前缀异或,因为异或有很多性质,比如:

    1. 满足交换律、结合律
    2. 异或自身为零,与零异或等于自身,即A ^ 0 = A,A ^ A = 0
    3. 异或逆运算还是异或,比如加法逆运算是减法,a+b=c能推a=c-b。异或的话,a^b=c能推a=c^b,也就是abc两两异或都等于另一个
    • 我们算一下前缀异或,得到pre_xor_a和pre_xor_b,这样a[L] ^ a[L+1] ^ ...^ a[R] = pre_xor_a[R] ^ pre_xor_a[L-1]
    • 转换问题为求有多少个L和R使得pre_xor_a[R] ^ pre_xor_a[L-1] = pre_xor_b[R] ^ pre_xor_b[L-1]
    • 用一下异或的性质,A^B=C^D,两边同时异或B^C,就有A^B^B^C=C^D^B^C,化简一下就是A^C=B^D,就是求pre_xor_a[L-1] ^ pre_xor_b[L-1] = pre_xor_a[R] ^ pre_xor_b[R]
    • 现在只要构造一下f(x) = pre_xor_a[x] ^ pre_xor_b[x],用f(x)的值建个哈希表,关注超过1的那些值就行。