《JavaScript高级程序设计》摘要(一)

持续更新...

主要是对《JavaScript高级程序设计》里的要点摘抄,构建自己的知识体系。

新手上路,如有不对或不足的地方,还请大家多多指正 :)

第2章 ECMAScript基础

ECMAScript仅仅是一个描述,定义了脚本语言的所有属性、方法和对象。其他语言可以实现ECMAScript来作为功能的基准,如JavaScript。

2.1    语法

ECMAScript的基础概念如下:

  • 区分大小写;与Java一样,变量,函数名,运算符以及其他一切东西都是区分大小写的。
  • 变量是弱类型的; 与Java和C不同,ECMAScript中的变量无特定的类型。定义变量时只用var运算符,可以将它初始化为任意的值。
  • 每行结尾的分号可有可无;(最好的代码编写习惯是总加入分号:)
  • 注释与Java、C和PHP语言的注释相同;
  • 括号表明代码块;

2.2    变量

如前所述,ECMAScript中的变量使用var运算符(variable的缩写) 加变量名定义的。

用同一个var语句定义的变量不必具有相同的类型,如

var test = "hi", age = 25;

此外,变量还可以存放不同类型的值,这也是弱类型变量的优势。

变量名需遵守第一个字符必须是字母,下划线或$符号。

变量还应遵守一下某条著名的命名规则:

  • Camel标记法——首字母小写,接下来字母以大写开头。
    ​var myTestValue = 0;
    
    ​

     

  • Pascal标记法——首字母大写,接下来字母以大写开头。
    var MyTestValue = 0;

     

  • 匈牙利类型标记法——在以Pascal标记法命名的变量前附加一个小写字母,以说明该变量的类型。
    var iMyTestValue = 0;
    var sMySecondValue = "hi";

     

ECMAScript另一个有趣的方面是在使用变量之前不必声明,例如

var sTest = "hello";
sTest2 = sTest + " world";
alert(sTest2);  //outputs "hello world"

就像已经声明过它。

ECMAScript的解释程序遇到未声明的标识符时,用该变量名创建一个全局变量,并将其初始化为指定的值。不过如果不能紧密跟踪变量,这样做也很危险。最好的习惯是像使用其他程序设计语言一样,总是声明所有变量。

2.3    关键字

2.4    保留字

2.5    原始值和引用值

在ECMAScript中,变量可以存放两种类型的值,即原始值和引用值。

  • 原始值是存储在中的简单数据段,也就是说,它们的值直接存储在变量访问的位置。
  • 引用值是存储在中的对象,也就是说,存储在变量处的是一个指针,指向存储对象的内存处。

为变量赋值时,ECMAScript的解释程序必须判断该值是原始类型的,还是引用类型的。要实现这一点,解释程序则需尝试判断该值是否为ECMAScript的原始类型之一,即Undefined , Number , Null , Boolean 和String型。由于这些原始类型占据的空间是固定的,所以可将它们存储在较小的内存区域——栈中,这样存储便于迅速查寻变量的值。

而如果一个值是引用类型的,那么它的存储空间将从堆中分配。由于引用值的大小会改变,所以不能把它放在栈中,否则会降低变量查寻的速度。相反,放在变量的栈空间中的值是该对象存储在堆中的地址。地址的大小是固定的,所以把它存储在栈中对变量的性能无任何负面影响。

2.6    原始类型

  • Undefined类型 ;当声明的变量未初始化时,该变量的默认值是undefined。
  • Null类型;值undefined实际上是从值null派生来的,null用于表示尚未存在的对象。
  • Boolean类型;true or false。
  • Number类型;Number类型既可以表示32位的整数,还可以表示64位的浮点数。 浮点字面量的有趣之处在于用它进行计算前,真正存储的是字符串;特殊值NaN
  • String类型;String类型的独特之处在于,它是唯一没有固定大小的原始类型。可由单引号或双引号声明。

typeof运算符:ECMAScript把术语类型(type)定义为值的一个集合,并提供了typeof运算符来判断一个值是否在某种类型的范围内。

2.7    转换

所有程序设计语言最重要的特征之一是具有进行类型转换的能力,ECMAScript给开发者们提供了大量简单的转换方法,都是简短的一步操作。

  • 转换成字符串;ECMAScript的Boolean值,数字和字符串的原始值的有趣之处在于它们都是伪对象,这意味着它们实际上具有属性和方法。这3种主要的原始值都有toString( )方法,可以把它们的值转换成字符串。

    Boolean类型的toString()方法只是输出“true”或“false”,结果由变量的值决定。

    Number类型的toString()方法比较特殊,它有默认模式和基模式。默认模式只是用相应的字符串输出数字值的十进制形式;而基模式可以用不同的基输出数字,例如二进制的基是2,八进制的基是8,十六进制的基是16。例如

var num = 10;
alert(num.toString(2));  //outputs "1010"
alert(num.toString(8));  //outputs "12"
alert(num.toString(16));  //outputs "A"
  • 转换成数字; ECMAScript提供了parseInt()和parseFloat()两种把非数字的原始值转换成数字的方法。but,只有对String类型调用这些方法,它们才能正确运行;对其它类型返回的都是NaN。

    此外,parseInt()方法还有基模式,可以把二进制,八进制,十六进制或其它任何进制的字符串转换成整数,基是由方法的第二个参数指定的。

var num1 = parseInt("AF",16);  //return 175
var num2 = parseInt("10",8);  //return 8
  • 强制类型转换; ECMAScript中可用的3种强制类型转换如下:
  1. Boolean(value)——把给定的值转换成Boolean型
  2. Number(value)——把给定的值转换成数字(可以使整数或浮点数)
  3. String(value)——把给定的值转换成字符串

    在处理ECMAScript这样的弱类型语言时,强制类型转换非常有用,不过应该确保使用值的正确。

2.8    引用类型

引用类型通常叫做(class),也就是说,遇到引用值时,所处理的就是对象。

对象是由new运算符加上要实例化的类的名字创建的。例如,下面代码创建了Object类的实例:

var o = new Object();

第3章将更深入地探讨对象及其行为。这一节的重点是具有等价的原始类型的引用类型。

  • Object类;ECMAScript中的所有类都由这个类继承而来,Object类中的所有属性和方法都会出现在其他类中,所以理解了Object类,就可以更好地理解其他类。

    Object类具有下列属性:

  1. Constructor——对创建对象的函数的引用(指针)。
  2. Prototype——对该对象的对象原型的引用。对于所有类,它默认返回Object对象的一个实例。

    Object类还有几个方法:

  1. HasOwnProperty(property)——判断对象是否有某个特定的属性,必须用字符串指定该属性。例如
    o.hasOwnProperty("name");

     

  2.  IsPrototypeOf(object)——判断该对象是否为另一个对象的原型。
  3. PropertyIsEnumerable(property)——判断给定的属性是否可以用for...in语句进行枚举。
  4. ToString()——返回对象的原始字符串表示。
  5. ValueOf()——返回最适合该对象的原始值。 对于许多类,该方法返回的值都与toString()的返回值相同。

    上面列举的每种属性和方法都会被其他类覆盖。

  • Boolean类

    Boolean类是Boolean原始类型的引用类型。需传递Boolean值作为参数:

var booleanObject = new Boolean(true);

遗憾的是,在ECMAScript中很少使用Boolean对象,即使使用,也不易理解。问题通常出现在Boolean表达式中使用Boolean对象时。例如:

var falseObject = new Boolean(false);
var result = falseObject && true;  //outputs true

按正常的理解,false 和 true进行AND操作的结果是false。不过,在这行代码中,计算的是falseObject,而不是它的值false。因为在Boolean表达式中,所有对象都会被自动转换为true。so,以上的进行的AND操作结果为true。

  • Number类

要创建Number对象,采用如下代码:

var numberObject = new Number(55);

要得到数字对象的Number原始值,只需要使用valueOf()方法:

var number = numberObject.valueOf();

当然,Number类也有toString()方法,在讨论类型转换的小节中已经讨论过该方法。

除从Object类继承的标准方法外,Number还有几个处理数值的专用方法。

toFixed()返回的是具有指定位数小数的数字的字符串表示。例如:

alert(numberObject.toFixed(2));  outputs "55.00"

对于处理货币的应用程序,该方法非常有用。不过toFixed()方法只能表示具有0到20位小数的数字,超出这个范围的值会引发错误。

  • String类

String对象的valueOf()方法和toString()方法都会返回String型的原始值。

String类具有属性length,它是字符串中的字符个数。ps. 另外即使字符串中包含双字节的字符,每个字符也只算一个字符。

String类具有大量的方法。首先,两个方法charAt()和charCodeAt()访问的是字符串中的单个字符。大家应该非常熟悉,第一个字符的位置是0,第二个字符的位置是1,以此类推。这两个方法都有一个参数,即要操作的字符的位置。

charAt()方法返回的是指定位置处的字符:

var stringObject = new String("hello world");
alert(stringObject.charAt(1));  outputs "e"

 

如果想得到的不是字符,而是字符代码,那么可以调用charCodeAt();

接下来是concat()方法,用于把一个或多个字符串连接到String对象的原始值上。该方法返回的是String原始值,保持原始的String对象不变:

var stringObject = new String("hello ");
var result = stringObject.concat("world");
alert(result);  //outputs "hello world"
alert(stringObjejct);  //outputs "hello "

实际中较常见的是用加号(+)连接字符串;

如果无法确定在某个字符串中是否存在一个字符,这时可调用indexOf()和lastIndexOf()方法。这两个方法的不同之处在于,indexOf()方法是从字符串的开头(位置0)开始检索,而lastIndexOf()是从结尾开始。

下一个方法是localeCompare(),对字符串值进行排序。该方法有一个参数——要进行比较的字符串。(大写字母在顺序上排在小写字母之后)

instanceof运算符

在使用typeof运算符时采用引用类型存储值会出现一个问题,无论引用的是什么类型的对象,它都会返回“object”。so,ECMAScript引入了另一个Java运算符来解决这个问题。

与typeof方法不同的是,instanceof方法要求开发者明确地确认对象为某特定类型。 例如:

var stringObject = new String("hi");
alert(stringObject instanceof String);  //outputs "true"

 

2.9    运算符

  • 一元运算符; 一元运算符只有一个参数,即要操作的对象或值。它们是ECMAScript中最简单的运算符。
  1. delete
  2. void
  3. 前增量 / 前减量运算符 (++i/--i)
  4. 后增量 / 后减量运算符 (i++/i--)
  5. 一元加法和一元减法
  • 位运算符; 这套运算符是在数字底层(即表示数字的32个数位)进行操作的。在探讨这些运算符之前,你首先需要重温一下ECMAScript中的整数!

位运算NOT(~); 它是ECMAScript中为数不多的与二进制算术有关的运算符之一。位运算NOT是三步的处理过程:

                (1) 把运算数转换成32位数字;

                (2) 把二进制形式转换成它的二进制反码;

                (3) 把二进制反码转换成浮点数;

                例如:

var num1 = 25;  //25 is equal to 0000000000000000011001
var num2 = ~num1  //convert to 1111111111111111100110
alert(num2); // outputs "-26"

位运算符NOT实质上是对数字求负,然后减1,因此 25 变为 -26。

位运算AND(&); 位运算符AND由和号(&)表示,直接对数字的二进制形式进行运算。它把每个数字中的数位对齐,然后用下面的规则对同一位置上的两个数位进行AND运算:

第一个数字中的数位第二个数字中的数位结果
111
100
010
000

例如,要对数字 25 和 3 进行AND运算,代码如下所示:

var result = 25 & 3;
alert(result); // outputs "1"

其结果是1,为什么呢?分析如下:

   25 = 0000 0000 0000 0000 0000 0000 0001 1001

     3 = 0000 0000 0000 0000 0000 0000 0000 0011

------------------------------------------------------

AND = 0000 0000 0000 0000 0000 0000 0000 0001

在 25 和 3 中,只有一个位数(位0)存放的是1,其他位数生成的都是0,所以结果是1。

位运算OR(|); 在计算每个位时,OR采用下列规则:

第一个数字中的数位第二个数字中的数位结果
111
101
011
000

 

对 25 和 3 进行OR运算,结果为 28。

位运算XOR(^); XOR不同于OR,当只有一个数位存放的是1时,它才返回1。

对 25 和 3 进行XOR运算,结果为 26。

左移运算(<<); 左移运算符是把数字中的所有数位向左移动指定的数量。

例如,把数字2(等于二进制中的10)左移5位,结果为64(等于二进制中的100000)。

注意在左移数位时,数字右边会多出5个空位。左移运算用 0 填充这些空位,使结果为完整的32位数字。

有符号右移运算(>>); 它将32位数字中的所有数位整体右移,同时保留该数的符号。同样,移动数位后会造成空位。这次,空位位于数字的左侧,但位于符号位之后。ECMAScript用符号位的值填充这些空位,创建完整的数字。

有意思的是,有符号右移运算与左移运算相反。例如,把64右移5位,将变为2.

无符号右移运算(>>>); 对于正数,无符号右移运算的结果与有符号右移运算的结果一样。

但对于负数,情况就不同了。无符号右移运算用0填充所有空位,而负数则被作为正数来处理,所以负数的无符号右移运算得到的总是一个非常大的数字。出于这种原因,使用无符号右移运算要小心。

  •  Boolean运算符; Boolean运算符与等式运算符同等重要,是它们使得程序设计语言得以正常运行。Boolean运算符有三种,即NOT(!)、AND(&&)和OR(||)。
  • 乘性运算符; 乘性运算符有三种,乘法运算符(*)、除法运算符(/)和取模(余数)运算符(%)。不过它们还具有一些自动的类型转换功能,这一点需要注意。
  • 加性运算符; 在程序设计语言中,加性运算符(即加号和减号)通常是最简单的数学运算符。不过在ECMAScript中,每个加性运算符都有大量的特殊行为。

加法运算符(+),如果两个运算数都是数字,将执行算术加法。不过如果某个运算符是字符串,那么采用下列规则:

1、如果两个运算数都是字符串,把第二个字符串连接到第一个字符串上。

2、如果只有一个运算数是字符串,把另一个运算数转换成字符串,结果是两个字符串连接成的字符串。例如:

var result = 5 + 5;  // two numbers
alert(result);  //outputs "10"
var result2 = 5 + "5";  //a number and a string
alert(result2);  //outputs "55"
  • 关系运算符; 关系运算符 小于(<)、大于(>)、小于等于(<=)和大于等于(>=)执行的是两个数的比较运算,比较方式与算术比较运算相同。每个关系运算符都返回一个Boolean值。
  • 等性运算符; 判断两个变量是否相等是程序设计中非常重要的运算。在处理原始值时,这种运算相当简单,但涉及对象,任务就稍有点复杂。ECMAScript提供了两套运算符处理这个问题,等号和非等号用于处理原始值,全等号和非全等号用于处理对象。
  • 条件运算符; 条件运算符是ECMAScript中功能最多的运算符,它的形式与Java中的相同:variable = boolean_expression ? true_value : false_value; 例如:
    var max = (num1 > num2) ? num1 : num2;

    在这个例子中,max将被赋予数字中的最大值。

  • 赋值运算符; 简单的赋值运算符由等号(=)实现,只是把等号右边的值赋予等号左边的变量。而复合赋值运算是一些缩写形式。比如:乘法/赋值(+=)、除法/赋值(/=)、取模/赋值(%=)……等等.

2.10    语句

  • if 语句;
  • 迭代语句 (循环语句);  ECMAScript提供了四种迭代语句:do-while语句,while语句,for语句和for-in语句(for-in语句用于枚举对象的属性)。
  • 有标签的语句; 可以用下列语法给语句加标签,以便日后调用:
    label: statement

    例如:

    start: var count = 10;

    标签start可被后来的break语句或continue语句引用。

  • break 语句 和 continue 语句;
  • with 语句;
  • switch 语句;ECMAScript和Java中的switch语句有两点不同。在ECMAScript中,switch语句可以用于字符串,而且能用不是常量的值说明情况:
    var BLUE ="blue", RED = "red", YELLOW = "yellow";
    
    switch(color){
       case BLUE: alert("Blue");
           break;
       case RED: alert("Red"):
           break;
       case YELLOW: alert("Yellow");
           break;
       default: alert("Other");
    }

    这里,switch语句用于字符串color,声明case使用的是变量BLUE、RED和YELLOW,这在ECMAScript中是完全有效的。

2.11    函数

  • 无重载; ECMAScript中的函数不能重载。可用相同的名字在同一个作用域中定义两个函数而不会引发错误,但真正使用的是后一个函数。考虑下面的例子:
    function doAdd(num){
        alert(num + 100);
    }
    
    function doAdd(num){
        alert(num + 10);
    }
    
    doAdd(10);
    

    你认为这段代码会显示什么?

          警告将显示“20”,因为第二个doAdd()函数定义覆盖了第一个定义。虽然这让开发者有些头疼,不过可以使用arguments对象避开这种限制。

  • arguments 对象; 在函数代码中,使用特殊对象arguments,开发者无需明确指出参数名就能访问它们。

    用arguments对象判断传递给函数的参数个数,即可模拟函数重载:

function doAdd(){
    if(arguments.length == 1){
        alert(arguments[0] + 10);
  } else if(arguments.length == 2){
        alert(arguments[0] + arguments[1]);
       }
}

doAdd(10);  //outputs "20"
doAdd(30,20);  //outputs "50"

虽然不如重载那么好,不过已足可避开ECMAScript的这种限制。

  • Funtion 类; 尽管可用Function构造函数创建函数,但最好不要使用它,因为用它定义函数比用传统方式慢得多。不过,所有函数都应看做是Function类的实例。还有两个Function类的方法与对象的谈论相关,下一章将讨论它们。
  • 闭包; ECMAScript最容易让人误解的一点是它支持闭包(closure)。所谓闭包,就是指该函数能使用函数外定义的变量。在ECMAScript中使用全局变量是一个简单的闭包实例:
    var message = "hi";
    
    function sayHi(){
        alert(message);
    }
    
    sayHi();

    而在一个函数中定义另一个函数会使闭包变得更复杂,如下所示:

    var baseNum = 10;
    
    function addNumbers(num1,num2){
        function doAddition(){
             return num1 + num2 + baseNum;
        }
        return doAddition();
    }

    这里要掌握的重要概念是doAddition()函数根本不接受参数,它使用的值是从执行环境中获取的

        可以看到,闭包是ECMAScript中非常强大多用的一部分。就像使用任何高级函数一样,在使用闭包时要当心,因为它们可能会变得非常复杂。

 

  

转载于:https://my.oschina.net/u/3415601/blog/877628

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值