前端开发

前端JavaScript高级面试技巧[1]

2019-12-07  本文已影响0人  Mark同学

第1章 课程介绍

1-1 导学

课程概述

知识点介绍

课程安排

讲授方式

课程收获

1-2 课程重要提示

1-3 架构-题目

ES6

模块化的使用和编译环境?

Class 与 JS 构造函数的区别?

Promise 的用法?

ES6 其他常用功能?

异步

什么是单线程,和异步有什么关系?

什么是 event-loop?

目前 JS 解决异步的方案有哪些?

如果只用 jquery 如何解决异步?

Promise 的标准?

async/await 的使用?

原型

原型如何实际应用?

原型如何满足扩展?

vdom

什么是 vdom,为何要用 vdom?

vdom如何使用,核心函数有哪些?

了解 diff 算法吗?

MVVM

之前使用 jquery 和现在使用 Vue 或 React 框架的区别?

你如何理解MVVM?

Vue 如何实现响应式?

Vue 如何解析模版?

介绍 Vue 的实现流程?

组件化

对组件化的理解?

JSX 是什么?

JSX 和 vdom 什么关系?

简述 React 的 setState?

简述自己如何比较 React 和 Vue?

hybrid

hybrid 是什么,为何要用hybrid?

hybrid 如何更新上线?

hybrid 和 h5 有何区别?

JS 如何与客户端通信?

第2章 ES6 语法

2-1 开始

ES6

题目

2-2 模块化

【题目】

ES6 模块化如何使用,开发环境如何打包?

【知识点】

1. 模块化的基本语法

// util1.js
export default {
  a: 100
};

// util2.js
export function fn1() {
  alert('fn1');
};
export function fn2() {
  alert('fn2');
};
// index.js
import util1 from './util1.js';
import { fn1, fn2 } from './util2.js';

console.log(util1);
fn1();
fn2();

2. 开发环境配置

babel

1. 电脑有 node 环境,运行 npm init
2. npm install --save-dev babel-core babel-preset-es2015 babel-preset-latest
3. 创建 .babelrc 文件,输入以下内容:
    { 
        "presets": ["es2015", "latest"],
        "plugins": []
    }
4. sudo npm install -g babel-cli
5. babel --version
1. 创建:./src/index.js
2. 内容:[1, 2, 3].map(item => item + 1);
3. 运行:babel ./src/index.js

webpack

1. npm install webpack webpack-cli babel-loader@^7.1.2 --save-dev
2. 配置 webpack.config.js,输入以下内容:
    module.exports = { 
        entry: './src/index.js',
        output: { 
          path: __dirname,
          filename: './build/bundle.js'
        },
        module: { 
          rules: [{
            test: /\.js?$/,
            exclude: /{node_modules}/,
            loader: 'babel-loader'
          }]
        }
    }
3. 配置 package.json 中的 scripts
    "scripts": {
        "start": "webpack"
    }
4. 运行 npm start
5. 创建:index.html
    <script type="text/javascript" src="./build/bundle.js"></script>
6. http-server -p 8881
7. 访问 http://localhost:8881/index.html

rollup

https://www.rollupjs.com/guide/tutorial rollup 中文网

1. npm init
2. npm i rollup rollup-plugin-node-resolve rollup-plugin-babel@^3.0.3 babel-plugin-external-helpers babel-preset-latest babel-core --save-dev
3. 配置 .babelrc
{
  "presets": [
    ["latest", {
      "es2015": {
        "modules": false
      }
    }]
  ],
  "plugins": ["external-helpers"]
}
4. 配置  rollup.config.js
import babel from 'rollup-plugin-babel';
import resolve from 'rollup-plugin-node-resolve';

export default {
  input: 'src/index.js',
  output: {
    file: 'build/bundle.js',
    format: 'cjs'
  },
  plugins: [
    resolve(),
    babel({
        exclude: 'node_modules/**'
    })
  ]
};
1. 将 webpack 环境的 JS 代码拷贝过来
2. 修改 package.json 的 scripts
  "scripts": {
    "start": "rollup -c rollup.config.js"
  }
3. 运行 npm start
rollup 功能单一,webpack 功能强大
参考设计原则和《Linux/Unix设计思想》
工具要尽量功能单一,可集成,可扩展
wangEditor 用的 gulp + rollup

3. 关于 JS 众多模块化标准

【解答】

2-9 class

【题目】

Class 与 JS 构造函数的区别?

【知识点】

JS 构造函数

function MathHandle(x, y) {
  this.x = x;
  this.y = y;
}

MathHandle.prototype.add = function () {
  return this.x + this.y;
};

var m = new MathHandle(1, 2);
console.log(m.add());

// typeof MathHandle // "function"
// MathHandle === MathHandle.prototype.constructor // true
// m.__proto__ === MathHandle.prototype // true

Class 基本语法

class MathHandle {
  constructor (x, y) {
    this.x = x;
    this.y = y;
  }

  add() {
    return this.x + this.y;
  }
}
const m = new MathHandle(1, 2);
console.log(m.add());
// typeof MathHandle // "function"
// MathHandle === MathHandle.prototype.constructor // true
// m.__proto__ === MathHandle.prototype // true

语法糖

class MathHandle {
  // ...
}

typeof MathHandle // "function"
MathHandle === MathHandle.prototype.constructor // true

继承

ES6 之前的继承,是把低级构造函数的原型,赋值成高级构造函数的实例这种方式来实现的
// 动物
function Animal() {
  this.eat = function () {
    console.log('animal eat');
  }
}
// 狗
function Dog() {
  this.bark = function () {
    console.log('dog bark');
  }
}
// 绑定原型,实现继承
Dog.prototype = new Animal();
// 哈士奇
var hashiqi = new Dog();
hashiqi.eat(); // animal eat
hashiqi.bark(); // dog bark
// 动物
class Animal {
  constructor(name) {
    this.name = name;
  }
  eat() {
    console.log(`${this.name} eat`);
  }
}
// 狗
class Dog extends Animal {
  constructor(name) {
    super(name);
    this.name = name;
  }
  say() {
     console.log(`${this.name} say`);
  }
}
// 哈士奇
const dog = new Dog('哈士奇');
dog.say(); // 哈士奇 say
dog.eat(); // 哈士奇 eat

【解答】

class Ad extends Component {
    constructor(props) {
        super(props);
        this.state = {
            data: []
        }
    }
    render() {
        return (
            <div>Hello, World!</div>
        )
    }
    componentDidMount() {

    }
}

2-13 Promise

【题目】

Promise 的用法?

【知识点】

Promise 的基本使用

function loadImg(src, callback, fail) {
  var img = document.createElement('img');
  img.onload = function () {
    callback(img);
  }
  img.onerror = function () {
    fail();
  }
  img.src = src;
}

var src = 'https://www.imooc.com/courseimg/s/cover042_s.jpg';
loadImg(src, function (img) {
  console.log(img.width);
}, function () {
  console.log('failed');
})
function loadImg(src) {
  const promise = new Promise(function (resolve, reject) {
    var img = document.createElement('img');
    img.onload = function () {
      resolve(img);
    }
    img.onerror = function () {
      reject();
    }
    img.src = src;
  })
  return promise;
};

var src = 'https://www.imooc.com/courseimg/s/cover042_s.jpg';
var result = loadImg(src);

result.then(function (img) {
  console.log(img.width);
}, function () {
  console.log('failed');
});

result.then(function (img) {
  console.log(img.height);
});

【解答】

2-16 总结一下 ES6 其他常用功能

题目

总结一下 ES6 其他常用功能?

知识点

// JS
var i = 10;
i = 100;

// ES6
let i = 10;
i = 100;  // 正确
const j = 20;
j = 200;  // 报错
// JS
var name = 'zhangsan', age = 20, html = '';
html += '<div>';
html += ' <p>' + name + '</p>';
html += ' <p>' + age + '</p>';
html += '</div>';

// ES6
const name = 'zhangsan', age = 20;
const html = `<div>
                     <p>${name}</p>
                     <p>${age}</p>
             </div>`;
console.log(html);
// JS
var obj = { a: 100, b: 200 };
var a = obj.a;
var b = obj.b;

var arr = ['xxx', 'yyy', 'zzz'];
var x = arr[0];
// ES6
const obj = { a: 10, b: 20, c: 30 };
const { a, c } = obj;
console.log(a);
console.log(c);

const arr = ['xxx', 'yyy', 'zzz'];
const [x, y, z] = arr;
console.log(x);
console.log(y);
console.log(z);
// JS
var obj = { a: 100, b: 200 };
for (var item in obj) {
  console.log(item);
}
console.log(item); // 'b'

// ES6
const obj = { a: 100, b: 200 };
for (let item in obj) {
  console.log(item);
}
console.log(item); // undefined
// JS
function fn(a, b) {
  if (b == null) {
    b = 0;
  }
}

// ES6
function fn(a, b=0) {

}
// JS
var arr = [1, 2, 3];
arr.map(function (item) {
  return item + 1;
});

// ES6
const arr = [1, 2, 3];
arr.map(item => item + 1);
arr.map((item, index) => {
  console.log(index);
  return item + 1;
});
function fn() {
  console.log('real', this); // {a: 100}
  var arr = [1, 2, 3];
  // 普通 JS
  arr.map(function (item) {
    console.log('js', this); // window
    return item + 1;
  });
  // 箭头函数
  arr.map(item => {
    console.log('es6', this); // {a: 100}
    return item + 1;
  });
}
fn.call({a: 100});

第3章 原型

3-1 开始

题目

原型如何实际应用?

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <p>jquery test 1</p>
    <p>jquery test 2</p>
    <p>jquery test 3</p>

    <div id="div1">
        <p>jquery test in div</p>
    </div>

    <script type="text/javascript" src="./jquery-3.2.1.js"></script>
    <script type="text/javascript">
        var $p = $('p');
        $p.css('color', 'red'); // css 是原型方法
        console.log($p.html()); // html 是原型方法
        
        var $div1 = $('#div1')
        $div1.css('color', 'blue'); // css 是原型方法
        console.log($div1.html()); // html 是原型方法
    </script>
</body>
</html>
(function (window) {

  var zepto = {};

  function Z(dom, selector) {
      var i, len = dom ? dom.length : 0;
      for (i = 0; i < len; i++) {
          this[i] = dom[i];
      }
      this.length = len;
      this.selector = selector || '';
  }

  zepto.Z = function (dom, selector) {
      return new Z(dom, selector);
  };

  zepto.init = function (selector) {
      var slice = Array.prototype.slice;
      var dom = slice.call(document.querySelectorAll(selector));
      return zepto.Z(dom, selector);
  };

  var $ = function (selector) {
      return zepto.init(selector);
  };
  window.$ = $

  $.fn = {
      css: function (key, value) {
          alert('css');
      },
      html: function (value) {
          return '这是一个模拟的 html 函数';
      }
  }
  Z.prototype = $.fn;
})(window);
(function (window) {

    var jQuery = function (selector) {
        return new jQuery.fn.init(selector)
    };

    jQuery.fn = {
        css: function (key, value) {
            alert('css');
        },
        html: function (value) {
            return 'html';
        }
    };

    var init = jQuery.fn.init = function (selector) {
        var slice = Array.prototype.slice;
        var dom = slice.call(document.querySelectorAll(selector));

        var i, len = dom ? dom.length : 0;
        for (i = 0; i < len; i++) {
            this[i] = dom[i];
        }
        this.length = len;
        this.selector = selector || '';
    }

    init.prototype = jQuery.fn;

    window.$ = jQuery;

})(window);

原型如何满足扩展?

第4章 异步

题目

什么是单线程,和异步有什么关系?

// 循环运行期间,JS 执行和 DOM 渲染暂时卡顿
var i, sum = 0;
for (i = 0; i < 1000000000; i++) {
  sum += i;
}
console.log(sum);

// alert 不处理, JS 执行和 DOM 渲染暂时卡顿
console.log(1);
alert('hello');
console.log(2);
浏览器需要渲染 DOM
JS 可以修改 DOM 结构
JS 执行的时候,浏览器 DOM 渲染会暂停
两段 JS 也不能同时执行(都修改 DOM 就冲突了)
webworker 支持多线程,但是不能访问 DOM
问题一:没按照书写方式执行,可读性查
问题二:callback 中不容易模块化

什么是 event-loop?

事件轮询,JS 实现异步的具体解决方案
同步代码,直接执行
异步函数先放在 "异步队列" 中
待同步函数执行完毕,轮询执行 "异步队列" 的函数

如果只用 jquery 如何解决异步?- Deferred

jQuery 1.5 的变化
使用 jQuery Deferred
初步引入 Promise 概念
var ajax = $.ajax({
  url: 'data.json',
  success: function () {
    console.log('success1');
    console.log('success1');
    console.log('success1');
  },
  error: function () {
    console.log('error');
  }
})
console.log(ajax); // 返回一个 XHR 对象
var ajax = $.ajax('data.json');
ajax.done(function () {
      console.log('success 1');
    })
    .fail(function () {
      console.log('error');
    })
    .done(function () {
      console.log('success 2');
    })
console.log(ajax); // 返回一个 deferred 对象
// 很像 Promise 的写法
var ajax = $.ajax('data.json');
ajax.then(function () {
        console.log('success 1');
      }, function () {
        console.log('error 1');
      })
      .then(function () {
        console.log('success 2');
      }, function () {
        console.log('error 2');
      })
无法改变 JS 异步和单线程的本质
只能从写法上杜绝 callback 这种形式
它是一种语法糖形式,但是解耦了代码
很好的体现:开放封闭原则 ( 对扩展开发,对修改封闭 )
var wait = function () {
  var task = function () {
     console.log('执行完成');
     console.log('此处新需求......');
     console.log('第一步');
     console.log('第二步');
     console.log('第三步');
  };
  setTimeout(task, 2000);
};
wait();
function waitHandle() {
   var dtd = $.Deferred();
   var wait = function (dtd) {
       var task = function () {
           console.log('执行完成');
           dtd.resolve();
           // dtd.reject()
       }
       setTimeout(task, 2000);
       return dtd.promise(); // return dtd; => return dtd.promise();
   }
   return wait(dtd);
}

var w = waitHandle();
// w.then(function () {  
// => 1.w 接收到的不再是一个 dtd 对象,而是一个 promise 对象
// => 2.只有 .then .done .fail 这种被动监听方法
// => 3.不再支持 .resolve .reject 这种主动方法的调用
$.when(w).then(function () {
    console.log('ok 1');
}, function () {
    console.log('err 1');
});
总结,dtd 的 API 可分成两类,用意不同
第一类: dtd.resolve  dtd.reject
第二类: dtd.then  dtd.done  dtd.fail
这两类应该分开,否则后果很严重!
可以在上面代码最后执行 dtd.reject() 试一下后果

Promise 的基本使用和原理?

function loadImg(src) {
  const promise = new Promise(function (resolve, reject) {
    var img = document.createElement('img');
    img.onload = function () {
      resolve(img);
    }
    img.onerror = function () {
      reject();
    }
    img.src = src;
  })
  return promise;
};

var src = 'https://www.imooc.com/courseimg/s/cover042_s.jpg';
var result = loadImg(src);

result.then(function (img) {
  console.log(img.width);
}, function () {
  console.log('failed');
});

result.then(function (img) {
  console.log(img.height);
});
// 捕获程序错误异常
// throw new Error('自定义错误');

result.then(function (img) {
  console.log(img.width);
  return img;
}).then(function (img) {
  console.log(img.height);
}).catch(function (ex) {
  // 统一捕获异常
  console.log(ex);
})
// 捕获业务逻辑异常
// reject('图片加载失败');
// var src = 'https://cover042_sXXX.jpg';

result.then(function (img) {
  console.log(img.width);
  return img;
}).then(function (img) {
  console.log(img.height);
}).catch(function (ex) {
  // 统一捕获异常
  console.log(ex);
})
//业务需求;先加载一个,再加载另外一个
var src1 = 'https://www.imooc.com/courseimg/s/cover042_s.jpg';
var result1 = loadImg(src1);
var src2 = 'https://coding.imooc.com/static/module/class/content/img/190/section5-img.png';
var result2 = loadImg(src2);

// 链式操作
result1.then(function (img) {
  console.log('第一个图片加载完成', img.width); // 240
  return result2;
}).then(function (img) {
  console.log('第二个图片加载完成', img.width); // 998
}).catch(function (ex) {
  // 统一捕获异常
  console.log(ex);
})
// 全部完成才执行
Promise.all([result1, result2]).then(function (datas)  {
 console.log(datas[0]);
 console.log(datas[1]);
});
// 只要有一个完成就执行
Promise.race([result1, result2]).then(function (data)  {
 console.log(data);
});
// 关于“标准”的闲谈
任何技术推广使用都需要一套标准来支撑
如 html js css http 等,无规矩不成方圆
任何不符合标准的东西,终将会被用户抛弃
不要挑战标准,不要自造标准
// Promise 标准 - 状态变化
三种状态:pending fulfilled rejected
初始状态是 pending
pending 变为 fulfilled ,或者 pending 变为 rejected
状态变化不可逆
// Promise 标准 - then
Promise 实例必须实现 then 这个方法
then() 必须可以接收两个函数作为参数
then() 返回的必须是一个 Promise 实例

介绍一下 async/await(和 Promise 的区别、联系)?

var w = waitHandle();
w.then(function () { 
    console.log('ok 1');
}, function () {
    console.log('err 1');
}).then(function () { 
    console.log('ok 2');
}, function () {
    console.log('err 2');
});
const load = async function () {
  const result1 = await loadImg(src1);
  console.log(result1);
  const result2 = await loadImg(src2);
  console.log(result2);  
}
load();
使用 await ,函数必须用 async 标识
await 后面跟的是一个 Promise 实例
需要 babel-polyfill
// webpack 打包
1.首先,npm i babel-polyfill -D
2.运行报错,Uncaught ReferenceError: regeneratorRuntime is not defined
3.在 .babelrc 文件中添加:
    "plugins": [
        [
            "transform-runtime",
            {
                "helpers": false,
                "polyfill": false,
                "regenerator": true,
                "moduleName": "babel-runtime"
            }
        ]
    ]
4.运行报错,ReferenceError: Unknown plugin "transform-runtime" specified
5.npm install babel-plugin-transform-runtime -D
6.运行再次报错,Cannot use import statement outside a module
7.<script type="module"></script>
8.成功
// rollup 打包
1.npm i babel-polyfill -D
之前也报和 webpack 相同的错误,自己就好了,原因未知
promise 是对异步回调的封装
async await 是使用 promise 时的一种扩展
完全是同步的写法,再也没有回调函数
但是:改变不了 JS 单线程、异步的本质

目前 JS 解决异步的方案有哪些?

上一篇下一篇

猜你喜欢

热点阅读