作用域基础
作用域的目的
提高代码程序的可靠性更重要的是减少命名冲突
js作用域(es6)之间:全局作用域和局部作用域
全局作用域 : 整个script标签 或者是一个单独的js文档
局部作用域(函数作用域) : 在函数内部是局部作用域 这个代码的名字只在函数内部起效果和作用
变量
全局变量: 在全局作用域下的变量 在函数内部没有 var 声明的变量
局部变量: 在函数内部的变量 函数的形参也可以看做是局部变量
作用域链
内部函数访问外部函数的变量,采取的是链式查找的方式来决定取那个值,这种结构称之为作用域链 就近原则
站在目标出发,一层一层往外找.
/*
作用域:js代码所作用的范围。
1. 一旦进入作用域,浏览器就会启动JS解析器。
2. 声明在script作用域中的变量,称为全局变量。作用范围:整个页面。生存周期,与页面同寿。同时也是顶级对象window的属性。声明在函数作用域中的变量,称为局部变量,作用范围:仅限于当前函数内。生存周期:函数调用时开辟空间,函数调用结束后,释放空间。
3. 使用变量时,首先在自己作用域中查找,如果没有,向父级作用域查找,依次向上查找,一直查找到script作用域,这个过程称为作用域链。
一、预解析(var function 形参)
fn = function(){}
a = 2
//1. 当找到var时,取出var后面的名字放到内存中,并且给它初始化一个undefined值.
//2. 当找到function时,取出function后面的名字放到内存中,并且将整个函数块赋值给这个名字。
//3. 当变量与函数同名时,丢变量,保函数。
//4. 多个script作用域时,从上到下依次解析每一个script,所以上面script作用域中找到的东西,下面可用。如果是下面找到东西,上面无法使用。建议将所有声明的语句放到第一个script作用域中。
//5. 隐式声明的变量会因为赋值号的关系,在全局作用域中自动生成这个变量。
//6. 如果在所以的作用域中都没有找到这个变量,则会在全局作用域中因为赋值号会在全局作用域中自动生成这个变量.
二、逐行解读代码(遇到函数声明,直接跳过)
1. 执行表达式
2. 函数调用(函数也是一个作用域)
一、预解析(var function 形参)
二、逐行解读代码
1. 执行表达式
2. 函数调用
*/
面试题分析
function fool(){ return { bar : 'hello', he : "hehe" } } alert(fool()); 没有声明,直接跳过,遇到调用,{ }表示对象,对象里面存储的是属性和属性值 结果:[object Object] 中括号的第一个元素,表示数据类型是object 第二个元素表示当前对象的名称叫做Object function fool() { return { bar : "hello" } } alert(fool()); return后面没有内容,表示 结果:undefined // var a = 10; function test(){ alert(a); //undefined a = 100; alert(a); //100 alert(window.a); //10全局变量,也是window对象的属性 var a; alert(a); //100 return a; } test(); // 100 alert(a); //10 // 结果: undefined 100 10 100 10 var a = 6; function fn(){ alert(a); a = 666; } alert(a); fn(); alert(a); a = 66; 函数内部没有var a 结果:6 6 666 function test(){ console.log(a); console.log(foo()); var a = 1; function foo(){ return 2; } } test(); 结果: var a = 10; sayHi(); function sayHi(){ var a = 20; alert(a); } alert(a); 结果: var a = 10; sayHi(); function sayHi(){ a = 20; alert(a); } alert(a); 结果: var a = 10; sayHi();第一次调用父级改为20 function sayHi(){ a = a + 10; alert(a); 20 第二次调用20+10 return a; 返回20 第二次返回30 } alert(a); 输出20 alert(sayHi() + 10); sayhi()第一次调用30 第二次30+10= 40 结果: var a = 10; sayHi(); function sayHi(){ var a = a + 10; alert(a); return a; } alert(a); alert(sayHi() + 10); 结果: function f1(){ var n = 999; nAdd = function(){ n += 1; } function f2(){ alert(n); } return f2; } var result = f1(); result 等待的是 调用f1()后的返回值 f2 又是谁? function f2(){} result(); nAdd(); result(); 结果: var s = ‘abc12345’; var num = parseInt(s); if(num == NaN){ alert(“NaN”); }else if(typeof num == ‘number’){ alert(‘number’); }else if(num == ‘abc’){ alert(‘abc’); }else { alert(‘str’); } 结果: var a = 1; function b(){ a=10; return; function a(){ console.log(a); } } b(); console.log(a); f1(); console.log(c); console.log(b); console.log(a); function f1 (){ var a = b = c = 9; console.log(a); console.log(b); console.log(c); } var num = 10; fun(); function fun () { console.log(num); var num = 20; } function aaa(){ var a=b=10; } aaa(); alert(a); alert(b) var a=10; function aaa(a){ alert(a); var a=20; } aaa(a); var i= 9; function n(){ i = 1; console.log(i) } n(); // this 代表它所在function 被那个对象调用了,代表这个对象 // 如果没有明确的调用对象,那么this代表window var i = 9; function n(){ this.i = 1; this 指的是我这个代词 console.log(this.i) } n() alert(i) a = 9; var a; console.log(a);