十道前端面试题第【06】篇

1、Webpack 和 Gulp 的区别

  • grunt、gulp 是基于任务运行的工具:它们会自动执行指定的任务,就像流水线,把资源放上去然后通过不同插件进行加工,它们包含活跃的社区,丰富的插件,能方便的打造各种工作流。

  • webpack 是基于模块化打包的工具:webpack 把一切都当做模块,当 webpack 处理程序时,会递归地构建一个依赖关系图,其中包含应用程序需要的每个模块,然后将所有的模块打包成一个或者多个 bundle。


2、Webpack中常用的loaders和plugins有哪些

常用 loaders

  • file-loader 把文件输出到一个文件夹中,在代码中通过相对 URL 引用输入的文件
  • url_loader 和 file-loader 类似,能在文件很小的情况下以 base64 的方式将文件内容注入到代码中
  • source-map-loader 加载额外的 Source Map 文件,方便断点调试
  • image-loader 加载并压缩图片文件
  • babel-loader 将 ES6 转换为 ES5
  • css-loader 加载 css,支持模块化、压缩、文件导入等特性
  • style-loader 把 css 代码注入到 JavaScript 中,通过 DOM 操作去加载 css
  • eslint-loader 通过 ESLint 检查 JavaScript 代码
  • html-minify-loader 压缩HTML

常用的 plugins

  • define-plugin 定义环境变量
  • html-webpack-plugin 简化 html 文件创建
  • uglifyjs-webpack-plugin 通过 UglifyES 压缩 ES6 代码
  • webpack-parallel-uglify-plugin 多核压缩,提高压缩速度
  • webpack-bundle-analyzer 可视化 webpack 输出文件的体积
  • mini-css-extract-plugin CSS 提取到单独的文件中,支持按需加载
  • clean-webpack-plugin 在每次构建前清理 /dist 文件夹


3、手写 reduce() 方法

Array.prototype._reduce = function(fn, initialValue) {
  var arr = Array.prototype.slice.call(this);
  var res, startIndex;
  res = initialValue ? initialValue : arr[0];
  startIndex = initialValue ? 0 : 1;
  for(var i = startIndex; i < arr.length; i++) {
    res = fn.call(null, res, arr[i], i, this); 
  }
  return res;
}


4、Vue-Loader 的工作原理

  • Vue Loader 是什么?
  • Vue Loader 原理分析


5、手动实现 instanceof 和 new

// 实例.__ptoto__ === 类.prototype
function _instanceof(example, classFunc) {
    let proto = Object.getPrototypeOf(example);
    while(true) {
        if(proto == null) return false;
        // 在当前实例对象的原型链上,找到了当前类
        if(proto == classFunc.prototype) return true;
        // 沿着原型链__ptoto__一层一层向上查
        proto = Object.getPrototypeof(proto); // 等于proto.__ptoto__
    }
}

new 操作符做了这些事:

  • 创建一个全新的对象
  • 这个对象的 __proto__ 要指向构造函数的原型 prototype
  • 执行构造函数,使用 call/apply 改变 this 的指向
  • 返回值为object类型则作为new方法的返回值返回,否则返回上述全新对象。
function _new(fn, ...args) {
    let instance = Object.create(fn.prototype);
    let res = fn.apply(instance, args); // 改变this指向

    // 确保返回的是一个对象(万一fn不是构造函数)
    return typeof res === 'object' ? res: instance;
}


6、Webpack热更新的工作原理

  • Webpack HMR
  • Webpack 热更新原理


7、手写 Promise

class MyPromise {
  constructor(fn) {
    this.resolvedCallbacks = [];
    this.rejectedCallbacks = [];    
    this.state = 'PENDING';
    this.value = '';    
    fn(this.resolve.bind(this), this.reject.bind(this));    
  }
  
  resolve(value) {
    if (this.state === 'PENDING') {
      this.state = 'RESOLVED';
      this.value = value;      
      this.resolvedCallbacks.map(cb => cb(value));   
    }
  }
  
  reject(value) {
    if (this.state === 'PENDING') {
      this.state = 'REJECTED';
      this.value = value;      
      this.rejectedCallbacks.map(cb => cb(value));
    }
  }
  
  then(onFulfilled, onRejected) {
    if (this.state === 'PENDING') {
      this.resolvedCallbacks.push(onFulfilled);
      this.rejectedCallbacks.push(onRejected);      
    }    
    if (this.state === 'RESOLVED') onFulfilled(this.value);    
    if (this.state === 'REJECTED') onRejected(this.value);
  }
}


8、解释下述代码的运行机理

function bar() {
    console.log(a)
}

function foo() {
    var a = 100
    var b = 1000
    bar()
    function fn() {
        console.log(a)
        console.log(b)
    }
    fn()
}
var a = 200
var b = 2000

foo()

答案:依次打印2001001000


9、手写浏览器嗅探方法

// Browser environment sniffing
var inBrowser = typeof window !== 'undefined';
var inWeex = typeof WXEnvironment !== 'undefined' && !!WXEnvironment.platform;
var weexPlatform = inWeex && WXEnvironment.platform.toLowerCase();
var UA = inBrowser && window.navigator.userAgent.toLowerCase();
var isIE = UA && /msie|trident/.test(UA);
var isIE9 = UA && UA.indexOf('msie 9.0') > 0;
var isEdge = UA && UA.indexOf('edge/') > 0;
var isAndroid = (UA && UA.indexOf('android') > 0) || (weexPlatform === 'android');
var isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios');
var isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge;
var isPhantomJS = UA && /phantomjs/.test(UA);
var isFF = UA && UA.match(/firefox\/(\d+)/);


10、给一个无序的数组,这个数组中包含 N 连续数字中的 N-1,已知上下边界,要求找到这个数组缺失的数字。

function findMissingNumber(arr) {
  var sum_of_integers = 0;
  var min = arr[0]
  var max = arr[0]
  for (var i = 0; i < arr.length; i++) {
    sum_of_integers += arr[i];
    min = Math.min(min, arr[i])
    max = Math.max(max, arr[i])
  }
  upper_limit_sum = (max * (max + 1)) / 2;
  lower_limit_sum = (min * (min - 1)) / 2;
  theoretical_sum = upper_limit_sum - lower_limit_sum;
  return (theoretical_sum - sum_of_integers)
}

// 测试
var integers = [23,26,24,22,28,25];
var miss = findMissingNumber(integers);
console.log('miss', miss)  // 27


本周结束,下周继续!!!

你可能感兴趣的:(十道前端面试题第【06】篇)