美文网首页
JavaScript前端面试

JavaScript前端面试

作者: 风吹燕尾 | 来源:发表于2017-07-19 10:24 被阅读78次

    考查点:

    • 基层工程师——基础知识
    • 高级工程师——项目经验
    • 架构师——解决方案
    • 技术没有好坏,关键看使用场景

    面试战术

    • 拿到一个面试题,你的第一时间看到的是什么?(考点)
    • 如何看待网上永远看不完的题海(不变应万变)
    • 如何对待遇到的面试题?(题目到知识再到题目)

    JS typeof 运算符

    • undefined
    • string
    • number
    • boolean
    • object
    • function

    ==运算符和===运算符

    ==会发生强制类型转换;===则不会。比如obj.a==null其实就相当于obj.a===null || obj.a===undefined,==属于一种简写形式,是JQuery推荐写法,其他情况一般使用===

    如何理解JSON

    在js中JSON不仅仅是一种数据格式,同时也是也是一个js对象。

    构造函数

     function Person( name){
            this.name =name;
          }
           var p1=new Person('John');
    

    注意:构造函数默认首字母大写

    • var a={} 等价于 var a = new Object()
    • var a=[] 等价于 var a = new Array();
    • function Foo(){……} 等价于 var Foo = new Function(……);
    • 使用instanceof判断一个函数是否是另一变量的构造函数

    原型规则
    1.所有引用类型(数组、对象、函数),都具有对象特性,即可自由扩展属性(null除外)
    2.所有引用类型(数组、对象、函数),都有一个proto(隐式原型)属性,属性值是普通对象
    3.所有的函数,都有一个prototype(显式类型)属性,属性值也是一个普通对象。
    4.所有的引用类型(数组、对象、函数),proto属性值指向它的构造函数的“prototype”属性值

    var arr=[1,2,3];
        arr._proto_===Array.prototype
    

    5.当试图得到一个对象的属性时,如何这个对象本身没有这个属性,那么就会去它的proto(即它的prototype)中寻找。

    instanceof判断逻辑
    f instanceof Foo,f的proto一层层向上找,能否找到Foo.prototype

    image.png

    new一个js对象的过程

    • 首先有一个构造函数创建一个新对象
    • this指向这个对象
    • 执行代码,即对this赋值
    • 返回this(默认都没有写,其实系统已经实现了)

    原型和原型链实例

    function Elem(id){
        this.elem = document.getElementsByClassName(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 div = new Elem('search-body');
    div.html("<p>hello</p>").on('click',function(){
        alert('click');
    });
    

    this

    • this要在执行时才能确认,定义时无法确认。
      使用场景:
    • 作为构造函数执行
    function Foo(name){
       this.name=name; 
     }
    var foo =new Foo("tom");
    
    • 作为对象属性执行
    var obj = {
        name="tom"
        print:function(){
          alert(this.name);
         }
      }
    obj.print();
    
    • 作为一个普通函数执行
    function fn(){
       alert(this);//window
    }
    fn();
    
    • call、apply和bind
    function fn(){
       alert(this);//window
    }
    fn();
    
    function fn(name){
      alert(this);  //[Object object]
    }
    fn.call({age:22},"tom");
    
     >var fn =function (name){
       alert(this); 
    }.bind({age:22});
    fn("tom");
    

    作用域

    • js没有块级作用域,有函数作用域和全局作用域


      image.png
    • 作用域链


      image.png
    • 一个函数的父级作用域是定义时的作用域,而不是运行时

    闭包

    • 函数作为返回值
    • 函数作为参数来传递
      实际开发中的闭包的应用
    • 用于封装变量,收敛权限
    image.png

    前端使用异步场景

    • 定时任务:setTimeout,setInterval
    • 网络请求:ajax请求,
    • 动态<img/>加载
    • 事件绑定
    • 共同点:都需要等待

    同步和异步的区别

    • 同步会阻塞代码,而异步不会
    • alert是同步,setTimeout是异步
      其他API
    image.png image.png
    获取2017-07-01格式的日期
    function formatDate(dt){
        if(!dt){
            dt=new Date();
        }
    var year =dt.getFullYear();
    var month=dt.getMonth()+1;
    var date=dt.getDate();
        if(month<10)
            month="0"+month;
        if(date<10)
            date="0"+date;
        return (year+"-"+month+"-"+date);
    }
    var dt=new Date();
    var formatDate= formatDate(dt);
    console.log(formatDate);
    

    写一个能遍历对象和数组的forEach函数

    function forEach(obj,fn){
        if(obj instanceof Array){
            obj.forEach(function(item,index){
                fn(index,item);
            });
        }else{
            for(key in obj){
                fn(key,obj[key]);
            }
        }
    }
    var arr=[1,2,3];
    forEach(arr,function(index,item){
        console.log(index,item);
    });
    var obj ={x:1,y:2};
    forEach(obj,function(key,value){
        console.log(key,value);
    });
    

    DOM节点的Attribute和property有何区别

    • property只是一个JS对象的属性的修改和获取
    • Attribute是对HTML标签属性的修改和获取

    如何检测浏览器类型

    function checkBrower(){
      var agent = navigator.userAgent;
      if(agent.indexOf("chrome")>-1)
        return "Chrome";
      if(agent.indexOf("Firefox")>-1)
        return "Firefox";
      if (agent.indexOf("Safari")>-1)
        return "Safari";
      if(agent.indexOf("compatible")>-1 && agent.indexOf("MSIE")>-1)
        return "IE";
    }
    

    通用事件绑定

    function bindEvent(elem,type,fn){
      elem.addEventListener(type,fn);
    }
    var a = document.getElementById("");
    bindEvent(a,'click',function(e){
      e.preventDefault();
      alert("click");
    });
    

    事件代理

    div1.addEventListener('click',function(e){
      var target=e.target;
      if(target.nodeName=='a')
         alert(target.innerHTML);
    })
    代理的好处
    * 代码简洁
    * 减少浏览器内存的使用
    

    通用事件绑定事件函数

    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);
            }
        })
    }
    

    手动编写一个ajax

    var xmlhttp=null;//声明一个变量,用来实例化XMLHttpRequest对象
    if (window.XMLHttpRequest)
      {
      xmlhttp=new XMLHttpRequest();// 新版本的浏览器可以直接创建XMLHttpRequest对象
      }
      
    else if (window.ActiveXObject)
      {
      xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");// IE5或IE6没有XMLHttpRequest对象,而是用的ActiveXObject对象
      }
      
      
    if (xmlhttp!=null)
      {
      xmlhttp.onreadystatechange=state_Change;//指定响应函数为state_Change
      xmlhttp.open("GET","/example/xdom/note.xml",true);//指定请求,这里要访问在/example/xdom路径下的note.xml文件,true代表的使用的是异步请求
      xmlhttp.send(null);//发送请求
      } 
    else
      {
      alert("Your browser does not support XMLHTTP.");
      }
    
    //创建具体的响应函数state_Change
    function state_Change()
    {
    if (xmlhttp.readyState==4)
      {
      if (xmlhttp.status==200)
        {
        // 这里应该是函数具体的逻辑
        }
      else
        {
        alert("Problem retrieving XML data");
        }
      }
    }
    

    跨域

    • 浏览器有同源策略,不允许ajax访问其他域接口。
    • 跨域条件:协议、域名、端口,有一个不同就算跨域。
    • 三个标签无跨域障碍
     1.<img>用于打点统计,统计网站可能来自其他域。
    2.<link><script>可以使用CDN、CDN也是其他域。
    3.<script>可以用于JSONP
    
    • 所有的跨域请求都必须经过信息提供方允许

    JSOP实现原理

    服务器端设置http header解决跨域

    http header
    描述一个cookie,sessionStorage和localStorage的区别

    cookie

    • 本身用户客户端和服务器端通信
    • 但是它有本地存储的功能,于是被“借用了”
    • 使用document.cookie=……
      缺点
    • 存储量太小,只有4KB
    • 所有http请求都带着,会影响获取资源的效率
    • API简单,需要封装才能用 document.cookie=…
      locationStorage和sessionStorage
    • HTML5专为存储而设计,最大容量为5M
    • API简单易用
    • localStorage.setItem(key,value);
    • localStorage.getItem(key);
    • localStorage为持久存储,session为回话存储

    区别:

    • 容量
    • 是否会携带到ajax中
    • API易用性

    多人协作常用git命令

    • git.add .
    • git checkout xxx 还原之前
    • git commit -m "xxx"
    • git push origin master
    • git pull origin master
    • git branch 查看当前分支
    • git branch xxx(创建分支)/git checkout -b xxx(创建并切换分支) / git checkout xxx 切换分支
    • git merge xxx 把xxx分支合并到当前分支(合并前先pull最新的代码,合并后还要push上去)
    • git diff 查看变化

    模块化

    模块化
    AMD

    CommonJS http://www.ruanyifeng.com/blog/2012/10/asynchronous_module_definition.html

    • nodejs模块化规范,现被大量用于前端
    • 前端开发依赖的插件和库,都可以从npm中获取
    • 构建工具的高度自动化,使得使用npm的成本非常低
    • CommonJS不会异步加载JS,而是同步一次性加载

    AMD和CommonJS的使用场景

    • 需要异步加载JS,使用AMD
    • 使用了npm之后建议使用CommonJS

    构建工具webpack

    • npm init (生成package.json文件)

    • **npm install webpack --save-dev **(简写:npm i webpack --save-dev)
      "devDependencies": { //用于开发环境的依赖
      "webpack": "^3.3.0"
      },
      npm install jquery--save
      "dependencies": { //用于正式上线时的依赖
      "jquery": "^3.2.1"
      }

    • 卸载npm uninstall jquery--save

    • webpack.config.js配置

    var path = require('path')
    var webpack = require('webpack')
    module.exports = {
    context: path.resolve(__dirname,'./src'),
    entry:{
    app:'./app.js'
    },
    output: {
    path: path.resolve(__dirname,'./dist'),
    filename: 'bundle.js'
    }
    }

    • 配置package.json文件中的


      image.png
    • 执行 npm start,生成bundle.js文件


      image.png

    上线流程要点

    • 将测试完成代码提交到git版本库的master分支
    • 经当前服务器的代码全部打包并记录版本号,备份
    • 将master分支的代码提交覆盖到线上服务器,生成新版本号

    回滚流程要点

    • 将当前服务器的代码打包并记录版本号,备份
    • 将备份的上一个版本号解压,覆盖到线上服务器,并生成新的版本号。

    页面加载资源的过程

    • 浏览器根据DNS服务器得到域名的IP地址
    • 向这个IP的机器发送http请求
    • 服务器收到、处理并返回http请求
    • 浏览器得到返回内容

    浏览器渲染页面的过程

    • 根据HTML生成DOM Tree
    • 根据CSS生成CSSOM
    • 将DOM和CSSOM整合形成RenderTree
    • 根据RenderTree开始渲染和展示
    • 遇到<script>时,会执行并阻塞渲染,所以放在</body>上面。

    window.onload和DOMContentLoaded区别

    • load事件是在页面的全部资源加载完才会执行,包括图片、视频等
    • DOMContentLoaded事件是在DOM渲染完即可执行,此时图片、视频还可能没有加载完。

    加载资源优化

    • 静态资源的压缩合并
    • 静态资源缓存
    • 使用CDN让资源加载更快
    • 使用SSR后端渲染,数据直接输出到HTML中

    渲染优化

    • CSS放前面,JS放后面
    • 懒加载(图片懒加载、下拉加载更多)


      懒加载
    • 减少DOM查询,对DOM查询做缓存


      DOM缓存
    • 减少DOM操作,多个操作尽量合并在一起执行(documentFragment)


      合并操作
    • 事件节流(减少一些不必要的频繁行为,例如增加延迟)


      事件节流
    • 尽早执行操作(如DOMContentLoaded)


    安全性(非重点)

    • XSS跨站请求攻击
      在别人的网站发布的信息中插入一段 <script>攻击代码,用于获取查看者cookie,发送到自己的服务器。
      解决方案:
      • 前端替换关键字,例如替换<为&lt;>为&gt
      • 后端替换
    • XSRF跨站请求伪造
      一些网站或邮箱中隐藏的伪造请求,比如<img src=xxx.com/pay?id=100
      解决方案:
      • 增加验证流程,如输入指纹、密码、短信验证码

    简历

    • 简洁明了,重点突出项目经历和解决方案
    • 把个人博客放在简历中,并且定期维护更新博客
    • 把个人的开源项目放在简历中,并维护开源项目
    • 简历千万不要造假,要保持能力和经历上的真实性

    面试过程中

    • 如何看待加班?加班就像借钱,救急不救穷
    • 千万不可挑战面试官,不要反考面试官
    • 学会给面试官惊喜,但不要太多
    • 遇到不会回答的问题,说出你知道就可以了
    • 谈谈你的缺点——说一下你最近正在学什么就可以了

    PS常用

    • 图像拖到透明图层中——裁切——透明像素
    • 文件——编辑——首选项:性能和常规
    • 查看图像大小——Ctrl+alt+I
    • 合并图层——Ctrl+E
    • 切图优化
      • 颜色代替图片
    • 雪碧图的制作
    • 字体图标的使用
    • 切图辅助
      • TinyPng
      • 前端自动化

    相关文章

      网友评论

          本文标题:JavaScript前端面试

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