JavaScript学习笔记(一)

来源:互联网 发布:时间旅行 辩证法 知乎 编辑:程序博客网 时间:2024/05/29 04:11

数据类型:

       有Undefine,Number(不分int和float),Boolean,String,Object(包括null和普通对象)。

       Undefine是当变量没有初始化或赋值时的状态,这时无法确定它的变量类型,因此为undefine型。另外,未声明的变量也是undefine型的,但实际上不存在和声明了未赋值的不同。Object变量有一种特殊情况,值为null,表明这是一个oject对象(本质是指向对象的指针),然而这个对象还没有指定(即指针为空)。

       Number类型不分float和int,它会自动地识别所附的值,并在后台动态地调整存储空间(比如将1.0存储为整型的1,节省空间),Number也有两种特殊情况,一个是溢出状态Infinite还有非法数字NaN。

       undefine,null,NaN,空字符串"",这四种特殊情况有点复杂:

       (1)对于逻辑操作:undefine,null,NaN,"",都是false。另外undefine==null为true,而NaN==NaN为false,NaN无论与什么比(大小等于)都是false,只有!NaN还有NaN!=NaN为true。

       (2)对于转换为字符串:toString()(所有类型的变量都有toString()方法,显示或隐式地执行,除了undefine和null用String()强制转换)或者ValueOf(),有undefine和null,NaN转换成"undefine"和"null","NaN"。

       (3)对于转换成数值:有Number()或者parseInt()和parseFloat()这三种,显示或隐式地执行,true变成1,false转成0,null转成0,非法数字字符串(至少要最前面一部分为正常某进制数字)转成NaN,空字符串转成0,undefine转成NaN。对与Object则先用ValueOf转成字符串再转数字。

       (4)++,--,+(正),-(负),-(减):对于这些,默认为数值操作,各种类型先转成数值型再操作。

       (5)+(加):这个默认为字符串连接操作,所以无论什么先转成字符串再连接。

       (6)比较:数值之间,字符串之间直接比,对象先变字符串,布尔先变数值,若有一方为数值,将另一方变为数值再比较(即数值和字符串比较执行的是数值的比较)。


语句:

       (1)条件if else,也可以用a<b?a:b;的条件操作符。

       (2)label标签和break,continue可以跳出循环。break,continue和c一样。可以给他们加一个目标label。比如:

var sum=0;outer:for(var i=0;i<10;i++) {  for(var j=0;j<10;j++) {    sum++;    if(i==5&&j==5) {      break outer;  //或者continue outer;    }  }}
       break的结果是sum=50而continue的结果是95。这里label的用法是label: expression 则break和continue的对象是这个label所指的expression。因此break了外层循环,continue向外层循环的下一个。

       (3)switch语句可以对字符串做判断,有着比c语言更自由的语法,switch()内可以是所有类型和表达式,case也可以是所有类型常亮或变量或表达式。


函数:

       js中的函数不是签名机制实现的(即不是由声明参数类型,返回值类型...的机制实现的),一个js的函数调用,将参数做成一个arguments的数组传入函数,作为局部变量,然后返回值默认为undefine。因此,可以很自由地对函数做定义,可以不定义参数,但是传入参数,这样用arguments[0],[1],[2]这些来访问参数。也可以定义参数但是不传入参数,则参数为undefine(或者对应的arguments[x]为undefine)。不显示地返回则实际上返回了undefine,return;也是返回了undefine。

       由于不是签名机制,且参数和返回值很自由,靠参数数值等实现,因此js中不存在函数重载。

       关于引用参数传递在下面会讲到。


变量,作用域,内存:

       JS中的变量分为两种类型:基本类型(Number,String,Boolean,Undefine,Null),引用类型(Object,Array,RegExp后两种都是Object)。

       基本类型存储在栈区,引用类型在栈区存储一个引用,在堆区存储数据。可以这么说,基本类型的变量大小都是固定的,而引用类型的不固定,因为是动态分配。但是,Number的Int和Float的后台转换不是动态的吗?实际上,是JS的引擎为存储着整型值的Float新建一个Int大小的Number变量来存储它。字符串的拼接和值的改变不是动态的吗?实际上JS中字符串拼接或者改变值时,都是通过新建一个字符串变量来存放的,然后将引用由原来那块移到新的这块。

       下图中str原引用为1,拼接之后为2,原来的空间等着浏览器的JS引擎做垃圾回收。而obj1=new Object(); obj2=obj1; 这两个obj引用同一块内存。


       JS的引用机制:每个变量名都是一个引用。它不像C语言那样只代表固定的内存地址,它是隐式可变化的。但是!!此引用非彼引用!它不代表所有变量都是引用类型的。在函数参数传递时,只有引用类型的Object才是引用参数传递,而基本类型都是值传递。


执行环境和作用域:

       每个页面都有一个window执行环境(全局环境),在调用函数则进入函数的执行环境,再调用又进入下一级的执行环境,函数调用结束该执行环境从这个链的前端删除。其实就是函数栈。每个执行环境有自己的变量和函数,这样形成一个作用域链。


       变量,标识符的解析是沿着作用域链一级一级向上地搜索的过程。所以在函数中可以直接使用全局变量,可以直接使用任何它的上级环境的变量或函数。但是父级环境不能访问其下级环境中的变量。另外,若父级环境与子级环境中有声明相同名字的变量,由于是向上解析的,因此先在子级环境中查到这个变量,因此为子级的。


注意:

       1. 可以用with延长作用域链,即用了with之后,with中进入了新的环境。如:

var qs = "?debug=true";with(location) {    var url = href + qs;}
       这里with花括号中,为loaction对象的环境,url为新建的局部变量,href在location环境中查到存在为location.href,而qs查不到loaction.qs,因此为上级的qs="?debug=true"。


       2.JS中不存在块级作用域

       即if{},或者for{},或者光一个{}中不是新的子环境。它隶属于if,for,{}所在的环境。因此,if,for,{}中定义的变量不会随着他们的结束而释放(失去引用)


引用计数:循环引用的问题,比如函数中有两个对象,他们指向彼此,这样这两个对象各有2个引用计数,当函数结束时,变量名引用消失,但是这两个对象仍存在1个引用计数。永远都不会变成0,永远都不会被回收。这种时候,要显式地在不使用他们的时候,将指向变成指向null。

内存管理:当某个obj不再使用的时候,显式地将它obj=null,可以让它能被垃圾回收。而不是等到环境结束时才允许回收。


0 0
原创粉丝点击