● 首先,我们先创建一个函数,和以前一样,计算一个年龄的
function calcAge(birthYear) {const age = 2037 - birthYear;return age;
}
● 然后我们创建一个全局变量,并调用这个函数
const firstName = "IT知识一享";
calcAge(1998);
● 因为firstName是一个全局变量,所以在函数中,我们也可以调用这个变量
function calcAge(birthYear) {const age = 2037 - birthYear;console.log(firstName);return age;
}
注:这里函数首先会在自己的作用域中找这个变量,如果找不到,会向上从作用域链中寻找这个变量,直到找到为止,如果找不到的话就会报错!
● 现在我们在函数内再添加一个函数
function calcAge(birthYear) {const age = 2037 - birthYear;function printAge() {const output = `你${age}岁了,出生于${birthYear}年`;console.log(output);}printAge();return age;
}
注:printAge函数中调用了age变量,但是再函数作用域中并未找到,所以就通过作用域链再父范围去寻找,最终找到打印出来,但是age变量只能再calcAge整个函数内部使用,外部无法使用这个变量
function calcAge(birthYear) {const age = 2037 - birthYear;function printAge() {const output = `你${age}岁了,出生于${birthYear}年`;console.log(output);}printAge();return age;
}const firstName = 'IT知识一享';
calcAge(1998);
console.log(age);
记住,翻译链是单项的,只能内部访问外部,外部无法访问到内部!
● 当然,在函数中,我们也可以把firstName加上,因为他是全局变量
function printAge() {const output = `${firstName},你${age}岁了,出生于${birthYear}年`;console.log(output);}printAge();return age;
}
● 现在,我们在printAge中添加if判断
function printAge() {const output = `${firstName},你${age}岁了,出生于${birthYear}年`;console.log(output);}if(birthYear >= 1981 && birthYear <= 1996) {const str = `哇哦,你是千禧一代的人,${firstName}`;console.log(str);}printAge();return age;
}
因为firstName是全局变量,所以if条件仍然可以通过作用域链找到这个变量。
● 但是str的变量在if之外的区域则无法被访问
function printAge() {const output = `${firstName},你${age}岁了,出生于${birthYear}年`;console.log(output);}if (birthYear >= 1981 && birthYear <= 1996) {const str = `哇哦,你是千禧一代的人,${firstName}`;console.log(str);}console.log(str);printAge();return age;
}
因为let和const是块作用域,所以上述才能生效
● 现在我们使用var创建一个变量
if (birthYear >= 1981 && birthYear <= 1996) {var millenial = true;const str = `哇哦,你是千禧一代的人,${firstName}`;console.log(str);}console.log(millenial);
因为var并不是块级作用域,而是函数作用域,它知识在函数中调用可以,但是全局中或者脱离上一级函数情况下仍然不可以,这是还是要符合作用域链的;
● 当然,现在我们在if中创建一个功能函数,仍然是块级区域,无法在外部访问
if (birthYear >= 1981 && birthYear <= 1996) {var millenial = true;const str = `哇哦,你是千禧一代的人,${firstName}`;console.log(str);function add(a, b) {return a + b;}}console.log(millenial);console.log(add(2, 3));
注:这仅仅是在严格模式下
● 但是如果我们把严格模式去除的话,则会被正常调用
但是我们使用会用严格模式去编写我们的代码,这样会让代码出现奇奇怪怪的的情况变得很少!
● 如果我们在if条件中去声明姓名变量的话,会发生什么情况呢?
if (birthYear >= 1981 && birthYear <= 1996) {var millenial = true;const firstName = "mark";const str = `哇哦,你是千禧一代的人,${firstName}`;console.log(str);function add(a, b) {return a + b;}}
这更加验证了,它会首先在在自己所在的作用域去寻找,如果找到的话,它不会通过作用域链去向父范围查找;除此之外,我们不应该把内部的firstName和外部的看作是一个变量,从本质来讲,它们就是两个变量,只是恰巧名字一样罢了。
● 那如果我们在内部讲外部的函数重新赋值,那又是什么情况呢?
function calcAge(birthYear) {const age = 2037 - birthYear;function printAge() {let output = `${firstName},你${age}岁了,出生于${birthYear}年`;console.log(output);if (birthYear >= 1981 && birthYear <= 1996) {var millenial = true;const firstName = 'mark';const str = `哇哦,你是千禧一代的人,${firstName}`;console.log(str);function add(a, b) {return a + b;}output = 'NEW OUTPUT';}console.log(millenial);// console.log(add(2, 3));console.log(output);}printAge();return a
● 但是如下
const output = 'NEW OUTPUT';
重新赋值变量和创建变量是不同的!