Javascript 模块模式与原型的结合
我试图用模块模式封装一些方法。我还试图通过使用原型来避免在创建新对象时出现新的函数定义。问题是我必须实现一个构造函数,但我不知道如何实现。我的代码:Javascript 模块模式与原型的结合,javascript,design-patterns,Javascript,Design Patterns,我试图用模块模式封装一些方法。我还试图通过使用原型来避免在创建新对象时出现新的函数定义。问题是我必须实现一个构造函数,但我不知道如何实现。我的代码: // constructor function Anagram(original) { this.original = original.toLowerCase() this.sortedOriginal = this.sort(this.original) } // prototype as a module Anagram.prot
// 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'
TypeError:对象#没有方法“sort”
我理解为什么构造函数中没有定义排序。如何修复它?问题在于排序不是原型的属性。原型只有一个名为match的属性,要修复它,您需要对Anagram的原型进行排序。因此,在使用“match”函数返回对象文本时,该对象还需要一个“sort”函数属性
return {
match: function(words) {
return words.filter(isAnagram, this)
},
sort: function(str) {
return str.split('').sort().join('')
}
}
因此,每个字谜从它的原型继承两个函数,这个.sort()是有效的
但是,您的代码还有一些其他问题。您定义的函数不属于成为原型的返回对象的一部分(例如sameLetters),它们不会绑定到适当的“this”。如果您想让他们得到正确的值,他们还需要继续原型,或者您需要在调用他们时向他们传递对此的引用。我创建了一个名为的库,它将模块模式与原型继承相结合。例如,您可以使用
augment
按如下方式实现您的Anagram
“类”:
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);
};
});
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;
}
现在您可以按如下方式使用它:
new Anagram("ant").match(["tan", "stand", "at"]);
请参见演示:
编辑:如果您希望使用
deflcass
作为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);
};
});
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;
}
请参阅演示:您的代码将无法工作,因为在
sameLetters
中调用了sort
,而不仅仅是在构造函数中。感谢您指出此问题。有没有一种方法可以在闭包中隐藏一个函数,并让它引用一个正确的this
,除非显式地传递它?答案并不准确。它的值取决于调用函数的方式,因此,如果您希望拥有一个不在原型上的“私有”函数,那么您需要将“this”传递给该函数。否则,此
将从调用函数的对象中推断出来。你可以这样做:privateUtilFunction.call(this,word)
从原型上的函数,但你必须确保每当你调用privateUtilFunction
时,你都确保设置了“this”。谢谢,有趣的解决方案,但是有没有一种方法可以在没有外部库的情况下解决我的问题?当然。您可以使用defclass
作为augment
的替代品。看看我最新的答案。我试着去理解defclass,我不得不承认这对我来说是一种思维扭曲。特别是行var构造函数=(body.call(prototype,uber),prototype.constructor)你能解释一下吗?你能推荐一些关于这个话题的阅读吗?