美文网首页
前端JavaScript面试技巧

前端JavaScript面试技巧

作者: Mark同学 | 来源:发表于2019-12-06 10:32 被阅读0次

    1-1 课程概述

    • 要做什么?——讲解前端 JS 基础面试题
    • 哪些部分?——JS 基础,JS-WEB-API,JS 开发环境
    • 使用技术?——JS,直指面试题

    知识点介绍

    基础知识(三座大山)
    • 原型 原型链
    • 作用域 闭包
    • 异步 单线程
    JS API
    • DOM 操作
    • AJAX
    • 事件绑定
    开发环境
    • 版本管理
    • 模块化
    • 打包工具
    运行环境
    • 页面渲染
    • 性能优化

    讲述方式

    • 以面试题引出知识点,深化知识点,举一反三

    课程收获

    • 前端 JS 基础知识以及知识体系

    1-2 前言

    关于面试(分成三个阶段)

    • 基层工程师 - 基础知识
    • 高级工程师 - 项目经验
    • 架构师 - 解决方案

    关于基础

    • 工程师的自我修养 - 基础
    • 扎实的基础会让你高效学习新技术

    1-3 几个面试题

    JS 中使用 typeof 能得到哪些类型?
    考点:JS 变量类型

    何时使用 ===,何时使用 ==?
    考点:强制类型转换

    window.onload 和 DOMContentLoaded 的区别?
    考点:浏览器的渲染过程

    用 JS 创建10个<a>标签,点击的时候弹出来对应的序号?
    考点:作用域

    简述如何实现一个模块加载器,实现类似 require.js 的基本功能?
    考点:JS 模块化

    实现数组的随机排序?
    考点:JS 基础算法

    思考

    • 拿到一个面试题,你第一时间看到的是什么?
      答:考点。(考的哪里)
    • 如何看待网上搜出来的永远也看不完的题海?
      答:不变应万变。(知识不变)
    • 如何对待接下来遇到的面试题?
      答:题目到知识再到题目。

    第二章 JS基础知识

    2-1 变量类型和计算

    题目

    JS 中使用 typeof 能得到哪些类型?
    考点:JS 变量类型(6种),不能区分引用类型*

    typeof undefined // undefined
    typeof 'abc' // string
    typeof 123 // number
    typeof true // boolean
    typeof {} // object
    typeof [] // object
    typeof null // object
    typeof console.log // function
    

    何时使用 ===,何时使用 ==?
    考点:强制类型转换(==有类型转换,===没有)

    JS 中有哪些内置函数?
    考点:数据封装类对象

    Object
    Array
    Boolean
    Number
    String
    Function
    Date
    RegExp
    Error
    

    JS 变量按照存储方式区分为哪些类型,并描述其特点?
    考点:值类型(分块存储) vs 引用类型(共享内存)
    前者是值的拷贝,后者是引用的拷贝

    如何理解 JSON?
    答:JS 对象(同 Math)|| 数据格式

    // 常用的方法有两个
    JSON.stringify({a:10, b:20}); // 对象 => 字符串
    JSON.parse('{"a":10,"b":20}'); // 字符串 => 对象
    

    知识点

    1.变量类型:值类型 vs 引用类型

    • 值类型
    var a = 100;
    var b = a;
    a = 200;
    console.log(b); // 100
    
    • 引用类型(对象、数组、函数),引用类型的设计是为了共享内存空间
    var a = {age:20};
    var b = a;
    b.age = 21;
    console.log(a.age); // 21
    

    2.变量计算 - 强制类型转换

    • 字符串拼接
    var a = 100 + 10;    // 110
    var b = 100 + '10';  // '10010'
    
    • == 运算符
    100 == '100' // true
    0 == '' // true
    null == undefined // true
    
    • if 语句
    var a = true;
    if (a) { // ... }
    var b = 100;
    if (b) { // ... }
    var c = '';
    if (c) { // ... }
    
    • 逻辑运算
    console.log(10 && 0); // 0
    console.log('' || 'abc'); // 'abc'
    console.log(!window.abc); // true
    

    2-5 原型和原型链

    题目

    如何准确判断一个变量是数组类型?

    var arr = [];
    arr instanceof Array; // true
    typeof arr; // object,typeof 是无法判断是否是数组的
    

    写一个原型链继承的例子?

    // 动物
    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();
    
    // 写一个封装 dom 查询的例子,演示原型链继承
    function Elem(id) {
      this.elem = document.getElementById(id);
    }
    
    Elem.prototype.html = function (val) {
      var elem = this.elem;
      if (val) {
        elem.innerHTML = val;
        return this; // 链式操作
      } else {
        return elem.innerHTML;
      }
    }
    
    Elem.prototype.on = function (type, fn) {
      var elem = this.elem;
      elem.addEventListener(type, fn);
    }
    
    var div1 = new Elem('div1');
    // console.log(div1.html());
    div1.html('<p>hello imooc</p>').on('click', function () {
      alert('clicked');
    });
    

    描述 new 一个对象的过程?
    考点:构造函数

    • 创建一个新对象
    • this 指向这个新对象
    • 执行代码,即对 this 赋值
    • 返回 this
    function Foo(name, age) {
      this.name = name;
      this.age = age;
      this.class = 'class-1';
      // return this; // 默认有这一行
    }
    var f = new Foo('zhangsan', 20);
    

    zepto (或其他框架)源码中如何使用原型链?

    知识点

    构造函数

    function Foo(name, age) {
      this.name = name;
      this.age = age;
      this.class = 'class-1';
      // return this; // 默认有这一行
    }
    var f = new Foo('zhangsan', 20);
    

    构造函数 - 扩展

    var a = {} 其实是 var a = new Object() 的语法糖
    var a = [] 其实是 var a = new Array() 的语法糖
    function Foo(){...}其实是 var Foo = new Function(...) 
    使用 instanceof 判断一个函数是否是一个变量的构造函数
    

    原型规则和示例

    5条原型规则:原型规则是学习原型链的基础
    1. 所有的引用类型(数组、对象、函数),都具有对象特性,即可以自由扩展属性(除了'null'以外)
    var obj = {}; obj.a = 100;
    var arr = []; arr.a = 100;
    function fn () {}
    fn.a = 100;
    
    1. 所有的引用类型(数组、对象、函数),都具有一个_proto_属性,属性值是一个普通的对象
    console.log(obj.__proto__);
    console.log(arr.__proto__);
    console.log(fn.__proto__);
    
    1. 所有的函数,都具有一个prototype属性,属性值也是一个普通的对象
    console.log(fn.prototype);
    
    1. 所有的引用类型(数组、对象、函数),_proto_属性值指向它的构造函数的'prototype'属性值
    console.log(obj.__proto__ === Object.prototype);
    
    1. 当试图得到一个引用类型(数组、对象、函数)的某个属性时,如果这个引用类型本身没有这个属性,那么会去它的_proto_(即它的构造函数的 prototype )中寻找
    // 构造函数
    function Foo(name, age) {
      this.name = name;
    }
    Foo.prototype.alertName = function () {
      alert(this.name);
    }
    // 创建实例
    var f = new Foo('zhangsan');
    f.printName = function () {
      console.log(this.name);
    }
    // 测试
    f.printName();
    f.alertName();
    

    补充:循环对象自身的属性

    var item
    for (item in f) {
      if (f.hasOwnProperty(item)) {
        console.log(item);
      }
    }
    

    原型链(顶级原型 Object.prototype)

    f.toString(); // 要去 f.__proto__.__proto__ 中去找
    

    instanceof(用于判断引用类型属于哪个构造函数的方法)

    解答

    第三章 JS基础知识

    闭包和作用域

    题目

    说一下对变量提升的理解?预解析
    考点:变量定义和函数声明

    说明 this 几种不同的使用场景?

    // 作为构造函数执行
    // 作为对象属性执行
    // 作为普通函数执行
    // call apply bind 
    

    创建 10 个 <a> 标签,点击的时候弹出来对应的序号?

    // 这是错误的写法!
    var i, a;
    for (i = 0; i < 10; i++) {
      a = document.createElement('a');
      a.innerHTML = i + '<br>';
      a.addEventListener('click', function (e) {
        e.preventDefault();
        alert(i);
      });
      document.body.appendChild(a);
    }
    
    // 这是正确的写法!
    var i;
    for (i = 0; i < 10; i++) {
      (function (i) {
        var a = document.createElement('a');
        a.innerHTML = i + '<br>';
        a.addEventListener('click', function (e) {
          e.preventDefault();
          alert(i);
        });
        document.body.appendChild(a);
      })(i);
    }
    

    如何理解作用域?

    • 自由变量
    • 作用域链,即自由变量的查找
    • 闭包

    实际开发中闭包的应用?

    // 实际开发中闭包主要用于封装变量,收敛权限
    function isFirstLoad() {
      var _list = [];
      return function (id) {
        if (_list.indexOf(id) >= 0) {
          return false;
        } else {
          _list.push(id);
          return true;
        }
      }
    }
    
    // 使用
    var firstLoad = isFirstLoad();
    firstLoad(10); // true
    firstLoad(10); // false
    firstLoad(20); // true
    

    知识点

    执行上下文

    console.log('a is...', a); // undefined
    var a = 100;
    
    fn('zhangsan'); // 'zhangsan' 20
    function fn(name) {
      age = 20
      console.log(name, age);
      var age
    }
    
    • 范围:一段 <script> 或者一个函数
    • 全局:变量定义、函数声明
    • 函数:变量定义、函数声明、this、arguments

    this

    this 要在执行时才能确认值,定义时无法确认
    var a = {
      name: 'A',
      fn: function () {
        console.log(this.name);
      }
    }
    a.fn(); // this === a
    a.fn.call({name: 'B'}); // this === {name: 'B'}
    var fn1 = a.fn;
    fn1(); // this === window
    
    • 作为构造函数执行
    function Foo(name) {
      // this = {};
      this.name = name;
      console.log('this is...', this);
      // return this; 
    }
    var f = new Foo('zhangsan'); 
    // this === f
    
    • 作为对象属性执行
    var obj = {
      name: 'A',
      printName: function () {
        console.log('this is...', this);
      }
    };
    obj.printName(); 
    // this === obj
    
    • 作为普通函数执行
    function fn() {
      console.log('this is...', this);
    }
    fn();
    // this === window
    
    • call apply bind (指定第一个参数是 this, 第二个参数是形参)
    function fn(name) {
      console.log('name is...', name);
      console.log('this is...', this);
    }
    fn.call({x:100}, 'zhangsan');
    // this === {x:100}
    
    var fn = function (name) {
      console.log('name is...', name);
      console.log('this is...', this);
    }.bind({x:100});
    fn('zhangsan');
    // this === {x:100}
    

    作用域

    // 无块级作用域
    if (true) {
      var name = 'zhangsan';
    }
    console.log(name);
    
    // 函数和全局作用域
    var a = 100;
    function fn() {
      var a = 200;
      console.log('fn ', a);
    }
    console.log('global ', a); // global  100
    fn(); // fn  200
    
    • 没有块级作用域
    • 只有函数和全局作用域

    作用域链

    var a = 100;
    function fn() {
      var b = 200;
      
      // 当前作用域没有定义的变量,即“自由变量”
      console.log(a);
    
      console.log(b);
    }
    fn();
    
    var a = 100;
    function fn1() {
      var b = 200;
      function fn2() {
        var c = 300;
        console.log(a);
        console.log(b);
        console.log(c);
      }
      fn2();
    }
    fn1();
    

    闭包

    闭包的使用场景
    • 函数作为返回值
    function fn() {
      var a = 100;
      
      // 返回一个函数(函数作为返回值)
      return function () {
        console.log(a);
      }
    }
    // f1 被赋值为一个函数
    var f = fn();
    var a = 200;
    f(); // 100
    
    • 函数作为参数传递
    function fn1() {
      var a = 100;
      return function () {
        console.log(a);
      }
    }
    var f1 = fn1();
    
    function fn2(fn) {
      var a = 200;
      fn();
    }
    fn2(f1);
    

    解答

    第四章 JS基础知识

    异步和单线程

    题目

    同步和异步的区别是什么?分别举一个同步和异步的例子?

    一个关于 setTimeout 的笔试题?

    前端使用异步的场景有哪些?

    知识点

    什么是异步(对比同步)

    • 异步和同步最大的区别是有没有阻塞程序运行
    异步
    console.log(100);
    setTimeout(function () {
      console.log(200);
    }, 1000);
    console.log(300);
    // 执行顺序 100 300 200
    
    同步
    console.log(100);
    alert(200); // 10秒钟之后点击确认,确认之前,300永远不会被打印
    console.log(300);
    

    何时需要异步

    • 在可能发生等待的情况
    • 等待过程中不能像 alert 一样阻塞程序运行
    • 因此,所有“等待的情况”都需要异步

    前端使用异步的场景

    • 定时任务
    • 网络请求
    • 事件绑定
    // AJAX 请求代码示例
    console.log('start');
    $.get('/api/data.json', function (data) {
      console.log(data);
    });
    console.log('end');
    
    // <img> 加载示例
    console.log('start');
    var img = document.createElement('img');
    img.onload = function () {
      console.log('loaded');
    }
    img.src = '/xxx.png';
    console.log('end');
    
    // 事件绑定示例
    console.log('start');
    document.getElementById('btn').addEventListener('click', function () {
      alert('clicked');
    });
    console.log('end');
    

    异步和单线程

    一次只能干一件事
    • 执行第一行,打印100
    • 执行 setTimeout 后,传入 setTimeout 的函数会被暂存起来,不会立即执行(单线程的特点,不能同时干两件事)
    • 执行最后一行,打印300
    • 待所有程序执行完,处于空闲状态时,会立马看有没有暂存起来的要执行
    • 发现暂存起来的 setTimeout 中的函数无需等待时间,就立即来过来执行
    console.log(100);
    setTimeout(function () {
      console.log(200);
    });
    console.log(300);
    // 执行顺序 100 300 200
    

    解答

    第四章 JS-Web-API

    5-1从基础到JSWebAPI

    回顾 JS 基础知识

    • 变量类型和计算
    • 原型和原型链
    • 闭包和作用域
    • 异步和单线程
    • 日期、Math、各种常用API
    特点:表面看来并不能用于工作中开发代码
    内置函数:Object Array Boolean String ......
    内置对象:Math JSON ......
    我们连在网页弹出一句 hello world 都不能实现
    
    JS 基础知识:ECMA 262 标准(规定 JS 的基础语法)
    JS-Web-API:W3C 标准(规定浏览器提供给开发者操作页面的API和全局变量)
    

    JS 内置的全局函数和对象有哪些?

    • window document

    浏览器执行的JS = ECMA262 + W3C
    Node.js = ECMA262 + IO

    5-2 DOM

    DOM = Document + Object + Model

    题目

    DOM 是哪种基本的数据结构?

    DOM 操作的常用 API 有哪些?

    DOM 节点的 attr 和 property 有何区别?

    知识点

    DOM 本质

    • 浏览器把拿到的 html 代码,结构化成一个浏览器能识别、JS 可操作的一个模型(JS 对象)。

    DOM 节点操作

    • 获取 DOM 节点
    var div1 = document.getElementById('div1'); // 元素
    var divList = document.getElementsByTagName('div'); // 集合
    console.log(divList.length);
    console.log(divList[0]);
    
    var containerList = document.getElementsByClassName('.container'); //集合
    var pList = document.querySelectorAll('p'); // 集合
    
    • property [对象的属性]
    var pList = document.querySelectorAll('p');
    var p = pList[0];
    console.log(p.style.width); // 获取样式
    p.style.width = '100px'; // 修改样式
    console.log(p.className); // 获取 class
    p.className = 'p1'; // 修改 class 
    
    // 获取 nodeName 和 nodeType
    console.log(p.nodeName);
    console.log(p.nodeType);
    
    • Attribute [标签的属性]


      屏幕快照 2019-12-06 下午9.27.18.png

    DOM 结构操作


    • 屏幕快照 2019-12-06 下午9.32.16.png

    • 屏幕快照 2019-12-06 下午9.33.34.png

    • 屏幕快照 2019-12-06 下午9.33.17.png

    5-8 BOM

    BOM = Brower + Object + Model

    题目

    如何检测浏览器的类型?

    拆解 URL 的各部分?

    知识点

    • navugator
    • screen
    屏幕快照 2019-12-06 下午9.41.14.png
    • location
    • history


      屏幕快照 2019-12-06 下午9.42.12.png

    6-1 事件绑定

    题目

    编写一个通用的事件监听函数?

    function bindEvent(elem, type, selector, fn) {
      if (fn === null) {
        fn = selector;
        selector = null;
      }
      elem.addEventListener(type, function (e) {
        var target;
        if (selector) {
          target = e.target;
          if (target.matches(selector)) {
            fn.call(target, e);
          }
        } else {
          fn(e);
        }
      });
    }
    
    // 使用委托
    var div1 = document.getElementById('div1');
    bindEvent(div1, 'click', 'a', function (e) {
      console.log(this.innerHTML);
    });
    
    // 不使用委托
    var a1 = document.getElementById('a1');
    bindEvent(a1, 'click', function (e) {
      console.log(this.innerHTML);
    });
    

    描述事件冒泡流程?

    对一个无限下拉加载图片的页面,如何给每个图片绑定事件?

    知识点

    通用事件绑定

    var btn = document.getElementById('btn1');
    btn.addEventListener('click', function (event) {
      console.log('clicked');
    });
    
    function bindEvent(elem, type, fn) {
      elem.addEventListener(type, fn);
    } 
    var a = document.getElementById('link1');
    bindEvent(a, 'click', function (e) {
      e.preventDefault(); //阻止默认行为
      alert('clicked');
    })
    

    事件冒泡

    事件冒泡

    事件委托

    事件委托

    6-4 AJAX

    题目

    手动编写一个 AJAX,不依赖第三方库?

    跨域的几种实现方式?

    知识点

    XMLHttpRequest

    var xhr = new XMLHttpRequest();
    xhr.open("GET", "/api", false);
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          alert(xhr.responseText);
        }
      }
    }
    xhr.send(null);
    

    状态码说明

    跨域

    • 什么是跨域


    • JSONP


    • 服务端设置 http header



    6-6 存储

    题目

    请描述一下 cookie, sessionStorage 和 localStorage 的区别?

    知识点

    cookie

    • 本身用于客户端和服务端通信
    • 但是它有本地存储的功能,于是就被“借用”
    • 使用 document.cookie = ...获取和修改即可
    • 只有 4KB
    • 请求携带影响效率
    • 需要封装才能用

    localStorage 和 sessionStorage

    • 容量5M
    • 不用在请求中携带
    • sessionStorage(浏览器关了会清掉)

    相关文章

      网友评论

          本文标题:前端JavaScript面试技巧

          本文链接:https://www.haomeiwen.com/subject/kmesgctx.html