JS深入学习笔记 - 第三章.变量作用域与内存
1.原始值和引用值
ECMScript变量包含两种不同类型是数据:原始值和引用值。
原始值:最简单的数据。有6中原始值:Undefined、Null、Boolean、Number、String和Symbol。原始值是按值访问。
引用值:由多个值构成的对象。三大引用类型:1.object 2.Array类型 3.Function类型。引用值是保存在内存中的对象,由于js不允许直接访问内存位置,所以对引用值的访问是访问该对象的引用而非对象本身。
这里可以类比java中的基本数据类型和引用数据类型。
2.复制
通过变量把一个原始值复制到另一个另一个变量时,原始值会在内存中增加一个值,赋值为新的变量,如num2上
let num1 = 5
let num2 = num1
此时修改num1 的值,猜一猜会不会对num2有影响?
let num1 = 5;
let num2 = num1;
num1 = 545454;
console.log(num2);//5
答案是不会的,因为在上面提到了,num1与num2对应的是两个独立的值。

但是如果是引用值呢?
let arr1 = [1,2]
let arr2 = arr1
arr1.push(6)
console.log(arr2)//(3) [1, 2, 6]
欸?arr2也改变了呢,是什么原因呢?
原因是这里的复制的值实际上是一个指针,它指向存储在堆内存中的对象。他们指向的是同一个值。

那如果传递是对象呢?
//对象
function setName(obj) {
obj.name = "zooey";
}
const person = new Object();
setName(person);
console.log(person.name); //zooey
此时对象类型person复制给obj,看起来很像是引用类型的改变,
但是事实上,对象仍然是按值传进函数的,但是obj是按照引用访问的person,怎么?你不信?
//对象
function setName(obj) {
obj.name = "zooey";
obj = {
name: "anan",
};
console.log(obj.name);//anan
}
const person = new Object();
setName(person);
console.log(person.name); //zooey
看吧,的确是没有改掉吧,确实是按值引用。
令人觉得很复杂,对吧。
object对象本身是按值访问的,而对象的属性则是按照引用访问的
3.确定类型
1.typeof
最适合用来判断变量是否是原始类型。更确切的说它是判断一个变量是否是字符串、数值、布尔值或者undefined的最好的方式。
et str = "absce";
let num = 12;
let boo = true;
let und = undefined;
let obj = { name: "aaa" };
console.log(typeof num); //number
console.log(typeof str); //string
console.log(typeof boo); //boolean
console.log(typeof und); //undefined
console.log(typeof obj); //object
但是,typeof对引用值的作用不大
2.instanceof
按照定义,所有引用值都是Object的实例,因此通过instanceof操作符检测任何引用值和Object构造函数都会返回true。
类似的,如果用instanceof检测原始值,则始终会返回false,因为原始值不是对象。
let arr = [1, 23, 4];
let fun = () => {
console.log("i am function");
};
class Myclass {
constructor() {
name;
}
}
function Cons() {
return "sss";
}
console.log(typeof arr); //object
console.log(typeof fun); //function
console.log(typeof Myclass); //function
console.log(typeof Cons); //function
console.log(arr instanceof Array); //true
console.log(fun instanceof Function); //true
console.log(Myclass instanceof Function); //true
console.log(Cons instanceof Function); //true
4.执行上下文和作用域
1.什么是执行上下文(以下简称上下文)?
变量和函数的上下文决定了它们可以访问哪些数据,以及他们的行为。
每个上下文都有一个关联 变量对象(variable object),而这个上下文中定义的所有变量和函数都存在于这个对象上。虽然没办法通过代码真正的访问它。
2.什么是全局上下文?
最外层的上下文。在浏览器中,全局上下文就是我们常说的window对象,因此,所有通过var定义的全局变量和函数都会成为window对象的属性和方法
3.上下文什么时候销毁?
上下文在其所有的代码都执行完毕后会被销毁,包括定义在它上面的所有变量和函数。
全局上下文在应用程序退出前才会被销毁,比如关闭页面或者退出浏览器。
4.上下文的执行流程
每个函数调用都有自己的上下文。当代码执行流进入到函数时,函数的上下文被推到一个上下文栈上,在函数执行文之后,上下文栈会弹出该函数上下文,将控制器泛黄之前的执行上下文。ECMAScript程序的执行流就是通过这个上下文栈进行控制的。
上下文中代码在执行的时候,会创建变量对象的一个作用域链(scope chain),这个作用域链决定看各级上下文中代码在访问变量和函数时的顺序。代码正在执行的上下文的变量对象始终位于作用域的最前端。
5.标识符解析在上下文中的寻找规则
代码执行时的标识符解析时通过沿着作用域链逐级搜索标识符名称完成的。搜索过程始终从作用域链的最前端开始,然后逐级往后,直到找到标识符。(如果没有找到则会报错)
let name = "zooey";
function getName() {
let myname = "anan";
if (name === "zooey") {
name = myname;
} else {
name = "zooey";
}
}
getName();
console.log(name); //anan
在这个例子中,函数getName的作用域链包含两个对象“一个是他自己的变量对象myname,一个是全局上下文的变量对象name,之所有能够访问color,就是因为可以在作用域链中找到它。
此外,局部作用域中定义的变量可以用于在局部上下文中替换全局变量。
总结一下:
类似于java的局部变量和全局变量,
局部上下文中的变量只能在本作用域中使用
全局上下文中的变量可以在全局使用
如果包含嵌套关系,那么父作用域中的变量,子作用域也可以使用 。
即,内部上下文可以通过作用域链访问外部上下文中的一切,但外部上下文无法访问内部上下文中的任何东西。
每个上下文都可以到上一级上下文中去搜索变量和函数,但任何上下文都不能去下一级上下文中去搜索。
(此处举一个不恰当的例子,儿子可以继承父亲的房子,换掉父亲的凳子椅子,但是父亲不能继承儿子的房子,换掉儿子的家具,儿子会生气的~)
注意:函数参数(实参)被认为是当前上下文中的变量,因此也跟上下文中的其他变量遵循相同的访问规则。
JS深入学习笔记 - 第三章.变量作用域与内存的更多相关文章
- JVM学习笔记-第三章-垃圾收集器与内存分配策略
JVM学习笔记-第三章-垃圾收集器与内存分配策略 tips:对于3.4之前的章节可见博客:https://blog.csdn.net/sanhewuyang/article/details/95380 ...
- The Road to learn React书籍学习笔记(第三章)
The Road to learn React书籍学习笔记(第三章) 代码详情 声明周期方法 通过之前的学习,可以了解到ES6 类组件中的生命周期方法 constructor() 和 render() ...
- Spring学习笔记 - 第三章 - AOP与Spring事务
原文地址:Spring学习笔记 - 第三章 - AOP与Spring事务 Spring 学习笔记全系列传送门: Spring学习笔记 - 第一章 - IoC(控制反转).IoC容器.Bean的实例化与 ...
- 《DOM Scripting》学习笔记-——第三章 DOM
<Dom Scripting>学习笔记 第三章 DOM 本章内容: 1.节点的概念. 2.四个DOM方法:getElementById, getElementsByTagName, get ...
- [HeadFrist-HTMLCSS学习笔记]第三章构建模块:Web页面建设
[HeadFrist-HTMLCSS学习笔记]第三章构建模块:Web页面建设 敲黑板!! <q>元素添加短引用,<blockquote>添加长引用 在段落里添加引用就使用< ...
- Qt 学习笔记 - 第三章 - Qt的三驾马车之一 - 串口编程 + 程序打包成Windows软件
Qt 学习笔记全系列传送门: Qt 学习笔记 - 第一章 - 快速开始.信号与槽 Qt 学习笔记 - 第二章 - 添加图片.布局.界面切换 [本章]Qt 学习笔记 - 第三章 - Qt的三驾马车之一 ...
- JavaScript高级编程学习笔记(第三章之一)
继续记笔记,JavaScript越来越有意思了. 继续... 第三章:JavaScript基础 ECMAScript语法在很大程度上借鉴了C和其它类似于C的语言,比如Java和Perl. 大小写敏感: ...
- python学习笔记——第三章 串
第三章 字符串学习 1.字符串不灵活, 它不能被分割符值 >>> format = "hello, %s. %s enough for ya?" >> ...
- Java 学习笔记 ------第三章 基础语法
本章学习目标: 认识类型与变量 学习运算符的基本使用 了解类型转换细节 运用基本流程语法 一.类型(基本类型) 所谓基本类型,就是在使用时,得考虑一下数据用多少内存长度存比较经济,利用程序语法告诉JV ...
- c#高级编程第七版 学习笔记 第三章 对象和类型
第三章 对象和类型 本章的内容: 类和结构的区别 类成员 按值和按引用传送参数 方法重载 构造函数和静态构造函数 只读字段 部分类 静态类 Object类,其他类型都从该类派生而来 3.1 类和结构 ...
随机推荐
- 记一次 .NET 某药材管理系统 卡死分析
一:背景 1. 讲故事 前段时间有位朋友找到我,说他们在查询报表的时候发现程序的稳定性会受到影响,但服务器的内存,CPU都是正常的,让我帮忙看下怎么回事,问了下程序的稳定性指的是什么?指的是卡死,那既 ...
- 【QCustomPlot】使用方法(源码方式)
说明 使用 QCustomPlot 绘图库辅助开发时整理的学习笔记.同系列文章目录可见 <绘图库 QCustomPlot 学习笔记>目录.本篇介绍 QCustomPlot 的一种使用方法, ...
- CF1810G The Maximum Prefix
经典套路. 题意 你将随机生成一个长度为 \(k\) 的数组 \(a\),其中 \(a_i\) 有 \(p_i\) 概率为 \(1\),否则为 \(-1\).定义其前缀和数组 \(s_i = \sum ...
- SQL SERVER 查看表说明,字段属性
查询表字段属性,说明等: 1 SELECT 2 表名=case when a.colorder=1 then d.name else '' end, 3 表说明=case when a.colorde ...
- [HUBUCTF 2022 新生赛]simple_RE
[HUBUCTF 2022 新生赛]simple_RE 查壳,64位 找main函数,F5查看伪代码,简单分析一下 int __cdecl main(int argc, const char **ar ...
- C语言变量常量
目录 前言 一.数据类型 1.整形 2.浮点型 3.字符型 二.变量的操作 1.变量的创建 2.变量的使用 2.1 变量的赋值 2.2 变量的加减 2.3 变量的隐式类型转换 2.4 强制类型转换 3 ...
- Centos7 安装部署 Kubernetes(k8s) 高可用集群
目录 一.系统环境 二.前言 三.Kubernetes(k8s)高可用简介 四.配置机器基本环境 五.部署haproxy负载均衡器 六.部署etcd集群 七.部署Kubernetes(k8s) mas ...
- Spring 的依赖注入
Spring 的依赖注入 @ 目录 Spring 的依赖注入 每博一文案 1. 依赖注入 1.1 构造注入 1.1.1 通过参数名进行构造注入 1.1.2 通过参数的下标,进行构造注入 1.1.3 不 ...
- Object.equals 和 String.equals的区别
一. 源码展示: 1. Object.equals: ①引用类型地址值比较,直接返回结果:true || false public class Object { public boolean equ ...
- Centos7下Oracle启动命令
1.查询挂载历史记录 在root账户下使用一下命令 查看历史使用挂载的那个磁盘 # 查看挂载历史命令 history | grep mount # 调用挂载历史命令,主要是为了找到挂载Oracle的磁 ...