Eli*_*gem 5 javascript closures object this
我以为我对thisJavaScript 中的对象有了合理的理解.在处理对象,回调以及事件和处理程序时,我从远古时代就没有遇到过任何问题.然而,现在一切都发生了变化.
爱上了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);
Run Code Online (Sandbox Code Playgroud)
在所有三种情况下,this日志都作为窗口对象.当然,这是一个简单的解决方法:
function makeClosure(func)
{
return function(par)
{
return func.call(this,par);
}
}
Run Code Online (Sandbox Code Playgroud)
这个修复工作,我把它放在这里,以避免人们回答这个问题,而不解释我需要知道的事情:为什么这样做会像在这里一样?
确保调用者实际上是闭包属于的对象.我不明白的是:this在第一种情况下,指向窗口对象,但在其他情况下,它不应该.我this在返回之前尝试登录makeClosure函数,它确实记录了对象本身,而不是window对象.但是当使用实际的闭包时,this返回指向窗口对象.为什么?
我唯一能想到的是,通过将anyFunc函数作为参数传递,我实际上是在传递window.anyFunc.所以我尝试了这个快速修复:
function makeClosure(func)
{
var theFunc = func;
return function(par)
{
theFunc(par);
}
}
Run Code Online (Sandbox Code Playgroud)
有了预期的结果,this现在指向对象,但又一次:为什么?我有一些想法(theFunc是对本地范围[ this > private: theFunc]中的函数的引用?),但我确信这里有人在JS方面有更多的技术诀窍,所以我希望得到一些更多解释或链接到值得他们阅读的文章......
谢谢
更新
这是一个小提琴,可能是我留下了一些东西,但这里记录了各种各样的东西;)
编辑/更新2
令我困惑的案例就在这里.
最终编辑
好的,这是一个相当混乱的帖子.所以澄清:我期待的是一种类似于此的行为:
function makeClosure()
{
function fromThisFunc()
{
console.log(this);
}
return fromThisFunc;
}
var windowContext = makeClosure();
windowContext();
var objectContext = {cls:makeClosure()};
objectContext.cls();
Run Code Online (Sandbox Code Playgroud)
引起我的是,该函数anyFunc未在正确的范围内声明,因此this指向窗口对象.我通过阅读我在网上找到的一个古老的卷轴找到了这个.
但是发生了一些更复杂的事情,因为globalVar现在引用的函数对象是使用[[scope]]属性创建的,该属性引用包含属于创建它的执行上下文的Activation/Variable对象的作用域链(和全球对象).现在,无法对Activation/Variable对象进行垃圾收集,因为globalVar引用的函数对象的执行需要将整个作用域链从其[[scope]]属性添加到为每次调用创建的执行上下文的作用域中.它.
所以我需要做的是简化而不是复杂化:
function fromThisFunc()
{
console.log(this);
}
function makeClosure(funcRef)
{
//some code here
return funcRef;
}
Run Code Online (Sandbox Code Playgroud)
那应该有用,对吗?
PS:除了Alnitak的回答,我会这么做,但特别感谢Felix Kling的所有耐心和信息.
只要您致电:
return func(par);
Run Code Online (Sandbox Code Playgroud)
您正在创建一个新的作用域(带有它自己的this),在这种情况下,因为您没有指定对象,this === window通常或在严格模式下未定义。被调用函数不会继承this调用范围内的任何内容。
为此设置值的方法是:
myobj.func(par); // this === myobj
Run Code Online (Sandbox Code Playgroud)
或者
func.call(myobj, ...) // this === myobj
Run Code Online (Sandbox Code Playgroud)
还有: