Javascript 闭包,维护外部对象

发布于 2024-10-01 18:43:43 字数 1032 浏览 4 评论 0原文

我一直在使用 Javascript 闭包来保护变量,方法是将它们设置为返回函数的本地变量,例如:

closure = function() {
    var secretVar = 'Secret';

    return {
        "msg" : function() {
            console.log(secretVar);
        }
    };
}();
console.log(closure.secretVar); // Undefined
closure.msg(); // Secret

我觉得我对此有很好的掌握,使我能够控制内部变量的访问方式(如果有的话)。

我现在遇到这个问题,

closure = function() {
    var secretVar = ['Secret One','Secret Two'];

    return {
        "del" : function(modMe) {
            modMe = secretVar;
            modMe.slice(1,1);
            console.log(modMe);
        }(secretVar),
        "secretVar" : function() {
            console.log(secretVar);
        }
    };
}();
closure.del(); // Secret One
closure.secretVar(); // Secret One

我希望closure.del()返回Secret One,但我希望secretVar保持不变,然而,事实并非如此。 del() 函数正在修改引用而不是副本,我不确定如何让它复制 SecretVar 并修改它。

我猜它会以以下形式出现,

(function(y) {
    //..Body that changes y
})(secretVar)

但我还没能让它发挥作用。有什么想法吗?

I've been using Javascript closures to protect variables by making them local to the returned functions, such as:

closure = function() {
    var secretVar = 'Secret';

    return {
        "msg" : function() {
            console.log(secretVar);
        }
    };
}();
console.log(closure.secretVar); // Undefined
closure.msg(); // Secret

I feel that I have a pretty good grasp of that, giving me the ability to control how inner variables are accessed if at all.

I'm now running into this problem

closure = function() {
    var secretVar = ['Secret One','Secret Two'];

    return {
        "del" : function(modMe) {
            modMe = secretVar;
            modMe.slice(1,1);
            console.log(modMe);
        }(secretVar),
        "secretVar" : function() {
            console.log(secretVar);
        }
    };
}();
closure.del(); // Secret One
closure.secretVar(); // Secret One

I want closure.del() to return Secret One, but I want the secretVar to remained untouched, however, it's not. The del() function is modifying the reference rather than a copy, and I'm unsure of how to get it to copy secretVar and modify that.

I'm guessing it's going to be in the form of

(function(y) {
    //..Body that changes y
})(secretVar)

but I haven't been able to get that to work. Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

走过海棠暮 2024-10-08 18:43:43

你的问题实际上与闭包无关。当您这样做时:

modMe = secretVar;

您只是创建一个指向相同数组的新变量。您对一个变量所做的操作将反映在两个变量中,因为它们指向同一事物。

如果您想对数组执行某种修改(同时保留原始数组),您需要先复制它:

var copied = [];
for(var i = 0; i < secretVar.length; i++){
    copied.push(secretVar[i]);
}

编辑:顺便说一句,当您说您使用闭包来“保护变量”时,您并没有保护它们防止被执行闭包的返回函数修改。您刚刚做到了这一点,以便从这些函数的范围之外无法访问该变量。但是,在作用域内,例如当您执行切片时,该变量就在那里并且可供该函数访问,并且不会仅仅因为它是一个闭包而受到“保护”。

编辑 2:如果您要经常复制数组,您可以通过创建一个封闭函数来为您进行复制来消除迭代的一些麻烦:

closure = function() {
    var secretVar = 'Secret';
    var clone = function(){
        var clonedArr = [];
        var length = secretVar.length;
        for(var i = 0; i < length; i++){
            clonedArr.push(secretVar[i]);
        }
        return clonedArr;
    }

    return {
        "msg" : function() {
            var duplicate = clone();
        }
    };
}();

Your problem actually has nothing to do with closures. When you do:

modMe = secretVar;

You are just creating a new variable pointing to the same array. What you do to one will be reflected in both variables, since they are pointing to the same thing.

If you want to perform some sort of modification on the array (while maintaining the original), you need to copy it first:

var copied = [];
for(var i = 0; i < secretVar.length; i++){
    copied.push(secretVar[i]);
}

Edit: As an aside, when you say you are using closures to "protect variables" you're not protecting them from being modified by the returned functions that performed the closure. You just made it so that the variable is inaccessible from outside the scope of those functions. But, inside the scope, such as when you do your slice, the variable is there and accessible to that function and is not "protected" just because it is a closure.

Edit 2: If you are going to be copying the array frequently, you can eliminate some of the irritation of the iteration by creating a closured function to do the copying for you:

closure = function() {
    var secretVar = 'Secret';
    var clone = function(){
        var clonedArr = [];
        var length = secretVar.length;
        for(var i = 0; i < length; i++){
            clonedArr.push(secretVar[i]);
        }
        return clonedArr;
    }

    return {
        "msg" : function() {
            var duplicate = clone();
        }
    };
}();
挽清梦 2024-10-08 18:43:43

非常接近——形式为:

(function(y) {
    return function() {
        // that changes y
    };
})(secretVar)

注意:这仍然会传递引用,任何破坏性或改变操作仍然会影响secretVar。如果您想避免更改,则需要制作 secretVar 的深层副本。

请参阅:http://jsfiddle.net/B3ryr/2/

Very close -- the form is:

(function(y) {
    return function() {
        // that changes y
    };
})(secretVar)

NOTE: This will still pass a reference, and any destructive or altering operations will still affect secretVar. You'll need to make a deep copy of secretVar if you want to avoid altering it.

SEE: http://jsfiddle.net/B3ryr/2/

凡尘雨 2024-10-08 18:43:43

Robert 做了很好的评论,但也要注意 closure.del 不是一个函数,而是未定义的。再看看你的代码。该函数会自动执行并且不返回任何内容,因此 del 将不会返回任何内容。

var del = function(modMe) {
  modMe = secretVar;
  modMe.slice(1,1);
  console.log(modMe);
}(secretVar);

一般是这样的形式:

var a = function(b){
  console.log(b)
}('input');

console.log( typeof a ); // undefined
a(); // error: a is not a function

Robert made a good comment, but also note that closure.del is not a function, but undefined. Take another look at your code. The function is automatically executed and returns nothing, so del will be nothing.

var del = function(modMe) {
  modMe = secretVar;
  modMe.slice(1,1);
  console.log(modMe);
}(secretVar);

It's generally this form:

var a = function(b){
  console.log(b)
}('input');

console.log( typeof a ); // undefined
a(); // error: a is not a function
梦初启 2024-10-08 18:43:43

您的 function(modMe) { ... }(secretVar) 表达式实际上返回一个值而不是函数,因为您正在执行该函数。结合马特的答案,您需要:

  1. 从表达式中删除 (secretVar) 组件以及 modMe 参数 - 该函数已经可以访问 secretVar无论如何。
  2. 在处理数组之前实际复制该数组。请参阅马特的回答。

Your function(modMe) { ... }(secretVar) expression is actually returning a value and not a function, since you are executing the function. Coupled with Matt's answer, you need to:

  1. Remove the (secretVar) component from the expression as well as the modMe parameter -- the function already has access to secretVar anyway.
  2. Actually copy the array before working on it. See Matt's answer.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文