企业公司面试超详细的 JS 面试题

文章目录

  • 1.**面试题:`null`和`undefined`的区别? **
  • 2.面试题:请描述下面的代码输出结果是什么? 考察parseInt
  • 3.面试题:请描述一下什么是变量的预解析?| 请描述一下什么是变量提升?
  • 4.*面试题:`||`符号和`??`符号的区别?*
  • 5. 面试题解析:请简要描述一下,循环过程中如何终止`forEach`循环?
  • 6.*面试题:请描述一下你对函数默认参数的理解?*
  • 7.*面试题:观察下图,请通过代码计算青蛙跳到台阶的顶端有几种方法?*

1.**面试题:nullundefined的区别? **


nullundefined都是原生JS中基础类型的数据,语法上都用于表示无效数据


null一般表示空值,更多的时候和对象的描述有关;转换成整数为0;null是语法中的一个关键词

undefined一般表示未定义/未声明值,通常一个声明了但是没有赋值的变量会自动赋值undefined,和基础类型的数据表示相关;转换成整数为NaNundefined不是语法中的关键词


项目中使用这两个数据时,如果我们希望一个变量中可能要存储对象,在存储对象之前可以赋值null;如果希望一个变量中可能存储基础数据,可以不赋值默认就是undefined


我们使用undefined时需要注意,这不是一个关键词,所以尽量不要使用undefined给变量直接赋值,很容易出现BUG,如果非要给一个变量显示赋值undefiend建议使用下面的语法:

let _username;    // 推荐,默认undefined
let _username = undefined; // 不推荐,存在BUG
let _username = void 0;    // 赋值一个表达式,表达式返回undefined

2.面试题:请描述下面的代码输出结果是什么? 考察parseInt

const result = parseInt('111', 2)
console.log("result:", result)

题目分析:

  • parseInt()函数:主要用于类型转换,将其他类型数据转换成整数
  • 最常见:将字符串的数值,转换成整数数值
  • 出现了第二个参数:2,将需要转换的数据当成指定的进制进行转换
parseInt("12") => 12
parseInt("200px") => 200
parseInt("$200.00") => NaN
parseInt("500X200") => 500

结论分析:

# 将'111'按照2进制的方式进行处理,转化得到10进制数据
const result = parseInt('111', 2) // 7
# 0 1 10 11 100 101 110 111    
# 0 1  2  3  4   5   6   7

拓展:分析下面的代码输出结果?

const result = parseInt('123', 2)
console.log("result: ", result)		// 1

const result2 = parseInt('321', 2)
console.log("result2: ", result2)		// NaN

3.面试题:请描述一下什么是变量的预解析?| 请描述一下什么是变量提升?


变量预解析,是原生JS中的一种语法机制,通过var声明的变量,在当前的命名空间中解释执行时,会将变量的声明部分提升到命名空间最前面,赋值部分保留在原地不变;

预解析是为了保障在声明变量的命名空间中,声明前后使用变量不会出现错误,是一种程序开发的容错语法,保障程序正常运行,不因为出现的错误导致崩溃退出!


ES6语法中又提供了let、const关键字声明变量和常量,声明的变量不再支持预解析效果,项目开发过程中原来的预解析功能尽管有容错的好处,但是很容易导致某些变量赋值前被使用出现了一些意料以外的结果,提高了BUG出现的几率,同时容易出现全局污染!所以新语法标准中推荐使用let声明变量提高语法操作中变量使用安全性!

保障安全性的基础上,通过try-catch语法保障容错性!

项目开发中,根据不同的开发场景,var、let、const关键字都可以使用!

4.面试题:||符号和??符号的区别?


总:||??都是原生JS中的操作符,都可以用于变量默认值的赋值


分:||是逻辑或条件操作符,可以用于逻辑条件判断,也可以用于默认值赋值;默认值赋值时空字符串、0、nullundefined都可以用于false条件判断

var name = result || "默认值"
# 结果:result中如果是""0null或者undefined,name就会被赋值:"默认值"

分:??ES2020规范新增的专门用于变量默认值赋值的操作符,主要用于判断赋值的数据是否为null或者undefined

var name = result ?? "默认值"
# 结果:result中是null或者undefined,name会赋值:"默认值"

**总:**项目业务开发中,空字符串和0有时候是有效数据,如购买数量可以为0,用户邮箱赋值""空字符串表示没有设置邮箱,就可以使用??进行默认值赋值,使用||反倒出现bug

var buyCnt = count || 1
# bug: 用户购买商品时,某个商品直接选择了数量0-> 结算的时候:给用户售出了1件商品

var buyCnt = count ?? 1
# 用户购买商品某个商品选择了数量0,这个商品结算的时候就会按照0处理,不会出现bug

5. 面试题解析:请简要描述一下,循环过程中如何终止forEach循环?


普通的数据循环,可以通过break关键字跳出循环;但是forEach本质上是一个函数,所以不能通过break跳出循环,出现语法错误

函数中可以通过return结束执行函数,但是forEach(fn)内部包含了一个回调函数,间接的形成了一种闭包结构,内部使用return只是返回内部闭包函数,并没有结束forEach()函数,所以也不能使用return跳出循环

可以通过异常语法完成forEach()跳出循环的操作,如满足某个条件时可以通过throw Error("错误消息")的方式抛出一个异常,外部通过try-catch结构捕获异常保障代码不因为出现的异常而崩溃退出,这样就实现了forEach()中满足条件时跳出循环的操作

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]

try {
  arr.forEach((index, item) => {
    console.log(item)
    if (index >= 5) {
      // break
      // return
      // 抛出错误
      throw Error("跳出循环")
    }
  })
} catch (e) { }

console.log("循环执行结束")

6.面试题:请描述一下你对函数默认参数的理解?

回答思路:先回答主体内容,什么是默认参数和如何使用默认参数!

拓展:原生JS中默认参数如何处理的?ES6中可以对默认参数如何处理?

函数的默认参数,是ES6语法中对函数声明的一种语法扩展,可以在函数的形式参数中给参数直接赋值作为函数参数的默认值,默认值形式参数要放在位置参数的后面声明;如果调用执行函数时这个参数没有传递实际数据,参数中就会使用默认赋值的数据参与函数内部代码的运算

function buy(price, count) {
  // 计算过程
  return price * count
}

const total = buy(2.88, 1) // 结果 2.88
const total2 = buy(3.56)   // 结果 ?

// ES6 默认参数
function buy(price, count=1){
  ....
}
const total = buy(2.88, 2) // 结果 5.76
const total2 = buy(3.56)   // 结果 3.56

拓展:原生JS中没有提供默认参数的情况下,我们可以通过赋值语法给一些经常使用的变量进行赋值操作

function buy(pricer, count) {
  // 设置默认值
  var cnt = count || 1
  // 参数运算
  ....
}

做一些特殊运算的时候,逻辑运算符||针对数值0或者空字符串也会进行默认值判断,将数值0空字符串“”以及null/undefined都会当成无效数据,所以ES6中可以通过扩展运算符对数值0或者空字符串这样的有效数据进行过滤

function buy(pricer, count) {
  // 设置默认值
  var cnt = count ?? 1
  // 参数运算
  ....
}

7.面试题:观察下图,请通过代码计算青蛙跳到台阶的顶端有几种方法?

  • 限制:青蛙每次跳1个台阶或者2个台阶

企业公司面试超详细的 JS 面试题_第1张图片

1、类推法

不要尝试直接找一个多级台阶去手工画图尝试

一般都是从只有一个台阶、只有两个台阶、只有三个台阶…找出前面几个数据的规律,通过代码将这样的规律实现出来

规律:f(n) = f(n-1) + f(n-2)

2、倒推法

规律:f(n) = f(n-1) + f(n-2)

终点:一层台阶一层台阶向下计算,当n取值为3的时候,就是第一级台阶和第二级台阶的和,第一级台阶只有1种跳法;第二级台阶2种跳法

3、实现代码

function qingWa(n) {
  // 确定n=1和n=2的情况
  if(n > 0 && n<=2){
    return n
  }
  // 计算下一级台阶跳法
  return qingWa(n-1) + qingWa(n-2)
}

思考:上面的算法是通过函数递归实现的,函数的递归存在常驻内存的问题,思考一下是否可以通过循环实现呢?

    /**
     * 方案二,通过规律进行for循环替代
     */

    @Test
    public void run02(){
        int count =24;
        int a=1;
        int b=2;
        int num =0;
        for (int i=2; i<count; i++){
            num =a+b;
            a=b;
            b=num;
        }
        System.out.println(num);
    }

你可能感兴趣的:(JS,面试,javascript,职场和发展)