zoukankan      html  css  js  c++  java
  • javascript 为啥不用instanceof检测数组,这里有一个示例坑

    前些天写js遇到了一个instanceof的坑,我们的页面中有一个iframe,我在index页面中计算得到了一个array,然后需要传递到Flight页面

    这个嵌套的iframe中的一个函数(SearchFlight)中,作为防御性编程,我需要在SearchFlight函数中进行参数检测,也就是判断过来的参数一

    定是Array类型。

    一:抛出问题

    举个例子,下面有两个页面。

    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页面

    复制代码
     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却判断不出来呢?

    我们知道instancof其实是一个js语法糖,我就修改成简单点的,判断arr.constructor是否指向Array,于是我把关键字改成如下形式,再来看看看效果。

    复制代码
     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(),为啥都不能相等呢?不过事实就摆在眼前,容不得狡辩,只能静下心来想一想,我们

    知道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的内

    部实现,只能黑盒的记住了。

     

  • 相关阅读:
    【第40套模拟题】【noip2011_mayan】解题报告【map】【数论】【dfs】
    【模拟题(63550802...)】解题报告【贪心】【拓扑排序】【找规律】【树相关】
    【模拟题(电子科大MaxKU)】解题报告【树形问题】【矩阵乘法】【快速幂】【数论】
    IMemoryBufferReference and IMemoryBufferByteAccess
    SoftwareBitmap and BitmapEncoder in Windows.Graphics.Imaging Namespace
    Windows UPnP APIs
    编译Android技术总结
    Windows函数转发器
    Two Ways in Delphi to Get IP Address on Android
    Delphi Call getifaddrs and freeifaddrs on Android
  • 原文地址:https://www.cnblogs.com/laiqun/p/5645801.html
Copyright © 2011-2022 走看看