预解释
为何学习预解释:
- 报错的时候,为何会报错?
- 带var和不带var的区别?
- 代码应该写在什么地方?
- 当代码不一样的时候,弹出同样的i,结果却不同?
undefined
- obj.xxx–>xxx属性下的值不存在的时候
- function的没有返回值的时候;
- 定义形参执行的时候没有传
- 在预解释的时刻,var声明的变量在赋值之前是undefined;
全局变量和私有变量
- 定义在script里的变量就是全局变量;定义在函数里的就是私有变量
- 在函数外不可以读取函数内定义的私有变量,在函数内部是可以读取全局变量甚至修改
- 尽量不要往全局变量存值
全局作用域和私有作用域
- 函数执行的时候形成一个私有作用域,
- 全局作用域只要打开浏览器就已经产生,一般用window表示
声明和定义
- 概念:在当前作用域下,在JS代码执行之前,浏览器会对带var和带function的进行声明或定义;
- 带var的:只声明不定义; var abc;
- 带function声明过的函数:声明加定义
- 如果函数名字和变量名字重名,在预解释阶段以最后一个函数为准,当代码执行到变量赋值的那一行,以这个变量为准
关于函数
- 函数定义三阶段:
- 开辟一个空间地址
- 把函数体中的所有JS代码作为字符串放在这个空间中
- 把空间地址赋值给函数名
函数执行四阶段:
- 形成一个私有作用域
- 形参赋值
- 预解释:
- 代码从上到下的执行;1234567var n=123;function fn(){alert(n)n=456;alert(n)}fn(4);
以上题涉及到的新知识点:
- 作用域链:当函数被调用的时候,形成一个私有作用域;我们找私有变量n;
如果有私有变量n,那么整个函数中的n都是该函数的私有变量,跟外界没有任何关系;
如果没有私有变量n,就到该函数的上级作用域进行查找,找不到,继续往上找,一直找到window,还没有的话:报错! - 带var 和不带var 的区别:
- 带var会进行预解释;在全局作用域下,他也是window的全局属性;
- 不带var不会进行预解释;如果进行赋值的话,就是给window进行全局属性的赋值;window.xxx=xx;
- 私有变量有2种:1)形参 2)函数中带var的;
- 上级作用域:跟函数在哪里调用无关;只跟函数对应的堆内存在哪里开辟有关;
内存和内存释放
- 作用域链:当函数被调用的时候,形成一个私有作用域;我们找私有变量n;
栈内存:形成一个供JS代码执行的环境:1)全局作用域 2)私有作用域
- 全局作用域:当浏览器加载完页面的时候,全局作用域就形成了
- 销毁:关闭页面
私有作用域:一般当函数执行完成的时候,自己就销毁,有两种情况不销毁:
不销毁:当函数里面的东西,被外面的变量或其他东西占用的时候,就不会销毁了
- return被占用:当函数执行完成的时候,会返回一个引用数据类型的值,这个值销毁,所有的函数才能销毁;fn()();
- 函数内的引用数据类型被同时赋予给函数外的变量;(如果不return出来,那么可以到函数里去占用它)
- 在绑定时间的时候,也有可能和作用域不是释放掺和在一起123456Element.onlick= (function(){var count = 0;return function fn(){console.log(++count);}}())
自执行函数也不不立即销毁:
- 全局作用域:当浏览器加载完页面的时候,全局作用域就形成了
- 堆内存:他用来存放数据的;
- 只对等号左边带var,声明不定义
- 自执行函数不会进行预解释,只有执行到他的时候,声明+定义+调用同步完成
- 条件判断语句中无论条件是否成立都会进行预解释;–提醒我们:不要在条件判断语句中写函数的定义阶段
- return后面的语句不会进行预解释,return下面的语句虽然不执行,但会进行预解释
- 已经声明过的变量不会进行重复声明;
运算符的优先级:算术》比较》逻辑》赋值 ; 所以一般用到赋值运算符的时候,都要加()提高优先级;
++i 先++,后运算; i++ 先运算再++; ++i也有强制转化为数字的默认行为
函数执行的过程
- 只要函数执行就需要浏览器提供一个私有作用域
- 形参赋值:形参相当于定义在当前函数体内的私有变量
- 先预解释当前函数体内带var和function的
- 代码从上往下执行