🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
~~~ v; // v打印出为undefined var v = 1; // 如果没有这行定义,上面一行会报错 Uncaught ReferenceError: v is not defined(…) ~~~ 这是为什么呢? 定义在下面应该还没有生效啊,怎么感觉就像是提前定义了一样呢。 实际上js在解释执行代码时,代码就相当于被转换成这样了: ~~~ var v; // 只是申明了,所以下面v会打印出undefined v; var v = 1; ~~~ 这就是申明提前,在函数中也是如此。 ~~~ function foo() { console.log(a); var a = 1; console.log(a); } foo(); // 先打印出undefined后打印出1 ~~~ 其实受“申明提前”的作用,这段代码相当于: ~~~ function foo() { var a; console.log(a); var a = 1; console.log(a); } foo(); ~~~ >[info] 注意:在语句中申明提前会将声明提前到语句的最上面,在函数中申明会被你提前到函数的最顶部。 明白了吧。 * * * * * ### 由申明提前引发的BUG ```javascript // 全局的变量 viewport = document.querySelector("meta[name=viewport]"); console.log(viewport) // meta Element function scale () { console.log(viewport); // 意外吧,竟然是undefined if (viewport == null) { var viewport = metaEl = document.createElement('meta'); } else { viewport.content = str; } // 后面要用viewport,所以才想着即使没有viewport也要定义,哪成想到申明提前这么厉害啊 console.log(viewport.content); } ``` 奇怪了吧,viewport在全局环境中可以打印出来,在函数中就打印未定义了,按道理说,函数中应该能找到全局的变量啊。 其实都是提前申明惹的祸。 这里诡异奇葩的是,根本没执行到这儿来的地方,也会被拿出来提前申明,无语了吧。 所以问题找到了,优化代码逻辑,不要这么写就能避免这个坑了。 ```javascript // 全局的变量 viewport = document.querySelector("meta[name=viewport]"); console.log(viewport) // meta Element function scale () { console.log(viewport); // undefined if (viewport == null) { var metaEl = document.createElement('meta'); } else { viewport.content = str; } // 既然所有变量都会申明提前,那么即使没执行到metaEl定义部分也不会出错 var _viewport = viewport || metaEl; console.log(_viewport.content); } ``` * * * * * last update:2018-7-21 05:51:42