Javascript 函数封装

Javascript Function Encapsulation

本文关键字:封装 函数 Javascript      更新时间:2023-09-26

当我定义并调用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

  1. 你叫它太早了。
  2. 当您保存函数引用而不保存它附加到的对象时,这会被破坏。

溶液?

使用 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的行为,因此这可能也不是您想要的。