範围鍊(Scope Chain)
Def:
当函式本身使用的变数不存在 就会向外层寻找
(这里的外层不一定是全域!!)
我们在前面有提到
当 函式fn1 没有 num 变数时
会向外层寻找
而寻找过程与执行环境毫无关係 (请牢记!!)
是依据函式文法本身来决定範围鍊
所以这里的 fn1 与 fn2 的範围鍊
皆指向 全域
var num = 1;function fn1(){ //请看这里 console.log(num);}function fn2(){ var num = 10; fn1();}fn2();
提升(Hoisting)
重要!!
在 JS基础篇 我们有提到
//这里其实是两个步骤var name = '皮杰先生';//宣告变数var name;//赋予值道变数上name = '皮杰先生';//这两个结果会是一样的
那到底是为什么呢??
这里我们要先来提一下 我们上一篇提到的 执行环境
在建立一个执行环境的时候
其实是有两个阶段
我们刚刚都是着重在 执行
那创造阶段到底是做什事情??
创造阶段
先将变数配置一个 记忆体空间
(所以用console来看会是undefined)
执行
赋予值
在创造环境把记忆体空间準备好
就称为 提升(Hoisting)
比较不同的是
若是 函式陈述式(这里是函式陈述式 并非函式表达式)
在创造阶段就会优先载入(请牢记!!)
简单来说
创造阶段,函式已经可以执行
而变数要等到执行阶段才会赋予值
例:
var a = '1';function fn(){ //.....}
创造阶段
执行阶段
例 1
var name; //创造阶段name = '皮杰先生'; // 执行
例 2
console.log(name); // undefinedvar name = '皮杰先生';
例 3
function fn(){ console.log('皮杰先生') //皮杰先生}fn();
例 4
fn();function fn(){ console.log('皮杰先生') //皮杰先生}
例 5( 例3 , 例4拆解 )
//创造阶段function fn(){ console.log('皮杰先生') }//执行fn();
会发现 例3 , 例4 皆会执行
是因为创造阶段 函式就已经载入
而不会像 例2 呈现 undefined
因为变数是在执行阶段 才赋予值
例 6 (函式表达式)
fn();var fn = function(){ console.log('皮杰先生'); //undefined}
例 7 ( 例6拆解 )
//创造阶段var fn; //配置记忆体 但尚未赋予值//执行//若使用函式表达式 要等到函式赋予到变数上 才能运行函式fn();fn = function(){ console.log('皮杰先生'); //undefined}
这里要额外提一个重要观念
在 创造阶段的时候 函式优先(请牢记!!)
这里举个例子 方便釐清
例 8
var fn = function(){ console.log('皮杰先生 2');}function fn(){ console.log('皮杰先生 1');}fn(); //皮杰先生 2
例 9
// 两个函式位置互换var fn = function(){ console.log('皮杰先生 2');}function fn(){ console.log('皮杰先生 1');}fn(); //皮杰先生 2
会发现 例8 , 例9
皆为 皮杰先生 2
为什么!!!!
因为上面有提到
在创造阶段的时候函式优先
例 10 ( 例8 , 例9拆解 )
//创造阶段//函式优先function fn(){ console.log('皮杰先生 1');}var fn;//执行fn = function(){ console.log('皮杰先生 2');}fn();
例 11
fn();function fn(){ console.log(man); //undefined}var man = '皮杰先生';//拆解//创造阶段function fn(){ console.log(man); }var man;//执行fn(); // 这里执行 fn 时 , man尚未赋予值 所以为undefinedman = '皮杰先生';
例12
function fn(){ console.log('皮杰先生'); //小鸡公主}fn();function fn(){ console.log('小鸡公主'); //小鸡公主}fn();//拆解//创造阶段function fn(){ console.log('皮杰先生'); //小鸡公主}function fn(){ console.log('小鸡公主'); //小鸡公主}//执行fn();fn();//所以函式名称相同的话 后面的会覆盖前面的
那今天的介绍就到这里啦~~
内容很多 也很重要
务必多看几次
明天我们将介绍
执行绪与同步非同步
若有任何问题 或 内容有误
请别吝啬的跟我说唷~~