JavaScript预解析及相关技巧分析


Posted in Javascript onApril 21, 2016

本文实例讲述了JavaScript预解析及相关技巧。分享给大家供大家参考,具体如下:

变量

同样,以这两个小例子的错误对比提示开始。

alert(y1);     //代码段1
var y1 = 'dddd';
alert(y2);     //代码段2 // alert(typeof y2);
y2 = 'xxxxx';

先思考一下,为什么一个会提示 undefined , 一个却抛出变量未定义的错。。先看JavaScript的解析过程。

javascript在执行过程之前,会做一件事件“预解析”。解析引擎会以块为单位级别,执行所有 var 变量的创建,并赐予它们一个初始值:undefined。这样一来,第一个例子为什么会弹出undefined的原因就显而易见了。

所以第一段代码其实就等价于

var y1;
alert(typeof y1); //很自然,它此时值为undefined
y1 = 'dddd';

那第二段代码为什么又抛错呢,此时就不再属于“预解析”阶段了,(在这里我假设浏览器遇到一个script标签时只做两件事:预解析和执行,其实不 只这两件事情),而处于执行阶段,抛错原因在于js在执行段状态并不知晓y2的状态(预解析阶段没有捕获到y2的任何信息),当然就抛出未定义的错误信 息。这里又牵扯到另一个问题: js 是弱类型语言,变量不定义可以用,那为什么这里又抛出为定义错误呢。

事出总有因,javascript总有很多自身奇怪的特性,有一个叫变量的读写不均等。未定义的变量,仅仅是可写,并不可读。何为可写,每个人都熟悉这样的写法:

y2 = 'exam';  
//在没出现它的定义操作之前(即在它还没有自己的scope之前)该操作会将这段代码认为是定义一个全局变量,在window上注册一个属性y2,并赋值为exam

但在对它的读操作,js引擎搜寻不到它的任何相关信息,就以自己的脾气行事,毫不客气抛一个未定义的错,这是js的游戏规则。还有但是,那为什么却 可以获取它的类型呢。还记得 js对对象的操作吧。如果访问对象一个不存在的属性及类型,会提示undefined, (因为它当前是window对象的一个属性)。

再注:这里需要区分, 变量的读写不均等 仅用于变量,读取所有对象的属性,不存在该特性,如果不存在,会提示undefined。

结论

到这里,我的思考结果: 对于变量和对象的写操作,他们有一定的类似之处.但是读操作,各有各的一套规则,正因为此,所以有了上面的问题。
这样一来,下面这个题应该就很容易得到答案了吧。

if (!('a' in window)) {
  var a = 1;
}
alert(a);

函数

引申一下,function. 还记得上面提到的预解析,在javascript的预解析中,除了对var 变量的预定义,还包括了提取对函数的定义,所以可以在script的任何地方定义函数,在任何地方调用。不限于它之前.

但函数的定义方式,包括了一种叫字面量定义法, 用var的方法声明function.看下面

alert(typeof y3); //结果?
var y3 = function (){ console.log('1'); }

还记得这个约定吧:调用必须出现在声明之后,为什么呢,如果理解了上面,其实这里答案已经明了。javascript 引擎在预解析 var 时 会给他们一个初始值 undefined,这样一来,如果我们在它的声明之前调用它,javascript 引擎还没拿到它的真实值,自然会报"xxx is not a function" 的错.这也理清了为什么同为函数声明,一个却关系到声明和调用的顺序,一个却无这样的约束。

结论

它是函数,是js执行,动态修改的结果,依然遵循了变量的预解析规则(在上面alert的时候,它还并没有拿到字面量函数的信息)。
如果是两个混合呢。看下面, 同时存在了为y4的变量和function。

alert(typeof y4); //结果?
function y4(){
  console.log('y4')
}
var y4;

因为 javascript 在预解析时function的声明优先级高的缘故,所以y4自然为function类型, 但是在当y4 赋值之后(此时js引擎处于执行过程中),它对js的赋值操作将会覆盖function的声明。所以:

alert(typeof y5);
var y5 = 'angle';
function y5(){
  console.log('ghost');  
}
alert(y5);

第一次alert结果,因为它处于js 执行过程中的顶端,所以为 function。 第二次再alert时, 它的值已经被重写为5(不要被function的定义位置在下所迷惑。)

从js的解析和执行分开来想,才发现眼前豁然开朗,很多问题的答案都很自然得浮出水面,正如那篇文章作者所说,"一旦理解了执行环境、调用对象、闭包、词法作用域、作用域链这些概念,JS语言的很多现象都能迎刃而解。"

现在再看,即使在这个存在着很多不可思议的语言中,也有很多可以追溯到它的缘由。

如何更好的做参数判断

讨论了上面那么多,那如何让它更贴近于实际开发呢,既然javascript的读写不均等性,如何才能避免在不报错的情况下做参数判断呢。

eg:

if(cusVar){ //这里的判断,是不是存在隐含的问题呢。 }

如何严谨一些呢。

if(window['cusVar']) { //保证它不报错。
  //或者这样的判断也是可行的 window.cusVar | typeof cusVar !== 'undefined'
  //干活咯
}

最后补充又一个小quiz, (理解 预解析与执行的分离)

var y7 = 'test';
function fun1(){
  alert(y7);
  var y7 = 'sex';
}
fun1();

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
AutoSave/自动存储功能实现
Mar 24 Javascript
精选的10款用于构建良好易用性网站的jQuery插件
Jan 23 Javascript
jquery 追加tr和删除tr示例代码
Sep 12 Javascript
浏览器的JavaScript引擎的识别方法
Oct 20 Javascript
如何从jQuery的ajax请求中删除X-Requested-With
Dec 11 Javascript
JS中怎样判断undefined(比较不错的方法)
Mar 27 Javascript
页面刷新时记住滚动条的位置jquery代码
Jun 17 Javascript
javascript常用正则表达式汇总
Jul 31 Javascript
jquery实现先淡出再折叠收起的动画效果
Aug 07 Javascript
JS中使用FormData上传文件、图片的方法
Aug 07 Javascript
从源码里了解vue中的nextTick的使用
Nov 22 Javascript
vue 实现LED数字时钟效果(开箱即用)
Dec 08 Javascript
JavaScript实现显示函数调用堆栈的方法
Apr 21 #Javascript
JS实现队列与堆栈的方法
Apr 21 #Javascript
JS、jQuery中select的用法详解
Apr 21 #Javascript
jQuery中iframe的操作(点击按钮新增窗口)
Apr 20 #Javascript
JS生成某个范围的随机数【四种情况详解】
Apr 20 #Javascript
浅析JS动态创建元素【两种方法】
Apr 20 #Javascript
纯JS代码实现一键分享功能
Apr 20 #Javascript
You might like
PHP类中Static方法效率测试代码
2010/10/17 PHP
PHP和javascript常用正则表达式及用法实例
2014/07/01 PHP
php实现插入数组但不影响原有顺序的方法
2015/03/27 PHP
PHP网络操作函数汇总
2015/05/18 PHP
thinkphp如何获取客户端IP
2015/11/03 PHP
PHP将URL转换成短网址的算法分享
2016/09/13 PHP
laravel5.5添加echarts实现画图功能的方法
2019/10/09 PHP
关于图片验证码设计的思考
2007/01/29 Javascript
javascript一点特殊用法
2008/05/28 Javascript
一款js和css代码压缩工具[附JAVA环境配置方法]
2010/04/16 Javascript
jquery控制背景音乐开关与自动播放提示音的方法
2015/02/06 Javascript
JS实现可自定义大小,可双击关闭的弹出层效果
2015/10/16 Javascript
jquery解析json格式数据的方法(对象、字符串)
2015/11/24 Javascript
js从输入框读取内容,比较两个数字的大小方法
2017/03/13 Javascript
微信小程序 动态绑定事件并实现事件修改样式
2017/04/13 Javascript
jQuery 控制文本框自动缩小字体填充
2017/06/16 jQuery
微信小程序 配置顶部导航条标题颜色的实现方法
2017/09/20 Javascript
Javascript中JSON数据分组优化实践及JS操作JSON总结
2017/12/22 Javascript
Vue.js实现可排序的表格组件功能示例
2019/02/19 Javascript
JavaScript数据结构与算法之二叉树插入节点、生成二叉树示例
2019/02/21 Javascript
浅谈Vue的响应式原理
2019/05/30 Javascript
解决layui的radio属性或别的属性没显示出来的问题
2019/09/26 Javascript
JavaScript对象原型链原理解析
2020/01/22 Javascript
vue登录页实现使用cookie记住7天密码功能的方法
2021/02/18 Vue.js
[00:32]2018DOTA2亚洲邀请赛出场——VP
2018/04/04 DOTA
python client使用http post 到server端的代码
2013/02/10 Python
浅析Python 简单工厂模式和工厂方法模式的优缺点
2020/07/13 Python
css3实现六边形边框的实例代码
2019/05/24 HTML / CSS
Myprotein意大利官网:欧洲第一运动营养品牌
2018/11/22 全球购物
世界上第一个水枕头:Mediflow
2018/12/06 全球购物
信息技术专业大学生个人的自我评价
2013/10/05 职场文书
2014学年自我鉴定
2014/02/23 职场文书
社区领导班子四风问题原因分析及整改措施
2014/09/28 职场文书
2014年小学数学工作总结
2014/12/12 职场文书
创业计划书之熟食店
2019/10/16 职场文书
Nginx反向代理多个服务器的实现方法
2021/03/31 Servers