javascript--12---作用域
作用域
- 什么是作用域
- 作用: 对代码的一个读写操作
- 域:空间 范围 js能实现的一个范围
<script>
console.log(a);
var a =1;
</script>
结果是undefined
没有声明为什么会报undefined? 首先预解析 找到a 为undefined 执行代码 =改变变量的值 但是console在等号之前 所以结果是 undefined
<script>
a =1;
console.log(a);
</script>
为什么没有声明却能打印出1?
- 如果 在script没有声明 直接赋值 也能行
<script>
console.log(a);
a =1;
</script>
直接报错
为啥是报错? 预解析 没找到a 没有var 在console.log之前 既没有声明 也没有赋值 所以报错 后面的a=1相当于没有
<script>
var a=1;
console.log(window.a);
</script>
结果是1 window是script标签中最大的一个对象
- 平时在script 中var的时候 其实是在最大的window上加了一个属性
<script>
a=1;
console.log(window.a);
</script>
结果是1
- 没有var也会自动在window上加一个属性 这是系统在找不到声明的时候 自动加的
解释器
js是一种直译式脚本语言
- 解释器:在浏览器内核中有一个解释器 看到script标签 就直接撸起袖子干 没有长期的准备
- 解释器在读取js代码的时候 也至少分为两步
-
找一些东西 根据关键字 去查找 var(变量声明) function(函数声明) 参数
找到变量声明之后 不去读取赋值 而是直接给一个undefined值找到函数声明之后不会执行函数 而是把函数的内容当作一块直接存起来 比如 a:function(){}
解释代码 先找到我们的 预解析找到的变量 如果有能改变变量值的运算:+ — ++ -- */% 修改了这个先找到的undefined/function(){}
<script>
alert(a);//结果是function a(){alert(3)}
var a=1;
alert(a);//结果是1
function a() {
alert(2);
}
alert(a);//结果是1
var a=3;
alert(a);//结果是3
function a() {
alert(3);
}
alert(a);//结果是3
a();//报错
</script>
- 预解析
- a :undefined 如果预解析过程中 函数名和变量重名了 函数会把变量无情覆盖
- a :function{alert(2)}
- 如果预解析中 有重名函数 后者会把前者覆盖
- a :function{alert(3)}
- 执行阶段
- 第一个alert 结果是打印函数体
function{alert(3)}
- 修改a=1,第二个alert 结果是打印1
- function只在预解析会用到 跳过function 第三个alert 结果是打印1
- 修改a=3,第四个alert 结果是打印3
- 跳过function 第五个alert 结果是打印3
- a=3 3();是啥哦 会报错
全局作用域 和 局部作用域
全局作用域
- 最大的作用域是 script标签之间 全局中最大的对象是 window window是最大的作用域 但是script是分别解释的 代码自上而下执行 script全部解读完之后 window还是最大的对象 在引入代码的时候一定要注意引入顺序 因为script是分别解释的
<script>
alert(a);
</script>
<script>
var a =1;
</script>
结果会报错 代码自上而下执行 没有解析下面的var a=1;
<script>
var a =1;
</script>
<script>
alert(a);
</script>
结果是1; 会把a=1存起来 执行到下一个script 会在小仓库里找a
局部作用域
- 函数内部也是一个空间 函数构建的空间 可以被看作一个局部作用域
- 如果局部作用域的预解析的空间 没有找到 那么我的代码执行 会从上一级作用域寻找 上一级作用域不能在下一级作用域寻找
- 预解析的空间 :AO ----活动对象
<script>
var a =1;
function fn1() {
alert(a);
var a =2;
}
fn1();
alert(a);
</script>
第一个结果是 undefined 第二个结果是 1
- 预解析 AO分析
- a:undefined fn1{}
- 代码执行 a=1
- fn1执行 :进入函数内部 1预解析 a:undefined 2 执行 alert(a) a=2
- alert(a) 所以结果是先 undefined 后1
<script>
var a =1;
function fn1() {
alert(a);
}
fn1();
alert(a);
</script>
结果是1 1
- 预解析
- a:undefined fn1{}
- 代码执行 a=1
- fn1执行 :进入函数内部 1预解析 预解析是空 2 执行 alert(a) 跳出函数在全局中寻找a a=1 所以结果是1
- alert(a) 所以结果是先 1 后1
参数
- 形参 相当于隐式声明 在AO上为undefined
- 实参 会在AO分析时候 给形参一个初始值
<script>
var a =1;
function fn1(a) {
alert(a);
a =2;
}
fn1();
alert(a);
</script>
- 预解析
- a:undefined fn1{}
- 代码执行 a=1
- fn1执行 :进入函数内部 1预解析 形参相当于声明变量a:undefined 2 执行 alert(a)所以结果是undefined 之后赋值a=2;
- alert(a) 所以结果是先 undefined 后1
<script>
var a =1;
function fn1(a) {
alert(a);
a =2;
alert(a);
}
fn1(a);
alert(a);
</script>
- 预解析
- a:undefined fn1{}
- 代码执行 a=1
- fn1执行 :进入函数内部 1预解析 实参传值 a=1 2 执行 alert(a)所以结果是1 之后赋值a=2;
- alert(a) 所以结果是先 1 后2 再 1
<script>
var a =1;
function f1() {
alert(a);
a=2;
}
f1();
alert(a);
</script>
结果是 1 2
<script>
var age =99;
function t(age) {
alert(age);
}
t(5);
t();
</script>
- 预解析
- age:undefined t:function{}
- 代码执行 age=99
- t(5)执行 :进入函数内部 1预解析 实参传值 age=5 2 执行 alert(age)所以结果是5
- t()执行 进入函数 1 预解析 形参相当于声明变量a:undefined alert(age) 所以结果是先5 后undefined
<script>
function t2(green) {
alert(green);
function green() {
}
green="hello";
alert(green);
}
t2(null);
- 预解析
- green:null 进入函数内部 有一个函数声明 会覆盖 green=function green() {}
- 代码执行 alert(green) 结果是 function
- green:hello
- alert(green) 结果是hello 所以 第一个是函数体 第二个是hello
<script>
function a(b) {
alert(b);
function b() {
alert(b);
}
b();
}
a(1);
</script>
- 预解析
- b=1 进入函数内部 有一个函数声明 会覆盖 b=function b(){}
- 代码执行 alert(b) 结果是 function
- b() 执行 进入b(){}内部 并没有 var b 跳出当前函数 找到b为function 所以alert(b) 是函数本身 结果两个都是函数本身
<script>
function a(b) {
alert(b);
b=function(){
alert(b);
}
b();
}
a(1);
</script>
- 预解析
- b=1 进入函数内部 没有函数声明 变量声明
- 代码执行 alert(b) 结果是1
- 赋值b=function(){}
- b()执行 进入函数体内部 没有var b 跳出 b=function 结果是function 所以第一个是1 第二个是函数本身
作用域分析
- 先看看有没有参数 实参会把形参初始化 如果只有形参 那么形参为undefined
- 再看看有没有变量声明 函数会把同名变量覆盖 包括实参
jquery部分代码
- 传window是为了性能
- 不穿undefined 是为了函数内部不被污染
<script>
(function (window,undefined) {
function(){
function(){
function(){
window.document.getElementById()
}
}
}
})(window);
</script>
如果函数内部没有 window 那么document.getElementById()
要执行 会跳出这个函数 当层数太多 性能就会很低 所以会实参会传一个window到函数内部 形参undefined 初始值就是undefined 不用实参传 再低版本的ie中 undefined可以被赋值 如果在函数外部 定义undefined=1 实参传undefined 那么函数内部undefined 就会被污染为1 如果函数内部做判断 if(a==undefined)就不可以
作用域链
内层作用域在寻找变量时候未找到 会沿着作用域上的AO 向上寻找 直到全局
上一篇: 牛课题霸--数组中只出现一次的数字
下一篇: 作用域 & LHS、RHS查询