如何在单例模式中保留 javascript "this" 上下文?
How to preserve javascript "this" context inside singleton pattern?
我有类似的东西:
var a = (function () {
return {
b: 1,
c: function () {
console.log(this.b);
}
};
})();
所以,
a.c(); // = 1
但如果我这样做
b = 2;
a.c.apply(this); // = 2
是否可以在不改变(太多)"a" 对象的结构的情况下,在 "a.c()" 中保留 "this" 的上下文?我无法控制函数的调用,因此我需要一种解决方法来在对象本身内部处理此问题。
更新:
更具体地说,这是我的文件结构:
结构 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;
}
}
})();
结构二:
var b = {
c: 1,
d: function () {
console.log(this.c);
}
};
解决方案:
我已经根据 Mahout 的回答实现了一个解决方案,在 init() 中拆分 return 语句,因此在任何情况下它对对象上下文(和实例)都是安全的。
对于单例模式:
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 ()
{
return {
b: 1,
c: function ()
{
console.log(this.b);
}
}
})();
var decorator = function() { return a; };
var b = 2;
decorator.call(this).c(); // => 1
基本上看起来您想要绑定 IIFE,并且 而不是 它 returns 的对象到外部范围,以便嵌套返回的对象保留内部的价值 b
.
您可以稍微更改从匿名函数返回对象的方式:
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
它都将不再有效 'as expected' - 它会解决这里出现的问题。
我做了这支笔来说明差异,希望对您有所帮助:
http://codepen.io/dieggger/pen/BNgjBa?editors=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);
}
};
})();
所以,
a.c(); // = 1
但如果我这样做
b = 2;
a.c.apply(this); // = 2
是否可以在不改变(太多)"a" 对象的结构的情况下,在 "a.c()" 中保留 "this" 的上下文?我无法控制函数的调用,因此我需要一种解决方法来在对象本身内部处理此问题。
更新:
更具体地说,这是我的文件结构:
结构 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;
}
}
})();
结构二:
var b = {
c: 1,
d: function () {
console.log(this.c);
}
};
解决方案:
我已经根据 Mahout 的回答实现了一个解决方案,在 init() 中拆分 return 语句,因此在任何情况下它对对象上下文(和实例)都是安全的。
对于单例模式:
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 ()
{
return {
b: 1,
c: function ()
{
console.log(this.b);
}
}
})();
var decorator = function() { return a; };
var b = 2;
decorator.call(this).c(); // => 1
基本上看起来您想要绑定 IIFE,并且 而不是 它 returns 的对象到外部范围,以便嵌套返回的对象保留内部的价值 b
.
您可以稍微更改从匿名函数返回对象的方式:
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
它都将不再有效 'as expected' - 它会解决这里出现的问题。
我做了这支笔来说明差异,希望对您有所帮助:
http://codepen.io/dieggger/pen/BNgjBa?editors=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