确保“安全”的最佳实践是什么;这";Javascript中的上下文?
下面是一个带有公共和私有方法(fiddle:)的简单Javascript类的示例确保“安全”的最佳实践是什么;这";Javascript中的上下文?,javascript,this,Javascript,This,下面是一个带有公共和私有方法(fiddle:)的简单Javascript类的示例 从公共函数调用私有函数会导致“this”成为窗口对象。如何确保使用类上下文而不是窗口调用我的私有方法?这是不可取的吗?我想最常用的方法是将this的值缓存(存储)在本地上下文变量中 function Example() { var that = this; // ... function privateFunction() { console.log(that); }
从公共函数调用私有函数会导致“this”成为窗口对象。如何确保使用类上下文而不是窗口调用我的私有方法?这是不可取的吗?我想最常用的方法是将
this
的值缓存(存储)在本地上下文变量中
function Example() {
var that = this;
// ...
function privateFunction() {
console.log(that);
}
this.publicFunction = function() {
privateFunction();
}
}
更方便的方法是调用Function.prototype.bind
将上下文绑定到函数(永远)。然而,这里唯一的限制是,这需要一个支持ES5的浏览器,并且绑定的功能稍微慢一点
var privateFunction = function() {
console.log(this);
}.bind(this);
使用闭包。基本上,函数中声明的任何变量都可用于该函数中的函数:
var Example = (function() {
function Example() {
var self = this; // variable in function Example
function privateFunction() {
// The variable self is available to this function even after Example returns.
console.log(self);
}
self.publicFunction = function() {
privateFunction();
}
}
return Example;
})();
ex = new Example;
ex.publicFunction();
如果您不使用ECMAScript 5,我建议您使用下划线(或LoDash)函数。除了这里给出的其他答案之外,如果您没有支持ES5的浏览器,您可以使用如下代码创建自己的“永久绑定函数”:
function boundFn(thisobj, fn) {
return function() {
fn.apply(thisobj, arguments);
};
}
然后像这样使用它:
var Example = (function() {
function Example() {
var privateFunction = boundFn(this, function() {
// "this" inside here is the same "this" that was passed to boundFn.
console.log(this);
});
this.publicFunction = function() {
privateFunction();
}
}
return Example;
}()); // I prefer this order of parentheses
var Example = (function() {
function Example() {
function privateFunction() {
// "this" is window when called.
console.log(this);
}
this.publicFunction = function() {
privateFunction.call(this);
}
}
return Example;
})();
ex = new Example;
ex.publicFunction();
瞧——这个
神奇地是外部上下文的这个
,而不是内部上下文
如果您的浏览器中缺少类似ES5的功能,您甚至可以获得类似ES5的功能(如果您已经拥有了它,则不会有任何作用):
然后使用var yourFunction=function(){}.bind(thisobj)代码>完全相同的方式
与ES5类似的完全兼容(尽可能)的代码,检查参数类型等,可以在中找到。如果您正在使用函数执行一些不同的高级操作,则可能会遇到一些差异,因此如果您想使用这些功能,请在链接中阅读这些差异。另一种方法是使用“应用”明确设置“this”应绑定的方法
function Test() {
this.name = 'test';
this.logName = function() {
console.log(this.name);
}
}
var foo = {name: 'foo'};
var test = new Test();
test.logName()
// => test
test.logName.apply(foo, null);
// => foo
另一种方法是使用“调用”:
“apply”和“call”都将要绑定“this”的对象作为第一个参数,并将一组参数作为第二个参数传递给正在调用的方法。除了让别人告诉您代码修复之外,还需要了解javascript中this
的值是如何确定的。在javascript中,此由以下方式确定:
object.method()
,则此
将设置为方法内的对象function()
)的情况下直接调用函数,则此
将设置为全局对象(浏览器中的窗口
),或在严格模式下,将其设置为未定义
new
运算符创建新对象,则将调用该对象的构造函数,并将this
的值设置为新创建的对象实例。您可以将其视为与上面的第1项相同,即创建对象,然后调用其上的构造函数方法.call()
或.apply()
调用函数,就像在函数.call(xxx)
中一样,那么您可以通过传递给.call()
或.apply()
的参数来准确确定此设置为什么。您可以阅读有关MDN的更多信息
function.bind(xxx)
这将创建一个小存根函数,确保使用所需的this
值调用函数。在内部,这可能只使用了.apply()
,但它是一个快捷方式,用于在调用单个回调函数时(当您不是该函数的直接调用方时),该函数将具有正确的this
值this
的所需值。例如,在事件处理程序回调函数中,浏览器通常将this
设置为处理事件的DOM对象privateFunction()
时,您正在进行一次正常的函数调用。因此,正如预期的那样,此
的值设置为上述选项2中的值
如果要在方法中将其明确设置为当前值this
,则可以这样做:
var Example = (function() {
function Example() {
var privateFunction = boundFn(this, function() {
// "this" inside here is the same "this" that was passed to boundFn.
console.log(this);
});
this.publicFunction = function() {
privateFunction();
}
}
return Example;
}()); // I prefer this order of parentheses
var Example = (function() {
function Example() {
function privateFunction() {
// "this" is window when called.
console.log(this);
}
this.publicFunction = function() {
privateFunction.call(this);
}
}
return Example;
})();
ex = new Example;
ex.publicFunction();
其他方法,如使用闭包和defined
var=this
最适合用于回调函数,因为您不是函数的调用方,因此不能使用1-4。在你的特殊情况下,没有理由这样做。我想说使用.call()
是一种更好的做法。然后,您的函数实际上可以使用这个
,并且可以像私有方法一样运行,这似乎就是您所寻求的行为。我想说,将自身
分配给这个
是一种常见的技术:
function Example() {
var self = this;
function privateFunction() {
console.log(self);
}
self.publicFunction = function() {
privateFunction();
};
}
使用apply
(正如其他人所建议的)也可以,尽管在我看来有点复杂
这可能超出了这个问题的范围,但我也建议您考虑一种不同的JavaScript方法,您实际上根本不使用
this
关键字。我在ThoughtWorks的前同事皮特·霍奇森(Pete Hodgson)写道,他解释了一种方法。我认为正确的方法是使用原型,因为它毕竟是Javascript的设计方式。因此:
var Example = function(){
this.prop = 'whatever';
}
Example.prototype.fn_1 = function(){
console.log(this.prop);
return this
}
Example.prototype.fn_2 = function(){
this.prop = 'not whatever';
return this
}
var e = new Example();
e.fn_1() //whatever
e.fn_2().fn_1() //not whatever
这里有一个小把戏可以在这里找到管理
此
范围的小技巧:另一个解决方案:与此
问题无关,您不能从内部函数示例()
周围移除立即调用的匿名函数包装器吗?在我看来,如果您只声明function Example()
di,您会得到相同的结果
var Example = function(){
this.prop = 'whatever';
}
Example.prototype.fn_1 = function(){
console.log(this.prop);
return this
}
Example.prototype.fn_2 = function(){
this.prop = 'not whatever';
return this
}
var e = new Example();
e.fn_1() //whatever
e.fn_2().fn_1() //not whatever