将模块模式与Prototype相结合

时间:2014-01-17 17:00:57

标签: javascript design-patterns

我试图通过使用模块模式封装一些方法。我也试图通过使用原型来避免新对象创建的新函数定义。问题是我必须实现一个构造函数,我无法弄清楚如何。我的代码:

 // constructor
function Anagram(original) {
  this.original = original.toLowerCase()
  this.sortedOriginal = this.sort(this.original)
}

// prototype as a module
Anagram.prototype = (function() {
  function isAnagram(word) {
    word = word.toLowerCase()
    return this.original != word && sameLetters(word)
  }
  function sameLetters(word) {
    return this.sortedOriginal === sort(word)
  }
  function sort(str) {
    return str.split('').sort().join('')
  }
  return {
    match: function(words) {
      return words.filter(isAnagram, this)
    }
  }
}())

module.exports = Anagram

运行

Anagram.new('ant').match(['tan', 'stand', 'at'])

失败
TypeError: Object #<Object> has no method 'sort'

我理解为什么,sort没有在构造函数中定义。我该如何解决?

2 个答案:

答案 0 :(得分:1)

我创建了一个名为augment的库,它将模块模式与原型继承相结合。例如,您可以使用Anagram实现augment“类”,如下所示:

var augment = require("augment");

var Anagram = module.exports = augment(Object, function () {
    this.constructor = function (original) {
        this.original = original.toLowerCase();
        this.sortedOriginal = sort(this.original);
    };

    function isAnagram(word) {
        word = word.toLowerCase();
        return this.original !== word && sameLetters.call(this, word);
    }

    function sameLetters(word) {
        return this.sortedOriginal === sort(word);
    }

    function sort(str) {
        return str.split("").sort().join("");
    }

    this.match = function(words) {
        return words.filter(isAnagram, this);
    };
});

现在您可以按如下方式使用它:

new Anagram("ant").match(["tan", "stand", "at"]);

请参阅演示:http://jsfiddle.net/GbWXB/


修改:如果您希望可以使用deflcass替代augment

function defclass(base, body) {
    var uber = base.prototype;
    var prototype = Object.create(uber);
    var constructor = (body.call(prototype, uber), prototype.constructor);
    constructor.prototype = prototype;
    return constructor;
}

请参阅演示:http://jsfiddle.net/sy4fz/

答案 1 :(得分:0)

问题在于排序不是原型的属性。原型只有一个名为match的属性来修复它 - 你需要对Anagram的原型进行排序。因此,当您使用“match”函数返回对象文字时,该对象还需要一个“sort”函数属性。

return {
   match: function(words) {
      return words.filter(isAnagram, this)
   },

   sort: function(str) {
      return str.split('').sort().join('')
   }
}

因此,每个Anagram都从它的原型继承了两个函数,this.sort()是有效的。

但是,您的代码还存在其他一些问题。您定义的不属于返回对象的函数(例如sameLetters)将不会绑定到正确的“this”。如果你希望他们为此获得正确的值 - 他们还需要继续使用原型,或者你需要在调用它们时向它们传递引用。