81-89JS函数变量作用域和预解析
2019-05-06 本文已影响1人
饥人谷_island
1.在JavaScript中定义变量有两种方式
ES6之前: var 变量名称;
ES6开始: let 变量名称;
*/
// 2.两种定义变量方式的区别
// 2.1是否能够定义同名变量
/*
1.通过var定义变量,可以重复定义同名的变量,并且后定义的会覆盖先定义的
var num = 123;
var num = 456;
console.log(num);
2.2如果通过let定义变量, "相同作用域内"不可以重复定义同名的变量
let num = 123;
let num = 456; // 报错
*/
// 2.2是否能够先使用后定义
/*
2.3通过var定义变量, 可以先使用后定义(预解析)
console.log(num);
var num = 123;
2.4通过let定义变量, 不可以先使用再定义(不会预解析)
console.log(num); // 报错
let num = 123;
*/
// 2.3是否能被{}限制作用域
/*
2.5无论是var还是let定义在{}外面都是全局变量
var num = 123;
let num = 123;
2.6将var定义的变量放到一个单独的{}里面, 还是一个全局变量
{
var num = 123;
}
console.log(num); //不会报错
2.7将let定义的变量放到一个单独的{}里面, 是一个局部变量
{
let num = 123;
}
console.log(num); //会报错
*/
/*
1.在JavaScript中{}外面的作用域, 我们称之为全局作用域
2.在JavaScript中函数后面{}中的的作用域, 我们称之为"局部作用域"
3.在ES6中只要{}没有和函数结合在一起, 那么应该"块级作用域"
4.块级作用域和局部作用域区别
4.1在块级作用域中通过var定义的变量是全局变量
4.2在局部作用域中通过var定义的变量是局部变量
5.无论是在块级作用域还是在局部作用域, 省略变量前面的let或者var就会变成一个全局变量
*/
/*
{
// 块级作用域
}
if(false){
// 块级作用域
}
while (false){
// 块级作用域
}
for(;;){
// 块级作用域
}
do{
// 块级作用域
}while (false);
switch () {
// 块级作用域
}
function say() {
// 局部作用域
}
*/
/*
{
// 块级作用域
var num = 123; // 全局变量
}
console.log(num);
function test() {
var value = 666; // 局部变量
}
test();
console.log(value);
*/
/*
if(true){
var num = 666;
}
console.log(num);
*/
/*
{
// var num = 678; // 全局变量
// let num = 678; // 局部变量
num = 678; // 全局变量
}
console.log(num);
*/
function test() {
// var num = 123; // 局部变量
// let num = 123; // 局部变量
num = 123; // 全局变量
}
test();
console.log(num);
// 1.找出下列哪些是全局变量,哪些是局部变量
/*
var num1 = 123; // 全局变量
function test() {
var num2 = 456; // 局部变量
}
{
var num3 = 789; // 全局变量
}
function test() {
num4 = 666; // 全局变量
}
*/
// 2.找出下列哪些是全局变量,哪些是局部变量
/*
let num1 = 123; // 全局变量
function test() {
let num2 = 456; // 局部变量
}
{
let num3 = 789; // 局部变量
}
function test() {
num4 = 666; // 全局变量
}
*/
// 3.下列代码运行是否会报错
/*
var num = 123;
var num = 456; // 不会报错
*/
/*
{
var num = 123;
{
var num = 456; // 不会报错
}
}
*/
/*
console.log(num); // 不会报错
var num = 123;
*/
// 4.下列代码运行是否会报错
/*
let num = 123;
let num = 456; // 会报错
*/
/*
{
let num = 123;
{
// 注意点: 在不同的作用域范围内, 是可以出现同名的变量的
let num = 456; // 不会报错
}
}
*/
/*
console.log(num); // 会报错
let num = 123;
*/
// 5.下列代码运行是否会报错
/*
// 注意点: 只要出现了let, 在相同的作用域内, 就不能出现同名的变量
let num = 123;
var num = 456; // 会报错
*/
/*
var num = 123;
let num = 456; // 会报错
*/
注意点: 初学者在研究"作用域链"的时候最好将ES6之前和ES6分开研究
1.需要明确:
1.ES6之前定义变量通过var
2.ES6之前没有块级作用域, 只有全局作用域和局部作用域
3.ES6之前函数大括号外的都是全局作用域
4.ES6之前函数大括号中的都是局部作用域
2.ES6之前作用域链
1.1.全局作用域我们又称之为0级作用域
2.2.定义函数开启的作用域就是1级/2级/3级/...作用域
2.3.JavaScript会将这些作用域链接在一起形成一个链条, 这个链条就是作用域链
0 ---> 1 ----> 2 ----> 3 ----> 4
2.4.除0级作用域以外, 当前作用域级别等于上一级+1
3.变量在作用域链查找规则
3.1先在当前找, 找到就使用当前作用域找到的
3.2如果当前作用域中没有找到, 就去上一级作用域中查找
3.3以此类推直到0级为止, 如果0级作用域还没找到, 就报错
*/
// 全局作用域 / 0级作用域
// var num = 123;
function demo() {
// 1级作用域
// var num = 456;
function test() {
// 2级作用域
// var num = 789;
console.log(num);
}
test();
}
demo();
注意点: 初学者在研究作用域的时候最好将ES6之前和ES6分开研究
1.需要明确:
1.ES6定义变量通过let
2.ES6除了全局作用域、局部作用域以外, 还新增了块级作用域
3.ES6虽然新增了块级作用域, 但是通过let定义变量并无差异(都是局部变量)
2.ES6作用域链
1.1.全局作用域我们又称之为0级作用域
2.2.定义函数或者代码块都会开启的作用域就是1级/2级/3级/...作用域
2.3.JavaScript会将这些作用域链接在一起形成一个链条, 这个链条就是作用域链
0 ---> 1 ----> 2 ----> 3 ----> 4
2.4.除0级作用域以外, 当前作用域级别等于上一级+1
3.变量在作用域链查找规则
3.1先在当前找, 找到就使用当前作用域找到的
3.2如果当前作用域中没有找到, 就去上一级作用域中查找
3.3以此类推直到0级为止, 如果0级作用域还没找到, 就报错
*/
// 全局作用域 / 0级作用域
// let num = 123;
{
// 1级作用域
// let num = 456;
function test() {
// 2级作用域
// let num = 789;
console.log(num);
}
test();
}
1.什么是预解析?
浏览器在执行JS代码的时候会分成两部分操作:预解析以及逐行执行代码
也就是说浏览器不会直接执行代码, 而是加工处理之后再执行,
这个加工处理的过程, 我们就称之为预解析
2.预解析规则
2.1将变量声明和函数声明提升到当前作用域最前面
2.2将剩余代码按照书写顺序依次放到后面
3.注意点
通过let定义的变量不会被提升(不会被预解析)
// 预解析之前
console.log(num); //undefined
var num = 123;
// 预解析之后
var num;
console.log(num);
num = 123;
// 不会预解析之前
console.log(num); // 报错
let num = 456;
// ES6之前定义函数的格式
console.log(say);
say();
// ES6之前的这种定义函数的格式, 是会被预解析的, 所以可以提前调用
function say() {
console.log("hello it666");
}
// 预解析之后的代码
function say() {
console.log("hello it666");
}
say();
console.log(say);
say(); // say is not a function
// 如果将函数赋值给一个var定义的变量, 那么函数不会被预解析, 只有变量会被预解析
var say = function() {
console.log("hello itzb");
}
var say; //undefined
say();
say = function() {
console.log("hello itzb");
}
// ES6定义函数的格式
say(); // say is not defined
let say = () => {
console.log("hello itzb");
}
// 1.下列程序的执行结果是什么?
var num = 123;
fun();
function fun() {
console.log(num);
var num = 666;
}
var num;
function fun() {
var num;
console.log(num); // undefined
num = 666;
}
num = 123;
fun();
// 1.下列程序的执行结果是什么?
var a = 666;
test();
function test() {
var b = 777;
console.log(a);
console.log(b);
console.log(c);
var a = 888;
let c = 999;
}
var a;
function test() {
var b;
var a;
b = 777;
console.log(a); // undefined
console.log(b); // 777
console.log(c); // 报错
a = 888;
let c = 999;
}
a = 666;
test();
*/
// 1.下列程序的执行结果是什么?
// 在ES6之前没有块级作用域, 并且没有将这两个函数定义到其它的函数中,
// 所以这两个函数应该属于全局作用域
// 注意点:
// 1.在高级浏览器中, 不会对{}中定义的函数进行提升
// 2.只有在低级浏览器中, 才会按照正常的方式解析
if(true){
function demo() {
console.log("hello demo1111111111");
}
}else{
function demo() {
console.log("hello demo2222222222");
}
}
demo();
function demo() {
console.log("hello demo1111111111");
}
function demo() {
console.log("hello demo2222222222");
}
if(true){}else{}
demo();
*/
// 1.下列程序的执行结果是什么?
// 注意点: 如果变量名称和函数名称同名, 那么函数的优先级高于变量
// 一定要记住, 在企业开发中千万不要让变量名称和函数名称重名
console.log(value); // 会输出函数的定义
var value = 123;
function value() {
console.log("fn value");
}
console.log(value); // 会输出123
function value() {
console.log("fn value");
}
console.log(value);
var value;
value = 123;
console.log(value);
*/