JS变量、作用域、内存
写到这个题目《JS变量、作用域,内存》,我就不由自主想起了黄金三嫖客。可能是名字有点像,嗯,一定是这样子的!
JS接触下来,应该是要比Java简单不少的,所以,要学好啊。立个flag半年后来看到底学得怎么样。
这会儿来到了本书的第四章。感觉这水平,后天的面试要跪啊,唉想不了那么多了,就当为实习做准备吧。
ES变量的两种数据类型
- 基本类型值:5种,Undefined、Null、Boolean、Number、String。按值访问(因为可以操作保存在变量中的实际值)。
- 引用类型值:保存在内存中的对象,按引用访问。
定义基本类型值和引用类型值的方式类似,都是创建一个变量并为该变量赋值。
- 区别1,对于引用类型的值,我们可以为其添加属性和方法,也可以改变和删除其属性和方法,而对于基本类型值,我们不能给其添加属性,尽管这样不会导致错误。
例如
var person = new Object();
person.name = "Nicholas";
person.sex = "male";
alert(person.sex);
alert(person.name); //"Nicholas"
1 var name = "Nicholas";
name.age = 27;
alert(name.age); //undefined
- 区别2 复制变量值不同
在从一个变量向另一个变量复制基本类型值和引用类型值时,存在不同。
如果从一个变量向另一个变量复制基本类型的值,会在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上。
拿书中的例子来说,基本类型值的复制如下
var num1 = 5;
var num2 = num1;
num1 中保存的值是 5,当使用 num1 的值来初始化 num2 时, num2 中也保存了值 5. 但是 num2 中的 5 和 num1 中的 5 是完全独立的,该值只是 num1 中 5 的一个副本。这两个变量互不影响。上图即此过程。
而对于引用类型值的复制就不一样了。
当从一个变量向另一个变量复制引用类型的值时,同样也会把存储在变量对象中的值复制一份到为新变量分配的空间中。不同的是,这个值的副本其实是一个指针。这个指针指向存储在堆中的一个对象。复制操作结束后,两个变量实际上将引用同一个对象。因此,改变其中一个变量,就会影响另一个变量。它们之间相互影响。
var obj1 = new Object();
var obj2 = obj1;
obj1.name = "Nicholas";
alert(obj2.name); // "Nicholas"
分析此过程:
首先,变量 obj1 保存了一个对象的实例,然后,这个值被复制到了 obj2 中。obj1 和 obj2 指向同一个对象。这样,当为 obj1 添加 name 属性后,可以通过 obj2 来访问这个属性,因为这两个变量引用的都是同一个对象。
# 传递参数
ES中所有的函数都是按值传递。 访问变量有按值和按访问 这两种方式,但参数只能是按值传递。这个是一个困惑点。
在向参数传递基本类型的值时,被传递的值会被复制给一个局部变量。在向参数传递引用类型的值时,会把这个值在内存中的地址复制给一个局部变量,因此这个局部变量的变化会反映在函数的外部。
看例子理解个中玄妙
function addTen(num) {
num += 10;
return num;
} var count = 20
var result = addTen(count);
alert(count); //
alert(result); //
这里的函数 addTen()有一个参数 num,参数实际上是函数的局部变量。在调用这个函数时,变量 count 作为参数被传递给函数,这个变量的值是 20. 于是,数值 20 被复制给参数 num 以便于在 addTen()中使用。在函数的内部,参数 num 的值被加上了 10 ,但这一变化不会影响函数外部的 count 变量。参数 num 与变量 count 互不认识。它们仅仅是具有相同的值。加入 num 是按引用传递,那么变量 count的值也会是30,从而反映函数内部的修改。
再举一个例子
function setName(obj) {
obj.name = "Nicholas";
} var person = new Object();
setName(person);
alert(person.name); //"Nicholas"
代码创建了一个对象,并将其保存在变量 person 中。然后,这个对象被传递到 setName()函数中之后就被复制给了 obj。在这个函数内部,obj 和 person 引用的是同一个对象。换句话说,即使这个对象是按值传递的,obj 也会按引用来访问同一个对象。于是,当函数内部为 obj 添加 name 属性后,函数外部的 person 也将有所反映。因为 person 指向的对象在堆内存中只有一个,而且是全局对象。
(以上不太好理解。)
有人建议,可以把ES函数的参数想象成局部变量。
# 检测类型
typeof 操作符,可检测变量为 字符串、数值、布尔值、undefined,然鹅,对 null 失效,null 会被检测成 object。
怎么办?
var s = "Nicholas";
var b = true;
var i = 22;
var u;
var n = null;
var o = new Object(); alert(typeof s); //string
alert(typeof i); //number
alert(typeof b); //Boolean
alert(typeof u); //undefined
alert(typeof n); //object
alert(typeof o); //object
通常,通过 typeof 操作符,我们只能得到对象是 object ,但用处不大,就好像,我通过检测知道,你是一个 人 ,但重要的是要获知你究竟是什么人,这是更重要的。这一点上,typeof 就显得没那么有效了。ES提供了另一个操作符满足我们的要求——instanceof 操作符
result = variable instanceof constructor
如果变量是给定引用类型的实例,instanceof 操作符就会返回 true。所有的引用类型都是 object 的实例。
# 执行环境
全局执行环境是 window 对象。每个函数都有自己的执行环境。当执行流进入到一个函数时,函数的环境就会被推入一个环境栈中。在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境。
当代码在一个环境中执行时,会创建变量对象的一个作用域链。
作用域链,是保证对执行环境有权访问的所有变量和函数的有序访问。作用域链的前端是当前执行的代码所在环境的变量对象。如果这个环境是函数,则将其活动对象作为变量对象。作用域链中的下一个变量对象来自包含(外部)环境,而再下一个变量对象则来自下一个包含环境。这样,已知延续到全局执行环境。全局执行环境的变刘昂对象始终都是作用域链中的最后一个对象。
标识符解析是沿着作用域链一级一级地搜索标识符的过程。搜索过程始终从作用域链的前端开始,然后逐级向后回溯,直到找到标识符未知。如果找不到标识符,通常会导致错误发生。
var color = "blue"; function changeColor(){
if (color === "blue"){
color = "red";
} else {
color = "blue";
}
} changeColor(); alert("Color is now " + color);
明天再干,今晚干不动了已经,脑子要不好使了。
JS变量、作用域、内存的更多相关文章
- [刘阳Java]_步步窥探JS变量作用域
今天的这个文章题目名称甚是让人会突发异想.JS变量作用域是务必需要搞懂的,单从面试过程就会让面试者烧脑壳.所以,我们还是写一篇关于JS变量作用域的技术专题,让所有小伙伴能够借此文章去整理JS的基础学习 ...
- js 变量 作用域及内存
由于Javascript是松散型的,所以其变量只是在特定时间用于保存特定值的一个名字而已,并不存在某个变量必须保存某种类型的值的规则,变量的值以及其数据类型都可以在脚本的声明周期内改变 一.基本类型与 ...
- javaScript的闭包 js变量作用域
js的闭包 js的变量作用域: var a=90; //定义一个全局变量 function test(){ a=123; //使用外层的 a变量 } test(); document.write(&q ...
- 原型模式故事链(5)--JS变量作用域、作用域链、闭包
上一章 JS执行上下文.变量提升.函数声明 传送门:https://segmentfault.com/a/11... 本次我们主要讲讲变量作用域和闭包变量作用域:顾名思义:变量起作用的范围.变量分为全 ...
- 解释JS变量作用域的范例
JS的变量作用域只有两种:全局作用域与函数作用域. 用var声明的变量不能简单的说是属于函数作用域,应该是说属于其最近的作用域. var a = 10; function test(){ var a; ...
- 浅谈js变量作用域
变量的作用域也是前端面试题常考的一个问题,掌握下面几个规律可以帮你更好的理解js的作用域. 1.作用域优先级遵循就近原则,函数内部的作用域优先级大于外部 var a=456; var b=111; f ...
- js变量作用域--变量提升
1.JS作用域 在ES5中,js只有两种形式的作用域:全局作用域和函数作用域,在ES6中,新增了一个块级作用域(最近的大括号涵盖的范围),但是仅限于let方式申明的变量. 2.变量声明 var x; ...
- JS变量作用域与解构赋值
用var变量是有作用域的 变量在函数内部声明时,那么该变量只属于整个函数体,函数外不可调用 当两个不同的函数里,使用了用一个相同的变量名,二者不互相影响,相互独立 遇到嵌套函数时,外部函数不可调用内部 ...
- JS变量、内存、作用域小结
确保占用最少的内存可以让页面获得更好的性能,优化内存占用的最佳方式:为执行中的代码 只保存必要的数据.一旦数据不再有用,最好通过将其值置为null来释放其引用.适用于大多 数全局变量和全局对象的属性. ...
- js变量作用域和闭包的示例
<script> /* js是函数级作用域,在函数内部的变量,内部都能访问, 外部不能访问内部的,但是内部可以访问外部的变量 闭包就是拿到本不该属于他的东西,闭包会造成内存泄漏,你不知道什 ...
随机推荐
- android端的ormlite框架
安卓端有很多优秀的数据库框架来操作sqlite,如ormlite框架,这个框架可以用来实现表到对象的解析和转化. 使用: 首先去官网下载两个jar包,core和android(如果在安卓端开发的话), ...
- SqlServer 批量添加记录
declare @i int ) begin INSERT INTO [dbo].[Settlements] ([ID] ,[Count] ,[SettlementDate]) VALUES ( ne ...
- String str = "1,2,3,4,5,6" 如何将这个字符串转换成int数组
String str = "1,2,3,4,5,6"; string[] strS = str.Split(','); int[] num = new int[strS.Lengt ...
- 小米OJ 有多少个等差数列
题目链接 https://code.mi.com/problem/list/view?id=20 代码 #include <bits/stdc++.h> using namespace s ...
- 沉淀再出发:dubbo的基本原理和应用实例
沉淀再出发:dubbo的基本原理和应用实例 一.前言 阿里开发的dubbo作为服务治理的工具,在分布式开发中有着重要的意义,这里我们主要专注于dubbo的架构,基本原理以及在Windows下面开发出来 ...
- Android启动外部应用的方法
1.根据package的名称获取应用的Launch Intent Intent LaunchIntent = getPackageManager().getLaunchIntentForPackage ...
- SCRUM与XP的区别和联系
相同点:SCRUM和XP都是敏捷开发的方法论,都体现了快速反馈,强调交流,强调人的主观能动性等基本原则,而且多数“最佳实践活动”都互相适用. 不同点:Scrum非常突出Self-Orgnization ...
- 深入浅出SharePoint——常用的url命令
?&displaymode=design 页面可编辑
- August 12th 2017 Week 32nd Saturday
That which does not kill us makes us stronger. 但凡不能杀死你的,最终都会使你更强大. Seemingly I have heard this from ...
- [EffectiveC++]item21:Don't try to return a reference when you must return an object