美文网首页
node.js面试

node.js面试

作者: 暗送秋波掌 | 来源:发表于2016-01-10 19:47 被阅读1351次

    InterviewQuestions

    some questions and answers


    Q1:JS 继承有哪几种方式?

    首先有两个构造函数Animal,Dog

    function Animal(){
      this.species = 'animal';
    }
          
    function Dog(name,color){
      this.name = name;
      this.color = color;
    }
    

    我们要让Dog继承Animal的属性。(通过utils.inherits只能继承基于原型的属性)

    ANSWER:

    1.构造函数绑定

    使用apply或者call方法

    function Dog(name,color){
       Animal.apply(this,arguments);
      //Animal.call(this,name,color);
      this.name = name;
      this.color = color;
    }
        
    var lucky = new Dog('lucky','brown');
    console.log(lucky.species; // animal'
    
    2.prototype模式
    Dog.prototype = new Animal();
    Dog.prototype.constructor = Dog;
    var lucky = new Dog('lucky','Brown');
    console.log(lucky.species);
    

    先将Dog的prototype对象指向一个Animal的实例,然后将prototype.constructor指向构造函数Dog,这样就实现了继承

    3.直接继承prototype
    function Animal(){}
    Animal.prototype.species = 'animal';
    
    function Dog(name,color){
        this.name = name;
        this.color = color;
    };
    
    Dog.prototype = Animal.prototype;
    Dog.prototype.constructor = Dog;
    var lucky = new Dog('lucky','brown');
    console.log(lucky.species);
    
    

    这样做的好处是效率高,速度快,省内存,但是Dog.prototype和Animal.prototype现在指向了同一个对象,修改Dog.prototype会直接修改Animal.prototype。

    4.利用空对象作为中介
    var F = function(){};
    F.prototype = Animal.prototype;
    Dog.prototype = new F();
    Dog.prototype.constructor = Dog;
    
    console.log(Animal.prototype.constructor); //Animal
    var lucky = new Dog('lucky','brown');
    console.log(lucky.species); // animal
    
    5.拷贝继承
    function extend(Child,Parent){
        var p = Parent.prototype;
        var c = Child.prototype;
        for(var i in p){
            c[i] = p[i];
        }
        c.uber = p;//为子对象留有可以访问父对象的接口
    }
    
    function Dog(name,color){}
    
    extend(Dog,Animal);
    var lucky = new Dog('lucky','brown');
    console.log(lucky.species); //animal
    

    Q2:JS 严格模式跟普通模式的区别?

    ANSWER:

    1.在js文件中使用'use strict‘进入严格模式
    • 消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;
    • 消除代码运行的一些不安全之处,保证代码运行的安全;
    • 提高编译器效率,增加运行速度;
    • 为未来新版本的Javascript做好铺垫。
    2.会将拼写错误转成异常
    'use strict';
    
    var maxNumber = 100;
    maxNumbre = 10;//ReferenceError
    console.log(maxNumber);
    
    3.全局变量显式声明

    正常模式中,一个变量未声明直接赋值,默认是全局变量,严格模式中禁止这种用法,全局变量必须显示声明

    'use strict';
    v1 = 1;//error
    
    4.禁用with,eval
    5.禁止删除声明变量
    'use strict';
    
    var x;
    delete x; //语法错误
    

    Q3:V8垃圾回收机制

    ANSWER:

    V8使用是垃圾回收器(GC)进行回收,
    具体信息可以参考下列文章:
    1.阿里云团队博客
    2.Segmentfault


    Q4:web后端缓存策略有哪些?

    ANSWER:

    1.利用redis(node-redis)或 memcached

    在服务器与数据库之间设置redis数据库作为缓存介质,在需要缓存的请求到达时,先检查redis数据库是否有,使用

    var redis = require('redis').createClient();
    redis.get('key',function (err,reply){
          //logic code
    });
    

    进行判断,如果不存在,则从对应数据库获取数据,然后将数据写入redis数据库,并设置过期时间。

    var redis = require('redis').createClient();
    redis.set('key','value');
    redis.expire('key',1000);//ms
    
    2.max-age和cache-control

    主要针对静态资源的缓存

    response.setHeader('Cache-Control','public,max-age=3600');
    
    3.etag

    从req.headers里取'if-none-match',如果存在且hash值一致,返回304

    var hashStr = "A hash string.";
    var hash = require("crypto").createHash('sha1').update(hashStr).digest('base64');
    require("http").createServer(function(req, res){  
        if(req.headers['if-none-match'] == hash){ 
            res.writeHead(304);
            res.end(); 
            return; 
        } 
        res.writeHead(200, { "Etag": hash }) 
        res.write(hashStr); res.end();
    }).listen(9999);
    

    这样可以在输出没有变化的时候过滤请求,减轻服务器压力。

    4.CDN缓存

    将图片等数据放在CDN缓存,可以大大减轻自己服务器压力,可以参考这个模块express-cdn

    参考资料:
    Web开发后端缓存思路
    Etag缓存
    缓存策略


    Q5:TCP与UDP的区别?

    A:

    1.TCP是面向链接的,虽然说网络的不安全不稳定特性决定了多少次握手都不能保证连接的可靠性,但TCP的三次握手在最低限度上(实际上也很大程度上保证了)保证了连接的可靠性;
      而UDP不是面向连接的,UDP传送数据前并不与对方建立连接,对接收到的数据也不发送确认信号,发送端不知道数据是否会正确接收,当然也不用重发,所以说UDP是无连接的、不可靠的一种数据传输协议。
    2.也正由于1所说的特点,使得UDP的开销更小数据传输速率更高,因为不必进行收发数据的确认,所以UDP的实时性更好。

    Q6:为什么选择mocha这种测试框架?

    ANSWER:

    • 与node完美结合,可以在node端和浏览器端测试
    • 可以使用不同的断言库(chai,should等)
    • 异步方法测试简单
    • 支持before,after等hook

    mocha git
    mocha测试

    Q7:TDD/BDD分别是什么?

    ANSWER:

    TDD(测试驱动开发)

    即先写测试用例,再一一实现功能

    BDD(行为驱动开发)

    先写功能,再对功能进行测试,更贴近人类思维方式

    Q8:闭包

    ANSWER:

    我理解的闭包就是外部函数获取内部函数私有属性的一种方法,简单的用下面的例子解释一下:

    function myHouse(){
      var __myname = 'Kevin';
      var getMyname = function(){
          return __myname;
      };
      return getMyname;
    }
    
    var getName = myHouse();
    console.log(getName());//Kevin
    

    即通过在myHouse()中返回getMyname函数,getMyname函数中返回私有变量__myname,从而获取私有变量,同时保护私有变量不会直接暴露给外部,以免改变私有变量值。

    Q9:node.js跨域问题

    ANSWER:

    var express = require('express');
    var app = express();//设置跨域访问
    app.all('*', function(req, res, next) { 
        res.header("Access-Control-Allow-Origin", "*"); //核心
        res.header("Access-Control-Allow-Headers", "X-Requested-With"); //核心
        res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS"); //核心
        res.header("X-Powered-By",' 3.2.1') ;
        res.header("Content-Type", "application/json;charset=utf-8"); next();
    });
    app.get('/auth/:id/:password', function(req, res) { 
        res.send({
            id:req.params.id, 
            name: req.params.password
        });
    });
    app.listen(3000);console.log('Listening on port 3000...');
    

    还可以参考这个模块:cors
    参考:推酷

    Q10:ES6新特性:

    ANSWER:

    这个写的很不错,推荐阅读
    阮一峰的日志

    相关文章

      网友评论

          本文标题:node.js面试

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