javascript setInterval和setTimeout的this问题
来源:互联网 发布:王诺诺 知乎 编辑:程序博客网 时间:2024/06/06 08:15
The "this
" problem
如果你通过setTimeout函数(或其他函数,或其他情况),调用的时候this的值可能并不能像你期待的那样。这种情况已经在Javascript reference里面详细的介绍过了。
说明
setTimeout()函数里执行的代码是与调用setTimeout函数的执行上下文分开的。正常的方法是为被调用的函数设置this的关键字,而如果你没有为该函数设置call或者bind的话,在不严格模式下会默认this为全局变量(也可以是window)。所以调用setTimeout的时候的this值可能不同。
Note:即使在严格模式下,setTimeout回调的默认值仍然是window对象,而不是undefined。
来看看下面的例子:
myArray = ['zero', 'one', 'two'];myArray.myMethod = function (sProperty) { alert(arguments.length > 0 ? this[sProperty] : this);};myArray.myMethod(); // prints "zero,one,two"myArray.myMethod(1); // prints "one"
以上的结果是因为当myMethod被调用的时候,它的this值被设置为myArray,所以在该函数里,this[sProperty]等于myArray[sProperty]。
然而,再看看下面:
setTimeout(myArray.myMethod, 1000); // prints "[object Window]" after 1 secondsetTimeout(myArray.myMethod, 1500, '1'); // prints "undefined" after 1.5 seconds
myArray.myMethod函数通过setTimeout来调用,这样当它被调用的时候,它的this值就没有设置,所以是默认值windwo对象。还有,如果没有选择将this参数传递给setTimeout,就像在forEach,reduce等数组函数中一样,如下所示,使用call来设置this变量是不起作用。setTimeout.call(myArray, myArray.myMethod, 2000); // error: "NS_ERROR_XPC_BAD_OP_ON_WN_PROTO: Illegal operation on WrappedNative prototype object"setTimeout.call(myArray, myArray.myMethod, 2500, 2); // same error
解决方法
一般的解决这种问题的方法是包装函数,将this设置为需要的值:
setTimeout(function(){myArray.myMethod()}, 2000); // prints "zero,one,two" after 2 secondssetTimeout(function(){myArray.myMethod('1')}, 2500); // prints "one" after 2.5 seconds
箭头函数也是一个可能的选择:setTimeout(() => {myArray.myMethod()}, 2000); // prints "zero,one,two" after 2 secondssetTimeout(() => {myArray.myMethod('1')}, 2500); // prints "one" after 2.5 seconds
另一种解决"this"问题的方法是将原本的setTimeout()和setInterval()替换为允许传递this对象和通过使用Function.prototype.call设置this在回调函数中,例如:
// Enable setting 'this' in JavaScript timers var __nativeST__ = window.setTimeout, __nativeSI__ = window.setInterval; window.setTimeout = function (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */) { var oThis = this, aArgs = Array.prototype.slice.call(arguments, 2); return __nativeST__(vCallback instanceof Function ? function () { vCallback.apply(oThis, aArgs); } : vCallback, nDelay);}; window.setInterval = function (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */) { var oThis = this, aArgs = Array.prototype.slice.call(arguments, 2); return __nativeSI__(vCallback instanceof Function ? function () { vCallback.apply(oThis, aArgs); } : vCallback, nDelay);};
Note:这两个替换方案也可以使HTML5标准的任意参数能通过IE的定时器的回调函数。所以它们也被用来作profills 。
有关profill,大家可以自行查阅。
替换setInterval和setTimeout后的新功能的测试:
myArray = ['zero', 'one', 'two'];myArray.myMethod = function (sProperty) { alert(arguments.length > 0 ? this[sProperty] : this);};setTimeout(alert, 1500, 'Hello world!'); // the standard use of setTimeout and setInterval is preserved, but...setTimeout.call(myArray, myArray.myMethod, 2000); // prints "zero,one,two" after 2 secondssetTimeout.call(myArray, myArray.myMethod, 2500, 2); // prints "two" after 2.5 seconds
Note:Javascript 1.8.5 引入了Function.prototype.bind()函数来为给定函数设置this值。这样可以避免使用包装函数为设置回调中的值。使用bind()的例子:
myArray = ['zero', 'one', 'two'];myBoundMethod = (function (sProperty) { console.log(arguments.length > 0 ? this[sProperty] : this);}).bind(myArray);myBoundMethod(); // prints "zero,one,two" because 'this' is bound to myArray in the functionmyBoundMethod(1); // prints "one"setTimeout(myBoundMethod, 1000); // still prints "zero,one,two" after 1 second because of the bindingsetTimeout(myBoundMethod, 1500, "1"); // prints "one" after 1.5 seconds
翻译资料:https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout中的 The "this" problem 选段。 - javascript setInterval和setTimeout的this问题
- Javascript对象中关于setTimeout和setInterval的this介绍
- setInterval和setTimeout函数中This的指向问题
- javascript 的setTimeout 和 setInterval
- setInterval和setTImeout中的this指向问题
- javascript setTimeout 和 setInterval
- javascript setTimeout 和 setInterval
- javascript setTimeout和setInterval
- setInterval和setTimeout ----javascript
- javascript中setTimeout 和setInterval的区别
- javascript中setTimeOut 和setInterval的区别
- JavaScript中setTimeout和setInterval的使用
- javascript 中的 setTimeout和setInterval的使用
- javascript中setTimeout 和setInterval的区别
- javascript中setTimeout 和 setInterval 的区别
- javascript中setTimeout和setInterval的使用
- Javascript的setTimeOut和setInterval用法
- Javascript的setTimeOut和setInterval用法
- [转]关于javascript中apply()和call()方法的区别
- centos 6 安装 mysql
- 超简单的listview加载数据
- git上传,现有仓库克隆功能
- Mac启动磁盘不能被分区或恢复成单个分区
- javascript setInterval和setTimeout的this问题
- 关于0x80000000为什么等于-2147483648和负数在内存上储存的问题
- java b2b b2c o2o全渠道云平台
- HLOCAL初探
- list.h内核链表是如何定义和操作的呢
- Java基础之IO流知识点总结二
- 双击uppaal图标打不开
- Java常用日志框架介绍
- 事件