美文网首页
JavaScript面试题(二)

JavaScript面试题(二)

作者: 迷人的洋葱葱 | 来源:发表于2017-09-05 09:35 被阅读0次

    一、对闭包的理解,实现一个暴露内部变量,而且外部可以访问修改的函数(get和set,闭包实现)

    Q1:闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数。
    ECMAScript中对闭包的解释:
    允许使用内部函数(即函数定义和函数表达式位于另一个函数的函数体内),而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其它内部函数。当内部函数在包含它的外部函数之外被调用时,就会形成闭包。即内部函数在外部函数返回后也可以被执行。当内部函数执行时,它访问的外部函数的局部变量、参数和函数声明是外部函数返回时的值,但也会受到内部函数的影响。
    Q2:

    var person=(function(){
        var name='xiaoming';
        return{
            getName:function(){
                return name;
            },
            setName:function(newName){
                name=newName;
                return newName;
            }
        };
    })();
    console.log(person.name);
    console.log(person.getName());
    console.log(person.setName('xiaohua'));
    

    二、{}=={}? []==[]? null==undefined?

    console.log({}=={});//false
    console.log([]==[]);//false
    console.log(null==undefined);//true
    

    [] == [] ?这个好理解. 当两个值都是对象 (引用值) 时, 比较的是两个引用值在内存中是否是同一个对象. 因为此 [] 非彼 [], 虽然同为空数组, 确是两个互不相关的空数组, 自然 == 为 false.
    {}=={}? 同上。
    [] == ![] 这个要牵涉到 JavaScript 中不同类型 == 比较的规则, 具体是由相关标准定义的. ![] 的值是 false, 此时表达式变为 [] == false, 参照标准, 该比较变成了 [] == ToNumber(false), 即 [] == 0. 这个时候又变成了 ToPrimitive([]) == 0, 即 '' == 0, 接下来就是比较 ToNumber('') == 0, 也就是 0 == 0, 最终结果为 true.

    参考文献:[] ==[] 为 false;[] == ![] 为 true;[] == {} 为 false;为什么?

    三、基本的数据类型

    String,Boolean,Number,Null,Undefined

    四、手写一个递归函数(考察arguments.callee,以及arguments的解释)

    例:求函数阶乘

    function factorial (num){
          if(num<=1){
                return 1;
          }else{
          return arguments.callee(num-1)*num;
        }
    }
    

    arguments.callee是指向正在执行的函数的指针,可以用它来实现对函数的递归调用。
    标识符arguments是指向实参对象的引用,实参对象是一个类数组,可以通过数字下标访问传入函数的实参值。(省略的实参都是undefined,多出的参数自动省略。)
    注意:arguments.callee只能用于非严格模式下,在严格模式下,不能通过脚本访问arguments.callee。可以使用命名函数表达式来解决。
    格式:var 变量=(函数f);//即把函数赋值给了另一个变量,函数的名字f仍然有效,所以递归调用可以照样完成。

    var factorial=(function f(num){
            if(num<=1) {return 1;
            }else{
                  return f(num-1)*num;
            }
    });
    

    参考文献:《JavaScript高级程序设计》

    五、对前端路由的理解?前后端路由的区别?

    路由:根据不同的url地址展示不同的内容或者页面。
    Q1:
    前端路由:把不同的路由对应不同的内容或页面的任务交给前端来做
    应用场景:单页面应用,大部分页面结构不变,只改变部分内容的使用。
    实现方式:
    1)改变hash值,监听onhashchange事件。
    优点:兼容低版本浏览器
    2)使用historyAPI,监听popState事件,用pushState和replaceState来实现。
    Q2:
    后端路由每次访问新页面需要向服务器重新发送请求,服务器再响应请求,这个过程可能会有延迟
    前端路由访问新页面时仅仅是变换路径,没有网络延迟
    参考文献:
    前端路由与后端路由
    关于前端路由和后端路由的一点思考

    六、前后端分离的意义以及对前端工程化的理解

    Q1:
    1、项目一开始制作前端页面时,不再需要后台配置服务器环境
    2、前端不需要向后台提供模板,或是后台在前端html中嵌入后台代码。
    3、后台没有时间提供接口时,前端可以将数据先写死或者调用本地的json文件即可。
    4、页面的增加和路由的修改可以在前端实现,开发更加灵活。
    5、通过前端路由配置,我们可以实现页面的按需加载无需一开始加载页面便加载网站的所有资源服务器也不再需要解析前端页面
    6、通过目前主流的MVC框架,我们可以非常快速的定位及发现问题的所在,客户端问题不再需要后台人员参与及调试,代码重构及可维护性强
    Q2:
    完整的前端工程体系应该包括:
    1、统一的开发规范;
    2、组件化开发;
    3、构建流程。

    参考文献:
    我们为什么要尝试前后端分离
    浅析前端工程化

    七、手写类式继承并解释。

    3.类式继承(适合new构造函数)
    利用构造函数继承的方式。
    JS中没有类的概念,把JS的构造函数看做类。

    Paste_Image.png
    function  Father(){
        this.name='晓明';
        }
    Father.prototype.showName=function(){
            alert(this.name);
            };      
    function Son(){}    
    
    Son.prototype=new Father();//一句话实现继承,但存在很多问题
    
    var s1=new Son();
    s1.showName();//晓明
    alert(s1.constructor);//Father
    

    存在问题:
    1.person.constructor指向Father而不是Son.
    这是因为Son.prototype=new Father();这句话重写了Son.prototype,Son.prototype下原有的constructor等属性被覆盖。
    解决:修正Son.prototype.constructor,Son.prototype.constructor=Son;
    2.子类实例的属性均指向父类中的属性,会相互影响。
    解决:属性和方法分别单独继承。

    Paste_Image.png
    1)创建一个没有属性的空函数F,专门用来继承父类的方法。
    2)属性采用call方法继承。
    类式继承完整例子:
    function  Father(){
        this.name=[1,2,3];
        }
    Father.prototype.showName=function(){
            alert(this.name);
            };
            
    function Son(){
        Father.call(this);//属性继承,用call方法修改this指向    
        }   
        
    //方法继承
    var F=function(){};//创建一个没有属性的空函数F,专门用来继承父类的方法。
    F.prototype=Father.prototype;
    Son.prototype=new F();//一句话实现继承
    Son.prototype.constructor=Son;
    
    var s1=new Son();
    s1.name.push(4);
    s1.showName();//1,2,3,4
    
    var s2=new Son();
    alert(s2.name);//1,2,3。属性单独继承后,不同实例的属性相互独立,互不影响。
    

    八、js轮播实现思路

    图片轮播的原理就是图片排成一行,然后准备一个只有一张图片大小的容器,对这个容器设置超出部分隐藏(overflow:hidden),在设定定时器或点击左右方向键来让这些图片整体左移或右移,这样呈现出来的效果就是图片在轮播。

    九、(==)和(!=)运算规则

    1、当两个操作数类型相同时,直接比较,相等返回true,不相等返回false。
    2,、当两个操作数类型不同时,先转换成相似类型再进行比较。
    转换规则:
    1)操作数是布尔值,比较之前先转换为数值。false转换为0,true转换为1。
    2)操作数是字符串和数值,比较之前先将字符串转换为数值
    3)操作数是对象和非对象,调用对象的valueof()方法,用得到的基本类型值进行比较或按照前面的规则进行转换。
    比较规则:
    1)null==undefined
    2)比较相等性之前,不能将null或者undefined转换成其他任何值
    3)有一个操作数为NaN,则==结果为false,!=结果为true。NaN!=NaN
    4)两个操作数都是对象,仅当两个操作数指向同一个对象时返回true,否则,返回false。

    十、文档模式doctype

    1、混杂模式:该模式下IE的行为与IE5相同。文档开始处没有发现文档类型声明或者文档类型声明有错误,所有浏览器会默认开启混杂模式。在混杂模式下,不同浏览器的行为差别很大,故不推荐。
    2、标准模式:该模式下IE的行为更接近标准行为。
    ①严格型(strict)
    ②过渡型(transitional)
    ③框架集型(frameset)

    相关文章

      网友评论

          本文标题:JavaScript面试题(二)

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