02-函数执行-作用域链-面试题-内存管理

函数执行-作用域链-面试题-内存管理

全局代码执行过程的回顾

var name = "why";
console.log(name);
console.log(num1);
var num1 = 20;
var num2 = 30;
var result = num1 + num2;
console.log(result);
/**
 * 1.代码被解析,V8引擎内部会帮助我们创建一个对象(globalObject -> go)
 * var globalObject = {
 *  String: "类",
 *  Date: "类",
 *  setTimeout: "函数",
 *  window: globalObject,
 *  name: undefined,
 *  num1: undefined,
 *  num2: undefined,
 *  result: undefined
 * };
 * 2.运行代码
 *  >2.1.v8为了执行代码,v8引擎内部会有一个执行上下文栈(Execution Context ECStack)(函数调用栈)
 *  2.2.因为我们执行的是全局代码,为了全局代码能够正常的执行,需要创建全局执行上下文(Global Context ECStack)(全局代码需要被执行才会创建)
 *    >2.2.1.生成一个VO(Variable Object)
 *      VO = var globalObject = {
 *        String: "类",
 *        Date: "类",
 *        setTimeout: "函数",
 *        window: globalObject,
 *        name: undefined,
 *        num1: undefined,
 *        num2: undefined,
 *        result: undefined
 *      };
 *    >2.2.1.开始执行代码
 *    var globalObject = {
 *      String: "类",
 *      Date: "类",
 *      setTimeout: "函数",
 *      window: globalObject,
 *      name: "why",
 *      num1: 20,
 *      num2: 30,
 *      result: 50
 *    };
 *    如果console.log(result) =>   打印50
 *    如果在var name = "why"之后console.log(name) 打印why
 *    如果在var name1 = "20;之前console.log(name1) 打印undefined
 */
// why
// undefined
// 50

函数执行

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script src="./全局代码执行过程(函数).js"></script>
  </body>
</html>

全局代码执行过程(函数).js

var name = "why";
console.log(num1);
var num1 = 20;
var num2 = 30;
var result = num1 + num2;
console.log(result);
console.log(window);
/**
 * 1.代码被解析,V8引擎内部会帮助我们创建一个对象(globalObject -> go)
 * var globalObject = {
 *  String: "类",
 *  Date: "类",
 *  setTimeout: "函数",
 *  window: globalObject,
 *  name: undefined,
 *  num1: undefined,
 *  num2: undefined,
 *  result: undefined
 * };
 * 2.运行代码
 *  >2.1.v8为了执行代码,v8引擎内部会有一个执行上下文栈(Execution Context ECStack)(函数调用栈)
 *  2.2.因为我们执行的是全局代码,为了全局代码能够正常的执行,需要创建全局执行上下文(Global Context ECStack)(全局代码需要被执行才会创建)
 *    >2.2.1.生成一个VO(Variable Object)
 *      VO = var globalObject = {
 *        String: "类",
 *        Date: "类",
 *        setTimeout: "函数",
 *        window: globalObject,
 *        name: undefined,
 *        num1: undefined,
 *        num2: undefined,
 *        result: undefined
 *      };
 *    >2.2.1.开始执行代码
 *    var globalObject = {
 *      String: "类",
 *      Date: "类",
 *      setTimeout: "函数",
 *      window: globalObject,
 *      name: "why",
 *      num1: 20,
 *      num2: 30,
 *      result: 50
 *    };
 *    如果console.log(result) =>   打印50
 *    如果在var name1 = "20;之前console.log(name1) 打印undefined
 *    window.num1 = 20
 *    window.num2 = 30
 *    window.result = 50
 */
// undefined
// 50
// window

var name = "why";
function foo() {
  console.log("foo");
}
foo();
var num1 = 20;
var num2 = 30;
var result = num1 + num2;
// foo

var name = "why";
foo();
function foo() {
  console.log("foo");
}
var num1 = 20;
var num2 = 30;
var result = num1 + num2;
// foo

var name = "why";
foo(123);
function foo(num) {
  console.log(m);
  var m = 10;
  var n = 20;
  console.log("foo");
}
/**
 * 编译
 *  var GlobalObject = {
 *    String: "类",
 *    window: GlobalObject,
 *    name: undefined,
 *    foo: foo的地址值 => {   地址值  内存中开辟一块空间,保存foo函数(父级作用域,执行的代码块)
 *      num: undefined
 *      m: undefined
 *      n: undefined
 *    }
 *  }
 * 执行
 *  var GlobalObject = {
 *    String: "类",
 *    window: GlobalObject,
 *    name: "why",
 *    foo: foo的地址值 => {
 *      num: 123
 *      m: 10
 *      n: 20
 *    }
 *  }
 */
// undefined
// foo

var name = "why";
foo(123);
function foo(num) {
  console.log(m);
  var m = 10;
  var n = 20;
  var name = "foo";
  console.log(name);
}
/**
 * 编译
 *  var GlobalObject = {
 *    String: "类",
 *    window: GlobalObject,
 *    name: undefined,
 *    foo: foo的地址值 => {   地址值  内存中开辟一块空间,保存foo函数(父级作用域,执行的代码块)
 *      num: undefined
 *      m: undefined
 *      n: undefined,
 *      name: undefined
 *    }
 *  }
 * 执行
 *  var GlobalObject = {
 *    String: "类",
 *    window: GlobalObject,
 *    name: "why",
 *    foo: foo的地址值 => {
 *      num: 123
 *      m: 10
 *      n: 20,
 *      name: "foo"
 *    }
 *  }
 */
// undefined
// foo

作用域链

  • 当我们查找一个变量时,真实的查找路径是沿着作用域链来查找的
var name = "why";
foo(123);
function foo(num) {
  console.log(m);
  var m = 10;
  var n = 20;
  console.log(name);
}
/**
 * 编译
 *  var GlobalObject = {
 *    String: "类",
 *    window: GlobalObject,
 *    name: undefined,
 *    foo: foo的地址值 => {   地址值  内存中开辟一块空间,保存foo函数(父级作用域,执行的代码块)
 *      num: undefined
 *      m: undefined
 *      n: undefined
 *    }
 *  }
 * 执行
 *  var GlobalObject = {
 *    String: "类",
 *    window: GlobalObject,
 *    name: "why",
 *    foo: foo的地址值 => {
 *      num: 123
 *      m: 10
 *      n: 20
 *    }
 *  }
 */
// undefined
// why
var name = "why";
foo(123);
function foo(num) {
  console.log(m);
  var m = 10;
  var n = 20;
  function bar() {
    console.log(name);
  }
  bar();
}
/**
 * 编译
 *  var GlobalObject = {
 *    String: "类",
 *    window: GlobalObject,
 *    name: undefined,
 *    foo: foo的地址值 => {   地址值  内存中开辟一块空间,保存foo函数(父级作用域,执行的代码块)
 *      num: undefined
 *      m: undefined
 *      n: undefined,
 *      bar: bar的地址 => {  地址值  内存中开辟一块空间,保存bar函数(父级作用域,执行的代码块}
 *    }
 *  }
 * 执行
 *  var GlobalObject = {
 *    String: "类",
 *    window: GlobalObject,
 *    name: "why",
 *    foo: foo的地址值 => {
 *      num: 123
 *      m: 10
 *      n: 20
 *      bar: bar的地址值 => {}
 *    }
 *  }
 */
// undefined
// why
foo(123);
function foo(num) {
  console.log(m);
  var m = 10;
  var n = 20;
  function bar() {
    console.log(name);
  }
  bar();
}
// name is not defined
var age = 100;
foo(123);
function foo(num) {
  console.log(m);
  var m = 10;
  var n = 20;
  function bar() {
    console.log(age);
  }
  bar();
}
// undefined
// 100
foo(123);
function foo(num) {
  console.log(m);
  var m = 10;
  var n = 20;
  function bar() {
    console.log(age);
  }
  bar();
}
// age is not defined
var message = "Hello Global";
function foo() {
  console.log(message);
}
function bar() {
  var message = "Hello Bar";
  foo();
}
bar();
// Hello Global
var message = "Hello Global";
function foo() {
  console.log(message);
}
function bar() {
  var message = "Hello Bar";
  foo();
}
bar();
/**
 * 编译
 *   var GlobalObject = {
 *    window: GlobalObject,
 *    message: undefined,
 *    foo: foo的地址值,
 *    bar: bar的地址值 => {
 *      message: undefined,
 *      foo: 和之前foo的地址值相同,为同一个
 *    }
 *  }
 * 执行
 *   var GlobalObject = {
 *    window: GlobalObject,
 *    mesage: "Hello Global"
 *    foo: foo的地址值,
 *    bar: bar的地址值 => {
 *      message: "Hello Bar",
 *      foo: 和之前foo的地址值相同,为同一个
 *    }
 *  }
 */
// Hello Global
变量环境和记录.png

作用域面试题

var n = 100;
function foo() {
  n = 200;
}
foo();
console.log(n);
/**
 * 编译
 *   var GlobalObject = {
 *    window: GlobalObject,
 *    n: undefined,
 *    foo: foo的地址值
 *  }
 * 执行
 *   var GlobalObject = {
 *    window: GlobalObject,
 *    n: 100,
 *    foo: foo的地址值 => {
 *      n: 200
 *    }
 *  }
 */
// 200
function foo() {
  console.log(n);
  var n = 200;
  console.log(n);
}
var n = 100;
foo();
/**
 * 编译
 *   var GlobalObject = {
 *    window: GlobalObject,
 *    n: undefined,
 *    foo: foo的地址值 => {
 *      n: undefined
 *    }
 *  }
 * 执行
 *   var GlobalObject = {
 *    window: GlobalObject,
 *    n: 100,
 *    foo: foo的地址值 => {
 *      n: 200
 *    }
 *  }
 */
// undefined
// 200
var n = 100;
function foo1() {
  console.log(n);
}
function foo2() {
  var n = 200;
  console.log(n);
  foo1();
}
foo2();
console.log(n);
/**
 * 编译
 *   var GlobalObject = {
 *    window: GlobalObject,
 *    n: undefined,
 *    foo1: foo1的地址值 => {}
 *    foo2: foo2的地址值 => {
 *      n: undefined,
 *      foo1: foo1的地址值 => {}
 *    }
 *  }
 * 执行
 *   var GlobalObject = {
 *    window: GlobalObject,
 *    n: 100,
 *    foo1: foo1的地址值 => {
 *       n: 100,
 *       foo1: foo1的地址值 => {}
 *    }
 *    foo2: foo2的地址值 => {
 *      n: 200
 *    }
 *  }
 */
// 200
// 100
// 100
var a = 100;
function foo() {
  console.log(a);
  return;
  var a = 100;
}
foo();
/**
 * 编译
 *   var GlobalObject = {
 *    window: GlobalObject,
 *    n: undefined,
 *    foo: foo的地址值 => {
 *      n: undefined
 *    }
 *  }
 * 执行
 *   var GlobalObject = {
 *    window: GlobalObject,
 *    n: 100,
 *    foo: foo的地址值 => {
 *      n: undefined
 *    }
 *  }
 */
// undefined
function foo() {
  var m = 100;
}
foo();
console.log(m);
// m is not defined
function foo() {
  m = 100;
}
foo();
console.log(m);
// 100
function foo() {
  var a = (b = 100);
}
foo();
console.log(a);
console.log(b);
// a is not defined
function foo() {
  var a = (b = 100);
}
foo();
console.log(b);
console.log(a);
// 100
// a is not defined
function foo() {
  var a = (b = 10);
  /**
   * var a = (b = 10); 转化为
   *  var a = 10
   *  b = 10
   */
}
foo();
console.log(b);
console.log(a);
// 19
// a is not defined

内存管理

内存管理

  • 不管什么样的编程语言,在代码的执行过程中都是需要给它分配内存的
    • 某些编程语言需要我们自己手动的管理内存
    • 某些编程语言会可以自动帮助我们管理内存

JavaScript的内存结构

  • 栈结构
  • 堆结构
var name = "why";
var age = 18;
var obj = { name: "kobe", age: 40 };
var names = ["abc", "cba"];
/**
 * 栈
 *  var name = "why"
 *  var age = 18;
 *  var obj => 堆  返回一个地址值 0xobj
 *  var names => 堆  返回一个地址值 0xnames
 * 堆
 *  0xobj { name: "kobe", age: 40 }
 *  0xnanes ["abc", "cba"]
 */
const obj = { name: "why" };
var info = { name: "kobe", friend: obj };
var p = { name: "james", friend: obj };
/**
 * 栈
 *  var obj => 堆 0xobj
 *  var info => 堆 0xinfo
 *  var p => 0x - p
 * 堆
 *  0xobj { name: "why" }
 *  0xinfo { name: "kobe", friend: 0xobj }
 *  0xp { name: "james", friend: 0xobj }
 * 垃圾回收期
 *  引用计数法
 *    指向obj
 *      指向一次 +1
 *      少一次指向  -1
 *      当为0时, 就GC被回收
 *    弊端
 *      引用计数存在一个很大的弊端 : 循环引用
 *      示例
 *        var obj1 = { friend: obj2 };
 *        var obj2 = { friend: obj1 };
 *    标记清除
 *      看附带图片
 */

垃圾回收器

  • 英文
    • Garbage Collection,简称GC
  • 对于那么不再使用的对象,我们都称之为是垃圾,他需要被回收,已释放更多的内存空间
  • 而我们的语言运行环境,比如Java的运行环境JVM,JavaScript的运行环境JS引擎都会内存垃圾回收器

GC算法

垃圾回收机制-引用计数.png
垃圾回收机制-标记清除.png
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容