可能重复:
JS: var self = this?
在查看用JavaScript编写的任意代码时(例如在GitHub上),许多开发人员使用var self = this
,然后使用self
代替this
来引用当前对象。
这种方法背后的理由是什么?
答案 0 :(得分:9)
this
的值是上下文的。编写var self = this
是一种在一个上下文中保存this
的值的方法,以便可以在另一个上下文中使用。
示例:
function Test() {
var self = this;
console.log(this);
setTimeout(function() {
console.log(this);
console.log(self);
}, 1000);
}
打印:
Test {}
Window 11918143#comment15869603_11918143
Test {}
请注意this
的值已更改,但我们仍然可以使用self
引用原始值。
这是有效的,因为JavaScript中的函数“关闭”它们词法范围中的变量(这只是说明内部函数可以看到在外部函数中声明的变量的更技术方式)。这就是我们写var self = this
的原因;变量self
可用于所有内部函数,即使这些函数在外部函数返回之后很久才执行。
答案 1 :(得分:5)
例如,当您在jQuery中使用回调时,您可能希望引用父函数的this
变量,该变量在您处于另一个函数时会采用不同的值:
$('#foo').click(function() {
var self = this;
$.get('foo.php', function(data) {
// In here, self != this
$(self).text(data);
});
});
在这种情况下,将$(self)
替换为$(this)
将无效。基本上,您将this
存储在变量中供以后使用。
答案 2 :(得分:2)
通常当你在某些代码中有一个嵌套的函数声明但你想从“child”函数中引用“parent”函数时。
Ext.define('MyPanel', {
extend: 'Ext.panel.Panel',
title: 'My Panel',
initComponent: function() {
var self = this;
Ext.applyIf(self, {
items: [
{
xtype: 'button',
text: 'MyButton',
handler: function() {
console.log(this); //the button
console.log(self); //the panel
}}
]
});
self.callParent(arguments);
}
});
Ext.onReady(function() {
var p = new MyPanel({
renderTo: Ext.getBody()
});
});
示例:
答案 3 :(得分:2)
让我给出更多技术性的解释。当您在Javascript中访问变量时,解释器会在所谓的范围堆栈中查找变量的值。您可以将其视为一堆对象。解释器将首先查看堆栈的顶部。如果未在该范围对象中定义变量,则它将查看其下方的对象。如果它不存在,那么解释器会向下看另一层,直到它到达堆栈的底部。
最初,堆栈中唯一的范围对象是全局对象。变量是否存在。当您调用函数时,解释器会将新对象推送到作用域堆栈 - 用于存储局部变量。当您访问 var1 时,解释器将首先查看本地范围对象。如果它在那里,那么它将使用存储在那里的值。如果不是,它将继续向下移动到范围对象 - 这恰好是全局范围。
在函数中创建函数时,会发生一些有趣的事情。解释器将创建所谓的“激活对象”。它基本上是外部函数的局部范围对象的快照。该激活对象与内部函数相关联。当调用内部函数时,激活对象在本地范围之前被推到范围堆栈上(即本地范围仍然在顶部)。在内部函数中访问变量意味着解释器将首先检查本地范围对象,然后是激活对象,然后是全局范围对象。
根据定义, this 变量始终存在于函数的本地范围内。它总是指隐含的第一个参数。当您调用plain-o函数时,编译器将null作为 this 传递。变量存在,但指向null。搜索 this 永远不会超出本地范围对象。
分配给 self 的目的基本上是愚弄解释器,因此它会超出内部函数的局部范围。当您在内部函数中访问 self 时,解释器将无法在本地范围内找到它。所以它会检查激活对象。如果self = this语句在创建内部函数之前发生,则 self 将存在于激活范围对象中,指向外部函数看到的 this 对象。