《JavaScript高级程序设计》学习笔记(3)——变量、作用域和内存问题

欢迎关注本人的微信公众号“前端小填填”,专注前端技术的基础和项目开发的学习。

本节内容对应《JavaScript高级程序设计》的第四章内容。

1、函数:通过函数可以封装任意多条语句,而且可以在任何地方、任何时候调用执行。ECMAScript中的函数用function关键字来进行声明,后面跟一组参数以及函数体。不必指定是否有返回值

 function functionName(args0,args1,...argsN){
      //statements       
 }

 2、函数的重载:为一个函数编写两个定义,只要这两个定义的签名(接受的参数的类型和数量)不同即可。ECMAScript函数没有签名,因为其参数是由包含零个或多个值得数组来表示的,而没有函数签名,真正的重载是不可能做到的。如果在ECMAScript中定义两个名字相同的函数(函数名和参数的个数均相同),则该名字只属于后定义的函数。

function add(num){
     return num + 100 ;   
}

function add(num){
     return num + 200 ;   
}

var result = add(100) ;   //300

3、JavaScript变量松散类型的本质决定了它至少在特定时间用于保存特定值的一个名字而已,由于不存在定义某个变量必须保存何种数据类型值得规则,变量的值及其数据类型可以在脚本的生面周期内改变。

4、ECMAScript变量包含两种不同的数据类型:基本类型值和引用类型值。基本类型值指的是简单的数据段,引用类型值指那些可能由多个值构成的对象。注意:在JavaScript中字符串是基本类型,是按值访问的,这一点与java中的不一样。对于引用类型的值(即对象),我们可以动态地为其添加属性和方法:

var person = new Object() ;
person.name = "Jack" ;  //添加属性name

5、变量值的复制:

  • 对于简单类型值:复制前后的两个变量没有任何关系,某一个变量的改变并不影响另一个变量的值
  • 而对于引用类型值:复制的内容实际上是一个指针,指向该对象的存储地址,所以复制前后的两个变量实际上指向同一个对象,某一个变量的值的改变会影响另一个变量的值。

6、ECMAScript中所有函数的参数都是按值传递的,即将函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样,应用类型的复制实际上是对象的存储地址的复制。

7、前面提到检测变量的数据类型用typeof,但是typeof的返回值只有string、number、boolean、undefined、function(函数和正则表达式均返回function)、object(null和引用类型均返回object)。所以,对于引用类型或null,我们无法具体确定是属于哪一种引用类型的对象。要确定属于哪一种引用类型,我们可以用instanceof操作符,如果变量是给定引用类型的对象,则instanceof操作符将返回true。因此,在检测一个引用类型值和object构造函数时,始终会返回true,而如果使用instanceof操作符检测基本类型的值,则该操作符始终会返回false,因为基本类型不是对象。

8、在javascript中,执行环境定义了变量或函数有权访问的其他数据类型,决定了他们各自的行为。每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中

  • 根据ECMAScript实现所在的宿主环境不同,表示执行环境的对象也不一样。
  • 某个执行环境中的所有代码执行完毕后,该环境就被销毁,保存在其中的所有变量和函数定义也随之销毁。
  • 全局执行环境是最外围的一个执行环境。在web浏览器中,全局执行环境被认为是window对象,因此所有全局变量和函数都是作为window对象的属性和方法创建的。
  • 每个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。而在函数执行完毕后,栈将其环境弹出,把控制权返回给之前的执行环境。
  • 当代码在一个环境中执行时,会创建变量对象的一个作用域链(scope chain)。作用域链的作用是保证对执行环境有权访问的所有变量和函数的有序访问。作用域链的前端始终都是当前执行的代码所在环境的变量对象。作用域链的下一个变量对象来自包含环境,再下一个变量对象则来自下一个包含环境。这样一直延续到全局执行环境,全局执行环境的变量对象始终是作用域链中的最后一个对象。
  • 标识符的解析是沿着作用域链一级一级地搜索标识符的过程。搜索过程始终从作用域链的前段开始,然后逐级地向后回溯,直至找到标识符为止(如果找不到标识符,通常会导致错误发生)。
  • 当执行流进入到try-catch语句的catch语句或者with语句中时,作用域链就会得到延长。
  • javascript中没有块级作用域。 if(true){ var color = "blue" ; } alert(color) ; //在java中,存在块级作用域,此时在if外面用到color变量则是不合规范的,但是在javascript中不存在这种问题

9、垃圾收集:javascript具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中是用得内存。这样,在编写javascript程序时,我们不需要关心内存使用问题,所需内存分配以及无用内存的回收完全实现了自动管理。则也解决了C++/C语言存在的很大一部分问题。对于垃圾收集,通常用到两种策略来判断一个变量是否是垃圾:

  • 标记清除(mark-and-sweep):当变量进入环境时,就将该变量标记为进入环境,当变量离开环境时,标记为离开环境。
  • 引用计数(reference counting):一个变量被引用(赋值给另一个变量)一次则应用数加1,相反,如果包含该对象应用的变量又取得了另外一个值,则减1。当一个变量计数为0时,表示该变量不再需要,可以清除了。注意循环引用的情况会导致变量无法被清除。

10、确保占用最少的内存可以让页面获得更好的性能。而优化内存占用的最佳方式,就是为执行中的代码只保存必要的数据。一旦数据不再用,最好通过将其值设置为null来释放其引用(这个方法叫解除引用)。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏WD学习记录

牛客网 python (1)

1. python my.py v1 v2 命令运行脚本,通过 from sys import argv如何获得v2的参数值? 

1781
来自专栏积累沉淀

Java类加载原理机制

1.类的加载过程 JVM将类加载过程分为三个步骤:装载(Load),链接(Link)和初始化(Initialize)链接又分为三个步骤,如下图所示: ? 1...

24710
来自专栏Python

python中__get__,__getattr__,__getattribute__的区别

__get__,__getattr__和__getattribute都是访问属性的方法,但不太相同。  object.__getattr__(self, nam...

1460
来自专栏专注 Java 基础分享

Java并发之synchronized关键字

     上篇文章我们主要介绍了并发的基本思想以及线程的基本知识,通过多线程我们可以实现对计算机资源的充分利用,但是在最后我们也说明了多线程给程序带来的两种典型...

2005
来自专栏cs

c++那些事儿6.0 STL中的string

---- 知识点综述 c++,string 类 string 是C++中的字符串对象,是一种特殊类型的容器,专门设计来操作的字符序列。 ...

2897
来自专栏搞前端的李蚊子

使用箭头函数的几个注意事项

刚才写一个需要递归操作的函数,在使用arguments.callee的时候,报错undefined,因为arguments.callee在严格模式下会失效,以为...

3766
来自专栏黑泽君的专栏

java基础学习_反射、装饰模式、JDK新特性_day27总结

962
来自专栏用户3030674的专栏

java单例模式

单例设计模式:解决一个类在内存中只存在一个对象  多用于环境变量设置等  单例模式的要求:1.只能有一个对象,禁止其他程序建立该类对象          2....

771
来自专栏余林丰

初识Java反射

要详细的了解Java反射,就得要了解Java的类加载以及何为运行时动态加载等等概念。本文抛开其余概念,简单介绍Java反射,详细介绍会在以后有一个系统而全面的认...

24810
来自专栏数据结构与算法

1750:全排列

1750:全排列 查看 提交 统计 提问 总时间限制: 1000ms 内存限制: 65536kB描述 给定一个由不同的小写字母组成的字符串,输出这个字符串的所...

37114

扫码关注云+社区

领取腾讯云代金券