Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/228.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 为什么Node';创建(foo)比新建foo()慢得多?_Javascript_Node.js - Fatal编程技术网

Javascript 为什么Node';创建(foo)比新建foo()慢得多?

Javascript 为什么Node';创建(foo)比新建foo()慢得多?,javascript,node.js,Javascript,Node.js,我在JS中使用回溯编写了一个简单的数独解算器。为了实现“纯功能”,我的所有9x9拼图数组都是不可变的,因此每当插入一个新的数字时,就会创建一个新的数组 第1版使用新的SudokuPuzzle 在第一个版本中,我使用新拼图(Puzzle)方法克隆对象: function SudokuPuzzle(obj) { if (obj instanceof SudokuPuzzle) { this.grid = obj.grid.slice(0); // copy array }

我在JS中使用回溯编写了一个简单的数独解算器。为了实现“纯功能”,我的所有9x9拼图数组都是不可变的,因此每当插入一个新的数字时,就会创建一个新的数组

第1版使用新的SudokuPuzzle 在第一个版本中,我使用
新拼图(Puzzle)
方法克隆对象:

function SudokuPuzzle(obj) {
   if (obj instanceof SudokuPuzzle) {
      this.grid = obj.grid.slice(0);  // copy array
   } // ...
}
然后,每当我更新阵列时,我都会执行以下操作:

SudokuPuzzle.prototype.update = function(row, col, num) {
    var puzzle = new SudokuPuzzle(this); // clone puzzle
    puzzle.grid[row*9 + col] = num;      // mutate clone
    return puzzle;                       // return clone
}
版本2使用
Object.create()
我编写了另一个版本,其中使用了
Object.create()
,并有一个基本对象
sudokuPuzzle
,我从中继承来创建新的拼图。以下是
clone()
方法:

sudokuPuzzle.clone = function() {
   var puzzle = Object.create(this); // create puzzle from sudokuPuzzle
   puzzle.grid = this.grid.slice(0); // copy array
   return puzzle;                    // return newly minted puzzle
}
在这种情况下,我的更新方法是

sudokuPuzzle.update = function(row, col, num) {
   var puzzle = this.clone();       // clone puzzle
   puzzle.grid[row*9 + col] = num;  // mutate clone
   return puzzle;                   // return clone
}
速度测试 使用
new
的第一个版本使用Node时速度非常快:

$ time node Sudoku.js
real    0m0.720s
user    0m0.699s
sys     0m0.016s
使用
Object.create()
的第二个版本的速度始终慢10倍以上:

$ time node Sudoku2.js
real        0m7.746s
user        0m7.647s
sys         0m0.091s
注意到
Object.create()
在浏览器中的速度要慢得多,同时我也看到了与的巨大差异。我当然可以看到JS引擎之间的计时差异,但差异大于10倍?!?有人知道为什么差异超过一个数量级吗

你可以在这里找到答案

更新带注释的答案 感谢Bergi下面的回答,我将
clone
方法中的行从

 var puzzle = Object.create(this); 
为此:

 var puzzle = Object.create(sudokuPuzzle); 
这避免了长而复杂的继承链(即,我总是从同一个基本对象继承),现在我可以获得与使用
new
相当的速度结果。谢谢Bergi。

你可以查看其他帖子,对我来说,这是直觉——如果你使用新关键字,那么引擎知道它想要创建什么。如果使用Object.create,则引擎需要执行一些额外的检查工作,覆盖类型


正如文章中所写,如果您只创建了几个对象,那么性能应该无关紧要(7秒?真的吗?)。然而-JS并不是为反射而构建的。因此,this.clone()或Object.create(this)方法确实无效。

您已经确定V8无法优化
对象。create
new
一样好(与SpiderMonkey相反)。至少在历史上是这样。另见

然而,这要慢得多还有第二个原因:您的两个代码有不同的结果。你必须使用

SudokuPuzzle.prototype.clone = function() {
   var puzzle = Object.create(SudokuPuzzle.prototype); // a new instance, without `new`
   puzzle.grid = this.grid.slice(0); // copy array (usually initialised in constructor)
   return puzzle;                    // return newly minted puzzle
};
创建与使用
new SudokuPuzzle()
创建的克隆等效的克隆


问题是,当您使用
Object.create(this)
时,您正在创建一个具有不同原型的新对象,即
this
实例。通常情况下,相互克隆会创建一个非常复杂的继承层次结构。所有这些对象,具有不同的原型,将有不同的隐藏类-这。

我对Node优化尾部递归的效果印象深刻-它们不优化
对象似乎很愚蠢。创建
--这是一个核心机制。实际上,回溯算法正在创建数亿个节点(想想按行大顺序填充数独谜题的所有可能性)。时间差远远超过一个完整的数量级——这不是一个很大的差异!杰出的那是票!我没有考虑复杂的继承层次结构。我想我做错了——尽可能从同一个对象继承!