简体   繁体   English

我真的不知道javascript闭包

[英]I don't really know javascript closure

Here is the plunker . 这是the

function factory() {
    var yscale = function() {
        console.log("original");
    };
    var status = {
        yscale: yscale
    };

    function render() {
        yscale = function() {
            console.log("I am a scale");
        };
    }

    render.__privateStatus = {
        yscale: yscale
    };

    render.__privateStatus2 = status;

    render.__privateStatusGetter = function() {
        return status;
    };

    render.__privateStatusGetter2 = function() {
        return yscale;
    };

    return render;
}

var chart = factory();
chart();
console.log(chart.__privateStatus.yscale); // "original"
console.log(chart.__privateStatus2.yscale); // "original"

console.log(chart.__privateStatusGetter().yscale); // "original"
console.log(chart.__privateStatusGetter2()); // "I am a scale"

I returned a function in a closure, if some initialization happens in closure function, what the reason preventing the new value revealed as status of the returned function? 我在闭包中返回了一个函数,如果在闭包函数中发生了一些初始化,为什么阻止新值显示为返回函数的状态的原因是什么?

Could anyone help explain this from the language itself? 有人可以从语言本身来帮助解释吗?

Update 更新

Base on @RobG's answer, I think the question could be simplified with 基于@RobG的答案,我认为可以通过以下方式简化问题:

  • Is function a primitive type? 函数是原始类型吗?
  • What's the difference between a function and an object? 函数和对象之间有什么区别? .

You could noticed that yscale is a function(it is undefined before the call of chart(), even initialize yscale with a function, result is the same). 您可能会注意到yscale是一个函数(在调用chart()之前未定义,即使使用函数初始化yscale,结果也是一样)。 If function is primitive type, we should not be able to attach properties to it. 如果函数是原始类型,则我们不应将属性附加到它。 If function is an object, we possibly could use the reference passing to change it status. 如果函数是一个对象,我们可以使用传递的引用来更改其状态。

I know my second question is kinda naive. 我知道我的第二个问题有点天真。 If you define a function and let a variable point it, you cannot simply change its inner states by assign it to another function. 如果定义一个函数并让变量指向它,则不能简单地通过将其分配给另一个函数来更改其内部状态 But think my first question--we could change a function(or function pointer)'s states by attaching method to do like render.__privateMethods to change its behaviors. 但是想想我的第一个问题-我们可以通过附加方法来更改函数(或函数指针)的状态,使其类似于render .__ privateMethods来更改其行为。

Everybody knows we could use a module pattern to use an object to return the API of a module. 大家都知道我们可以使用模块模式来使用对象来返回模块的API。 Mike Bostock shows here that we could use a function to achieve similar thing just as an object and even more, we could have something like a constructor. Mike Bostock 在这里展示我们可以使用一个函数来实现类似对象的功能,甚至可以拥有类似构造函数的功能。 I thought I know both function and object very well. 我以为我非常了解功能和对象。 But with some wild thoughts, I am confused. 但是带着一些狂野的想法,我感到困惑。

That's the reason I am looking for an answer from javascript language rather than what the result should be even from instinct. 这就是我从JavaScript语言中寻找答案的原因,而不是从本能中得到的结果。

I'll take a guess that you're surprised that the following returns undefined : 我猜您会惊讶以下内容未定义

console.log(chart.__privateStatus.yscale);

That is because when the following line is executed: 这是因为执行以下行时:

render.__privateStatus = {
        yscale: yscale
    }

the value of the yscale variable is undefined , so that's the value that gets assigned. yscale变量的值是undefined ,所以这是要分配的值。 Changing the value of the variable later has no effect. 以后更改变量的值无效。 Note that in javascript, assigning a primitive assigns the actual value, assigning an object assigns a reference to the object. 请注意,在javascript中,分配基元会分配实际值,分配对象会分配对该对象的引用。 So while __privateStatus is passed a reference to the object, the yscale property is assigned the actual value undefined . 因此,当__privateStatus传递对对象的引用时, yscale属性将被赋予实际值undefined

For the same reason: 出于同样的原因:

console.log(chart.__privateStatus2.yscale);

returns undefined because there is: 返回undefined,因为存在:

var yscale;
var status = {
    yscale: yscale  // yscale is undefined when this assignment is made
};

so status.yscale is undefined and later: 所以status.yscale是未定义的,以后:

render.__privateStatus2 = status;

is assigned a reference to the same object. 被分配了对同一对象的引用。 Changing the value of yscale later has no effect, its previous value has already been assigned. 稍后更改yscale的值无效,因为先前的值已被分配。

Same again for: 同样适用于:

console.log(chart.__privateStatusGetter().yscale); // undefined

To get the current value of yscale , change the function to: 要获取yscale的当前值,请将函数更改为:

render.__privateStatusGetter = function() {
    return yscale;  // use closure to variable to get current value
}

then: 然后:

console.log(chart.__privateStatusGetter());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM