JavaScript系列教程(三)

 一、作用域(scope)、作用域链

作用域(scope):一个变量的可用范围

作用域链:当前作用域没有定义的变量,这成为 自由变量 。自由变量的值如何得到 —— 向父级作用域寻找,

如果父级也没呢?再一层一层向上寻找,直到找到全局作用域还是没找到,就宣布放弃。这种一层一层的关系,就是 作用域链 。

ES6 之前 JavaScript 没有块级作用域,只有全局作用域函数作用域。ES6 的到来,为我们提供了‘块级作用域’,可通过新增命令 let 和 const 来体现。

全局作用域

  • 最外层函数和在最外层函数外面定义的变量拥有全局作用域
  • 所有末定义直接赋值的变量自动声明为拥有全局作用域
  • 所有 window 对象的属性拥有全局作用域

全局作用域有个弊端:如果我们写了很多行 JS 代码,变量定义都没有用函数包括,那么它们就全部都在全局作用域中。这样就会 污染全局命名空间, 容易引起命名冲突。

函数作用域

  函数作用域(局部作用域)是指声明在函数内部的变量,和全局作用域相反,局部作用域一般只在固定的代码片段内可访问到,最常见的例如函数内部。

  作用域是分层的,内层作用域可以访问外层作用域的变量,反之则不行

function foo(a) {
    var b = a * 2;
    function bar(c) {
       console.log(b,a,c)      
    }    
    bar(b * 3)
}

foo(a); // 2, 4, 12

   值得注意的是:块语句(大括号“{}”中间的语句),如 if 和 switch 条件语句或 for 和 while 循环语句,不像函数,它们不会创建一个新的作用域。在块语句中定义的变量将保留在它们已经存在的作用域中。

if (true) {
    // 'if' 条件语句块不会创建一个新的作用域
    var name = 'Hammad'; // name 依然在全局作用域中
}
console.log(name); // logs 'Hammad'

块级作用域

  块级作用域所声明的变量在指定块的作用域外无法被访问

  声明变量不会提升到代码块顶部

  禁止重复声明

二、JS预编译,执行过程详解

关于预编译的一些知识点
 1、函数声明整体提升
 2、变量仅声明提升
 3、如果变量未经声明就赋值,此变量就为全局对象所有
 4、一切声明的全局变量,全是window的属性

局部预编译 

1、创建AO对象(执行期上下文)
2、找形参和变量声明
3、将实参值和形参统一(全局预编译无这一块)
4、在函数体内找函数声明,值赋予函数体

全局预编译

1、创建AO对象(执行期上下文)
2、找变量声明
3、找函数声明,值赋予函数体

实例1-局部预编译

function check(a) {
  console.log(a);
  var a = 123; // 变量声明和定义
  console.log(a);
  function a() {}; // 函数声明
  console.log(a);
  var b = function() {} //变量声明和定义
  console.log(b);
  function d() {} //函数声明 
}
check(1); 
// 预编译结果
{
    a: function a() {},
    b: undefined
    d:function d() {}
}

实例2-全局和局部的预编译和解释执行过程

console.log(test);
function test(test) {
  console.log(test);
  var test = 234;
  console.log(test);
  function test() { }
}
test(1);
var test = 123; 
console.log(test);
// 全局预编译 
 {
   test: function test(test) {} // test: undefined被替换
 }
 // 局部预编译
 {
   test: function test() {}
 }

 

练习题1

 var z = 1;
 function tim() {
   console.log("第一:",z)
   var z = 4 
   console.log("第二:",z);
 }
 tim();

练习题2

var z = 1;
function tim() {
  function cope() {
    y = 3; //没有y属性,就会沿着作用域链往上找,一直没有就会挂载在GO上(作用域链)
  }
  var y = 4;
  cope();
  console.log(y);
}

tim();

 

posted @ 2021-10-22 15:37  张正宜  阅读(28)  评论(0)    收藏  举报