变量提升机制
目录
什么是变量提升
当栈内存(作用域)形成,JS代码自上而下执行之前,浏览器首先会把所有带 “VAR” “FUNCTION” 关键词的进行提前 “声明” 或者 “定义” ,这种预先处理机制称之为 “变量提升”。
声明(declare):var a (默认值undefined)
定义(defined):a=12 (定义其实就是赋值操作)
[变量提升阶段]
带“VAR”的只声明未定义
带“FUNCTION”的声明和赋值都完成了
变量提升只发生在当前作用域(例如:开始加载页面的时候只对全局作用域下的进行提升,因为此时函数中存储的都是字符串)
在全局作用域下声明的函数或者变量是“全局变量”,同理,在私有作用域下声明的变量是“私有变量” [带VAR FUNCTION的才是声明]
浏览器很懒,做过的事情不会重复执行第二遍,也就是,当代码执行遇到创建函数这部分代码后,直接跳过即可(因为在提升阶段就已经完成函数的赋值操作了)
var a = 12;
var b = a;
b = 13;
console.log(a);
function sum() {
var total = null;
for (var i = 0; i < arguments.length; i++) {
var item = arguments[i];
item = parseFloat(item);
!isNaN(item) ? total += item : null;
}
return total;
}
console.log(sum(12, 23, '34', 'AA'));
基本类型操作值;引用类型操作地址;
加VAR和不加的区别
在全局作用域下,加var就是全局变量,不加var就相当于windows的属性
加var就是全局变量
console.log(a);//=>undefined
console.log(window.a);//=>undefined
console.log('a' in window); //=>TRUE
var a = 12;//=>全局变量值修改,WIN的属性值也跟着修改
console.log(a);//=>全局变量A 12
console.log(window.a);//=>WINDOW的一个属性名A 12
在全局作用域下声明一个变量,也相当于给WINDOW全局对象设置了一个属性,变量的值就是属性值。
obj对象里没有name属性,obj.name值为undefined
有name属性值为undefined,obj.name值也为undefined
判断方法 in(检测某个属性是否隶属于这个对象)
‘name’ in obj
a = 13;
console.log(window.a);//=>13
window.a = 14;
console.log(a);//=>14
全局变量和WIN中的属性存在 “映射机制”(一个变,另一个跟着变)
不加var就相当于windows的属性
console.log(a);//=>Uncaught ReferenceError: a is not defined
console.log(window.a);//=>undefined
console.log('a' in window);//=>false
a = 12;//=>window.a=12
console.log(a);//=>12
console.log(window.a);//=>12
var a = 12,b = 13;//=>这样写B是带VAR的*/
var a = b = 12;//=>这样写B是不带VAR的
console.log(a, b);
var a = 12,
b = 12;
function fn() {
console.log(a, b);
var a = b = 13;
console.log(a, b);
}
fn();
console.log(a, b);
答案:
console.log(a, b);//=>undefined undefined
var a = 12,
b = 12;
function fn() {
console.log(a, b);//=>undefined 12
var a = b = 13;
/*var a=13; b=13;*/
console.log(a, b);//=>13 13
}
fn();
console.log(a, b);//=>12 13
console.log(b)找变量b,再沿作用域链找到windows,没有就报错
b=13 沿作用域链找到windows,没有则设置windows属性b=13
等号左边进行变量提升
匿名函数之函数表达式 var fn = function () {console.log(1);}; fn在变量提升阶段只声明不定义
条件判断下的变量提升
在当前作用域下,不管条件是否成立都要进行变量提升
=>带VAR的还是只声明
=>带FUNCTION的在老版本浏览器渲染机制下,声明和定义都处理,但是为了迎合ES6中的块级作用域,新版浏览器对于函数(在条件判断中的函数),不管条件是否成立,都只是先声明,没有定义,类似于VAR
当条件成立,进入到判断体中,代码执行之前,先进行函数定义(赋值)
console.log(a);//=>undefined
if ('a' in window) {
var a = 100;
}
console.log(a);//=>100
f = function () {return true;};
g = function () {return false;};
~function () {
if (g() && [] == ![]) {
f = function () {return false;};
function g() {return true;}
}
}();
console.log(f());
console.log(g());
答案
/*
* 变量提升:无
*/
f = function () {return true;};//=>window.f=...(TRUE)
g = function () {return false;};//=>window.g=...(FALSE)
~function () {
/*
* 变量提升:
* function g; //=>g是私有变量
*/
if (g() && [] == ![]) {//=>Uncaught TypeError: g is not a function (此时的g是undefined)
//=>[]==![]:TRUE
f = function () {return false;};//=>把全局中的f进行修改 window.f=...(FALSE)
function g() {return true;}
}
}();
console.log(f());// false
console.log(g());// false