我有一些工作Javascript来操纵一些DOM元素。问题是,我不明白为什么它起作用,这从来都不是一件好事。我正在尝试更多地了解面向对象的javascript和javascript最佳实践,因此组织可能看起来有点奇怪。
基本上,我将两个操作DOM的方法包装在CSContent
对象中。我在content
中创建了该对象的实例$(document).ready
,并将一些事件绑定到content
中的函数。但是,我对在$(document).ready
退出后如何仍然可以调用这些函数感到困惑。这是否意味着content
已超出范围,其功能不可用?无论如何,这是代码:
function CSContent() {
var tweetTextArea = document.getElementById('cscontent-tweet'),
tweetTextElement = document.getElementById('edit-cscontent-cs-content-tweet'),
charCountElement = document.getElementById('cscontent-tweet-charactercount');
this.toggleTweetTextarea = function () {
$(tweetTextArea).slideToggle();
};
this.updateTweetCharacterCount = function () {
var numOfCharsLeft = 140 - tweetTextElement.value.length;
if (numOfCharsLeft < 0) {
$(charCountElement).addClass('cscontent-negative-chars-left');
}
else {
$(charCountElement).removeClass('cscontent-negative-chars-left');
}
charCountElement.innerHTML = '' + numOfCharsLeft + ' characters left.';
};
}
$(document).ready(function () {
var content = new CSContent();
//If the twitter box starts out unchecked, then hide the text area
if ($('#edit-cscontent-cs-content-twitter:checked').val() === undefined) {
$('#cscontent-tweet').hide();
}
$('#edit-cscontent-cs-content-twitter').change(content.toggleTweetTextarea);
//Seems wasteful, but we bind to keyup and keypress to fix some weird miscounting behavior when deleting characters.
$('#edit-cscontent-cs-content-tweet').keypress(content.updateTweetCharacterCount);
$('#edit-cscontent-cs-content-tweet').keyup(content.updateTweetCharacterCount);
content.updateTweetCharacterCount();
});
答案 0 :(得分:5)
这个,m'lord,被称为闭包:局部变量content
将在$(document).ready
退出后保留在内存中。这也是内存泄漏的已知原因。
简而言之,您将此函数绑定到DOM元素的事件侦听器,然后JavaScript垃圾收集器知道它应保持本地变量不变。除非事件被触发,否则不能直接调用它(在函数外部)。如果你真的想在之后调用该函数(例如,使用element.click()
模拟点击),你可以“手动”执行此操作。
答案 1 :(得分:2)
我假设你想知道为什么事件处理程序喜欢
$('#edit-cscontent-cs-content-twitter').change(content.toggleTweetTextarea);
工作?
嗯,您不会将content
作为事件处理程序传递,而是content.toggleTweetTextarea
中包含的函数。在content
不再存在之后,此引用仍然存在。没什么特别的。您刚刚将一个对象(该函数)分配给另一个变量。只要存在至少一个对象的引用,该对象就不会被垃圾回收。
现在您可能会问为什么这些功能仍然可以访问例如tweetTextArea
?这确实是一个封闭。通过new CSContent()
创建函数时,此函数的激活上下文将添加到内部函数CSContent.toggleTweetTextarea
和CSContent.updateTweetCharacterCount
的范围链中。因此,即使您不再引用content
,此函数的范围仍包含在其他函数的范围链中。
content
完成后,您将无法再访问ready()
中包含的对象,这确实超出了范围。
答案 2 :(得分:1)
今天我的大脑已经关闭了,但在这种情况下你不应该使用闭包吗?
$('#edit-cscontent-cs-content-twitter').change(
function(){
content.toggleTweetTextarea();
}
);