javascript 中使用instanceof需要注意的一点
javascript中的instanceof需要注意的一点:
当跨页面传送对象的时候,可能会返回和预期不一样的结果。instanceof的原理是查找实例化对象的__proto__是否在构造函数的原型链上,如果是则返回true,否则false。
来个示例:
// test.js文件
1 function test (){ 2 this.name = 'evan'; 3 }
// child.html
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8" /> 5 <title></title> 6 <script src="test.js"></script> 7 <script> 8 document.evalData = eval("({obj: new test})"); 9 document.data = "{obj: new test}"; 10 </script> 11 </head> 12 <body> 13 14 </body> 15 </html>
// parent.html
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8" /> 5 <title></title> 6 <script src="test.js"></script> 7 </head> 8 <body> 9 <iframe src="child.html" frameborder="0" id="iframe"></iframe> 10 <script> 11 window.onload = function(){ 12 var iframe = document.getElementById('iframe'); 13 var doc = iframe.contentWindow.document; 14 (function fn(){ 15 if( !doc ){ 16 setTimeout(fn, 0); 17 } else { 18 doc.data = eval('(' + doc.data + ')'); 19 20 console.log(doc.evalData.obj instanceof test); 21 console.log(doc.data.obj instanceof test); 22 } 23 })(); 24 } 25 </script> 26 </body> 27 </html>
console.log(doc.evalData.obj instanceof test); 结果是false
其实从逻辑上一看它本身就是不应该这样做的,doc.evalData的数据已经在child页面中使用eval转换成javascript代码了,所以new test是在child页面的运行环境下运行的。
而parent页面引用了这个对象,然后用instanceof来检测是否是当前parent的运行环境中的test构造函数的实例化对象,两个独立运行环境执行的代码怎么可能相同呢。
console.log(doc.data.obj instanceof test); 结果是true
它实例化data的数据是在当前页面实现的,即
doc.data = eval('(' + doc.data + ')');
而其中 new test引用的是当前执行环境(parent页面)中的test构造函数,所以这是合理的。
每一个页面都会创建一个新的执行环境,iframe也不例外。
浏览器在执行script的时候会把所有脚本都装载到一个全局环境中,所以这里的test构造函数在script执行时会装载到当前全局环境中。
所以当前全局环境中构造函数的原型链上不可能有另一个全局环境中对象的__proto__
随笔记录,不对的地方请园子里的大神多多指正