JavaScript闭包和this对象 [英] JavaScript closure and the this object

查看:119
本文介绍了JavaScript闭包和this对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为我对JavaScript中的这个对象有了合理的理解。当处理对象,回调,事件和处理程序时,我从来没有遇到过问题。现在,所有都改变了。



我爱上了JavaScript,堕落了脚跟。纯JS,也就是说,不是jQuery,prototype.js,dojo ...所以自然,我已经考虑使用闭包。在某些情况下,这个在这里抓住了我。取这个代码段为一:

  function anyFunc(par)
{
//console.log par);
console.log(this);
}

函数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 )
{
return func.call(this,par);
}
}

避免人们回答这个问题,而不解释我需要知道的:为什么这是这里的做法?

确保调用者是有效的对象关闭属于。我不明白的是:
当然,这个指向第一种情况下的窗口对象,但在其他情况下,它不应该。我尝试在返回之前在makeClosure函数中记录 this ,它记录了对象本身,而不是窗口对象。但是当使用实际的闭包时,这个返回指向窗口对象。为什么?



我唯一可以想到的是,通过传递 anyFunc 函数作为参数,实际上传递 window.anyFunc 。所以我试着这个快速修复:

  function makeClosure(func)
{
var theFunc = func;
return function(par)
{
theFunc(par);
}
}

这个现在指向对象,但是:为什么?我有一些想法( theFunc 是对局部作用域中的函数的引用[ this> private:theFunc ]?),但我相信有人在这里有很多更多的知识,当它涉及到JS,所以我希望得到一些更多的解释或链接到文章值得从他们阅读...



感谢


$ b

更新

这里是一个小提琴,可能是我留下了一些东西,但在这里记录各种各样的东西;)



编辑/更新2



这让我感到困惑的情况就在这里。



p>

好吧,这是一个很乱的帖子。所以澄清:我所期望的是类似这样的行为:

  function makeClosure()
{
function fromThisFunc()
{
console.log(this);
}
return fromThisFunc;
}

var windowContext = makeClosure();
windowContext();
var objectContext = {cls:makeClosure()};
objectContext.cls();什么引起我的,是函数 anyFunc 未在正确的范围内声明,因此指向窗口对象。我通过阅读我在网络上找到的
古卷轴发现了这一点。


但是发生了一些更复杂的事情,因为globalVar现在引用的函数对象是使用[[scope]]属性创建的,包含属于创建它的执行上下文(和全局对象)的Activation / Variable对象的范围链。现在,Activation / Variable对象不能被垃圾收集,因为globalVar引用的函数对象的执行将需要从其[[scope]]属性添加整个范围链到为每个调用创建的执行上下文的范围


所以我需要做的是简化而不是复杂的事情:

  function fromThisFunc()
{
console.log(this);
}

函数makeClosure(funcRef)
{
//这里的一些代码
return funcRef;
}

这应该可以工作,对吗?



PS:除了Alnitak的回答,我会特别感谢Felix Kling所有的耐心和信息。

解决方案

一旦您呼叫:

 code> return func(par); 

您正在创建一个新范围(具有自己的 this ),在这种情况下,因为你在严格模式下没有指定对象,通常是 this === window undefined 。被调用的函数不会继承

$

$

$ <$ p
$ b <为 设置一个值:

  myobj.func // this === myobj 

  func.call(myobj,...)// this === myobj 

还有:




I thought I had a reasonable understanding of the this object in JavaScript. When dealing with objects, callbacks, and both events and handlers, I haven't had a problem with it since time immemorial. Now, however, all has changed.

I've fallen head over heels in love with JavaScript. Pure JS, that is, not jQuery, prototype.js, dojo... So naturally, I've taken to using closures. In some cases, though, this is catching me off guard here. Take this snippet for one:

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);

In all three cases, this logs as the window object. It's an easy fix, of course:

function makeClosure(func)
{
    return function(par)
    {
        return func.call(this,par);
    }
}

This fix works, I put it here to avoid people answering this, without explaining what I need to know: why is this behaving the way it does here?

ensures the caller is effectively the object that the closure belongs to. What I fail to understand is this: Sure enough, this points to the window object in the first case, but in other cases, it shouldn't. I tried logging this in the makeClosure function just before returning, and it did log the object itself, not the window object. But when the actual closure is used, this is back to pointing to the window object. Why?

The only thing I can think of is that, by passing the anyFunc function as an argument, I'm actually passing window.anyFunc. So I tried this quick fix:

function makeClosure(func)
{
    var theFunc = func;
    return function(par)
    {
        theFunc(par);
    }
}

With the expected results, this now points to the objects, but again: Why? I have a few idea's (theFunc is a reference to the function in the local scope [this > private: theFunc]?), but I'm sure there are people here with a lot more know-how when it comes to JS, so I was hoping to get some more explanation or links to articles worth reading from them...

Thanks

Update

Here's a fiddle, may be I left something out, but here this logs all sorts of things ;)

Edit/Update 2

The case that confuses me is here.

Final Edit

Ok, This is getting a rather messy post. So to clarify: What I was expecting was a behaviour similar to this:

function makeClosure()
{
    function fromThisFunc()
    {
        console.log(this);
    }
    return fromThisFunc;
}

var windowContext = makeClosure();
windowContext();
var objectContext = {cls:makeClosure()};
objectContext.cls();

What caught me, was that the function anyFunc wasn't declared within the correct scope, and therefore, this pointed to the window object. I found this out by reading an ancient scroll I found somewhere on the web.

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.

So what I needed to do, was simplify rather then complicate things:

function fromThisFunc()
{
    console.log(this);
}

function makeClosure(funcRef)
{
    //some code here
    return funcRef;
}

That should work, right?

PS: I'll except Alnitak's answer, but special thanks goes to Felix Kling for all the patience and info.

解决方案

As soon as you call:

return func(par);

You're creating a new scope (with its own this) and in this case because you haven't specified an object, this === window usually or undefined in strict mode. The called function does not inherit whatever this was in the calling scope.

Ways to set a value for this are:

myobj.func(par);  // this === myobj

or

func.call(myobj, ...)  // this === myobj

There are also:

这篇关于JavaScript闭包和this对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆