变量提升机制
1.数据值操作机制
2.变量提升机制
+什么是变量提升
+带var和不带的区别
+等号左边变量提升
+条件判断下的变量提升
+重名问题的处理
3.ES6中let不存在变量提升
+不允许重复定义
+暂时性死区
+不存在变量提升
1.为什么一般都把Js放到body的末尾
2.放在HEAD中可个可以?如何双到HEAD中也可以大境山从PDi/的效果?
3.SCRIPT标签中有两个属性: defer / async 的作用
1.js数据操作(渲染)
复习
var a = 12的过程
1. 先声明一个变量a,没有赋值(默认值是undefined)
2. 在当前作用域中开辟一个位置存储12这个值
3. 让变量a和12关联在一起(定义:赋值)
var a = 12
var b = a;
b = 13;
console.log(a);//12
var ary1 = [12, 23];
var ary2 = ary1;
ary2.push(100);
console.log(ary1);//[12,23,100]
任意数求和
console.log(sum('10', 10, 20, 'AA'));
function sum() {
var total = 0;
for (var i = 0; i < arguments.length; i++) {
if (isNaN(arguments[i]) == false) {
total = total + parseFloat(arguments[i]);
}
}
return total;
}
2.js变量提升(ES3/ES5)
console.log(a); 输出undefined,不会报错
var a =12;
变量提升:==当栈内存(作用域)形成之后,JS代码自上而下执行之前,==浏览器首先会把所有带 “var”/“function” 关键词的进行提前 “声明” 或者 “定义” ,这种预先处理机制称之为 “变量提升”
声明(declare):var a (默认值undefined)
定义(defined):a=12 (定义其实就是赋值操作)
[变量提升阶段]
带“var”的只声明未定义
带“function”的声明和赋值都完成了
变量提升只发生在当前作用域(例如:开始加载页面的时候只对全局作用域下的进行提升,因为此时函数中存储的都是字符串而己)
在全局作用域下声明的函数或者变量是"全局变量”,同理,在私有作用域下声明的变量是"私有变量“
浏览器很懒,做过的事情不会重复执行第二遍,也就是,当代码执行遇到创建函数这部分代码后,直接的跳过即可(因为在提升阶段就已经完成函数?的赋值操作了)
执行顺序
1.形参赋值2.变量提升 3.代码执行(私有作用域)
全局变量提升阶段
var a;var b;sum=0X88888(堆内存地址空间)
-----------------------------------------------
1.形参赋值2.变量提升 3.代码执行(私有作用域)
私有变量提升阶段
sum()函数
var total;var i; var item;
--------------------------------------------------------------
var a = 12
var b = a;
b = 13;
console.log(a);//12
var ary1 = [12, 23];
var ary2 = ary1;
ary2.push(100);
console.log(ary1);//[12,23,100]
console.log(sum('10', 10, 20, 'AA'));
function sum() {
var total = 0;
for (var i = 0; i < arguments.length; i++) {
if (isNaN(arguments[i]) == false) {
total = total + parseFloat(arguments[i]);
}
}
return total;
}
3.js带var和不带var的区别
全局变量
加var的本质是变量,存在变量提升
不加var的本质是window的属性,不存在变量提升
全局变量和window中的属性存在映射机制(一个改变另一个也改变)
加var
在全局作用域下声明一个变量,也相当于给window全局对象设置了一个属性,变量的值就是属性值
(私有作用域中声明的私有变量和window没啥关系)
console.log(a); 有属性a,由于变量提升机制,没有赋值 undefined
console.log('a' in window); true 在变量提升阶段,在全局作用域中声明了一个变量A,此时就已经把A当做属性赋值给window了,只不过此时还没有给A赋值,默认值uindefined
console.log(window.a); 有属性a,由于变量提升机制,没有赋值 undefined
var a = 12; 全局变量值修改,wIN的属性值也跟着修改
console.log(a); 全局变量A 12
console.log(window.a); window的一个属性名A 12
全局变量和window下的属性存在映射机制
不加var,给window对象新增属性
console.log(a); //Uncaught ReferenceError: a is not defined
console.log('a' in window);//false
console.log(window.a); //undefined
a = 12; //等价于window.a = 12 //给window添加属性a
console.log(a); //12
console.log(window.a); //12
var a= 12,b = 13; 这样写b是带var的
var a = b = 12 ; 这样写b是不带var的,a是带var
等价于var a=12; b=12;
私有变量
私有作用域中带var和不带也有区别:
1.带var的在私有作用域变量提升阶段,都声明为私有变量,和外界没有任何的关系
2.不带var不是私有变量,会向它的上级作用域查找,看是否为上级的变量,不是,继续向上查找,一直找到window为止(我们把这种查找机制叫做:“作用域链”)
3.在私有作用域中操作的这个非私有变量,是一直操作别人的
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
4.js作用域链的扩展
ES5 var
function fn() {
var a = 12;
b = 13; // 在作用域链查找的过程中,如果找到win也没有这个变量,相当于给win设置了一个属性B,(window.b=13)
console.log('b' in window); //true
console.log(a, b);//12 13
}
fn();
console.log(b); //13
console.log(a); //Uncaught ReferenceError: a is not defined
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ES6 let
let a = 12;
console.log(a, window.a);//12 undefined
5.只对等号左边变量提升
sum(); 可以正常执行,因为存在变量提升。在代码没执行前,在全局作用域中将sum()函数声明+定义
console.log(fn); undefined
变量提升 var fn;
fn();//报错 fn is not a function
匿名函数函数表达式(常用)
var fn = function () {//只对等号左边变量提升
console.log(11);
}
普通函数
function sum() {
console.log(22);
}