范围链(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); // undefined
var 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尚未赋予值 所以为undefined
man = '皮杰先生';
例12
function fn(){
console.log('皮杰先生'); //小鸡公主
}
fn();
function fn(){
console.log('小鸡公主'); //小鸡公主
}
fn();
//拆解
//创造阶段
function fn(){
console.log('皮杰先生'); //小鸡公主
}
function fn(){
console.log('小鸡公主'); //小鸡公主
}
//执行
fn();
fn();
//所以函式名称相同的话 後面的会覆盖前面的
那今天的介绍就到这里啦~~
内容很多 也很重要
务必多看几次
明天我们将介绍
执行绪与同步非同步
若有任何问题 或 内容有误
请别吝啬的跟我说唷~~
<<: Day34 | WebView元件开发 - 使用Ant Design Mobile UI Library
哈罗~ 昨天我们聊到隐写技术(Steganography), 今天就来做一些实作吧! Steghid...
该文章同步发布於:我的部落格 还记得我们使用 let 方法来实作一个物件来让我们可以快速使用! 但...
Rust的char型别是最基本的字母型别,用单引号包起来 例 let a = 'b'; Rust的字...
Helló,我是Charlie! 在Day21当中我们完成了後端的paypal sdk,在今天我们将...
前面的文章建立过了Release pipeline,但是那次并没有加入多个不同的Artifacts来...