instanceof 在跨 frame 对象构建的场景下会失效

发布时间 2023-11-15 22:37:57作者: 龙陌

如何判断一个js对象是否是Array,arr为要判断的对象,下面最准确的方法是?

A
typeof(arr)

B
arr instanceof Array

C
arr.toString==='[object Array]';

D
Object.prototype.toString.call(arr) === '[object Array]';

正确答案:D

解析看这里:http://www.nowamagic.net/librarys/veda/detail/1250

简单概括下:

  typeof(arr) 返回的是 Object 

  instanceof 在跨 frame 对象构建的场景下会失效 

  arr.toString 没有这种用法,正确的用法是 arr.toString() 返回的是数组的内容

其实Array本身有isArray这个方法判断

判断一个对象是否属于数组,最好怎么做?

  1. typeof(arr),typeof返回的是基本数据类型及object,不会详细到array的,所以不行
  2. arr instanceof Array,这一点还不透彻,说的是在多iframe/window环境下,通过Instanceof来识别对象是否属于数组会出错
  3. arr.toString,直接使用toString函数自然是数组有什么就返回什么了,例如[1,2] => '1,2'
  4. Object.prototype.toString.call(arr) === '[object Array]';这才是正确的
            var obj={};
            console.log(obj.__proto__)
            var arr=[2,3];
            console.log(arr.toString());
            console.log(arr instanceof Array);//true
            
            console.log(Object.prototype.toString.call(arr));//数组对象有prototype
            //[object Array]
            function one(){
                console.log('函数实例对象有prototype?')
            }
            console.log(Object.prototype.toString.call(one));//[object Function]
            var child=new one();
            console.log(Object.prototype.toString.call(child));//[object Object]
            console.log(child.prototype);//undefined
            // 需要注意的是,_proto_属性是所有对象都有的,而prototype属性是只有函数才有的,实例对象没有!
            
            
            console.log(Object.__proto__)
            console.log(Object.prototype);
            console.log(Object.prototype.toString);//这就是一个函数!!
            
            //注意,上面之所以用Object.prototype.toString.call(child)有效
            //是因为Object.prototype.toString就是被调用的函数,相当于 child.函数
            // 所以这样的toString自然是没错的,因为不是像我之前想的那样改成child.prototype.toString

instanceof 操作符的问题在于,它假定只有一个全局执行环境。如果网页中包含多个【frame】框架,那实际上就存在两个以上不同的全局执行环境,从而存在两个以上不同版本的 Array 构造函数。

toString为Object的原型方法,而Array ,Function等类型作为Object的实例,都重写了toString方法。
不同的对象类型调用toString方法时,根据原型链的知识,调用的是对应的重写之后的toString方法(Function类型返回内容为函数体的字符串,Array类型返回元素组成的字符串.....),
而不会去调用Object上原型toString方法(返回对象的具体类型),所以采用obj.toString()不能得到其对象类型,只能将obj转换为字符串类型;
因此,在想要得到对象的具体类型时,应该调用Object上原型toString方法。