2016-02-20 4 views
2

Я следующий код, написанный для NodeJS:Странное поведение массива в NodeJS

/* server.js */ 
'use strict'; 

const http = require('http'), 
    url = require('url'); 
    METHODS = ['GET','POST','PUT','DELETE'], 
    _routePathIndex = Array.apply(null, Array(METHODS.length)).map(() => {return []}), 
    _routeMethodIndex = _routePathIndex.slice(), 
    _server = http.createServer(); 

_server.on('request', (req, res) => { 
    let parsed = url.parse(req.url), 
     methodIndexVal = METHODS.indexOf(req.method), 
     PathIndexVal = _routePathIndex[methodIndexVal].indexOf(parsed.pathname); 

    _routeMethodIndex[methodIndexVal][PathIndexVal](req, res); 
}); 

module.exports = _init(); 

function _init(){ 
    let rs = { listen: _listen }; 
    METHODS.forEach((val,i) => { 
     rs[val.toLowerCase()] = function(route, handler){ 
      _routePathIndex[i].push(route); 
      _routeMethodIndex[i].push(handler); 
     }; 
    }); 

    return rs; 
}; 

function _listen(port, callback){ 
    _server.listen(port, callback); 
} 

Чтобы проверить это у меня есть у меня есть очень простой скрипт:

/* server.test.js */ 
var app = require('./server.js'); 
app.get('/', (req,res) => { console.log(req, res); }); 
app.listen(3000,() => { console.log('listening at port', 3000) }); 

Странность начинается на линии 2 server.test.js, который выполняет следующий код в server.js, я добавил комментарии для отображения значений как _routePathIndex, так и _routeMethodIndex.

... 
     rs[val.toLowerCase()] = function(route, handler){ 
      /* _routePathIndex: [ [], [], [], [], ] 
       _routeMethodIndex: [ [], [], [], [], ] */ 
      _routePathIndex[i].push(route); 

      /* _routePathIndex: [ ['/'], [], [], [], ] 
       _routeMethodIndex: [ ['/'], [], [], [], ] */ 
      _routeMethodIndex[i].push(handler); 


      /* _routePathIndex: [ ['/', [Function]], [], [], [], ] 
       _routeMethodIndex: [ ['/', [Function]], [], [], [], ] */ 
     }; 
... 

Мой вопрос, почему массив действует как Тхо привязаны друг к другу?

Сначала я подумал, может быть это был .slice(), который делает ссылку, но я развенчан, что, выполнив следующий сценарий в той же среде:

var a = [], b = a.slice(); 
a.push(1); 
console.log(a,b); // [1] [0] 

Другое дело, когда я не делаю .slice() трюк и переработан код в качестве такого

... 
    _routePathIndex = Array.apply(null, Array(METHODS.length)).map(() => {return []}), 
    _routeMethodIndex = Array.apply(null, Array(METHODS.length)).map(() => {return []}), 

странное поведение реферирование закончится и код работает отлично!

Дополнительная информация Я работаю с node -v: v5.4.1.

Также я попытался клонировать массив, используя [].concat(_routePathIndex) но он все еще имел, что странное поведение

+0

'Array.apply (NULL, Array (METHODS.length)) карту (() = > {return []}) 'кажется (мне) запутанным и нечитаемым способом записи' Array (METHODS.length) .fill ([]) ' – jcaron

ответ

5

slice только делает неполную копию, что _routePathIndex и _routeMethodIndex различны, но их элементы одинаковы. Рассмотрим упрощенный пример:

a = [[],[]]; 
 
b = a.slice(); 
 
    
 
b[0].push(1); 
 
document.write(a)

Получить картину:.

enter image description here

+0

не может принять ответ слишком рано, так как правила SO, во всяком случае, что вы сделали использовать для прохладной картинки? – jkris

+1

@jkris: http://merribithouse.net/arrows/ - разработал это для моего собственного использования некоторое время назад. – georg