在咱们的平常工做中,变量无处不在。更加深刻的去了解它,可以使得本身的JS水平更上一层楼, 从变量提高这个小知识点着手,让咱们一块儿来深刻了解JS吧!
html
console.log(a) // undefined
var a = 'hello JS'
/* 在咱们声明a以前为何输出a不会报错呢? 不急,让咱们接着往下看 */
num = 6;
num++;
var num;
console.log(num) // 7 好奇怪,为何给一个尚未声明的变量赋值会不报错呢
function hoistFunction() {
foo();
function foo() {
console.log('running...')
}
}
hoistFunction(); // running...
/* 最后一个栗子 */
alert(a) // function a { alert(10) }
a(); // 10
var a = 3;
function a() {
alert(10)
};
alert(a) // 3
a = 6;
a(); // throw error复制代码
JS引擎会在正式执行代码以前进行一次”预编译“,预编译简单理解就是在内存中开辟一些空间,存放一些变量和函数。具体步骤以下(browser):segmentfault
GO/window = {
//页面加载建立GO同时,建立了document、navigator、screen等等属性,此处省略
a: undefined,
c: undefined,
b: function(y){
var x = 1;
console.log('so easy');
}
}复制代码
GO/window = {
//变量随着执行流获得初始化
a: 1,
c: function(){
//...
},
b: function(y){
var x = 1;
console.log('so easy');
}
}
复制代码
预解析机制使得变量提高(Hoisting),从字面上理解就是变量和函数的声明会移动到移动到函数或者全局代码的开头位置。咱们再来分析一下小栗子加深一下理解。bash
console.log(a) // 执行以前,变量提高做为window的属性, 值被设置为undefined
var a = 'hello JS'
/* JavaScript 仅提高声明,而不提高初始化 */
num = 6;
num++;
var num;
console.log(num) // 变量提高 值为undefined的num赋值为6,再自增 => 7
function hoistFunction() {
foo();
function foo() {
console.log('running...')
}
}
hoistFunction(); // 函数声明提高,能够在函数体以前执行
/* 最后一个栗子 */
alert(a) // 最后的声明为函数声明, 所以a此时为函数体
a(); // 执行 a 函数,输出10
var a = 3; // 3 赋给a
function a() {
alert(10)
};
alert(a) // 3
a = 6; // 6赋给a,不是一个函数,故下方执行throw error
a(); // throw error
复制代码
注: JS并不存在真正的预编译,var与function的提高实际是在语法分析阶段就处理好的。并且JS的预编译是以一个脚本文件为块的。一个脚本文件进行一次预编译,而不是全文编译完成再进行”预编译”的。函数
理解了变量提高和函数提高能够使得咱们在JS上走的更远,可是咱们在开发中,不该该使用这一特性,而是要规范咱们的代码,作到可维护性和可读性。不管是变量仍是函数,都必须先声明后使用。PS:在开发中应该使用let来约束变量提高。
spa
参考资料: code
https://developer.mozilla.org/zh-CN/docs/Glossary/Hoisting https://www.cnblogs.com/liuhe688/p/5891273.html http://dmitrysoshnikov.com/notes/note-4-two-words-about-hoisting/ https://segmentfault.com/a/1190000010187653htm