zoukankan      html  css  js  c++  java
  • Javascript高级之变量、作用域与内存

    变量、作用域与内存

    原始值与引用值

    • 理解要点

      • ECMAScript中所有函数的参数都是按值传递的
      • 函数外的值会被复制到函数内部的参数中
      • 关于引用值(对象),也是按值传递的
        • 理解
          • 对象中保存的值是对象的key,也就是指针
          • 函数中按值传递时,可以给指针赋值,影响全局变量
          • 但是改变不了对象的key
          • 可以用对象的动态属性来理解
    • 确定类型

      • 如果变量是给定引用类型的实例,则instanceof操作符返回true
      • 如果用instanceof检测原始值,则始终会返回false
    let obj= null;
    let obj2= {};
    let fun= Function.prototype;
    let fun2= new Function();
    let arr= [];
    let str= '';
    let reg= new RegExp();
    let date= new Date();
    
    console.log(obj instanceof Object);     // false
    console.log(obj2 instanceof Object);    // true
    console.log(fun instanceof Function);   // false
    console.log(fun2 instanceof Function);  // true
    console.log(arr instanceof Array);      // true
    console.log(str instanceof String);     // false
    console.log(reg instanceof RegExp);     // true
    console.log(date instanceof Date);      // true
    

    执行上下文与作用域

    • 执行上下文

      • 每个上下文都有一个关联的变量对象
      • 所有变量和函数都存在于这个对象上
      • 这个对象就是上下文栈,在其所有代码执行完毕之后,就会被销毁
      • var定义的全局变量和函数,会成为window对象的属性和方法
    • 作用域链

      • 上下文中的代码在执行的时候,会创建变量对象的一个作用域链
      • 作用域链决定了各级上下文中的代码在访问变量和函数时的顺序
      • 如果上下文是函数,则其活动对象用作变量对象
      • 活动对象最初只有一个定义变量:arguments
        • arguments是包含函数形参的一个对象
        • 全局上下文没有这个变量
    • 作用域链增强

      • 在作用域链前端添加一个变量对象
        • with语句
          • 会向作用域链前端添加指定的对象
        • try/catch语句中的catch块
          • 会创建一个新的变量对象,这个变量对象会包含要抛出的错误对象的声明

    变量声明

    • 使用var的函数作用域声明

      • 变量会被自动添加到最接近的上下文
      • 未声明的变量,会自动被添加到全局上下文
      • var声明会被拿到函数或全局作用域的顶部,叫做提升
    • 使用let的块级作用域声明

      • 块级作用域由最近的一对包含花括号{}界定
      • let在同一作用域内不能声明两次
      • let非常适合在循环中声明迭代变量
    • 使用const的常量声明

      • const声明的变量必须同时初始化为某个值
      • const声明只应用到顶级原语或者对象
      • 使用Object.freeze()给对象赋值常量

    垃圾回收

    • 标记清理

      • 先给当前不使用的值加上标记,再回来回收它们的内存
    • 引用计数

      • 对每个值都记录它被引用的次数
      • 当引用次数为0时,垃圾回收程序会释放引用数为0的值的内存
    • 循环引用

      • 对象A有一个指针指向对象B,而对象B也引用了对象A
      • 只要涉及COM对象,就无法避免循环引用的问题

    内存管理

    • 解除引用

      • 如果数据不再必要,那么把它设置为null,从而释放其引用
    • 通过const和let声明提升性能

      • 块作用域比函数作用域更早让垃圾回收程序介入
    • 隐藏类和删除操作

      • 在构造函数中一次性声明所有的属性,因此实例共享隐藏类
      • 把不想要的属性设置为null,可以保持隐藏类不变和继续共享
    • 内存泄漏

      • 没有使用关键字声明变量
      • 定时器的回调通过闭包引用了外部变量
      • 闭包造成的内存泄漏
    • 静态分配和对象池

      • 避免动态分配操作
  • 相关阅读:
    查看变量是否删除在鼠标工具中用到了。
    poly 顶点坐标的函数
    out/target/product/generic/obj/EXECUTABLES/BufferQueue_test_intermediates/LINKED/BufferQueue_test] Error 1
    undefined reference to `pthread_mutexattr_destroy'
    [out/host/linuxx86/obj/STATIC_LIBRARIES/libutils_intermediates/RefBase.o] Error 1
    can't find a register in class `GENERAL_REGS' while reloading `asm'
    error: ‘ptrdiff_t’ does not name a type
    armeabi4.4.3 引起的错误
    error: "_FORTIFY_SOURCE" redefined [Werror]
    :0:0: 错误: “_FORTIFY_SOURCE”重定义 [Werror]
  • 原文地址:https://www.cnblogs.com/SharkJiao/p/14160468.html
Copyright © 2011-2022 走看看