1.提前声明没有赋值变量默认值是undefined
-
1.EC(G)变量提升 var a;
-
2.声明全局变量,存放到VO(G)
-
3.声明的全局变量,会给全局对象GO(window)也设置一个相同的属性window.a,
-
4.后期不论是全局对象还是全局变量,一个改变,另外一个也会跟着改变(映射机制)
console.log(a); //=>undefined var a = 12; a = 13; console.log(a); //=>13
2.报错:没有任何变量声明
-
在全局中,输出一个变量,首先看其是否为全局变量[VO(G)],如果不是,则继续观察其是否为全局对象对象[GO->window]中的一个属性,如果也不是则报错:变量未定义错误 Uncaught ReferenceError: a is not defined
console.log(a);//=>is not a defined a = 13; console.log(a);
3.给全局对象GO存储值
window.a = 13;
//=>在全局对象GO中设置一个属性
console.log(a);
//=>13 a是GO中的一个属性 => window.a
a = 14; //=>window.a=14
console.log(a); //=>14
4.LET 和 VAR 的区别:
-
1.基于LET/CONST/CLASS/IMPORT等ES6中的方式创建变量,不存在变量提升(也就是只有VAR和FUNCTION有变量提升机制)
console.log(a); //=>Uncaught ReferenceError: Cannot access 'a' before initialization //=>let声明的 a未初始化前不能使用 let a = 12; a = 13; console.log(a);
5.计算
console.log(a, b, c);//=>undefined*3
var a = 12,
b = 13,
c = 14;
function fn(a) {
console.log(a, b, c);//=>10 13 14
a = 100;
c = 200;
console.log(a, b, c);//=>100 13 200
}
b = fn(10);//=>函数执行完没有写return返回结果是unedefined
console.log(a, b, c);//=>12 undefined 200
6.计算题(数组)
var ary = [12, 23];//=>AAAFFF000 [100,23]
function fn(ary) {//=>AAAFFF111
console.log(ary);//AAAFFF111
ary[0] = 100;
ary = [100];//=>AAAFFF222 [0]
ary[0] = 0;
console.log(ary);[0]
}
fn(ary);
console.log(ary);[100,23]
7、计算 (函数不释放问题被占用)
-
一般函数执行,形成的上下文,在函数执行完都会出栈释放,以此保证内存优化;但是如果当前上下文中的某些东西,被上下文之外的变量等占用了,则不能出栈释放,此上下文之前存储的私有变量也就被保存下来了
-
作用域链只和函数创建的时候[scope]有关系,创建的时候就已经决定了未来作用域链的指向;和在哪里执行的没有关系
var i = 0; function A() { var i = 10; function x() { console.log(i); } return x; } var y = A(); y();//=>10 function B() { var i = 20; y(); } B();//=>10
8.计算(函数)
var a=1;
var obj ={
"name":"tom"
}
function fn(){
var a2 = a;
obj2 = obj;
a2 =a;
obj2.name =”jack”;
}
fn();
console.log(a);//=>1
console.log(obj);//=>{name:"jack"}
9.计算(函数)
var x = 100,
y = 100;
function fn() {
// 私有上下文 EC(FN)
// AO(FN) y=200
var y = 200;
console.log(x); //=>100 全局变量
x=1000; //=>把全局的x修改为1000
console.log(y); //=>200 私有变量
//console.log(z); //=>Uncaught ReferenceError: z is not defined
z = 300; //=>window.z=300
}
fn();
console.log(window.z); //=>300
10 计算(函数)
var a = 1;
function fn(a) {
console.log(a);
var a = 2;
function a() {}
console.log(a);
}
fn(a);
console.log(a);
分析:
/*
* EC(G)全局上下文
* VO(G)全局变量对象
* var a;
* function fn(a){...}; fn[[scope]]=EC(G)
*/
var a = 1; //=>全局a=1
function fn(a) {
/*
* 私有上下文 EC(FN)
* AO(FN)私有变量对象
* a = 1
* = 函数
* = 2
* SCOPE-CHAIN:<EC(FN),EC(G)>
* 形参赋值: a=1
* 变量提升:
* var a;(没用了,因为此时AO中有a了)
* a = 函数; 此处的操作,又把AO中的a的值修改为函数了
*/
console.log(a); //=>函数a
var a = 2; //=>a=2 让私有的a改为2
function a() {}
console.log(a); //=>2
}
fn(a);
//=>全局函数fn执行,传递实参“全局变量a的值”
//=>fn(1)
console.log(a); //=>1
11 计算(函数 )
console.log(a);
var a=12;
function fn(){
console.log(a);
var a=13;
}
fn();
console.log(a);
/!*
* EC(G)全局上下文
* var a;
* function fn(){...};
*!/
console.log(a); //=>undefined
var a=12; //=>全局变量a=12
function fn(){
/!*
* EC(FN)私有上下文
* var a;
*!/
console.log(a); //=>undefined
var a=13; //=>私有变量a=13
}
fn();
console.log(a); //=>全局变量a的值是12
12 变量提升与函数
console.log(a);
var a=12;
function fn(){
console.log(a);
a=13;
}
fn();
console.log(a);
/!*
* EC(G)全局上下文
* var a;
* function fn(){...};
*!/
console.log(a); //=>undefined
var a=12;//全局a=12
function fn(){
/!*
* EC(FN)私有上下文
*!/
console.log(a);
//=>不是自己的私有变量,找到的是EC(G)中的全局变量 12
a=13;//全局a=13
}
fn();
console.log(a); //=>13
13 计算(函数没声明)
console.log(a);
a=12;
function fn(){
console.log(a);
a=13;
}
fn();
console.log(a);
/!*
* EC(G)全局上下文
* function fn(){...};
*!/
console.log(a);//=>Uncaught ReferenceError: a is not defined
a=12;
function fn(){
console.log(a);
a=13;
}
fn();
console.log(a);
15 计算(变量提升与函数)
var a=10,b=11,c=12;
function test(a){
a=1;
var b=2;
c=3;
}
test(10);
console.log(a);
console.log(b);
console.log(c);
/!*
* EC(G)全局上下文
* var a; var b; var c;
* function test(){...}; test[[scope]]=EC(G);
*!/
var a=10,b=11,c=12; //全局a=10 b=11 c=12
function test(a){
/!*
*EC(TEST)私有上下文
*(形参和在函数体中声明过的变量是私有变量)
* a = 10
* b
* SCOPE-CHAIN:<EC(TEST),EC(G)>
* 形参赋值:a=10
* 变量提升:var b;
*!/
a=1; //私有a=1
var b=2; //私有b=2
c=3; //全局c=3
}
test(10);
console.log(a); //=>10
console.log(b); //=>11
console.log(c); //=>3
16 条件判断(变量提升)
if (!("a" in window)) {
}
console.log(a);
/!*
* EC(G)全局上下文
* var a;
* 声明一个全局变量 VO(G)
* 给GO(window)设置一个属性 window.a
*!/
if (!("a" in window)) { // "a" in window => undefined=>!false=>true
var a = 1;
}
console.log(a); //=>undefined
17 计算(函数形参赋值)
var a = 4;
function b(x, y, a) {
console.log(a);
arguments[2] = 10;
console.log(a);
}
a = b(1, 2, 3);
console.log(a);
/!*
* EC(G)全局上下文
* var a;
* function b(x,y,a){...}; b[[scope]]=EC(G);
*!/
var a = 4; //全局a=4
function b(x, y, a) {
/!*
* EC(B)私有上下文
* x=1
* y=2
* a=3
*
* 1.SCOPE-CHAIN:<EC(B),EC(G)>
* 2.初始化THIS
* 3.初始化ARGUMENTS = { 0:1, 1:2, 2:3, length:3 }
* 4.形参赋值:分别给x/y/a赋值
* 5.变量提升
* 6.代码执行
*
* 在JS非严格模式下,ARGUMENTS和形参变量存在映射机制(因为都是用来存储传递的实参信息的
* //=>,ARGUMENTS不管是否定义形参都会存在,定义形参后,不仅形参可以获取传递的值
* //=>,ARGUMENTS中也存储了传递的值,此时两者有映射机制了)
* 第一个形参变量 映射 ARGUMENTS[0]
* 第二个形参变量 映射 ARGUMENTS[1]
* ...
* 映射:后期不论是形参变量更改值,还是ARGUMENTS更改每一项的值,互相都会跟着改变
*!/
console.log(a); //=>3
arguments[2] = 10;
//=>把ARGUMENTS索引为2(也就是第三个传递的实参)修改为10,由于映射机制,形参a的值也会跟着变为10
console.log(a); //=>10
}
a = b(1, 2, 3);
//把b函数执行,分别传递1,2,3三个实参给函数,把函数执行的返回值(只看RETURN)赋值给全局变量a
=>全局a=undefined,因为函数没有写return返回值
console.log(a); //=>undefined
18 计算(函数形参赋值arguments集合)
function fn(x, y, z) {
console.log(x, y, z, arguments);
arguments[0] = 100;
y = 200;
arguments[2] = 300;
console.log(x, y, z, arguments);
}
fn(10, 20, 30);
function fn(x, y, z) {
console.log(x, y, z, arguments);
// => x=10 y=20 z=30
// => arguments = [10,20,30]
arguments[0] = 100; //[100,20,30] x=100
y = 200; //y=200 [100,200,30]
arguments[2] = 300; //[100,200,300] z=300
console.log(x, y, z, arguments);
// => x=100 y=200 z=300
// => arguments = [100,200,300]
}
fn(10, 20, 30);
19 计算(函数中的arguments在严格模式下是不起作用的)
"use strict";
function fn(x) {
console.log(x);
arguments[0] = 100;
console.log(x);
}
fn(10);
"use strict";
//=>使用JS严格模式(JS最开始位置加)
function fn(x) {
console.log(x); //=>10
arguments[0] = 100;
//严格JS模式下,映射机制不存在,此处只是把arguments修改了,x是不会跟着改变的
console.log(x); //=>10
}
fn(10);
20 计算提(自执行函数)
var foo = 'hello';
(function (foo) {
console.log(foo);
var foo = foo || 'world';
console.log(foo);
})(foo);
console.log(foo);
/!*
* EC(G)全局上下文
* var foo;
*!/
var foo = 'hello'; //全局foo='hello'
(function (foo) {
/!*
* EC(AN)私有上下文
* foo = 'hello'
*此处是私有变量,和全局不是一个,但是因为是把全局值给他的,所以此时两个变量的值是一样的,
*但是不是相同的变量
*
* SCOPE-CHAIN:<EC(AN),EC(G)>
* 初始THIS/ARGUMENTS
* 形参赋值:给foo赋值
* 变量提升:var foo;(已经声明了)
* 代码执行
*!/
console.log(foo); //=>'hello'
var foo = foo || 'world'; //foo='hello' || 'word'='hello'
console.log(foo); //=>'hello'
})(foo); //自执行函数执行,把全局foo的值作为实参传递给函数 ...('hello')
console.log(foo); //=>'hello'