IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 第4章 变量、作用域与内存 -> 正文阅读

[JavaScript知识库]第4章 变量、作用域与内存

第4章 变量、作用域与内存

4.1 原始值和引用值

  • 原始值 primitive value 保存原始值的变量是按值 by value访问的,操作的是存储在变量中的实际值,例如下面的6中原始值
    • Undefined
    • Null
    • Boolean
    • Number
    • String
    • Symbol
  • 引用值 reference value 引用值是保存在内存中的对象,JavaScript不允许直接访问内存位置,不能直接操作对象所在的内存空间,操作对象时,实际上操作的是该对象的引用 reference

注意 在很多语言中,字符串是使用对象表示,因此被认为是引用类型,但是ECMAScript打破了这个惯例

4.1.1 动态属性

动态属性的意思是对于引用值而言,可以随时添加、修改、删除其属性和方法

let person = new Object();
person.name = "冬篱的川";
console.log(person.name);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3cYEaPhr-1626868188152)(https://i.loli.net/2021/07/21/Toxk9Amn7wb6D3Y.png)]

但是如果给原始值添加属性或者方法,虽然不会报错,但是会报undefined

let name = "冬篱的川";
name.age = 23;
console.log(name.age);

image-20210721101130778

4.1.2 复制值

  • 原始值在复制变量到另一个变量时,原始值会被复制到新变量的位置,实际上的内存区域不同
  • 引用值从一个变量赋值到另一个变量时,复制的值实际上是一个指针,同时指向堆内存中的同一个对象

4.1.3 传递参数

可以这样理解:ECMAScript中所有函数的参数都是按值传递的,即引用值按照引用值复制值得方式,传递的是变量的引用;而原始值就是原始值的变量复制一样

4.1.4 确定类型

typeof操作符最适合判断一个变量是否为原始类型,是判断一个变量是否为字符串、数值、布尔值或undefined的最好方式,但是如果值是对象或null,那么typeof则返回object

let s = "冬篱的川";
let b = true;
let i = 22;
let u;
let n = null;
let o = new Object();

console.log(typeof s);
console.log(typeof b);
console.log(typeof i);
console.log(typeof u);
console.log(typeof n);
console.log(typeof o);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-weUCQoQ3-1626868188157)(https://i.loli.net/2021/07/21/SFrp9uwE1Gnmsdx.png)]

4.2 执行上下文与作用域

  • 全局上下文是最外层的上下文

  • 浏览器中的全局上下文是windows对象,所有通过var指定的全局变量和函数都会成为window对象的属性和方法

  • 上下文中的代码在执行的时候,会创建变量对象的一个作用链域 scope chain

  • 代码执行时的标识符解析是通过作用链域逐级搜索标识符名称完成的。搜索的过程始终从作用域链的最前端开始,然后逐级往后,直到找到标识符。

  • 局部作用域中定义的变量可以用于在局部上下文替换全局变量。

var color = "blue";

function changeColor() {
    let anotherColor = "red";
    
    function swapColors() {
        let tempColor = anotherColor;
        anotherColor = color;
        color = tempColor;
        
        // 这里可以访问 color, anotherColor, tempColor
    }
    
    // 这里可以访问 color,anotherColor, 不能访问 tempColor
    swapColor();
}

// 这里只能访问 color
changeColor();
  • 注意 函数参数是被认为当前上下文的变量

4.2.1 作用域增强

  • try/catch语句的catch
  • with语句

这两种情况都会在作用域链前端添加一个变量对象。

  • 对于with语句来讲,会向作用链域前端添加指定的对象
function buildUrl() {
    let qs = "?debug=true";
    
    with(location) {
        let url = href + qs;
    }
    
    return url;
}

这里,with语句将location对象作为上下文,因此location对象会被添加到作用链域最前端。这里的href变量实际上是引用的location.href变量

4.2.2 变量声明

  1. 使用var的函数作用域声明

使用var声明变量时,变量会自动添加到最接近的上下文,函数中最接近的上下文是函数的上下文,在with 语句中,最接近的上下文也是函数上下文。如果变量未经声明就被初始化了,那么它将自动的被添加到全局上下文。

var声明会被拿到函数或全局作用域的顶部,位于作用域中所有代码之前,这个现象就做提升 hoisting。提升让同一作用域的代码不必考虑变量是否已经声明就可以直接使用。

function test() {
    {
        var name = "冬篱的川";
    }
    console.log(name);
}

test();// 冬篱的川

function test2() {
    {
        let name = "冬篱的川";
    }
    console.log(name);
}

test()2;// Uncaught ReferenceError: name is not defined

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-umEe19fS-1626868188160)(https://i.loli.net/2021/07/21/YHEpZWtcK829seM.png)]

  1. 使用let的块级作用域声明
  • 块级作用域是由最近的一对包含花括号的{}界定,即if while function 块,甚至单独的块也是let声明变量的作用域
  • let在同一作用域不能声明两次,重复声明会跑出SyntaxError,重复的var声明会被忽略
    • let上面的行为就非常适合在循环中声明迭代变量,因为使用var的迭代变量会泄漏到循环外部
  1. 使用const的常量声明
  • 使用const声明的变量必须同时初始化为某个值,一经声明,在其生命周期的任何时候都不能在重新赋予新值
const a; // SyntaxError: 常量变量声明时没有初始化

const b = 3;
console.log(b); // 3
b = 4; // TypeError: 给常量赋值

image-20210721150624904

  • const声明值应用到顶级原语或对象,赋值为对象的cosnt变量不能被重新赋值为其它的引用值,但是对象的键不受限制
const o = {};
o.name =  "冬篱的川";
console.log(o.name); // 冬篱的川

image-20210721151215403

但是如果想让整个对象都不能修改,可以使用Object.freeze()方法,这样再给属性赋值时虽然不会报错,当会静默失败:

const o2 = Object.freeze({});
o2.name = "冬篱的川";
console.log(o2.name); // undefined

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0aIR0mK8-1626868188166)(https://i.loli.net/2021/07/21/WTZabR4cxMP9OC3.png)]

由于 const 声明暗示变量的值是单一类型且不可修改, JavaScript 运行时编译器可以将其所有实例都替换成实际的值,而不会通过查询表进行变量查找

注意 开发实践表明,如果开发流程并不会因此而受很大影响,就应该尽可能地多使用const声明,除非确实需要一个将来会重新赋值的变量。这样可以从根本上保证提前发现重新赋值导致的 bug

  1. 标识符查找

标识符查找开始与作用域链前端,以给定的名称搜索对应的标识符,如果在局部上下文中找到该标识符,则搜索停止,变量确定;如果没有,则继续沿作用链域搜索,这个过程一直持续到搜索至全局上下文的变量对象,如果仍未找到,则说明其未声明

4.3 垃圾回收

  • JavaScript是使用垃圾回收的语言,就是说执行环境负责代码执行时管理内存
  • JavaScript通过自动内存管理实现内存分配和闲置资源回收,主要是靠周期性的确定那个变量不再使用,然后释放内存

4.3.1 标记清理 mark-and-sweep

垃圾回收程序运行的时候,会标记内存中存储的所有变量(记住,标记方法有很多种)。然后,它会将所有在上下文中的变量,以及被在上下文中的变量引用的变量的标记去掉。在此之后再被加上标记的变量就是待删除的了,原因是任何在上下文中的变量都访问不到它们了。随后垃圾回收程序做一次内存清理,销毁带标记的所有值并收回它们的内存

即是把引用的变量的标记去掉,未引用的标记,然后释放

4.3.2 引用计数 reference counting

其思路是对每个值都记录它被引用的次数。声明变量并给它赋一个引用值时,这个值的引用数为 1。如果同一个值又被赋给另一个变量,那么引用数加 1。类似地,如果保存对该值引用的变量被其他值给覆盖了,那么引用数减 1。当一个值的引用数为 0 时,就说明没办法再访问到这个值了,因此可以安全地收回其内存了。垃圾回收程序下次运行的时候就会释放引用数为 0 的值的内存

这里会遇到循环引用的问题,即A引用B,B也引用A

function problem() {
    let a = {};
    let b = {};
    
    a.b = b;
    b.a = a;
}

4.3.3 性能

垃圾回收程序会周期性运行,如果内存中分配了很多变量,则可能造成性能损失,因此垃圾回收的时间调度很重要。尤其是在内存有限的移动设备上,垃圾回收有可能会明显拖慢渲染的速度和帧速率。开发者不知道什么时候运行时会收集垃圾,因此最好的办法是在写代码时就要做到:无论什么时候开始收集垃圾,都能让它尽快结束工作

4.3.4 内存管理

将内存占用量保持在一个较小的值可以让页面性能更好。优化内存占用的最佳手段就是保证在执行代码时只保存必要的数据。如果数据不再必要,那么把它设置为 null,从而释放其引用。这也可以叫作解除引用

  1. 通过constlet 声明提升性能, 块级作用域能够更早地让垃圾回收程序介入
  2. 隐藏类和删除操作
  3. 内存泄漏
  4. 静态分配与对象池
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-22 22:57:51  更:2021-07-22 22:58:12 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/6 6:14:20-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码