商汤前端实习二面

商汤前端实习二面
最新回答
﹛理葙﹜忄青λ

2026-10-31 13:35:56

1. 判断变量类型

问题:如何判断变量的类型?

回答:

  • 基本数据类型:使用 typeof 操作符。例如:

    typeof 42; // "number"typeof "hello"; // "string"typeof true; // "boolean"typeof undefined; // "undefined"
  • 复杂类型(对象):使用 Object.prototype.toString.call() 方法。例如:

    Object.prototype.toString.call([]); // "[object Array]"Object.prototype.toString.call({}); // "[object Object]"Object.prototype.toString.call(null); // "[object Null]"Object.prototype.toString.call(undefined); // "[object Undefined]"

关于 toString 判断基本类型:

  • 基本类型也可以通过 Object.prototype.toString.call() 判断,因为 JavaScript 会自动将基本类型转换为对应的包装对象。例如:Object.prototype.toString.call(42); // "[object Number]"Object.prototype.toString.call("hello"); // "[object String]"Object.prototype.toString.call(true); // "[object Boolean]"
  • 但通常不推荐用 toString 判断所有类型,因为:

    typeof 更简洁,适合基本类型。

    Object.prototype.toString.call() 需要写更长的代码,且可读性稍差。

2. 获取对象准确的数据类型

问题:如何获取对象准确的数据类型?

回答:

  • 使用 constructor 属性可以获取对象的构造函数,从而判断类型。例如:const obj = {};console.log(obj.constructor === Object); // trueconst arr = [];console.log(arr.constructor === Array); // true
  • 但需要注意:

    如果对象是通过 Object.create(null) 创建的,则没有 constructor 属性。

    更可靠的方法是 Object.prototype.toString.call()。

3. 函数作用域链

问题:讲一下函数作用域链。

回答:

  • 作用域链:JavaScript 中,函数在定义时会创建一个作用域链,用于解析变量。作用域链从当前函数的执行上下文开始,向外延伸到全局作用域。
  • 查找规则:

    在当前函数作用域中查找变量。

    如果找不到,则在外层作用域中查找,直到全局作用域。

    如果全局作用域也找不到,则抛出 ReferenceError。

  • 示例:const a = 1;function outer() { const b = 2; function inner() { const c = 3; console.log(a, b, c); // 1, 2, 3 } inner();}outer();

    inner 函数的作用域链:inner → outer → 全局作用域。

4. 对于框架的理解

问题:讲一下对于框架的理解。

回答:

  • 框架的作用:

    提供基础架构和工具,简化开发流程。

    统一代码风格,提高可维护性。

    解决常见问题(如状态管理、路由、性能优化等)。

  • 常见框架:

    React:组件化、虚拟 DOM、单向数据流。

    Vue:响应式数据、模板语法、组件化。

    Angular:完整的企业级解决方案,依赖注入、模块化。

  • 框架的核心思想:

    分离关注点(如 MVC、MVVM)。

    提供声明式编程(如 JSX、模板)。

    优化性能(如虚拟 DOM、懒加载)。

5. Webpack 配置顺序的影响

问题:Webpack 中 loader 和 plugin 的配置顺序的影响。

回答:

  • Loader 顺序:

    Loader 的执行顺序是从右到左(或从下到上)。

    例如:

    module: { rules: [ { test: /.css$/, use: ["style-loader", "css-loader"], // 先执行 css-loader,再执行 style-loader }, ],}

    如果顺序错误,可能导致功能异常(如 style-loader 必须在 css-loader 之后)。

  • Plugin 顺序:

    Plugin 的执行顺序通常不影响功能,因为插件是通过事件钩子工作的。

    但某些插件可能有依赖关系(如 HtmlWebpackPlugin 需要在 MiniCssExtractPlugin 之后)。

6. 手写 curry 函数

问题:实现 curry 函数,支持 add(1,2)(3)(4)(5,6,7) 的调用方式。

回答:

function curry(fn) { return function curried(...args) { if (args.length >= fn.length) { return fn.apply(this, args); } else { return function (...args2) { return curried.apply(this, args.concat(args2)); }; } };}function add(a, b, c, d, e, f, g) { return a + b + c + d + e + f + g;}const curriedAdd = curry(add);const res = curriedAdd(1, 2)(3)(4)(5, 6, 7);console.log(res()); // 287. 手写链式调用(支持同步和异步)

问题:实现链式调用的 Cat 类,支持同步和异步方法。

回答:

class Cat { constructor(name) { this.name = name; this.queue = Promise.resolve(); } sayHello() { this.queue = this.queue.then(() => { console.log(`${this.name} says hello`); }); return this; } sayName() { this.queue = this.queue.then(() => { console.log(`My name is ${this.name}`); }); return this; } sleep(ms) { this.queue = this.queue.then(() => { return new Promise((resolve) => { setTimeout(() => { console.log(`${this.name} slept for ${ms}ms`); resolve(); }, ms); }); }); return this; }}// 示例const cat = new Cat("Tom");cat.sayHello().sayName().sleep(1000).sayHello();

说明:

  • 使用 Promise 链实现异步链式调用。
  • 每个方法返回 this 以支持链式调用。
  • sleep 方法返回一个 Promise,实现异步延迟。