- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我以为我对 JavaScript 中的 this
对象有了合理的理解。在处理对象、回调以及事件和处理程序时,我从远古以来就没有遇到过问题。然而,现在一切都变了。
我已经爱上了 JavaScript。纯 JS,也就是说,不是 jQuery、prototype.js、dojo...所以很自然地,我开始使用闭包。但是,在某些情况下,this
在这里让我措手不及。以这个片段为例:
function anyFunc(par)
{
//console.log(par);
console.log(this);
}
function makeClosure(func)
{
return function(par)
{
return func(par);
}
}
var close = makeClosure(anyFunc);
close('Foo');
var objWithClosure = {cls:makeClosure(anyFunc),prop:'foobar'};
objWithClosure.cls(objWithClosure.prop);
var scndObj = {prop:'Foobar2'};
scndObj.cls = makeClosure;
scndObj.cls = scndObj.cls(anyFunc);
scndObj.cls(scndObj.prop);
在所有这三种情况下,this
都记录为窗口对象。当然,这很容易修复:
function makeClosure(func)
{
return function(par)
{
return func.call(this,par);
}
}
这个修复有效,我把它放在这里是为了避免人们回答这个问题,而没有解释我需要知道的内容:为什么它会像这里那样表现?
确保调用者实际上是闭包所属的对象。我不明白的是:果然,this
在第一种情况下指向了window对象,但在其他情况下,它不应该。我尝试在返回之前在 makeClosure 函数中记录 this
,它确实记录了对象本身,而不是 window
对象。但是当使用实际的闭包时,this
又回到指向 window 对象。为什么?
我唯一能想到的是,通过将 anyFunc
函数作为参数传递,我实际上传递了 window.anyFunc
。所以我尝试了这个快速修复:
function makeClosure(func)
{
var theFunc = func;
return function(par)
{
theFunc(par);
}
}
有了预期的结果,this
现在指向对象,但再次:为什么?我有一些想法(theFunc
是对局部范围 [this > private: theFunc
] 中函数的引用?),但我确定这里有人在 JS 方面有更多的专业知识,所以我希望能从他们那里得到更多的解释或指向值得阅读的文章的链接……
谢谢
更新
Here's a fiddle ,可能是我遗漏了一些东西,但是这里记录了各种各样的事情;)
编辑/更新 2
最终编辑
好的,这是一个相当困惑的帖子。所以澄清一下:我所期待的是与此类似的行为:
function makeClosure()
{
function fromThisFunc()
{
console.log(this);
}
return fromThisFunc;
}
var windowContext = makeClosure();
windowContext();
var objectContext = {cls:makeClosure()};
objectContext.cls();
引起我注意的是,函数anyFunc
没有在正确的范围内声明,因此,this
指向了window 对象。我通过阅读 ancient scroll 发现了这一点我在网上找到了某个地方。
But something a little more complicated has happened because the function object now referred to by globalVar was created with a [[scope]] property referring to a scope chain containing the Activation/Variable object belonging to the execution context in which it was created (and the global object). Now the Activation/Variable object cannot be garbage collected either as the execution of the function object referred to by globalVar will need to add the whole scope chain from its [[scope]] property to the scope of the execution context created for each call to it.
所以我需要做的是简化而不是复杂化:
function fromThisFunc()
{
console.log(this);
}
function makeClosure(funcRef)
{
//some code here
return funcRef;
}
这应该行得通,对吧?
PS:我将排除 Alnitak 的回答,但特别感谢 Felix Kling 的所有耐心和信息。
最佳答案
只要你打电话:
return func(par);
你正在创建一个新的范围(有它自己的 this
),在这种情况下,因为你没有指定一个对象,this === window
通常或者undefined 在严格模式下。被调用函数不会继承调用范围内的任何this
。
为 this 设置值的方法有:
myobj.func(par); // this === myobj
或
func.call(myobj, ...) // this === myobj
还有:
关于JavaScript 闭包和 this 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10512087/
我的问题是...在 TestObj 的 CallMeLaterTestObj 函数中,“this”是窗口对象,而不是 TestObj。我如何重构它,以便在 CallMeLater 函数中我不必包装 c
这个问题已经有答案了: JavaScript closure inside loops – simple practical example (45 个回答) 已关闭 8 年前。 下面的代码返回:10
我尝试学习一种不熟悉的编程语言的第一件事就是它如何处理闭包。它们的语义通常与语言处理范围和其他各种棘手位的方式交织在一起,因此理解它们可以揭示该语言的其他几个方面。另外,闭包是一种非常强大的构造,并且
我正在学习使用闭包,但我不确定什么是适合我的情况的最佳方法。为了清楚起见,我编辑了我的代码,它包含虚拟代码。如果用户单击 test 元素,我必须访问 handleCannon 函数。如果我在 onlo
所以在 d3 中我想要一个函数数组 var data = [44,23]; var line = []; for (var i = 0; i < data.length; i++) { lin
对于另一个闭包问题,我提前表示歉意,但我想澄清一下我对闭包在 JavaScript 中的实现方式的理解。 考虑以下代码: 01 'use strict'; 02 function foo() {} 0
闭包是我在 JS 中仍然没有完全掌握的东西。我认为这是一个关闭问题。我正在尝试创建一个进度条。每 x 秒我想增加一个 DIV 的宽度。这是应该执行此操作的部分: for(i=0;i<=counter;
我以为我对 JavaScript 中的 this 对象有了合理的理解。在处理对象、回调以及事件和处理程序时,我从远古以来就没有遇到过问题。然而,现在一切都变了。 我已经爱上了 JavaScript。纯
我创建的对象有问题,看起来像这样: var myObject = { AddChildRowEvents: function(row, p2) { if(document.at
我正在制作一个 DOM 生成器,我已经成功地工作了,但现在我正在尝试分配一些速记函数,以便 div() -> e("div") 这是我的代码: //assign these objects to a
有没有人愿意为像这样的闭包(使用 C# 获得)和匿名内部类发布等效的 Java 代码? public static Func IncrementByN() { int
我在控制台中运行此命令来查找结果的值,但我对为什么它是 122 感到困惑。我无法弄清楚为什么,也无法弄清楚在代码中如何使用奖金。有人可以解释一下奖金的值(value)以及他们如何获得开头声明的每个变量
以下代码定义了两个函数:lines 和 circles,它们返回一个函数 f 和 g分别。函数 f 和 g 相等(() -> size)只是为了简单起见,但通常它们是变量 的不同函数>尺寸。 line
function sampleDelay(delay) { return function(functionArray) { var count = 0; var func
这个问题已经有答案了: 已关闭12 年前。 Possible Duplicate: What is the difference between a 'closure' and a 'lambda'?
我正在尝试弄清楚 std::function 与闭包结合使用时发生了什么。我还不能全神贯注,例如:正在调用什么构造函数?任何人都可以发布一个工作示例来替换 std::function 以支持以下示例中
闭包通过引用(而不是值)存储它们的外部变量。但是,在下面的代码中,我想按值存储。谁能告诉我如何使用 IIFE 做到这一点? var i = -1; var f = function () {
我刚刚开始学习函数指针,当我阅读关于该主题的 K&R 章节时,第一个让我印象深刻的是,“嘿,这有点像闭包。”我知道这个假设在某种程度上是根本错误的,在网上搜索后,我没有找到任何关于这种比较的分析。 那
我的理解是,Java(以及 Clojure)中使用的默认 ClassLoader 持有指向任何创建的匿名类的指针,因此,持有 lambdas 和闭包。这些是 从不 垃圾收集,因此代表“内存泄漏”。有一
我很抱歉这个不那么具体的标题,因为我的英语不够好,无法在标题中清楚地描述这种情况。 我有这样的代码: var e = document.getElementsByClassName( "test" )
我是一名优秀的程序员,十分优秀!