如何保存javascript "this"单例模式中的上下文

How to preserve javascript "this" context inside singleton pattern?

本文关键字:quot 单例模式 this 上下文 何保存 保存 javascript      更新时间:2023-09-26

我有一个类似的东西:

var a = (function () {
    return {
        b: 1,
        c: function () {
            console.log(this.b);
        }
    };
})();

a.c(); // = 1

但是如果我做了

b = 2;
a.c.apply(this); // = 2

是否有可能在"a.c()"中保留"this"的上下文而不改变(太多)"a"对象的结构?我无法控制函数的调用,所以我需要在对象本身内部处理这个问题。

:

更具体地说,这是我的文件的结构:

结构1(类单例模式):

var a = (function () {
    var _instance;
    function init() {
        return {
            b: 1,
            c: function () {
                console.log(this.b);
            }
        };
    }
    return {
        getInstance: function () {
            if (_instance === undefined) {
                _instance = init();
            }
            return _instance;
        }
    }
})();

结构2:

var b = {
    c: 1,
    d: function () {
        console.log(this.c);
    }
};
<<p> 解决方案/strong>:

我已经基于Mahout的答案实现了一个解决方案,在init()中拆分返回语句,因此在任何情况下对对象上下文(和实例)都是安全的。

对于单例模式:

var a = (function () {
    var _instance,
        self;
    function init() {
        return self = {
            b: 1,
            c: function () {
                console.log(self.b);
            }
        };
    }
    return {
        getInstance: function () {
            if (_instance === undefined) {
                _instance = init();
            }
            return _instance;
        }
    };
})();

对于对象字面量:

var b = (function () {
    var self;
    return self = {
        c: 1,
        d: function () {
            console.log(self.c);
        }
    };
})();

a.getInstance().c(); // 1
a.getInstance().c.apply(this); // 1
setTimeout(a.getInstance().c, 1); // 1
$.ajax({ complete: a.getInstance().c }); // 1

您可以稍微改变一下从匿名函数返回对象的方式:

var a = (function () {
   var result = {};
   result.b = 2;
   result.c = function() {
     console.log(result.b);
   };
   return result;
})();

这应该具有相同的效果,但是它确实删除了this的使用。

如果你不能改变a的结构这么多,那么你可以(更)危险地使用:

a.c.apply = function() { // Stops the apply function working on a.c by overriding it
    return a.c();
}

如果你选择这个,虽然你必须小心,任何时候a.c.apply使用它将不再工作'如预期' -它将解决这里提出的问题,尽管

我制作了这支笔来说明两者的区别,希望对大家有所帮助:

http://codepen.io/dieggger/pen/BNgjBa?编辑= 001

var a = (function () {
    return { b: 1,
             c: function () {
              console.log(this.b);
            }
    };
})();

a.c(); //prints 1

b = 2; // global variable "b" which is being hoisted BTW

// The following will act like this:
//it throws "cannot read property 'apply' from undefined" 
//though it prints "1" since the first part invokes the "c" function 
//inside of the"a" module which has the console.log
a.c().apply(this); 

//In this case "this" is the window object which has the variable "b"
a.c.apply(this); // it'll print 2

你可以这样做:

var a = (function ()
{
    return {
        b: 1,
        c: function ()
        {
            console.log(this.b);
        }
    }
})();
var decorator = function() { return a; };
var b = 2;
decorator.call(this).c(); // => 1

基本上看起来你想要绑定IIFE,并且而不是它返回的对象到外部作用域,以便嵌套返回的对象保留内部b的值。