美文网首页
前端面试常见知识点总结

前端面试常见知识点总结

作者: linwalker | 来源:发表于2017-01-14 09:24 被阅读0次

HTML

  • 对html5的理解,web语义话,SEO
  • 页面加载过程
  • 新增API,本地存储,Canvas

CSS

  • 经典圣杯布局
  • CSS3 transition transform animate
  • w3c盒模型和IE盒模型,box-sizing属性
  • 居中
  • 浮动,position
  • 块级元素和行内元素
    • 块级元素: div,h1,p,ul,ol,li
    • 行内元素: a,span,img,em, input, label
    • 区别:
      • 块级元素占一行且宽度默认占满父元素,行内元素可以排在同一行;
      • 块级元素可以设置宽高,当仍然占一行;行内元素设置宽高无效;
      • 块级元素可以设置margin和padding属性,行内元素可以设置水平方向的margin和padding属性,竖直方向无效
  • BFC
  • 优先级
  • less与sass
  • background-*系列属性

JS

  • 原型

  • 对象

    工厂模式

    
    function createPerson(name, age, job) {
        var o = new Object();
        o.name = this.name;
        o.age = this.age;
        o.job = this.job;
        o.sayName = function () {
            alert(this.name);
        };
        return o;
    }
    var person1=createPerson('lin',29,'programmer');
    var person2=createPerson('li',30,'teacher');
    

    解决创建多个相似对象的问题,没解决对象识别的问题

    构造函数模式

    
    function Person(name, age, job) {
        this.name = name;
        this.age = age;
        this.job = job;
        this.sayName = function () {
            alert(this.name);
        };
    }
    var person1 = new Person('lin', 29, 'programmer');
    var person2 = new Person('li', 30, 'teacher');
    

    调用构造函数4个步骤:

    • 创建一个对象;
    • 将构造函数的作用域赋给新对象;(this指向新对象)
    • 执行构造函数中的代码
    • 返回新对象

    主要问题:每个方法都要在每个实例上重新创建一遍,不同实例上的同名函数是不想等的。

    原型模式

    function Person() {}
    Person.prototype.name = 'lin';
    Person.prototype.age = 29;
    Person.prototype.job = 'programmer';
    Person.prototype.sayName = function () {
        alert(this.name);
    }
    var person1 = new Person();
    
    • 创建函数会创建一个prototype属性,指向函数的原型对象
    • Person的每个实例内部包含一个属性,指向Person.prototype
    • 读取某个对象的某个属性,搜索先从对象实例本身开始,没有再搜索指针指向的原型对象
    • 在实例对象上添加或修改同名属性,会屏蔽原型对象属性,但对于包含引用类型值的属性,会直接修改原型对象上的属性
    • 对象字面量重写原型对象,其constructor属性会指向Object构造函数,切断现有原型与之前存在的实例对象之间的联系(即之前生成的的实例无法访问现有原型对象上的属性与方法)
    function Person() {
    }
    var friend = new Person();
    Person.prototype = {
         constructor: Person,
         name: 'lin',
         age: 29,
         sayName: function () {
             alert(this.name);
         }
    };
    friend.sayName(); //error
    

    原型模式问题:省略了构造函数参数传递,结果所有的实例在默认情况下都取得相同的属性值;实例改变包含引用类型值的属性时,会改变原型对象上的相应属性值,其他实例的相应属性值也会改变;

    组合使用构造和原型模式

    function Person(name.age,job) {
        this.name=name;
        this.age=age;
        this.job=job;
        this.friends=['lucy','lily']
    }
    Person.prototype={
        constructor:Person,
        sayName:function(){
            alert(this.name);
        }
    }
    var person1=new Person('lin',29,'programmer');
    

    动态原型模式

    function Person(name.age,job) {
        this.name=name;
        this.age=age;
        this.job=job;
        
        if(typeof this.sayName !='function') {
            Person.prototype.sayName = function() {
                alert(this.name);
            }
        }
    }
    var person1=new Person('lin',29,'programmer');
    

    注意不能使用对象字面量重写原型

    寄生构造函数模式

    稳妥构造函数模式

  • 继承

    原型链

    每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象内部的指针;让原型对象等于另一个构造函数的实例,此时原型对象就有指向另一个原型的指针,另一个原型也包含着指向另一个构造函数的指针,以此类推构成实例与原型的链条。

    function One() {
        this.oneprototype = true;
    }
    One.prototype.getOneValue = function () {
        return this.oneprototype;
    }
    function Two() {
        this.twoprototype = false;
    }
    Two.prototype = new One();
    Two.prototype.getTwoValue = function () {
        return this.twoprototype;
    }
    var Three = new Two();
    alert(Three.getOneValue()); //true
    

    通过重写Two的原型对象,继承One,原本存在One的实例中的属性和方法,现在也存在Two.prototype中,新原型中还有一个指向One原型的指针。最终时Three指向Two的原型,Two的原型指向One的原型。oneprototype在Two.prototype中,但getOneValue()方法仍在One.prototype上。

    给子类原型添加或则覆盖某个方法,添加方法的代码放在原型重写代码的后面。

    原型链继承的问题:超类实例中属性的值为引用类型值时,子类的实例修改该属性,其他子类实例中也会相应改变。

    function One() {
        this.color = ['red', 'blue'];
    }
    function Two() {
    }
    
    Two.prototype = new One();
    var three = new Two();
    three.color.push('black');
    alert(three.color);     // 'red,blue,black'
    var four = new Two();
    alert(four.color);      //'red,blue,black'
    var five = new One();
    alert(five.color);      //'red,blue'
    

    借用构造函数

    function One() {
        this.color = ['red', 'blue'];
    }
    function Two() {
        One.call(this);
        this.age=29;
    }
    var three = new Two();
    three.color.push('black');
    alert(three.color);      // 'red,blue,black'
    alert(three.age)         //29
    var four = new new Two();
    alert(four.color);       //'red,blue'
    
    

    问题:无法避免构造函数模式存在的问题。

    组合继承

    function Ono(name) {
        this.name = name;
        this.num = [1, 2, 3];
    }
    One.prototype.sayName = function () {
        alert(this.name);
    }
    
    function Two(name, age) {
        One.call(this, name);
        this.age = age;
    }
    
    Two.prototype = new One();
    Two.prototype.constructor = One;
    Two.prototype.sayAge = function () {
        alert(this.age);
    }
    
    var three = new Two('lin', 29);
    three.num.push(4);
    alert(this.num);     //1,2,3,4
    three.sayAge();       //29
    three.sayName();      //'lin'
    var four = new Two('li', 30);
    alert(four.num);    //1,2,3
    four.sayAge();      //30
    four.sayName();     //'li'
    

    通过原型链对原型属性和方法继承,通过借用构造函数对实例属性继承。

    问题:调用两次超类的构造函数,一次是创建子类型原型的时候,另一次是在子类型构造函数内部

    原型式继承

    function object(o) {
        function F(){};
        F.prototype=o;
        return new F();
    }
    
    ES5 Object.create()
    
    var person={
        name:'lin',
        num:[1,2,3];
    }
    
    var person2=Object.create(person);
    person2.name='li';
    person.num.push(4);
    alert(person.num); //1,2,3,4
    

    寄生式继承

    function createAnother(original) {
        var clone = abject(original);
        clone.sayHi = function () {
            alert('hi');
        }
        return clone;
    }
    
    var person = {
        name: 'lin',
        num: [1, 2, 3];
    }
    
    var person2 = createAnother(person);
    person2.sayHi(); //'hi';
    

    寄生组合继承

    function inheritPrototype(Two,One) {
        var prototype = Object(One.prototype);
        prototype.constructor=Two;
        Two.prototype=prototype;
    }
    
    function One(name) {
        this.name=name;
        this.num=[1,2,3];
    }
    
    One.prototype.sayName=function(){
        alert(this.name);
    }
    
    function Two(name,age) {
        One.call(this,name);
        this.age=age;
    }
    
    inheritPrototype(Two,One);
    Two.prototype.sayAge=function() {
        alert(this.age);
    }
    

    通过借用构造函数来继承实例属性,通过原型链的混成形式继承原型方法和属性。不必为了指定子类的原型而调用超类型构造函数,使用寄生式继承来继承超类型的原型,在将结果指定给子类型的原型

  • 变量 作用域

    变量

    变量包含两种不同数据类型值,基本类型值和引用类型值。

    基本类型值:简单的数据段;
    number,string,boolean,null,undefined

    引用类型值:由多个值构成的对象;保存在堆内存中,复制对象的某个变量时实际上是操作对象的引用,但在为对象添加属性时,操作的是实际对象。

    执行环境

    定义变量或函数有权访问的其他数据;

    环境中定义的所有变量和函数都保存在一个变量对象中;

    作用域链

    保证对执行环境有权访问的变量和函数的有序访问;

    作用域链的前端,是当前执行代码所在环境的变量对象,接着是来自包含环境的变量对象,以此类推,一直延续到全局执行环境,全局执行环境的变量对象是作用域链的最后一个对象。

    内部环境通过作用域链访问外部环境。

  • 闭包

    闭包是指有权访问另一个函数作用中的变量的函数,常见的创建方式,在一个函数内部创建另一个函数;

    闭包的作用包含外部函数的变量对象;

    闭包只能取得包含函数中任何变量的最后值

    function fun() {
      var result = new Array();
    
      for (var i = 1; i < 10; i++) {
        result[i] = function () {
            return i;
        };
       }
    
      return result;
    }         
    function fun() {
        var result = new Array();
    
        for (var i = 1; i < 10; i++) {
            result[i] = function (num) {
                return function(){
                    return num;
                };
            }(i);
        }
    
        return result;
    }
    

    在匿名函数中定义的任何变量会在执行结束被销毁,从而限制像全局作用中添加更多的变量和函数

    利用闭包的作用域链访问外部函数的变量,用于创建访问私有变量的公有方法

    模块模式:为单例(只有一个实例的对象,通过对象字面量创建)创建私有变量和特权方法(有权访问私有变量和函数)

    闭包的作用,通过作用域可以提供访问私有变量和函数的接口

  • 函数调用方式

    • 方法调用
    • 函数调用
    • 构造器调用
    • apply调用
  • JSON

  • 高阶函数

  • JSONP跨域iframe通信

  • Ajax

  • 原生DOM操作,逆序DOM节点

  • 事件捕获,冒泡,代理

    事件流
    * 手指放在同心圆的圆心,手指向的不是一个圆,而是所有的圆;即单击按钮的同时,也单击了按钮的容器元素,也单击了整个页面。
    * 事件流描述的是从页面中接受事件的顺序。
    * IE的事件流是事件冒泡,即事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点:div > body >html > document
    * Netscape事件流是事件捕获,与IE相反;
    * DOM 事件流包括三个阶段:事件捕获阶段,处于目标阶段和事件冒泡阶段

    事件处理

    • DOM2级事件处理程序
    
    var btn = document.getElementById('myBtn');
    btn.addEventListener('click',handle,fasle); //fasle表示事件在冒泡阶段触发
    btn.removeEventListener('click',handle,false)
    handle 如果为匿名函数则取消无效
    
    • IE事件处理程序
    
    var btn = document.getElementById('myBtn');
    btn.attachEvent('onclick',handle); 
    btn.detachEvent('onclick',handle)
    只有IE和Opera支持
    
    • 跨浏览器事件处理程序
    var EventUtil = {
        addHandler: function (element,type,handler) {
            if (element.addEventListener) {
                element.addEventListener (type,handler,false);
            } else {
                element.attachEvent ('on'+type,handler);
            } else {
                element['on'+type] = handler;
            }
        },
        removeHandler:function (element,type,handler) {
            if(element.removeEventListener) {
                element.removeEventListener (type,handler,false);
            } else {
                element.detachEvent ('on' + type,handle);
            } else {
                element['on'+type] = null;
            }
        }
    }
    var btn = document.getElementById('mybtn');
    EventUtil.addHandler(btn,'click',handler);
    EventUtil.removeHandler(btn,'click',handler);
    

    事件对象

    • DOM中的事件对象:event

      1. this = currentTarget :事件处理程序存在对象;

      2. target:事件的目标(如单击的按钮);

      3. 阻止特定的默认行为:event.preventDefault()

      4. 阻止事件冒泡:stopPropagation()

    • IE中的事件对象:window.event

      1. srcElemnt事件的目标
      2. 阻止特定的默认行为:window.event.returnvalue =false
      3. 阻止事件冒泡:window.event.cancelBubble()
      var EventUtil = {
        addHandler: function (element, type, handler) {
        },
        getEvent: function (event) {
          return event ? event : window.event;
        },
        getTarget: function (event) {
          return event.target || event.srcElement;
        },
        preventDefault: function (event) {
          if (event.preventDefault) {
            event.preventDefault();
          } else {
            event.returnvalue = false;
          }
        },
        stopPropagation: function (event) {
          if (event.stopPropagation) {
            event.stopPropagation();
          } else {
            event.cancelBubble = true;
          }
        }
      }
      

    事件委托

    • 事件处理程序数量关系到页面性能,因为每个函数都是对象,会占用内存
    • 利用事件冒泡,只指定一个事件处理程序,管理某一类型的所有事件;
    • 为document对象添加一个事件处理程序,处理页面上发生的某种特点类型的事件:document对象访问快,只添加一个事件处理程序所需DOM的引用少,用时短,占内存空间小
  • Array常用函数

    检测数组

    if(Array.isArray(value)) {
    }
    

    转换方法

    var colors =['red','blue','green'];
    alert(colors.toString());  //red,blue,green
    alert(colors.join('-'));   //red-blue-green
    
    

    栈方法

    • last-in-first-out
    • push():将任意数量的参数,逐个添加到数组末尾,并返回修改后数组的长度;
    • pop():从数组末尾移除最后一项,然后返回移除的项。
    var colors = new Array();
    var count = colors.push('red','blue');
    alert(count.length);      //2
    
    count.push('black');
    alert(count.length);      //3
    
    var item = count.pop();
    alert(item);             //'black'
    alert(count.length);     //2
    

    队列方法

    • first-in-first-out
    • shift():移除数组的第一项并返回该项,同时将数组长度减1;
    • unshift():在数组前端添加任意个项,并返回新数组的长度。
    var num = [1,2,3];
    num.push(4);
    var item = num.shift();
    alert(item);        //1
    alert(num.length)   //3
    num.unshift(5);
    alert(num.length);  //4
    

    重排序

    • reverse():反转数组项的顺序
    • sort():调用每个数组项的toString()转型方法,然后比较得到的字符串,确定如何排序
    function compare(value1, value2) {
         if (value1 < value 2) {
             return -1;
         } else if (value1 > value2) {
             return 1;
         } else {
             return 0;
         }
    }
    
    var values = [0,1,4,2,10];
    values.sort(compare);
    alert(values);  //0,1,2,4,10
    

    操作方法

    • concat():创建当前数组的副本,将接收到的参数添加到副本的末尾,返回新构建的数组;
    • slice():参数为起始和结束项位置,返回起始和结束位置之间的项不包括结束位置,没有结束位置,则到末尾,不影响原始数组;
    • splice():参数为删除项的起始位置,项数,插入的项。返回一个数组,包含从原始数组中删除的项(如没有删除则返回一个空数组);
    var colors = ['red','green'];
    var colors2 = colors.concat('yellow',['blue','purple']);
    alert(colors2);    //red,green,yellow,blue,purple
    
    var colors3 = colors2.slice(2);    //yellow,blue,purple
    var colors4 = colors2.slice(1,4);  //green,yellow,blue
    
    var removed = colors2.splice(0,2);  //red,green
    alert(colors2);                     //yellow,blue,purpel  
    
    var removed2 = colors2.splice(1,0,'red','green');  //空数组
    alert(colors2);                     //yellow,red,green,blue,purple
    

    位置方法

    • indexOf():参数为要查找的项和起点位置索引,返回查找项所谓位置索引,为找到返回-1
    • lastIndexOf()
    var num = [1,2,34,5,4,2,6];
    alert(num.indexOf(2));   //1
    alert(num.indexOf(2,3);  //5
    

    迭代方法

    • every():数组中每一项运行给定函数,每一项都返回true,则返回true;
    • some(): ...,任意项返回true,则返回true;
    • filter(): ...,返回该函数会返回true的项组成的数组;
    • forEach(): ...,没有返回值;
    • map(): ...,返回每次函数调用的结果组成的函数。
    var nums = [1,2,3,4,5];
    var everyResult = nums.every(function(item,index,array) {
        return (item > 2);
    })
    alert(everyResult);   //false
    
    var someResult = nums.some(function(item,index,array) {
        return (item > 2);
    })
    alert(someResult);   //true
    
    var filterResult = nums.filter(function(item,index,array) {
        return (item > 2);
    })
    alert(filterResult);   //[3,4,5]
    
    var mapResult = nums.map(function(item,index,array) {
        return (item * 2);
    })
    alert(mapResult);   //[2,4,6,8,10];
    
    

    归并方法

    • reduce():四个参数,前一个值,当前值,项的索引,数组对象
    var values = [1,2,3,4,5];
    var sum = values.reduce(function(prev,cur,index,array) {
        return prev + cur
    })
    alert(sum);    //15
    
  • string常用函数

    字符方法

    var stringvalue = 'Hello, world!';
    alert(stringvalue.charAt(2))
    

    字符操作方法

    • concat(): same as Array;
    • slice(): same as Array;
    • substring: same as slice;
    • substr: 第二个参数表示返回的个数

    字符串位置方法

    • indexOf()
    var stringValue = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit';
    var positions = [];
    var pos = stringValue.indexOf('e');
    while(pos > -1) {
      positions.push(pos);
      pos = stringValue.indexOf('e',pos + 1);
    }
    alert(positions);  //[3,24,32,35,52]
    

    trim()

    创建一个字符串的副本,删除前置及后缀的所有空格,返回结果;

    字符串大小写转换

    • toLowerCase()
    • toUpperCase()
    • toLocalLowerCase()
    • toLocalUpperCase()

    字符串匹配方法

    var text = 'cat, bat, sat, fat';
    var result = text.replace('at','ond);  //'cond, bat, sat, fat'
    result = text.replace(/at/g,'ond');    //'cond, bond, sond, fond'
    
    result.split(',');                     //['cond','bond','sond','fond']
    
  • ES5+ES6

  • 框架

  • 手动实现MVC

  • 衍生部分

  • HTTP1/2理解,状态码,优化,缓存控制

  • 页面加载过程

    • 输入URL
    • 解析URL获取协议,主机,端口,path,组装http请求报文,获取主机ip地址;
    • 打开socket与目标ip地址建立TCP链接:浏览器与远程Web服务器通过TCP三次握手协商来建立一个TCP/IP连接。该握手包括一个同步报文,一个同步-应答报文和一个应答报文,这三个报文在 浏览器和服务器之间传递。该握手首先由客户端尝试建立起通信,而后服务器应答并接受客户端的请求,最后由客户端发出该请求已经被接受的报文。
    • 发送HTTP请求,服务器接受,检查缓存,返回对应状态码
    • 浏览器接受响应,关闭TCP,检查响应状态码,进行缓存,解码
    • 解析HTML文档,构建DOM树,下载资源,构建CSSOM树,执行js脚本
  • TCP三次握手,四次挥手

  • XSS与CSRF

  • 学习经历和方法

  • 性能优化

  • 单元测试

  • React+Reduct

  • 模块机制 AMD CMD commonjs

  • webpack

相关文章

网友评论

      本文标题:前端面试常见知识点总结

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