为什么这个 Javascript 对象在 $(document).ready 之后没有超出范围?
我有一些有效的 Javascript 可以操作一些 DOM 元素。问题是,我不明白为什么它有效,这从来都不是一件好事。我正在尝试了解更多有关面向对象的 javascript 和 javascript 最佳实践的信息,因此该组织可能看起来有点奇怪。
基本上,我将两个操作 DOM 的方法包装在 CSContent
对象内。我在 $(document).ready
中创建该对象 content
的实例,并将一些事件绑定到 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();
});
I have some working Javascript that manipulates the some DOM elements. The problem is, I don't understand why it works, which is never a good thing. I am trying to learn more about object oriented javascript and javascript best practices, so the organization may seems a little strange.
Basically, I wrap two methods that manipulate the DOM inside a CSContent
object. I create an instance of that object, content
in $(document).ready
and bind some events to the functions in content
. However, I am confused as to how these functions can still be called after $(document).ready
exits. Doesn't that mean that content
has gone out of scope, and its functions are not available? Anyway, here is the code:
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();
});
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
大人,这称为闭包:局部变量
content
在$(document).ready
退出后将保留在内存中。这也是内存泄漏的已知原因。简而言之,您将此函数绑定到 DOM 元素的事件侦听器,然后 JavaScript 垃圾收集器知道它应该保持局部变量完整。您不能直接调用它(在函数之外),除非事件被触发。对于某些,如果您确实想稍后调用该函数(例如,使用
element.click()
来模拟点击),您可以“手动”执行此操作。This, m'lord, is called a closure: the local variable
content
will remain in memory after$(document).ready
exits. This is also a known cause of memory leaks.In short, you bind this function to an event listener of a DOM element and then the JavaScript garbage collector knows that it should keep the local variable intact. You can't call it directly (outside of the function), unless the event is triggered. With some, you can do this ‘manually’, if you really want to call the function afterward (e.g., using
element.click()
to simulate a click).我想您想知道为什么事件处理程序喜欢
工作?
那么,您不会将
content
作为事件处理程序传递,而是传递content.toggleTweetTextarea
中包含的函数。并且在content
不再存在后,该引用仍然存在。没有什么特别的。您刚刚将一个对象(函数)分配给另一个变量。只要至少存在一个对对象的引用,该对象就不会被垃圾收集。现在您可能会问为什么这些函数仍然可以访问例如
tweetTextArea
?这确实是一个封闭。当通过new CSContent()
创建函数时,该函数的激活上下文将添加到内部函数CSContent.toggleTweetTextarea
和CSContent 的作用域链中。更新TweetCharacterCount。因此,即使您不再引用
content
,该函数的作用域仍然包含在其他函数的作用域链中。ready()
完成后,您将无法再访问content
中包含的对象,这确实超出了范围。I assume you wonder why the event handlers like
work?
Well you don't pass
content
as event handler but the function that is contained incontent.toggleTweetTextarea
. And this reference will still exist aftercontent
does not exist anymore. There is nothing special about it. You just assigned an object (the function) to another variable. As long as at least one reference to an object exists, the object won't be garbage collected.Now you may ask why those functions have still access to e.g.
tweetTextArea
? This is indeed a closure. When the functions are created vianew CSContent()
, the activation context of this function is added to the scope chain of the inner functionsCSContent.toggleTweetTextarea
andCSContent.updateTweetCharacterCount
. So even if you don't have a reference tocontent
anymore, the scope of this function is still contained in the scope chain of the other functions.You won't be able to access the object contained in
content
anymore afterready()
is finished, this indeed goes out of scope.我今天脑子不好使了,但是在这种情况下你不应该使用闭包吗?
My brain is off today, but shouldn't you be using closures in this situation?