• javascript小结


    一、说明

    Javascript是动态语言,由浏览器执行,是解析性语言

    二、介绍  (大部分从JavaScript高级程序设计(第2版)摘录)

    五种基本数据类型

    基本类型值指的是那些保存在栈内存中的简单数据段,即这种值完全保存在内存中的一个位置。基本类型有五种,UndefinedNullBooleanNumberString。还有一种复杂数据类型——Object(本质上是由一组无序的名值对组成)

    可以使用使用typeof操作符来获得数据类型:

    l "undefined"——如果这个值未定义

    l "boolean"——如果这个值是布尔值

    l "string"——如果这个值是字符串

    l "number"——如果这个值是数值

    l "object"——如果这个值是对象或null

    l "function"——如果这个值是函数

    代码:

    View Code
     1 var a;
     2 var b = 1;
     3 var c = 'c';
     4 var d = {};
     5 var e = null;
     6 var f = true;
     7 var g=function(){
     8     
     9 };
    10 function show() {
    11     var aType = 'a:' + typeof a;
    12     var bType = 'b:' + typeof b;
    13     var cType = 'c:' + typeof c;
    14     var dType = 'd:' + typeof d;
    15     var eType = 'e:' + typeof e;
    16     var fType = 'f:' + typeof f;
    17     var gType = 'g:' + typeof g;
    18 
    19     alert(aType + "\n" + bType + "\n" + cType + "\n" + dType + "\n" + eType + "\n" + fType+"\n"+gType);
    20 }

    函数

    函数使用function关键字来声明,基本语法:

    function functionName(arg0,arg1){

    statements

    }

     

    注意下面几点:

    l 如果遇到return ; 函数会停止执行并返回undefined

    l 所有参数传递都是值,不可能通过引用传递参数

    l 参数在内部是用一个数组来表示的。函数接受到的始终都是这个数组,而不关心数组中包含哪些参数(如果有参数的话)。函数体内可以通过arguments对象来访问这个参数。arguments对象只是与数组类似(并不是Array实例)。

    l 没有传递值的命名参数将自动被赋予undefined值

    l 如果定义了两个名字相同的函数,则后面的会覆盖前面的。

    l 除了什么时候可以通过变量访问函数这一点区别外,函数声明与函数表达式的语法其实是等价的。

    l 要访问函数的指针而不执行函数的话,必须去掉函数名后面的那对圆括号。

    l 函数有两个特殊的对象:arguments和this。arguments还有一个名叫callee的属性(指针),指向拥有这个arguments对象的函数。this引用的是函数据以执行操作的对象。

    l 每个函数都包含两个属性:length和prototype。length表示函数希望接受的命名参数的个数。

    l 每个函数都包含两个非继承而来的方法:apply()和call()。这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。

    l 每个函数都有一个非标准的caller属性,该属性指向调用当前函数的函数。(只建议将该属性用于调试目的)。

    l 函数实际上是对象,每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法。由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定。

    l arguments.callee是一个指向正在执行的函数的指针

    l JavaScript中没有私有成员的概念,所有对象属性都是公有的。不过,在任何函数中定义的变量,都可以认为是私有变量,因此不能在函数的外部访问这些变量。但有两种方式创建特权方法

    l 函数f1内部定义了另外一个函数f2,当f1执行完毕后,当f2仍存在,则其活动对象也不会被销毁,因为f2的作用域仍然在引用这个活动对象,f1的执行环境的作用域链会被销毁,但它的活动对象仍然会留在内存中,直到f2被销毁后,f1的活动对象才会被销毁。

     

    构造函数

    注意下面几点:

    l 构造函数在不返回值的情况下,默认会返回新对象实例。

    l 寄生构造函数模式:返回的对象与构造函数或者与构造函数的原型属性之前没有关系:也就是说,构造函数返回的对象与在构造函数外部创建的对象没有什么不同。

    l 组合继承=原型链+构造函数(会用到call或apply),是最常用的继承模式

    l 寄生组合式继承是引用类型最理想的继承范式,YUI的YAHOO.lang.extend()方法采用了寄生组合继承,从而让这种模式首次出现在了一个应用非常广泛的javascript库中

    引用类型

    引用类型值是指那些保存在堆内存中的对象,意思是变量中保存的实际上只是一个指针,这个指针指向内存中的另一个位置,该位置保存对象。

     

    基本类型和引用类型在内存中保存情况如下图:

    注意下面几点:

    l 访问对象属性时一般都使用点表示法,不过也可以使用方括号表示法来访问对象属性,但属性必须以字符串的形式放在方括号中。

    l Array数组,每一项可以保存任何类型的数据,它的大小是可以动态调整的。

    l 使用索引设置数组的值时,如果超过了数组现有项数,数组会自动增加到该索引值加1的长度

    l 数组的length属性不是只读的。

    l 数组有栈方法和队列方法(IE对JavaScript的实现中存在一个偏差,其unshift方法总是返回undefined而不是数组的新长度)

    l 引用类型与基本包装类型的主要区别就是对象的生存期。使用new操作符创建的引用类型的实例,在执行流离开当前作用域之前都一直保存在内存中。而自动创建的基本包装类型的对象,则只存在与一行代码的执行瞬间,然后立即被销毁。

    l 对基本包装类型的实例调用typeof会返回"object",而所有基本包装类型的对象都会被转换为布尔值true。

     

    执行环境及作用域

    执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为。每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。虽然我们编写的代码无法访问这个对象,但解析器在处理数据时会在后台使用它。

    某个执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁(如果还能在其他环境中被访问到,则不销毁)

    环境的机制

    存在环境栈,可把环境推入或弹出。当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。而在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境。

    作用域链

    当代码在一个环境中执行时,会创建变量对象的一个作用域链。它的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。

    作用域链的前端,始终都是当前执行的代码所在环境的变量对象。如果这个环境是函数,则将其活动对象作为变量对象。全局环境的变量对象始终都是作用域链中的最后一个对象。

    标识符解析是沿着作用域链一级一级地搜索标识符的过程。

    延长作用域链

    try-catch语句的catch块和with语句可以延长作用域链,即当执行流进入其中一个语句时,在作用域链的前端临时增加一个变量对象,作用域链得到加长,该变量对象会在代码执行后被已移除。(作用域增加的临时变量对象都只是只读的,所以在它们中定义的变量,成了函数执行环境的一部分)

    注意下面几点:

    l JavaScript中没有块级作用域

    l 变量在未经声明的情况下被初始化,那么该变量会被自动添加到全局环境中。

    l 局部变量会在它们离开执行环境时自动被解除引用(解除的真正作用是让值脱离执行环境,以便垃圾收集器下次运行时将其回收)

    l 垃圾收集策略:标记清除、引用计数(不常使用,除了IE,如果有循环引用会出现问题,需要手动断开,即赋值为null,不然无法垃圾收集),不建议手动执行垃圾收集

    页面注意下面几点:

    l 在使用<script>嵌入JavaScript代码时,不能在代码的任何地方出现“</script>”字符串,会产生错误。因为按照解析嵌入式代码的规则,当浏览器遇到字符串“</script>"时,就会认为那是结束的标签。而通过把这个字符串分隔为两部分可以解决这个问题。例如alert("<scr"+"ipt"/>);

    l 解析器对<script>元素内部的所有代码求值完毕以前,页面中的 其余内容都不会被浏览器加载或显示。

    l 浏览器会按照<script>元素在页面最后能够出现的先后顺序对它们依次进行解析。

    l javascript代码放在<head><body>的区别

    l 变量定义没有使用var,会看作全局变量

    l 大量使用with语句会导致性能下降,同时也会给调试代码造成困难,因此在开发大型应用程序时,不建议使用with语句。

    l switch可以使用任何数据类型,每个case的值不一定是常量,可以是变量,甚至是表达式。switch语句在比较值时使用的是全等操作符,因此不会发生类型转换(例如,字符串“10”不等于数值10)

     

    三、理解

    关于引用类型

    javaC++中都采用了引用这个概念,但是二者的行为并不一样。java的引用其实更象c++中的指针,而非c++中的引用

    引用其实是特殊的"指针",它只是没有指针运算(a++,a- -这些),这样会更安全。所以声明定义一个引用时,它都会在栈中建立一个空间。

    var a={};

    var b=a;

    ab都代表同一个对象,而不是b拥有a的一个副本。

    a存放了一个对象的内存地址,然后把地址赋值给了b,所以他们都指向同一个对象。注意的是,ab都拥有自己的栈空间。

     

    关于string特殊的基本类型(希望有人可解答我疑问)

    Javascript中的基本类型都存放在栈中,并且所占空间大小固定,可是string大小并不固定,它为什么也是基本类型?。下面是我对此的理解:

    l 字符串值存放在栈中:

    上面所说空间固定,指的是当已经存放了值后,值的大小已经确定了,无法改变。而并不是指string基本类型在存放值之前空间大小已经固定,所以可能出现有a,b两个string类型的值,它们在栈中的空间大小却不一样

    赋值操作时:

    var a="a";

    var b=a;

    此时栈中有ab两块空间,存放的值都是"a",注意它们在不同的栈空间中。

    l 字符串值存放在堆中:

    上面所说空间固定,是指基本类型在存放值之前已经确定空间大小了。则string类型必定是一个引用,它存放指向堆空间的一个地址。可为什么不把它归于基本类型呢?理由如下:

    由于效率的原因,我们希望JS只复制对字符串的引用,而不是字符串的内容。但是另一方面,字符串在许多方面都和基本类型的表现相似,而字符串是不可变的这一事实(即没法改变一个字符串值的内容),因此可以将字符串看成行为与基本类型相似的不可变引用类型。

     

    关于关键字this

    在 Java 等面向对象的语言中,this 关键字的含义是明确且具体的,即指代当前对象。一般在编译期确定下来,或称为编译期绑定。而在 JavaScript 中,this 是动态绑定,或称为运行期绑定的

    我的理解是——this表示的是当前环境的变量对象。

    匿名函数是全局性的理由是,它不存在除全局环境之外的任何环境中,也就是说没有引用可以访问得到它。这时的this是全局环境的window对象。

    是否为匿名函数,主要看是否有引用指向它。

    代码:

    View Code
    /*
     * 是否为匿名函数,主要看是否有引用指向它
     */
    
    var ob={};
    
    ob.a=function () {
        (function() {//匿名函数
            alert("a this:" + this);
        })();
    }
    
    
    ob.b=function(){
         alert("b this:" + this);
    }
    
    ob.c=function(){
        return function(name){
           alert(name+" this:" + this); 
        };
    }
    
    ob.d=ob.c();//ob.c()返回一个匿名函数,但是ob.d指向了它,则它不再是匿名函数,this执行ob
    
    function show() {
        ob.a();
        ob.b();
        ob.c()('c');//ob.c()得到一个匿名函数,可是却没有指针指向它,所以执行后this是window
        ob.d('d');
    }

    参考:JavaScript高级程序设计(第2版)

  • 相关阅读:
    书单
    x&(x1)表达式的意义
    约瑟夫环,杀人游戏(静态循环链表实现)
    我的第一个动态规划程序(试图用递归求斐波拉契数)
    NYOJ 2题 括号配对问题
    为什么 C++不叫作++C? o(∩_∩)o
    文字常量区,字符串常量
    括号匹配(栈实现)
    Mybatis的逆向工程(generator)
    Mybatis学习一(介绍/举例/优化)
  • 原文地址:https://www.cnblogs.com/dann/p/2733184.html
Copyright © 2020-2023  润新知