Jor*_*mer 15 javascript module-pattern
我已经看到以下三个代码块作为JavaScript模块模式的示例.有什么区别,为什么我会选择一种模式而不是另一种?
模式1
function Person(firstName, lastName) {
var firstName = firstName;
var lastName = lastName;
this.fullName = function () {
return firstName + ' ' + lastName;
};
this.changeFirstName = function (name) {
firstName = name;
};
};
var jordan = new Person('Jordan', 'Parmer');
Run Code Online (Sandbox Code Playgroud)
模式2
function person (firstName, lastName) {
return {
fullName: function () {
return firstName + ' ' + lastName;
},
changeFirstName: function (name) {
firstName = name;
}
};
};
var jordan = person('Jordan', 'Parmer');
Run Code Online (Sandbox Code Playgroud)
模式3
var person_factory = (function () {
var firstName = '';
var lastName = '';
var module = function() {
return {
set_firstName: function (name) {
firstName = name;
},
set_lastName: function (name) {
lastName = name;
},
fullName: function () {
return firstName + ' ' + lastName;
}
};
};
return module;
})();
var jordan = person_factory();
Run Code Online (Sandbox Code Playgroud)
据我所知,JavaScript社区通常似乎侧重于模式3是最好的.与前两个有什么不同?在我看来,所有三种模式都可以用来封装变量和函数.
注意:这篇文章实际上没有回答这个问题,我不认为它是重复的.
Daf*_*aff 13
我不认为它们是模块模式,而是更多的对象实例化模式.就个人而言,我不会推荐你的任何例子.主要是因为我认为重新分配函数参数除了方法重载之外的其他任何东西都不好.让我们回过头来看看你在JavaScript中创建Objects的两种方法:
原型和new运营商
这是在JavaScript中创建对象的最常用方法.它与模式1密切相关,但将函数附加到对象原型,而不是每次都创建一个新的:
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
};
Person.prototype.fullName = function () {
return this.firstName + ' ' + this.lastName;
};
Person.prototype.changeFirstName = function (name) {
this.firstName = name;
};
var jordan = new Person('Jordan', 'Parmer');
jordan.changeFirstName('John');
Run Code Online (Sandbox Code Playgroud)
Object.create和工厂函数
ECMAScript 5引入了Object.create,它允许以不同的方式实例化对象.而不是使用new您Object.create(obj)用来设置Prototype 的运算符.
var Person = {
fullName : function () {
return this.firstName + ' ' + this.lastName;
},
changeFirstName : function (name) {
this.firstName = name;
}
}
var jordan = Object.create(Person);
jordan.firstName = 'Jordan';
jordan.lastName = 'Parmer';
jordan.changeFirstName('John');
Run Code Online (Sandbox Code Playgroud)
如您所见,您必须手动分配属性.这就是为什么创建一个为您执行初始属性赋值的工厂函数是有意义的:
function createPerson(firstName, lastName) {
var instance = Object.create(Person);
instance.firstName = firstName;
instance.lastName = lastName;
return instance;
}
var jordan = createPerson('Jordan', 'Parmer');
Run Code Online (Sandbox Code Playgroud)
像往常一样,我必须参考了解JavaScript OOP,这是关于JavaScript面向对象编程的最佳文章之一.
我还想指出我在研究JavaScript中的继承机制后创建的我自己的小库UberProto.它提供了Object.create语义作为更方便的包装器:
var Person = Proto.extend({
init : function(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
},
fullName : function () {
return this.firstName + ' ' + this.lastName;
},
changeFirstName : function (name) {
this.firstName = name;
}
});
var jordan = Person.create('Jordan', 'Parmer');
Run Code Online (Sandbox Code Playgroud)
最后,它并不是关于"社区"似乎更喜欢什么,而是更多地了解语言为实现某项任务所提供的内容(在您的情况下创建新的对象).从那里你可以更好地决定你喜欢哪种方式.
模块模式
似乎与模块模式和对象创建存在一些混淆.即使看起来很相似,它也有不同的责任.由于JavaScript 只有函数作用域模块用于封装功能(并且不会意外地创建全局变量或命名冲突等).最常见的方法是将您的功能包装在自执行功能中:
(function(window, undefined) {
})(this);
Run Code Online (Sandbox Code Playgroud)
因为它只是一个功能,你最终可能会返回一些东西(你的API)
var Person = (function(window, undefined) {
var MyPerson = function(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
};
MyPerson.prototype.fullName = function () {
return this.firstName + ' ' + this.lastName;
};
MyPerson.prototype.changeFirstName = function (name) {
this.firstName = name;
};
return MyPerson;
})(this);
Run Code Online (Sandbox Code Playgroud)
这几乎是JS中的模块.它们引入了一个包装函数(相当于JavaScript中的新作用域)和(可选)返回一个作为模块API的对象.