概念:
1.js的变量和函数在编译阶段会被提升到当前作用域最前面编译
2.函数是一等公民,优先编译函数
3.js是按照script块编译的
console.log(a);//undefined console.log(b);//error var a = 10;
根据变量的提升原则,var a会被优先提升到最前面编译,但赋值是在运行的时候完成的。实际上的代码是
var a; console.log(a); console.log(b); a = 10;
由于b没有声明就直接输出了,当前作用域中是没有变量b的记录的,所以报错
console.log(a);//function a(){} var a = 10; function a(){ }
console.log(a);//10
变量的声明虽然在函数声明之前,但是函数优先被编译,实际代码是
function a(){ } console.log(a); a = 10;
console.log(a);
这里的实际代码中是a = 10而不是var a = 10;因为函数声明不仅优先被编译了,还覆盖掉剩余的同名变量的声明。
<script> //这句话报错,必须注释掉 // console.log(b); var a = "a"; </script> <script> var b = "b"; console.log(a);//"a" </script>
js以script块为单位进行编译运行。
第一个块中没有变量b的声明,所以报错。
第二个块中成功输出变量a。也就是说,虽然以script块为单位,但是块之间并不是独立的,它们的编译执行结果都会被当前作用域保存,上面的两块script块都是在全局作用域环境下编译运行的。
几个测试js核心概念的小案例:
1.
if (!("a" in window)) { var a = 1; } console.log (a);
结果:undefined
2.
var a = 1, b = function a (x) { x && a (--x); }; console.log(a);
结果:1
var b = function a(){...}是具名函数表达式赋值,函数名a只能在函数体使用,一般用于递归调用
3.
function a (x) { return x * 2; } var a; console.log(a);
结果:function a
4.
function b (x, y, a) { arguments[2] = 10; console.log(a); } b(1, 2, 3);
结果:10
arguments对像保存实参值,x,y,a是形参名。实参值的改变会影响形参值
5.
function a () { alert (this); } a.call (null);
结果:window
显式绑定this,绑定对象是null时,则采用默认绑定。