Ant*_*onB 5 html javascript performance jquery html5
我想要实现的目标:使用javascript中的原型创建模块,以便用户可以使用不同的选项多次实例化模块.
问题:当使用var my_module3 = new module();然后尝试设置选项my_module3.init({ option: "value" });时,每次都不更改对象,它只更改一次.
测试:使用时console.log我们可以看到它打印出具有相同选项的两个对象,即使它们设置不同
Object {first: "Barry", second: "Larry", third: "Sam"}
Object {first: "Barry", second: "Larry", third: "Sam"}
Run Code Online (Sandbox Code Playgroud)
这是我的jsFiddle完整代码: http ://jsfiddle.net/11bLouc8/2/
var module = (function () {
// default options
var options = {
first: "test",
second: "test2",
third: "test3"
};
// take in useroptions and replace default options
var module = function(userOptions) {
if (userOptions != null && userOptions != undefined
&& userOptions != 'undefined') {
for (var opt in options) {
if (userOptions.hasOwnProperty(opt)) {
options[ opt ] = userOptions[ opt ];
}
}
}
};
//prototype
module.prototype = {
init: module,
options: options
};
return module;
})();
// create a new instance
var my_module3 = new module();
my_module3.init({
first: "Mike",
second: "Lisa",
third: "Mary"
});
// another instance
var my_module2 = new module();
my_module2.init({
first: "Barry",
second: "Larry",
third: "Sam"
});
Run Code Online (Sandbox Code Playgroud)
小智 5
函数本身的属性就像static类成员(函数的属性,而不是它的实例)
属性function prototype在实例中是不同的:
function test(){};
test.prototype = {
constructor : test,
first : '',
second : '',
third : '',
init : function(f, s, t){
this.first = f;
this.second = s;
this.third = t;
return this;
},
formatToString : function(){
return 'first : ' + this.first + ', second : ' + this.second + ', third : ' + this.third;
}
}
var t1 = new test().init(1, 2, 3);
var t2 = new test().init(4, 5, 6);
console.log(t1.formatToString());//outputs "first : 1, second : 2, third : 3"
console.log(t2.formatToString());//outputs "first : 4, second : 5, third : 6"
Run Code Online (Sandbox Code Playgroud)
您正在使用立即调用的函数表达式 (IIFE),就像模块模式所说的那样,但对于这种情况,您需要多次调用 IIFE。这涉及给它一个名称,以便您可以再次解决它,因此从技术上讲,它不再是 IIFE,但它的工作原理与 IIFE 相同。我会继续打电话
当您调用一个函数时,JavaScript 会为其中的变量和闭包创建一个上下文。只要 IIFE 之外的任何内容引用其中的任何内容,该上下文就会存在。这就是传统模块模式使用 IIFE 的原因:您可以在 IIFE 的上下文中隐藏私有数据和函数。
但是因为您只调用该函数一次,所以您的所有模块实例共享相同的上下文。您将模块选项存储在options变量中,该变量是该共享上下文的一部分而不是模块的一部分,因此当您更新其中一个选项时,它会更新所有选项中的选项。有时,这就是您想要的,但在您的情况下并非如此。
您要做的是为每个模块创建一个新的上下文。这意味着您需要携带您的 IIFE 并保留对它的引用,以便您可以多次调用它:换句话说,它不再是匿名函数(甚至不一定是 IIFE)。但这一切都是可行的。这是一种可能的解决方案:
var moduleContext = function () {
// default options
var options = {
first: "test",
second: "test2",
third: "test3"
};
// take in useroptions and replace default options
var module = function(userOptions) {
if (userOptions != null && userOptions != undefined
&& userOptions != 'undefined') {
for (var opt in options) {
if (userOptions.hasOwnProperty(opt)) {
options[ opt ] = userOptions[ opt ];
}
}
}
};
//prototype
module.prototype = {
init: module,
options: options
};
return module;
};
var my_module3 = new (moduleContext())();
my_module3.init({
first: "Mike",
second: "Lisa",
third: "Mary"
});
var my_module2 = new (moduleContext())();
my_module2.init({
first: "Barry",
second: "Larry",
third: "Sam"
});
console.log(my_module2.options, my_module3.options);
Run Code Online (Sandbox Code Playgroud)
神奇发生在这两new (moduleContext())()行中。该moduleContext()函数与您的 IIFE 一样,为模块构造函数设置上下文,然后返回它。然后new操作符处理返回的函数,并在不带参数的情况下调用它(最后一组括号)。需要围绕调用的额外括号的moduleContext()原因与 IIFE 上需要它们的原因相同:它们解决了 JavaScript 解析器中的一些歧义。
现在,您的两个模块是在两个不同的上下文中创建的。因此,您可以在任一模块中设置“通用”选项对象(就像您当前所做的那样),但只有该模块上下文中的选项对象会受到影响。另一个没有被触及,因此您可以单独设置您的选项。