can*_*nge 2 javascript closures encapsulation
我正在关注这个:
Javascript 构造函数模式- 滚动到“Closures with getter-setters (D3.js, jQuery))”
我对my声明的方式感到困惑:
function Person(firstName, lastName) {
var _firstName = firstName, // private
_lastName = lastName; // private
var my = {
firstName: _firstName, // <- why?
lastName: _lastName // <- why?
}; // var my = {};?
my.fullName = function() {
return _firstName + ' ' + _lastName; // a toString() wannabe
};
// Getter/setters
my.firstName = function(value) {
if (!arguments.length) return _firstName; // getter
_firstName = value; // setter
return my; // enable "method chaining" ...
};
my.lastName = function(value) {
if (!arguments.length) return _lastName; // getter
_lastName = value; // setter
return my; // ... so mark.firstName('Samuel').lastName('Clemens'); works
};
return my; // expose inner object but not the private instance variables
}
Run Code Online (Sandbox Code Playgroud)
添加上面部分的旁注是为了暴露我的想法。
//Use it like this:
var mark = Person('Mark', 'Twain'); // note: no `new` keyword!
mark.firstName('Samuel');
mark.lastName('Clemens');
mark.fullName(); // Samuel Clemens
Run Code Online (Sandbox Code Playgroud)
var my = {};在 chrome 控制台中测试时似乎有效。该代码旨在支持封装。此更改后的测试并未发现任何进入私有空间或损坏功能的新方法。但我担心我缺少一些需要这样做的魔法。
请检查我的想法。当 my.firstName 中的 _firstName 被重新定义为 getter/setter 函数时,它不是被踩了吗?我切换到会暴露或破坏某些东西吗var my = {};?
这是如何工作的?部分说:
“通常,当函数完成执行时,该函数内声明的变量会超出范围并被销毁。但有一个例外:如果函数外部的任何代码在函数完成执行后保存对这些变量的引用,则它们不会被清理。相反,将形成一个闭包,并且这些变量将保留在内存中。”
“在上面的示例中,由于 Person 构造函数返回内部对象 my,并且由于 my 引用局部变量 _firstName 和 _lastName(在 getter/setter 和 fullName 方法中),因此这些变量不会被销毁。 getter/setter 被调用,它们对相同的局部变量进行操作。”
有点讽刺的是,我在博客上看到的大多数“教授”闭包的人实际上并不理解闭包本身。你是对的,但是该代码中还有很多多余的东西,而不仅仅是那个对象。
function Person(firstName, lastName) { // [arguments] also "private"
this.fullName = function() {
return firstName + ' ' + lastName;
};
this.firstName = function(value) { // difficult to inspect
if (!arguments.length) return firstName; // soon: How's this working?
firstName = value; // yes those are still there
// ...still there...
return this; // ......always there....
}; // ........forever........
// ...haunting your memories
this.lastName = function(value) { // .......never forget...
if (!arguments.length) return lastName; // ....closure remembers...
lastName = value; // ...dream within a dream..
// ....within a closure....
return this; // ...no one returns......
}; // ...daddy..............
} // where do dead memories go?
Run Code Online (Sandbox Code Playgroud)
它是如何工作的?好吧,范围仍然存在。名字和姓氏也是如此。您也不需要返回内部对象,绝对没有理由不只构造一个 Person 的实例。
但只有当你打算用它来做一些非常奇特的东西时,这种模式才有用。对于存储字符串或整数或任何类似的东西,它的效率低得离谱。没有人会在 3 个函数加上一个闭包加上每个对象实例的数据中存储少量数据- 该对象的 1000 个实例是 1000 个闭包和 3000 个函数加上实际数据(在这个不公平的示例中,当然只有 2 个字符串,这使得那就更可笑了)。
因此,除非你觉得值得,否则就使用普通的老式无聊原型。我知道这很无聊,但如果你实际上并排运行这个无聊的版本,它不仅估计减少了 99% 的内存(你有 1 个单个对象仅保存每个实例所需的数据,其余部分是共享的)它也容易得多使用,因为一切都始终如您所期望的那样运行。
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
Person.prototype = {
get fullName () {
return this.firstName + ' ' + this.lastName;
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:但是尝试和尝试新事物当然是很好的,最好尝试一些东西并亲眼看看它是好是坏,而不是盲目地听从我的建议。我希望我没有对博客作者过度或不公平地批评。
| 归档时间: |
|
| 查看次数: |
2517 次 |
| 最近记录: |