Javascript 函数封装
Javascript Function Encapsulation
当我定义并调用setTimeout
函数时,我得到了undefined undefined
,如下所示:
var person = {
first: 'joe',
last: 'doe',
getName: function(){
console.log(this.first + ' ' + this.last);
}
}
setTimeout(person.getName(), 2000);
除非我将person.getName()
包装在函数中,如下所示:
setTimeout(function(){
person.getName()
}, 2000);
现在我得到了正确的输出。为什么会这样?
假设你的意思是:
var person = {
first: 'joe',
last: 'doe',
getName: function(){
console.log(this.first + ' ' + this.last);
}
}
setTimeout(person.getName, 2000);
你被定义未定义的原因是你有效地做的是:
var somefunc = person.getName;
setTimeout(somefunc, 2000);
所以somefunc在window的上下文中被调用,即window.somefunc((
但是,当您这样做时
setTimeout(function(){
person.getName()
}, 2000);
getName 的上下文将保留,因为您正在调用(而不是传递(person.getName
我刚刚在这里回答了类似的事情:
如何将参数传递给 setTimeout(( 回调?
setTimeout 函数将上下文固定到窗口,因此无法执行您想要的操作!
为此,我将 setTimeout 函数包装在另一个可以设置上下文的函数中:
myNass_setTimeOut = function (fn , _time , params , ctxt ){
return setTimeout((function(_deepFunction ,_deepData, _deepCtxt){
var _deepResultFunction = function _deepResultFunction(){
//_deepFunction(_deepData);
_deepFunction.apply( _deepCtxt , _deepData);
};
return _deepResultFunction;
})(fn , params , ctxt)
, _time)
};
// lets try this functions :
for(var i=0; i<10; i++){
setTimeout(function(){console.log(i)} ,1000 ); // stock setTiemout in closure
}
for(var i=0; i<10; i++){
setTimeout( console.log(i) ,1000 ); // stock setTiemout direct call
}
for(var i=0; i<10; i++){
setTimeout(console.log ,1000 , i); // stock setTiemout not compatible IE
}
for(var i=0; i<10; i++){
myNass_setTimeOut(console.log ,1000 , [i] , console); // wrapped setTimeout
}
所以回答你的问题:
var person = {
first: 'joe',
last: 'doe',
getName: function(){
console.log(this.first + ' ' + this.last);
}
}
setTimeout(person.getName(), 2000);
当你启动时:setTimeout(person.getName(), 2000);
setTimeout将在未来2秒(2000ms(执行第一个参数!
但是你的第一个参数的值是什么?:你的函数 person.getName 的结果 ( )
,所以它相当于:
var _arg1 = person.getName();
setTimeout(_arg1 , 2000);
这与以下方面非常不同:
var _arg1 = person.getName;
setTimeout(_arg1 , 2000);
第一种情况是将函数的结果传递给 setTimeout,该 setTime 等待对函数的引用。在第二种情况下,您将引用传递给函数(这是预期的(,但不是在良好的上下文中!
所以,现在你必须修复上下文:核心JavaScript函数:应用
现在试试这个:
var _arg1 = function(){ person.getName.apply(person) };
setTimeout(_arg1 , 2000);
myNass_setTimeOut(person.getName , 2000 , null , person);
所以你有两个选择:
- 修复传递给 setTimeout 的每个参数的上下文。
- 使用为您完成的功能
myNass_setTimeOut功能将使您有所作为!
现在,让我们看一些更深入的东西:
var person = {
first: 'joe',
last: 'doe',
getName: function(){
console.log(this.first + ' ' + this.last);
} ,
say : function(sentence){
console.log(this.first + ' ' + this.last + ' say : ' + sentence)
}
}
如何将参数句子传递给设置超时?
var heSay = "hello !"; setTimeout(person.say(heSay) , 1000 ); heSay = "goodBye !";
// not good : execute immediatly
var heSay = "hello !";setTimeout(function(){person.say(heSay)} , 1000 ); heSay = "goodBye !";
// not good : hesay googbye
var heSay = "hello !"; setTimeout(person.say , 1000 , heSay); heSay = "goodBye !";
// not good bad context
var heSay = "hello !"; setTimeout(function(whatHeSay){person.say(whatHeSay)} , 1000 , heSay);heSay = "goodBye !";
// GOOD ! ok but not compatible with IE
var heSay = "hello !"; myNass_setTimeOut(person.say , 1000 , [heSay] , person ); heSay = "goodBye !";
// just good !
希望这对您有所帮助!
编辑:
对于现代浏览器支持绑定,不要关心那个做什么说这里@dandavis
- 你叫它太早了。
- 当您保存函数引用而不保存它附加到的对象时,这会被破坏。
溶液?
使用 bind 并且不要提前调用它:
var person = {
first: 'joe',
last: 'doe',
getName: function(){
console.log(this.first + ' ' + this.last);
}
}
setTimeout(person.getName.bind(person), 2000);
var person = {
first: 'joe',
last: 'doe',
getName: function(){
console.log(this);
}
}
person.getName()
setTimeout(person.getName, 2000);
输出:
Object {first: "joe", last: "doe", getName: function}
Window {top: Window, window: Window, location: Location, external: Object, chrome: Object…}
我的猜测是,JavaScript 将 getName
函数拉出了person
您的第一个函数对我来说效果很好(在 Chrome 中测试(:
http://jsfiddle.net/fzrxK/1/
var person = {
first: 'joe',
last: 'doe',
getName: function(){
alert(this.first + ' ' + this.last);
}
}
setTimeout(person.getName(), 2000);
也许其他地方还有另一个问题?
调用person.getName()
执行函数并返回undefined
(因为该函数中没有声明要返回的任何内容(。
你想要的是:
setTimeout(person.getName, 2000);
调用 setTimeout(person.getName(), 2000);
会设置超时以执行person.getName()
返回的结果,undefined
而不是函数。
调用 setTimeout(person.getName, 2000);
会设置执行函数person.getName
的超时。
带括号执行函数。不带括号的变量(恰好被定义为函数(。
编辑:正如@Isaac指出的那样,将函数person.getName
传入也会改变this
的行为,因此这可能也不是您想要的。
- 在函数调用中封装数据除了隐藏数据之外还有什么优点
- 为什么封装的Javascript函数有如此巨大的性能差异
- Dijkstra's”;针对GOTO声明的案件“;与函数一样适用于现代调用代码的命名封装
- Javascript:正常函数的命名空间封装
- 为什么将函数引用封装到匿名函数中可以更正'这'指向
- 在封装的JavaScript函数中设置用于重用的私有变量
- 如何将 $http.put 封装到一个函数中,该函数执行某些操作,然后返回通过或失败的承诺
- 为什么我要在jQuery(function ($) { });中封装一个jQuery函数
- 将 chrome API 操作封装到函数中
- 用函数回调封装JavaScript
- 如何使用exports或module.exports将函数构造函数对象方法与原型封装在单个模块中
- 将D3函数封装在对象内部;不起作用.为什么?
- 我必须将$scope基元封装在对象中,但可以在不封装它们的情况下使用函数.为什么?
- 封装Javascript中Try-Catch块中的函数
- 事件处理程序调用Meteor中的封装异步函数
- 用更多的变量javascript封装单个变量回调函数
- 将函数封装在jQuery.removeClass()中是否安全
- 封装的API.对外部javascript函数的调用不工作
- 找不到封装在匿名函数中的递归函数调用
- 打破立即执行的匿名函数的封装