前些天写js遇到了一个instanceof的坑,咱们的页面中有一个iframe,我在index页面中计算获得了一个array,而后须要传递到Flight页面javascript
这个嵌套的iframe中的一个函数(SearchFlight)中,做为防护性编程,我须要在SearchFlight函数中进行参数检测,也就是判断过来的参数一html
定是Array类型。java
一:抛出问题编程
举个例子,下面有两个页面。数组
Index.html页面函数
1 <!DOCTYPE html> 2 <html xmlns="http://www.w3.org/1999/xhtml"> 3 <head> 4 <title></title> 5 </head> 6 <body> 7 8 <iframe name="childframe" src="Flight.html"></iframe> 9 10 <script type="text/javascript"> 11 12 window.onload = function () { 13 //航班 14 var airplanes = ["MU", "CA", "CZ"]; 15 16 var result = window.frames[0].flight.SearchFlight(airplanes); 17 }; 18 </script> 19 </body> 20 </html>
Flight.html页面spa
1 <!DOCTYPE html> 2 <html xmlns="http://www.w3.org/1999/xhtml"> 3 <head> 4 <title></title> 5 </head> 6 <body> 7 <script type="text/javascript"> 8 9 var flight = (function () { 10 11 return { 12 SearchFlight: function (arr) { 13 var result = arr instanceof Array; 14 alert(result); 15 } 16 }; 17 })(); 18 </script> 19 </body> 20 </html>
很惊讶的发现instanceof竟然不能判断出arr是一个数组,其实咱们用肉眼能够看到,压根它就是一个数组,可是为何instanceof却判断不出来呢?prototype
咱们知道instancof实际上是一个js语法糖,我就修改为简单点的,判断arr.constructor是否指向Array,因而我把关键字改为以下形式,再来看看看效果。3d
1 var flight = (function () { 2 3 return { 4 SearchFlight: function (arr) { 5 //var result = arr instanceof Array; 6 7 var result = arr.constructor == Array; 8 9 alert(result); 10 } 11 }; 12 })();
从图上看,还真有点奇怪,明明都是function Array(),为啥都不能相等呢?不过事实就摆在眼前,容不得狡辩,只能静下心来想想,咱们code
知道Array在js是属于引用类型,既然不相等那就说明他们实际上是两个引用,对不对,而且Array是挂在window下的一个属性,window属性
也就是一个窗口的实例,那就说明Index.html是一个window实例,Flight.html也是一个window实例,为了验证下,咱们看看两个window
是否相等?
看完图后,答案就很明白了,以C#的思惟考虑一下,既然大的window都不相等,里面的Array属性天然就不相等,终于问题是找到了,下面
怎么解决呢?
二:解决问题
1. length判断
这个很容易想到,也是最简单的,咱们知道每一个数组都有length,因此能够简简单单的看length是否存在就能够了,可是这个也不是万无一失
的,咱们知道function中有两个属性length和prototype,那这就有问题了。这样我会错误的把f认为是数组。
2.使用prototype的call方法来实现
这个方法有点巧妙,首先咱们要知道,每个function中都会有call方法和prototype属性,而js在Object.prototype中的tostring函数上作了一个
封装,就是调用tostring.call后,会返回[object constructorName]的字符串格式,这里的constructorName就是call参数的函数名,好比咱们把
arr传进去,就会返回“[object Array]”字符串格式,这个方法也可让咱们巧妙的判断是不是Array,可是比较遗憾的是,咱们看不到这个call的内
部实现,只能黑盒的记住了。