我跟着这个:
Javascript constructor patterns - 滚动到“使用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
}
上面一节中的附加评论被添加以揭示我的想法。
//Use it like this:
var mark = Person('Mark', 'Twain'); // note: no `new` keyword!
mark.firstName('Samuel');
mark.lastName('Clemens');
mark.fullName(); // Samuel Clemens
var my = {};
似乎在Chrome控制台中测试时有效。此代码旨在支持封装。在此更改之后进行测试并未发现任何进入私有或破坏功能的新方法。但是我担心我会缺少一些需要它的魔法。
请检查我的想法。当my.firstName中的_firstName被重新定义为getter / setter函数时,它是不是被踩到了?我是否通过切换到var my = {};
来暴露或破坏某些内容?
这是如何工作的?部分说:
“通常,当函数完成执行时,声明变量 在该函数内超出范围并被销毁。但是有 例外:如果函数外的任何代码都包含引用 函数完成执行后的这些变量,它们不会 清理干净了。相反,将形成一个闭包,以及那些变量 将留在记忆中。“
“在上面的例子中,因为Person构造函数返回 内部对象我,因为我指的是局部变量 _firstName和_lastName(在getter / setter和fullName方法中),变量不会被销毁。当。。。的时候 调用getter / setter,它们在同一个本地操作 变量“。
答案 0 :(得分:3)
有点讽刺的是,我在博客上看到“教学”封闭的大多数人实际上并不了解封闭本身。你是对的,但是代码中的冗余东西比那个对象要多得多。
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?
它是如何工作的?范围仍然存在。 firstName和lastName也是如此。您也不需要返回内部对象,绝对没有理由不构造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;
}
}
编辑:但实际上很好地尝试和尝试新事物,并且更好地尝试一些事情并亲自了解它是如何以及为什么它的好坏,而不是盲目地倾听像我这样的建议。我希望我对博客的作者不过分或不公平批评。