5道BAT大厂面试题,助你夯实js基础

前言:

最近看到了一篇大厂面试题集锦,在这里摘出来一些比较有意思的面试题跟大家分享,通过这些试题的分析,加深大家对js的理解,夯实基础知识。

1.输出以下代码的执行结果

var obj = {
  '2': 3,
  '3': 4,
  'length': 2,
  'splice': Array.prototype.splice,
  'push': Array.prototype.push
}
obj.push(1);
obj.push(2);
console.log(obj);

考察点1:

对push的理解,push是根据length来决定从哪里开始插入给定的值。

我们来去除其他代码,仅保留push来看看控制台输出

var obj = {
  '2': 3,
  '3': 4,
  'length': 2,
  // 'splice': Array.prototype.splice,
  'push': Array.prototype.push
}
obj.push(1);
obj.push(2);
console.log(obj);

输出:

{2: 1, 3: 2, length: 4, push: ƒ}
      

可以看到因为length为2,所以push是从下标为2的地方开始插入,下标为2跟3的值被push进去的值覆盖。

接下来我们修改length

var obj = {
  '2': 3,
  '3': 4,
  'length': 0,
  // 'splice': Array.prototype.splice,
  'push': Array.prototype.push
}
obj.push(1);
obj.push(2);
console.log(obj);

输出:

{0: 1, 1: 2, 2: 3, 3: 4, length: 2, push: ƒ}

可以看到如果length改为0,那么push是从0开始插入

考察点2:

当一个对象拥有splice函数作为属性时,控制台会以数组形式输出

var obj = {
  '2': 3,
  '3': 4,
  'length': 2,
  'splice': Array.prototype.splice,
  'push': Array.prototype.push
}
obj.push(1);
obj.push(2);
console.log(obj);
      
输出:

[empty × 2, 1, 2, splice: ƒ, push: ƒ]

虽然控制台输出的是数组形式,但是obj依然是对象类型

var obj = {
  '2': 3,
  '3': 4,
  'length': 2,
  'splice': Array.prototype.splice,
  'push': Array.prototype.push
}
obj.push(1);
obj.push(2);
console.log(obj);
console.log(obj instanceof Array)
console.log(obj instanceof Object)

输出:
[empty × 2, 1, 2, splice: ƒ, push: ƒ]
false
true

结合两个考察点,我们可以分析出最终结果

[empty × 2, 1, 2, splice: ƒ, push: ƒ]

2.输出以下代码的执行结果

var a = {n:1};
var b = a; 
a.x = a = {n:2};
console.log(a.x);
console.log(b.x);
考察点1:

连续赋值,顺序从右向左。

考察点2:

运算符优先级,点的优先级要高于等号。更多运算符优先级请参阅运算符优先级

考察点3

引用数据类型的值是指向堆的指针。

我们先看输出

undefined
{n: 2}

解析:

var a = {n:1};
var b = a;  //将b指向{n:1}
a.x = a = {n:2};
// 1. a.x 会在{n:1,x:undefined}
// 2. 将a重新指向{n:2}
// 3. 将{n:1,x:undefined}中的x指向{n:2}
// 4. 此时 b: {n:1,x:{n:2}}, a: {n:2}
console.log(a.x);
console.log(b.x);

3.输出以下代码的执行结果

var a = 10;
(function(){
 console.log(a);
 a=5;
 console.log(window.a);
 var a = 20;
 console.log(a)
})()
考察点1:

变量提升,es6之前只存在全局作用域跟函数作用域,变量提升就是将变量定义提升到当前作用域的开始。

考察点2:

作用域,es6之前只存在全局作用域跟函数作用域,当赋值变量或者查找变量时,会现在当前作用域查找,如果没有找到会向上级作用域查找,直到找到全局作用域。

解析:

var a = 10;
(function(){
 console.log(a);
 a=5;
 console.log(window.a);
 var a = 20;
 console.log(a)
})()
结果:
undefined 10 20
// 1. 立即执行函数内的 var a = 20; 会先进行变量提升。 var a = undefined;会提升到函数作用域顶部
// 2. 这时候console.log(a) 的a为undefined
// 3. console.log(window.a),这时候取的是window的a变量,这时候全局对象下的a变量为10
// 4. 运行到var a = 20; 这时候会在当前作用域查找a变量,找到了以后赋值为20
// 5. 这时候输出console.log(a) 这时候a的值为20

4.下面代码中a在什么情况下会打印1?

var a = ?;
if(a == 1 && a == 2 && a == 3){
 console.log(1);
}
考察点1:

隐式类型转换,当进行±等运算或者==时,会进行隐式类型转换。

考察点2:

对象转为原始类型时会先调用自身valueOf方法,如果没有返回原始值,会继续调用自身的toString方法,如果还是没有返回原始类型,则抛出异常。

var a = {
 i:1,
 toString:function(){
   console.log('toString',this.i)
   return this.i++
 },
 valueOf:function(){
   console.log('valueOf',this.i)
   return this.i++
 }
};
if(a == 1 && a == 2 && a == 3){
 console.log(1);
}

输出:
valueOf 1
valueOf 2
valueOf 3
1
// 1. a为一个对象,在转换为数字时会调用valueOf
// 2. valueOf执行完毕以后再次转换时会继续调用valueOf
// 3. 当()内的表达式执行完毕后a内的i变为4

5.输出以下代码的执行结果

var b = 10;
(function b(){
  b=20;
  console.log(b)
})()
console.log(b)
考察点1:

立即执行表达式会生成一个局部作用域,起到隔离参数的作用。

考察点2:

函数提升要高于变量提升
例子:

var a = 1;
function a(){

}
console.log(a)
输出:
1

由此可见,函数的优先级要高于var变量定义。

考察点3:

具名函数表达式只能由内部访问,并且具名函数表达式的name无法重新赋值

举个例子:

var a = function b(){
console.log(b);
b=1;
console.log();
}
输出:
ƒ b(){
  console.log(b);
  b=1;
  console.log(b)
}

ƒ b(){
  console.log(b);
  b=1;
  console.log(b)
}

解析:

var b = 10;
(function b(){
  b=20;
  console.log(b)
})()
console.log(b)
输出:
ƒ b(){
  b=20;
  console.log(b)
}
10

// 1. 立即执行函数有两种定义方式
      (1). (function(){})()
      (2). (function(){}())
      (3). !、,、+、-等符号 !function(){}()
// 2. 当函数被()包裹以后,这个函数就不是函数声明了,就变成了一个函数表达式
// 3. 具名函数表达式内部的b无法重新定义,所以输出的是b函数
// 4. b=20 赋值查找当前作用域,查到了具名函数表达式的name,但是无法重新赋值,查找到了不再继续向上查找
// 4. 最后的console输出的是全局变量b,所以是10

如果想获取更多内容,可以扫描下方二维码,一起学习,一起进步。
左道前端

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值