JavaScript 【变量、作用域和内存问题】基本类型和引用类型的值
以下大部分为学习《JavaScript 高级程序设计》》(第 3 版) 所做笔记。
目录:
1、动态的属性
2、复制变量值
3、传递参数
4、检测类型
ES 变量可能包含 2 种不同数据类型的值:基本类型值和引用类型值。
基本类型值(也叫简单数据类型)指的是简单的数据段。Undefined、Null、Boolean、Number 和 String 都是基本类型,它们是按值访问的,保存在栈中。
引用类型值是保存在内存中的对象。Object 是引用类型,是按引用访问的。保存在堆中。JS不允许直接访问内存中的位置,在操作对象时,实际上是操作对象的引用而不是实际的对象。
对于引用类型值,我们可以为其添加属性和方法,也可以改变其属性和方法。对于基本类型值,我们不能给其添加属性,尽管这样不会导致错误。
1 <script> 2 //引用类型的值 3 var a = new Object(); 4 a.name = "xiaoxu"; 5 console.log( a.name ); //输出:xiaoxu 6 //基本类型的值 7 var b = "nana"; 8 b.age = 22; 9 console.log( b.age ); //输出:undefined 10 </script>
① 基本类型值的复制
1 <script> 2 //num1 保存的值是 5 3 var num1 = 5; 4 //num2 保存了 5的一个副本,变量 num1 跟 num2 相互独立、互不影响 5 var num2 = num1; 6 console.log( num1 ); //输出:5 7 console.log( num2 ); //输出:5 8 num2 = 12; 9 console.log( num1 ); //输出:5 10 console.log( num2 ); //输出:12 11 </script>
②引用类型值的复制
1 <script> 2 var obj1 = new Object(); 3 //一个变量向另一个变量复制引用类型的值,这个值是一个指针,指针指向存储在堆中的一个对象 4 var obj2 = obj1; 5 //两个变量将引用同一个对象,改变其中一个变量,会影响另一个变量 6 obj.name = "xiaoxu"; 7 console.log( obj2.name ); 8 </script>
参数只能按值传递。 基本类型值的传递如同基本类型值的复制一样,引用类型值的传递如同引用类型变量的复制一样。
① 向参数传递基本类型的值
在向参数传递基本类型的值时,被传递的值会被复制给一个局部变量(即命名参数,或者用 ES 的概念来说,就是 arguments 对象的一个元素)。
1 <script> 2 //函数的参数实际上是函数的局部变量 3 function addTen( num ){ 4 num += 10; 5 return num; 6 } 7 var count = 20; 8 //调用函数,变量 count 作为参数被传递给函数,数值20被复制给 num 9 //参数按值传递,所以 count 跟 num 相互独立互不影响 10 //可以看到 num 在函数内部进行运算后变成了 30, 但是函数外部的 count 仍为20,说明了它们的确是按值传递的 11 var result = addTen( count ); 12 console.log( count ); //输出:20 13 console.log( result ); //输出:30 14 </script>
②向参数传递引用类型的值
在向参数传递引用类型的值时,会把这个值在内存中的地址复制给一个局部变量,因此这个局部变量的变化会反映在函数的外部。
1 <script>setName 2 function setName( obj ){ 3 obj.name = "xiaoxu"; 4 //重写 obj ,变量 obj 这是引用的是一个局部对象,这个局部对象会在函数执行完毕立即销毁 5 obj = new Object(); 6 obj.name = "mona"; 7 } 8 var person = new Object(); 9 setName( person ); 10 console.log( person.name ); //输出:xiaoxu 11 </script>
说明:
根据我的理解,将变量 person 传递给 setName() 函数之后被复制给了 obj, 变量值是 person 指向的对象的内存地址。每个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。函数 setName() 执行到 obj.name = "xiaoxu"之后,内存地址2中的对象的变量 name 的值为 “xiaoxu”,此时访问 person.name ,显示的值为 “xiaoxu”。在执行到语句 obj = new Object(); 之前的内存如下:
执行到语句 obj = new Object() 之后,相当于重写了 obj,obj 引用的就是一个局部对象了。此时访问 person.name ,显示的值仍然为 “xiaoxu”。
在函数执行完之后,栈将其环境弹出,把控制权返回给之前的执行环境。obj 引用的局部对象会在函数执行完毕之后立即销毁。
typeof 操作符在检测基本数据类型的值时用处比较大,在检测引用数据类型的值时用处不大。
1 <script> 2 var a = "a"; 3 var b = 0; 4 var c = true; 5 var d; 6 var e = null; 7 var f = new Object(); 8 function g(){}; 9 var h = new Array(); 10 var pattern1 = /at/g; 11 //基本类型值 12 console.log( typeof a ); //输出:string 13 console.log( typeof b ); //输出:number 14 console.log( typeof c ); //输出:boolean 15 //undefined、null 16 console.log( typeof d ); //输出:undefined 17 console.log( typeof e ); //输出:object 18 //引用类型值 19 console.log( typeof f ); //输出:object 20 console.log( typeof g ); //输出:function 21 console.log( typeof h ); //输出:object 22 console.log( typeof pattern1 ); //输出:object 23 </script>
所有引用类型的值都是 Object 的实例,因此在检测一个引用类型值和 Object 构造函数时,instanceof 操作符始终会返回 true。
1 <script> 2 var a = "a"; 3 var b = 0; 4 var c = true; 5 var d; 6 var e = null; 7 var f = new Object(); 8 function g(){}; 9 var h = new Array(); 10 var pattern1 = /at/g; 11 //基本类型值 12 console.log( a instanceof Object ); //输出:false 13 console.log( b instanceof Object ); //输出:false 14 console.log( c instanceof Object ); //输出:false 15 //undefined、null 16 console.log( d instanceof Object ); //输出:false 17 console.log( e instanceof Object ); //输出:false 18 //引用类型值 19 console.log( f instanceof Object ); //输出:true 20 console.log( g instanceof Object ); //输出:true 21 console.log( h instanceof Object ); //输出:true 22 console.log( pattern1 instanceof Object ); //输出:true 23 console.log( g instanceof Function ); //输出:true 24 console.log( h instanceof Array ); //输出:true 25 console.log( pattern1 instanceof RegExp ); //输出:true 26 </script>
如果变量是给定引用类型的实例(根据它的原型链来识别),那 instanceof 操作符会返回 true。
1 <script> 2 function a(){}; 3 function b(){}; 4 //b 继承了 a 5 b.prototype = new a(); 6 var instance = new b(); 7 console.log( instance instanceof a ); //true 8 console.log( instance instanceof b ); //true 9 //所有函数的默认原型都是 Object 的实例 10 console.log( instance instanceof Object ); //true 11 </script>
原文地址:https://www.cnblogs.com/xiaoxuStudy/p/12509729.html
- js运算符优先级笔记
- 通过协同绘制用GAN合成高分辨率无尽道路
- ASP.NET MVC的Model元数据与Model模板:预定义模板
- 为您的组织选择正确的企业云解决方案
- 搞定这些疑难杂症,向css3动画说yes
- 前十一个网络游戏业务收入1341亿 同比增22.1%
- ASP.NET MVC Model元数据及其定制:一个重要的接口IMetadataAware
- 使用Docker 1.12.x构建多容器Web应用程序
- 基于 vue2 + vuex 构建一个具有 45 个页面的大型单页面应用
- 深度解剖dubbo源码
- .NET Core采用的全新配置系统[6]: 深入了解三种针对文件(JSON、XML与INI)的配置源
- 基于 vue2 构建和后台真实交互的 管理系统
- ASP.NET MVC的Model元数据与Model模板:模板的获取与执行策略
- python3.6抓取100知乎用户头像详解(四)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 《高性能网站建设指南》读书笔记
- generator处理异步操作
- bind、call、apply的实现
- 《现代前端技术解析》读书笔记
- 使用console.log在控制台打印图片
- CSS改变input光标颜色
- Firefox 如何对发送的参数进行调试
- ios摄像头推流(1)
- leetcode之最短补全词
- React基础(10)-React中编写样式CSS(styled-components)
- 十大经典排序算法 (动态演示 + 代码)
- 学生成绩管理系统案例
- C 语言指针详解
- 04 CentOS6.5系统语言切换为中文
- 【SpringBoot DB 系列】Redis 高级特性之 Bitmap 使用姿势及应用场景介绍