<!DOCTYPE html>
<html>
  <head>
   <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
   <style type="text/css">
      html { height: 100% }
      body { height: 100%; margin: 0; padding: 0 }
     
    </style>
    <script type="text/javascript"
      src="http://maps.googleapis.com/maps/api/js?key=AIzaSyD3dfd2O_9xqsqnfasdfKzJ3q2kdfggreQuVNM&sensor=true">
    </script>
    <script type="text/javascript">
     function importScript() {
      var mapScript = document.createElement("Script");
    mapScript.src = "http://maps.googleapis.com/maps/api/js?key=AIzaSyD3dfd2O_9xqsqnfasdfKzJ3q2kdfggreQuVNM&sensor=true";
    mapScript.id = "mapScript";
    document.getElementsByTagName("head")[0].appendChild(mapScript);
     }
      function initialize() {
        var mapOptions = {
          center: new google.maps.LatLng(-34.397, 150.644),
          zoom: 8,
          mapTypeId: google.maps.MapTypeId.ROADMAP
        };
        var map = new google.maps.Map(document.getElementById("map"),
            mapOptions);
      }
    </script>
  </head>
  <body onload="/*importScript();*/initialize();">
    <div id="map" style="width:100%; height:100%"></div>
  </body>
</html>如果采取importScript()方式则出错,而直接<script type="text/javascript"
      src="http://maps.googleapis.com/maps/api/js?key=AIzaSyD3dfd2O_9xqsqnfasdfKzJ3q2kdfggreQuVNM&sensor=true">
    </script>引用则可以,为什么??通过chrome跟踪发现在 new google.maps.LatLng(-34.397, 150.644),这里出错,google.maps为object,而google.maps.LatLng为null,Why?
也就是动态载入成功了,因为google.maps不为null,但是为什么google.maps.LatLng为null??
求大神赐教!!

解决方案 »

  1.   

    key=AIzaSyD3dfd2O_9xqsqnfasdfKzJ3q2kdfggreQuVNM
    已经被混淆过,请使用自己的google api id替换测试,谢谢。
      

  2.   

    看你 的importScript()功能,
    1 创建了一个 script
    2 并指定了 src。注意,在给 script 指定 src 到 src 中的内容加载完毕,是有一个时间间隔的所以,在 src 里的内容没加载完成前,你调用了 src 中的一个函数,就会发生一个函数未定义exception
      

  3.   

    至于这个间隔是多久,你要研究 javascript 的浏览器解释原理,可理解为 单线程+消息队列。
    太复杂了,不解释太深,等会发代码教你解决方案
      

  4.   

    <head>
    <script>
    //追加事件,当加载完成后,调用回调函数
    function bindEventLoaded(mapScript, callback){
    if(mapScript.addEventListener)              //火狐 谷歌 Opera
    {
    mapScript.addEventListener("load",
    function(){
    callback();
    }, 
    false
    );
    }
    else if(mapScript.attachEvent)              //IE
    {
    mapScript.attachEvent("onreadystatechange", 
    function(Dom){
    if(Dom.srcElement.readyState=="loaded" || Dom.srcElement.readyState=="complete"){
    callback();
    }
    }
    );
    }
    }
    function createScript(){
    var mapScript = document.createElement("Script");
    bindEventLoaded(mapScript, function(){alert(google.maps);});//当 script 标签加载完 src 中的内容后,再调用里面存在的函数
    mapScript.src = "http://maps.googleapis.com/maps/api/js?key=AIzaSyD3dfd2O_9xqsqnfasdfKzJ3q2kdfggreQuVNM&sensor=true";
    mapScript.id = "mapScript";
    document.getElementsByTagName("head")[0].appendChild(mapScript);
    alert(google.maps); //这里是不能调用的,这里调用时,可能 src 还没加载完
    }
    </script>
    </head>
    <body onload="createScript()">
    </body>
      

  5.   

    你好,首先感谢你的帮助,我也考虑是没有加载完的原因,但是Google.maps是有值,可以通过chrome查看,但是google.map.lanlng为null,这个是我想不通的地方,周末在家使用ipad回复十分不便,描述可能不是很清楚,敬请谅解。
      

  6.   

    等到周一有台式机再好好请教您,再次感谢。据我理解,通过插入script元素方式虽然是动态,但是并非异步,应该src文件加载完成之后才继续执行init的方法。
      

  7.   

    (function(){
       if(google && google.maps && google.maps.LatLng){
           initialize();
       }else{
           setTimeout(arguments.callee);
       }
    })();
      

  8.   

    感谢你,请问这段代码是否实现的是循环调用当前匿名方法,直到initialize();成功?
      

  9.   

    function getMyLocation() {    
        if(window.navigator) {   
             if(google && google.maps && google.maps.LatLng){
                navigator.geolocation.getCurrentPosition(displayLocation , displayError,options);
               
            }else{
                setTimeout(getMyLocation);
                return;
            }
    }不论执行多少次,始终不能得到google.maps.LanLng的值,LanLng是一个构造函数,这个会因为构造函数有影响么?
      

  10.   

    因为我看你代码 是异步加载了一个 js文件
    然后直接调用 该js文件中的相关属性 这个时候js文件还没加载完毕(肯定的)所以 一般可以在js dom的加载回调事件中 执行你的代码 不过这个又牵涉到 浏览器的兼容性所以我现在一般 写的 反复循环的 代码 
    当有 某个对象
         存在 则调用相关代码
         不存在 则继续调用循环代码
      

  11.   

    @KK3K2005 :直接调用 该js文件中的相关属性 这个时候js文件还没加载完毕(肯定的)
    这个为什么是肯定的???实验下来应该是这样子的,不过想从理论上讨论一下。
    按照道理来说http同时有2个线程访问资源,而javascript是单线程执行,我通过动态script加载js时候,加载过程中使用的是http的线程还是javascript执行线程?一般来说加载js过程会锁住dom的加载及执行,那么也就是应该加载完成才能继续执行后面的方法了吧。
    所以很多js引用必须强调顺序,后面的用到js库里面方法的函数,必须在的<script src=xx.js>标签后面,来保证xx.js加载完成,动态加载script不能保证这个顺序么?
    比如
    var mapScript = document.createElement("Script");      
            mapScript.src = "http://maps.googleapis.com/maps/api/js?key=AIzaSyD3dfd2O_9xqsqnfasdfKzJ3q2kdfggreQuVNM&sensor=true";
            mapScript.id = "mapScript";
            document.getElementsByTagName("head")[0].appendChild(mapScript);
            alert(google.maps); //这里是不能调用的,这里调用时,可能 src 还没加载完??
                                //我的理解是这个肯定可以调用了但是javascript还有一点是根据<script>标签分段加载,难道是这个的影响??
    我的理解与实际不符,但是我又不知道正确的理解方式,希望大家能够指正,非常感谢。
      

  12.   

    <script src="xxx"></script> 如果是写在页面中的,那么就是非异步
    如果使用 document.createElement("Script"); 就是异步的,你的理解错了,所以总也想不通
      

  13.   

    关于这个异步问题,你自己最好写个例子测试一下,以前我遇到这个问题的时候也很费解,不要用 setTimeout,因为你永远不知道对方的服务器网络质量有多好(差)
      

  14.   

    在 DOM对象 script 上追加 load 事件的监听是最正统的解决方案,这个已经经过项目的验证证实了的
      

  15.   

    首先感谢 @clark_kidd 、@KK3K2005  两位的帮助。
    function getMyLocation() {    
        if(window.navigator) {   
             if(google && google.maps && google.maps.LatLng){
                navigator.geolocation.getCurrentPosition(displayLocation , displayError,options);
               
            }else{
                setTimeout(getMyLocation);
                return;
            }
    }function initialize() {
       var mapScript = document.createElement("Script");
        bindEventLoaded(mapScript, getMyLocation);//当 script 标签加载完 src 中的内容后,再调用里面存在的函数
        mapScript.src = "http://maps.google.com/maps/api/js?sensor=true";
        mapScript.id = "mapScript";
        document.getElementsByTagName("head")[0].appendChild(mapScript);    
    }
    window.onload = initialize;结合使用了@clark_kidd 、@KK3K2005 两位的做法,但是仍然有问题,即
    Google.maps是有值,但是google.map.LanLng为undefined。
    chorme截图如下:估计这个已经不是加载顺序问题了,不论执行多少次,始终不能得到google.maps.LanLng的值,LanLng是一个构造函数,这个会因为构造函数有影响么?
      

  16.   

    你是不是笔误了?
    google.map.LatLng
      

  17.   

    你是不是笔误了?我也笔误了……
    google.maps.LatLng
      

  18.   

    @clark_kidd 谢谢,
    google.maps.LatLng
    没有笔误,我重新看了一下,上面是我从代码复制回来的。
    google.maps.LatLng,这里是复制的。
      

  19.   


    找到原因了http://maps.google.com/maps/api/js?sensor=true 这个js打开后,发现有这么一段代码function getScript(src) {
        document.write('<' + 'script src="' + src + '"' +
                       ' type="text/javascript"><' + '/script>');
      }
    //之后的调用
    getScript("http://maps.gstatic.com/intl/zh_cn/mapfiles/api-3/12/8/main.js");
    document.write,居然是 document.write!!document.write 有一个特性,那就是:
    页面没有加载完时,会在当前代码位置 write
    页面加载完后,再调用,会把 body 中的内容清空在 write所以,<script src="http://maps.google.com/maps/api/js?sensor=true"></script> 时,是正常的,而 window.onload 后发生的事,符合了页面加载完成这一条件,document中的东西都被清理了……其中包括 getScript("http://maps.gstatic.com/intl/zh_cn/mapfiles/api-3/12/8/main.js");输出的标签……,所以自然就没有 LatLng 了……
      

  20.   

    我们来做个实验
    <script>
    document.write("这里输出是正常的");
    </script>
    位置正常
    </head>
    <body>
    <input type="button" value="document.write after loaded" onclick="document.write('清空了,居然清空了……')">
    </body>
      

  21.   

    给你一个令人郁闷的结论
    要不,google改api
    要不,你只有写死 <script></script> 一条路……
      

  22.   

    @clark_kidd
    总算找到原因了,我太过相信google的api了,所以压根没有从这方面想,太感谢你了,终于得出结论了。哈哈哈,大笑三声。
    也感谢 @KK3K2005, 通过这个问题回顾了很多知识。