我使用JS编写了一个简单的数独求解器,采用回溯算法。为了实现“纯函数式”的要求,我将所有9x9的谜题数组变成了不可变的,因此每次插入新数字时都会创建一个新的数组。
第一版采用
在第一个版本中,我使用
使用
第二个版本使用
第一版采用new SudokuPuzzle
在第一个版本中,我使用new Puzzle(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
}
使用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
}
速度测试
在Node中使用new
的第一个版本非常快:
$ 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()
在浏览器中速度非常慢,而我在node.js中也看到了很大的差距。我当然可以看到JS引擎之间的时间差异,但是超过一个数量级的差异?!有人知道为什么差异如此之大吗?
您可以在这里找到源代码。
带注释答案的更新
感谢Bergi在下面的回答中,我将clone
方法中的行从
var puzzle = Object.create(this);
转换为:
var puzzle = Object.create(sudokuPuzzle);
这种方法避免了长而复杂的继承链 (即,我总是从同一个基本对象继承)。现在,我得到了与使用 new
相当的速度结果。感谢 Bergi。