写到这个题目《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变量、作用域、内存的更多相关文章

  1. [刘阳Java]_步步窥探JS变量作用域

    今天的这个文章题目名称甚是让人会突发异想.JS变量作用域是务必需要搞懂的,单从面试过程就会让面试者烧脑壳.所以,我们还是写一篇关于JS变量作用域的技术专题,让所有小伙伴能够借此文章去整理JS的基础学习 ...

  2. js 变量 作用域及内存

    由于Javascript是松散型的,所以其变量只是在特定时间用于保存特定值的一个名字而已,并不存在某个变量必须保存某种类型的值的规则,变量的值以及其数据类型都可以在脚本的声明周期内改变 一.基本类型与 ...

  3. javaScript的闭包 js变量作用域

    js的闭包 js的变量作用域: var a=90; //定义一个全局变量 function test(){ a=123; //使用外层的 a变量 } test(); document.write(&q ...

  4. 原型模式故事链(5)--JS变量作用域、作用域链、闭包

    上一章 JS执行上下文.变量提升.函数声明 传送门:https://segmentfault.com/a/11... 本次我们主要讲讲变量作用域和闭包变量作用域:顾名思义:变量起作用的范围.变量分为全 ...

  5. 解释JS变量作用域的范例

    JS的变量作用域只有两种:全局作用域与函数作用域. 用var声明的变量不能简单的说是属于函数作用域,应该是说属于其最近的作用域. var a = 10; function test(){ var a; ...

  6. 浅谈js变量作用域

    变量的作用域也是前端面试题常考的一个问题,掌握下面几个规律可以帮你更好的理解js的作用域. 1.作用域优先级遵循就近原则,函数内部的作用域优先级大于外部 var a=456; var b=111; f ...

  7. js变量作用域--变量提升

    1.JS作用域 在ES5中,js只有两种形式的作用域:全局作用域和函数作用域,在ES6中,新增了一个块级作用域(最近的大括号涵盖的范围),但是仅限于let方式申明的变量. 2.变量声明 var x; ...

  8. JS变量作用域与解构赋值

    用var变量是有作用域的 变量在函数内部声明时,那么该变量只属于整个函数体,函数外不可调用 当两个不同的函数里,使用了用一个相同的变量名,二者不互相影响,相互独立 遇到嵌套函数时,外部函数不可调用内部 ...

  9. JS变量、内存、作用域小结

    确保占用最少的内存可以让页面获得更好的性能,优化内存占用的最佳方式:为执行中的代码 只保存必要的数据.一旦数据不再有用,最好通过将其值置为null来释放其引用.适用于大多 数全局变量和全局对象的属性. ...

  10. js变量作用域和闭包的示例

    <script> /* js是函数级作用域,在函数内部的变量,内部都能访问, 外部不能访问内部的,但是内部可以访问外部的变量 闭包就是拿到本不该属于他的东西,闭包会造成内存泄漏,你不知道什 ...

随机推荐

  1. android头像上传(获取头像加剪切)

    因为项目中需要用到头像上传的功能,所以就下个Ddmo先来实现下. demo我是类似仿微信的,在一个GridView中展示所有的图片,其中第一个item可以去照相:获取到图片后再进行剪切. 图片的剪切是 ...

  2. python装饰器 高阶函数 函数闭包

    1.装饰器: 本质是函数,功能是为其他函数添加附加功能 原则:1.不修改被装饰函数的源代码 2.不修改被修饰函数的调用方式 装饰器=高阶函数+函数嵌套+闭包 #装饰器格式框架def wrap(func ...

  3. 应用程序 调用 webservice

    首先用VS创建一个WebService服务工程,并且完成基本功能,本人完成的是html转pdf功能. 然后,新建一个Windows应用程序. 添加WebService到Windows项目中,如图 然后 ...

  4. 我的MBTI小测试

    今天做了自己的MBTI测试,选了93道题版本的,测试结果是ESFP表演者型——有我在就有笑声.这个测试很有趣,我也觉得很神奇. 一.我的MBTI图形 二.才储分析:我的性格类型倾向为“ ESFP ”( ...

  5. 有关使用 iview 表单验证的问题

    Vue的UI解决框架,element-UI, iview-UI 有关表单验证使用的是同一个插件,async-validator,有关这个插件的用法就不做赘述,但是在iview表单的使用中可能会用到验证 ...

  6. 在小程序中修改上一个页面里data中的数据调用上一个页面的方法

    //获取已经打开的页面的数组 var pages = getCurrentPages(); //获取上一个页面的所有的方法和data中的数据  var lastpage = pages[pages.l ...

  7. 如何解决MSSQL中文数据乱码问题

    今天遇到了在数据库中直接写SQL语句,语句中包含中文,但是数据库的表里是包含“?” 的乱码. 我程序代码中,调试时得到的SQL不是乱码,在控制台中也不是乱码.但是在数据库中却出现了乱码. 当用MSSQ ...

  8. Centos 7配置docker-阿里云镜像加速

    阿里云加速网址:https://cr.console.aliyun.com/cn-hangzhou/mirrors(自行注册账密码) sudo mkdir -p /etc/docker sudo vi ...

  9. ASP.NET中的身份验证有那些?你当前项目采用什么方式验证请解释

    ASP.NET身份验证模式包括Windows.Forms(窗体).Passport(护照)和None(无). l  Windows身份验证—常结合应用程序自定义身份验证使用使用这种身份验证模式时,AS ...

  10. CSS标准文档流 块级元素和行内元素

    标准文档流 什么是标准文档流 宏观的将,我们的web页面和ps等设计软件有本质的区别,web 网页的制作,是个“流”,从上而下 ,像 “织毛衣”.而设计软件 ,想往哪里画东西,就去哪里画 空白折叠现象 ...