我一直在重构别人的 JavaScript 代码。
前:
function SomeObj(flag) {
var _private = true;
this.flag = (flag) ? true : false;
this.version="1.1 (prototype)";
if (!this._someProperty) this._init();
// leading underscore hints at what should be a 'private' to me
this.reset(); // assumes reset has been added...
}
SomeObj.prototype.reset = function() {
/* perform some actions */
}
/* UPDATE */
SomeObj.prototype.getPrivate = function() {
return _private; // will return undefined
}
/* ...several other functions appended via `prototype`...*/
后:
var SomeObj = function (flag) {
var _private = true;
this.flag = (flag) ? true : false;
this.version = "2.0 (constructor)";
this.reset = function () {
/* perform some actions */
};
/* UPDATE */
this.getPrivate = function() {
return _private; // will return true
}
/* other functions and function calls here */
}
对我来说,第一个例子看起来很难阅读,尤其是在更大的上下文中。reset
像这样使用属性添加类似 on 的方法prototype
似乎不太受控制,因为它可能发生在脚本中的任何地方。我重构的代码(上面的第二个示例)对我来说看起来更整洁,因此更容易阅读,因为它是独立的。我通过变量声明获得了一些隐私,但我失去了原型链的可能性。
...
问题:
首先,我很想知道前面提到的我还失去了什么
prototype
,或者原型链的丢失是否有更大的影响。这篇文章已有6 年历史,但声称prototype
在大规模上使用该属性比闭包模式更有效。上面的两个例子仍然是由
new
操作符实例化的;它们都是“经典”式的构造函数。最终,我什至想从这个模型转移到所有属性和函数都声明为var
s 的模型中,并且我有一个公开的方法,它能够返回一个对象,打开我需要的所有属性和方法,这些属性和方法具有特权(通过关闭)对那些私有的。像这样的东西:var SomeObj = (function () { /* all the stuff mentioned above, declared as 'private' `var`s */ /* UPDATE */ var getPrivate = function () { return private; } var expose = function (flag) { // just returns `flag` for now // but could expose other properties return { flag: flag || false, // flag from argument, or default value getPrivate: getPrivate } }; return { expose: expose } })(); // IIFE // instead of having to write `var whatever = new SomeObj(true);` use... var whatever = SomeObj.expose();
StackOverflow 上有一些解决“原型与闭包”问题的答案(例如,此处和此处)。但是,与
prototype
财产一样,我感兴趣的是,朝着这个方向发展并远离new
运营商对我的代码效率和任何可能性的损失(例如instanceof
丢失)意味着什么。如果无论如何我都不打算使用原型继承,那么在前面的new
运算符中我真的会失去任何东西吗?如果我被允许,一个更宽松的问题,考虑到我要求上面的细节:如果
prototype
和new
真的是最有效的方式,比关闭有更多的优势(无论你认为它们可能是什么),是否有任何指导方针或设计以更整洁的方式编写它们的模式?
...
更新:
请注意,expose
每次都会返回一个新对象,因此这是实例化发生的地方。据我了解,该对象指的是SomeObj
闭包中声明的方法,它们在所有对象中都是相同的方法(除非被覆盖)。在flag
变量的情况下(我现在已经更正了),这可以从 的参数继承expose
,具有默认值,或者再次引用封装的预先存在的方法或属性。所以有一些正在生成的对象的实例,并且这里正在进行一些继承(加上多态性?)。
所以重复问题 2:如果我无论如何都不打算使用原型继承,那么在前面的new
运算符中我真的会失去任何东西吗?
非常感谢到目前为止的回答,这有助于澄清我的问题。