JavaScript高级程序设计(第三版)5章

Menu

  • 第5章 引用类型
    • 5.1 Object类型
    • 5.2 Array类型
    • 5.4 RegExp 类型
      • 5.4.2 RegExp实例方法
      • 5.4.3 RegExp构造函数属性
    • 5.5 函数类型
      • 5.5.3作为值的函数
      • 5.5.4 函数内部属性
      • 5.5.5 函数属性和方法
    • 5.6 基本包装类型
      • 5.6.1 Boolean类型
      • 5.6.3 String类型
  • 5.7 单体内置对象
    • 5.7.1 Global对象
    • 5.7.2 Math对象

第5章 引用类型

5.1 Object类型
  • 创建Object 实例的方式有两种
// 第一种是使用 new 操作符后跟 Object 构造函数
var person = new Object();
person.name = "Nicholas";
person.age = 29;
// 另一种方式是使用对象字面量表示法。
var person = {
name : "Nicholas",
age : 29
};
  • 调用属性
alert(person["name"]); //"Nicholas"
alert(person.name); //"Nicholas"

5.2 Array类型

  • 创建数组的基本方式有两种。
var colors = new Array("red", "blue", "green");  // 1. 构造函数创建
var colors = ["red", "blue", "green"];  // 2. 使用数组字面量表示法
  • array可以在任何位置创建item,可以超出原本Array的长度;
  • 也可以控制Array的item长度;array_name.length = n
  • 未赋值的item默认是undefine值;
var values = ["red", "orange", "yellow"];  //创建字面量Array
values[3] = "green";  // 增加数组长度
values.length = 2;   // 调节array的长度;
document.write(values[3])  // 输出 undefined;
  • 在Array的末尾添加新的itme:
var colors = ["red", "orange", "yellow"]; // 创建一个包含 3 个字符串的数组
colors[colors.length] = "green"; //(在位置 3)添加一种颜色
colors[colors.length] = "cyan"; //(在位置 4)再添加一种颜色
colors.push("blue")  // 用Array方法在末尾添加item
  • Array类型检测
// 检测是否是Array的实例;
if (Array.isArray(value)){
    // do_something
}
// 检测是否是Array;
if(some_variable instanceof Array){
    // do something;
}
  • 栈方法 LIFO(Last-In-First-Out,后进先出)的数据结构

    • ECMAScript 为数组专门提供了 push()和 pop()方法,以便
      实现类似栈的行为;
  • 队列方法 FIFO(First-In-First-Out,先进先出)的数据结构

    • push()和 shift()方法;

    • shift(),它能够移除数组中的第一个项并返回该项,同时将数组长度减1;

    • Array 总结:

      • 头弹出 - shift(), 尾弹出 -pop()
      • 头插入 - unshift(), 尾插入 - push()
  • Array 升序排序 和 反转
  • sort()
    • sort()方法会调用每个数组项的 toString()转型方法,然后比较得到的字符串,以确定如何排序。和python不一样,即使数组中的每一项都是数值, sort()方法比较的也是字符串;如果需要对数字进行排序,需要些一个排序函数:
// 升序排序函数;降序-1 和 1互换位置即可;
   function compare(value1, value2) {
        if (value1 < value2) {
            return -1;       // -1 靠前排一位
        } else if (value1 > value2) {
            return 1;       // -1 靠后排一位
        } else {
            return 0;
        }
    }

   list.sort(compare)
   document.write(list)
  • 排序函数简写方式:
    list = [15, 11, 1, 6, 90];
    function compare(value1, value2){
        return value1 - value2;
    }
    document.write(list.sort(compare))
  • reverse (跟python一样的)

  • concat (合并多个数组)

var colors = ["red", "green", "blue"];
var colors2 = colors.concat("yellow", ["black", "brown"]);
alert(colors2); //red,green,blue,yellow,black,brown
  • slice(分片)
var colors = ["red", "green", "blue", "yellow", "purple"];
var colors2 = colors.slice(1);  // 相当于python的 clolrs[1:]
var colors3 = colors.slice(1,4);   // 相当于python的 clolrs[1:4]
alert(colors2); //green,blue,yellow,purple
alert(colors3); //green,blue,yellow
  • splice()方法
  • 删除:可以删除任意数量的项, 如果是前两项;
Array.splice(0, 2)     // 参数1是:下标, 参数2是删除n项;
  • 插入:可以向指定位置插入任意数量的项(不删除原有项)
    list = [15, 11, 1, 6, 90];
    list.splice(0, 0, "a", "b")   // 插入到下表0, 不删除原有项,插入item
    document.write(list) // a,b,15,11,1,6,90
  • 插入:可以向指定位置插入任意数量的项(要删除原有项)
    list = [15, 11, 1, 6, 90];
    list.splice(0, 1, "a", "b")   // 插入到下表0, 删除原有项,插入item
    document.write(list) // a,b,15,11,1,6,90
  • Array的位置方法

    • indexOf(要查找的项, [查找的起始位置的下标])
    • lastIndexOf(要查找的项, [查找的起始位置的下标])
    • 返回要查找的项的下标,没找到返回-1;
  • Array的迭代方法

    • every():对数组中的每一项运行给定函数,如果该函数对每一项都返回 true,则返回 true。
    • filter():对数组中的每一项运行给定函数,返回该函数会返回 true 的项组成的数组。
    • forEach():对数组中的每一项运行给定函数。这个方法没有返回值。
    • map():对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。
    • some():对数组中的每一项运行给定函数,如果该函数对任一项返回 true,则返回 true。以上方法都不会修改数组中的包含的值。
  • map example

function f(n) {
    return n ** 2
}
var n = [0, 1, 2, 3, 4, 5, 6]
document.write(n.map(f))  // 0,1,4,9,16,25,36
  • filter example
    var numbers = [1,2,3,4,5,4,3,2,1];
    var filterResult = numbers.filter(function(item, index, array){
        return (item > 2);
    });
    alert(filterResult); //[3,4,5,4,3]
  • Array的归并方法
  • reduce():数组的第一项开始,逐个遍历到最后,迭代数组的所有项,然后构建一个最终返回的值。
  • reduceRight():同上, 但是从最后向前遍历。
  • reduce()和 reduceRight()的函数接收 4 个参数:前一个值、当前值、项的索引和数组对象。
var values = [1,2,3,4,5];
var sum = values.reduce(function(prev, cur, index, array){
  return prev + cur;
  });
alert(sum); //15

  • Date
  • var now = new Date(); // 得到当前时间;
  • 如果想根据特定的日期和时间创建日期对象,必须传入表示该日期的毫秒数(即从 UTC 时间 1970 年 1 月 1 日午夜起至该日期止经过的毫秒数)。为了简化这一计算过程, ECMAScript 提供了两个方法: Date.parse() 和 Date.UTC()
var someDate = new Date(Date.parse("May 25, 2004"));
// Tue May 25 2004 00:00:00 GMT+0800 
  • 果传入 Date.parse()方法的字符串不能表示日期,那么它会返回 NaN。
  • 直接将表示日期的字符串传递给 Date 构造函数,也会在后台调用 Date.parse()。以下表达式等价于上面一个例子:
var someDate = new Date("May 25, 2004");
  • Date.UTC()方法同样也返回表示日期的毫秒数:
// GMT 时间 2000 年 1 月 1 日午夜零时
var y2k = new Date(Date.UTC(2000, 0));

// GMT 时间 2005 年 5 月 5 日下午 5:55:55
var allFives = new Date(Date.UTC(2005, 4, 5, 17, 55, 55));

// 构造函数Date也会模仿Date.UTC()方法来达到同样的效果:
// 本地时间 2000 年 1 月 1 日午夜零时
var y2k = new Date(2000, 0);

// 本地时间 2005 年 5 月 5 日下午 5:55:55
var allFives = new Date(2005, 4, 5, 17, 55, 55);
  • Date.now() == python的 time.time()

    • return 当前调用这个方法的时间戳;
  • 5.3.2 日期格式化方法

    • getTime() 返回表示日期的毫秒数;与valueOf()方法返回的值相同
    • setTime(毫秒) 以毫秒数设置日期,会改变整个日期
    • getFullYear() 取得4位数的年份(如2007而非仅07)
    • getUTCFullYear() 返回UTC日期的4位数年份
    • setFullYear(年) 设置日期的年份。传入的年份值必须是4位数字(如2007而非仅07)
    • setUTCFullYear(年) 设置UTC日期的年份。传入的年份值必须是4位数字(如2007而非仅07)
    • getMonth() 返回日期中的月份,其中0表示一月, 11表示十二月
    • getUTCMonth() 返回UTC日期中的月份,其中0表示一月, 11表示十二月
    • setMonth(月) 设置日期的月份。传入的月份值必须大于0,超过11则增加年份
    • setUTCMonth(月) 设置UTC日期的月份。传入的月份值必须大于0,超过11则增加年份
    • getDate() 返回日期月份中的天数(1到31)
    • getUTCDate() 返回UTC日期月份中的天数(1到31)
    • setDate(日) 设置日期月份中的天数。如果传入的值超过了该月中应有的天数,则增加月份
    • setUTCDate(日) 设置UTC日期月份中的天数。如果传入的值超过了该月中应有的天数,则增加月份
    • getDay() 返回日期中星期的星期几(其中0表示星期日, 6表示星期六)
    • getUTCDay() 返回UTC日期中星期的星期几(其中0表示星期日, 6表示星期六)
    • getHours() 返回日期中的小时数(0到23)
    • getUTCHours() 返回UTC日期中的小时数(0到23)
    • setHours(时) 设置日期中的小时数。传入的值超过了23则增加月份中的天数
    • setUTCHours(时) 设置UTC日期中的小时数。传入的值超过了23则增加月份中的天数
    • getMinutes() 返回日期中的分钟数(0到59)
    • getUTCMinutes() 返回UTC日期中的分钟数(0到59)
    • setMinutes(分) 设置日期中的分钟数。传入的值超过59则增加小时数
    • setUTCMinutes(分) 设置UTC日期中的分钟数。传入的值超过59则增加小时数
    • getSeconds() 返回日期中的秒数(0到59)
    • getUTCSeconds() 返回UTC日期中的秒数(0到59)
    • setSeconds(秒) 设置日期中的秒数。传入的值超过了59会增加分钟数
    • setUTCSeconds(秒) 设置UTC日期中的秒数。传入的值超过了59会增加分钟数
    • getMilliseconds() 返回日期中的毫秒数
    • getUTCMilliseconds() 返回UTC日期中的毫秒数
    • setMilliseconds(毫秒) 设置日期中的毫秒数

5.4 RegExp 类型
  • 正则表达式中的元字符包括:( [ { \ ^ $ | ) ? * + .]} 和python的一样;

  • RegExp 类型来支持正则表达式,有两种创建RegExp的方式:

    • var expression = / pattern / flags 通过字面量创建
    • pattern == 正则表达式
    • flags
      • g:表示全局(global)模式,即模式将被应用于所有字符串,而非在发现第一个匹配项时立即停止;
      • i:表示不区分大小写(case-insensitive)模式,即在确定匹配项时忽略模式与字符串的大小写;
      • m:表示多行(multiline)模式,即在到达一行文本末尾时还会继续查找下一行中是否存在与模式匹配的项。
  • example:

    //  匹配所有.at的字符,不区分大小写
    var re_exp = /.at/gi;
    while(true){
        re = re_exp.exec("asdfat..at;;;AtasdAt")
        if (re==null){break}
        document.write(re)  // fat.at;AtdAt 
    }
  • 另一种通过RegExp Object构造函数创建:var pattern2 = new RegExp("[bc]at", "i");
  • 参数1是re表达式, 参数2是匹配模式;
  • example:
    //  通过RegExp Object构造函数创建匹配所有.at的字符,不区分大小写
    var re_exp = new RegExp(".at", "gi");
    while(true){
        re = re_exp.exec("asdfat..at;;;AtasdAt");
        if (re==null){break;}
        document.write(re);  // fat.at;AtdAt
    }
  • 与python不同的是,即使是g模式,也是一次匹配到第一个匹配项,需要用while创建一个无限循环,每次检测是否匹配到了null,匹配到就退出;

  • 5.4.2 RegExp实例方法

    • exec()接受一个参数,即要应用模式的字符串,然后返回包含第一个匹配项信息的数组;
    var re_exp = new RegExp(".(at)", "gi");
    while(true){
        re = re_exp.exec("asdfat..at;;;AtasdAt");
        if (re==null){break;}
        document.write("匹配项->[{0}]捕获组->[{1}]".format(re[0],re[1]),"
"); // js没有format,需要自己写; } // 匹配项->[fat]捕获组->[at] // 匹配项->[.at]捕获组->[at] // 匹配项->[;At]捕获组->[At] // 匹配项->[dAt]捕获组->[At]
  • 实例return的Array实例包含两个额外的属性: index 和 input。

    • index是匹配到字符串的index;
    • input是要匹配的字符串;
  • pattern2 是全局模式,因此每次调用 exec()都会返回字符串中的下一个匹配项,直至搜索到字符串末尾为止。此外,还应该注意模式的 lastIndex 属性的变化情况。在全局匹配模式下, lastIndex 的值在每次调用 exec()后都会增加,而在非全局模式下则始终保持不变。

var pattern2 = /.at/g;
var matches = pattern2.exec(text);
alert(matches.index); //0
alert(matches[0]); //cat
alert(pattern2.lastIndex); //3

matches = pattern2.exec(text);
alert(matches.index); //5
alert(matches[0]); //bat
alert(pattern2.lastIndex); //8
  • test()
    • 正则表达式的第二个方法是 test(),它接受一个字符串参数。在模式与该参数匹配的情况下返回true;否则,返回 false。test()方法经常被用在 if 语句中,如下面的例子所示:
var text = "000-00-0000";
var pattern = /\d{3}-\d{2}-\d{4}/;
if (pattern.test(text)){
alert("The pattern was matched.");
}
  • RegExp 实例继承的 toLocaleString()和 toString()方法都会返回正则表达式的字面量,与创建正则表达式的方式无关。
var pattern = new RegExp("\\[bc\\]at", "gi");
alert(pattern.toString()); // /\[bc\]at/gi
alert(pattern.toLocaleString()); // /\[bc\]at/gi
  • 5.4.3 RegExp构造函数属性
    • RegExp构造函数属性基于所执行的最近一次正则表达式操作而变化;
    • 可以通过长属性名和短属性名这两种方式访问它们(Opera 不支持短属性名);
    • input ($_) 最近一次要匹配的字符串。
    • lastMatch ($&) 最近一次的匹配项。
    • lastParen ($+) 最近一次匹配的捕获组。
    • leftContext ($`) input字符串中lastMatch之前的文本
    • multiline ($*) 布尔值,表示是否所有表达式都使用多行模式。
    • rightContext ($') Input字符串中lastMatch之后的文本

例子:

var text = "this has been a short summer";
var pattern = /(.)hort/g;
/*
* 注意: Opera 不支持 input、 lastMatch、 lastParen 和 multiline 属性
* Internet Explorer 不支持 multiline 属性
*/
    if (pattern.test(text)){
        document.write(RegExp.input, "
"); // this has been a short summer document.write(RegExp.leftContext, "
"); // this has been a document.write(RegExp.rightContext, "
"); // summer document.write(RegExp.lastMatch, "
"); // short document.write(RegExp.lastParen, "
"); // s document.write(RegExp.multiline, "
"); // firefox display: undefined }
  • 短属性名必须通过方括号语法来访问;
var text = "this has been a short summer";
var pattern = /(.)hort/g;

if (pattern.test(text)){
alert(RegExp.$_); // this has been a short summer
alert(RegExp["$`"]); // this has been a
alert(RegExp["$'"]); // summer
alert(RegExp["$&"]); // short
alert(RegExp["$+"]); // s
alert(RegExp["$*"]);  // firefox display: undefined
}
  • 还有9个用于存储捕获组的属性;
/*RegExp.$1
RegExp.$2
…
RegExp.$9*/

var text = "this has been a short summer";
var pattern = /(..)or(.)/g;
if (pattern.test(text)){
alert(RegExp.$1); //sh
alert(RegExp.$2); //t
}
  • 5.4.4 模式的局限性
    尽管 ECMAScript 中的正则表达式功能还是比较完备的,但仍然缺少某些语言(特别是 Perl)所支持的高级正则表达式特性。下面列出了 ECMAScript 正则表达式不支持的特性(要了解更多相关信息,请访问 www.regular-expressions.info)。
    • 匹配字符串开始和结尾的\A 和\Z 锚①
    • 向后查找(lookbehind) ②
    • 并集和交集类
    • 原子组(atomic grouping)
    • Unicode 支持(单个字符除外,如\uFFFF)
    • 命名的捕获组③
    • s(single,单行)和 x(free-spacing,无间隔)匹配模式
    • 条件匹配
    • 正则表达式注释即使存在这些限制, ECMAScript 正则表达式仍然是非常强大的,能够帮我们完成绝大多数模式匹配任务。
      ——————————

5.5 函数类型
  • 5.5.3作为值的函数
    • 函数名是变量,所以函数也可以作为值来使用;也就是说,不仅可以像传递参数一样把一个函数传递给另一个函数,而且可以将一个函数作为另一个函数的结果返回。
    function callSomeFunction(someFunction, someArgument){
        return someFunction(someArgument);
    }
    function add10(num){
        return num + 10;
    }
    var result1 = callSomeFunction(add10, 10);
    document.write(result1); //20

    function getGreeting(name){
        return "Hello, " + name;
    }
    var result2 = callSomeFunction(getGreeting, "Nicholas");
    document.write(result2); //"Hello, Nicholas"
  • 5.5.4 函数内部属性
    • 函数内部,有两个特殊的对象: arguments 和 this
    • arguments 对象;
      • 是一个类数组对象,包含着传入函数中的所有参数。
      • arguments对象还有一个名叫 callee 的属性, 指向拥有这个 arguments 对象的函数;
    //紧密耦合:
    function factorial(num){
        if (num <=1) {
            return 1;
        } else {
            return num * factorial(num-1)
        }
    }
    document.write(factorial(5)) // 120
    //改良后, 函数名可以改变:
    function factorial(num){
        if (num <=1) {
            return 1;
        } else {
            return num * arguments.callee(num-1)
        }
    }
    var trueFactorial = factorial;
    factorial = function(){
        return 0;
    };
     document.write(trueFactorial(5)); //120
     document.write(factorial(5)); //0
  • this 对象;
    • 引用的是函数据以执行的环境对象;
    window.color = "red";
    var o = { color: "blue" };
    function sayColor(){
        document.write(this.color);
    }
    sayColor(); //"red"
    o.sayColor = sayColor;
    o.sayColor(); //"blue"
  • 函数对象的属性: caller 保存着调用当前函数的函数的引用,
    如果是在全局作用域中调用当前函数,它的值为 null。
    function outer(){
        inner();
    }
    function inner(){
        alert(inner.caller);
    }
    outer(); //function outer(){inner();} 
    //结果为显示 outer()函数的源代码, 因为是 outer()调用了 inter();
    function outer(){
        inner();
    }
    function inner(){
        alert(arguments.callee.caller); //用arguments.callee.caller实现更松散的耦合;
    }
    outer(); //结果同上
  • 5.5.5 函数属性和方法
    • 函数属性
      • length
        • length 属性表示函数希望接收的命名参数的个数;
      • prototype
        • prototype 是保存它们所有实例方法的真正所在。换句话说,诸如toString()和 valueOf()等方法实际上都保存在 prototype 名下,只不过是通过各自对象的实例访问罢了。
    • 函数方法
      • 每个函数都包含两个非继承而来的方法: apply()和 call()。
      • 这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内 this 对象的值。
  • apply()
    • f.apply(this, [num1, num2])
//第二个参数可以是 Array 的实例,也可以是
arguments 对象。
    function sum(num1, num2){
        return num1 + num2;
    }
    function callSum1(num1, num2){
        return sum.apply(this, arguments); // 传入 arguments 对象
    }
    function callSum2(num1, num2){
        return sum.apply(this, [num1, num2]); // 传入数组
    }
    document.write(callSum1(10,10)); //20
    document.write(callSum2(10,10)); //20
  • call()
    • 与 apply()方法的作用相同,但是传递给函数的参数必须逐个列举出来;
    function sum(num1, num2){
        return num1 + num2;
    }
    function callSum(num1, num2){
        return sum.call(this, num1, num2);
    }
    document.write(callSum(10,10)); //20
  • 传递参数并非 apply()和 call()真正的用武之地;它们真正强大的地方是能够扩充函数赖以运行的作用域。
    window.color = "red";
    var o = { color: "blue" };
    function sayColor(){
        document.write(this.color);
    }
    sayColor(); //red
    sayColor.call(this); //red
    sayColor.call(window); //red
    sayColor.call(o); //blue
  • 使用 call()(或 apply())来扩充作用域的最大好处,就是对象不需要与方法有任何耦合关系。在前面例子的第一个版本中,我们是先将 sayColor()函数放到了对象 o 中,然后再通过 o 来调用它的;而在这里重写的例子中,就不需要先前那个多余的步骤了。
  • ECMAScript 5 还定义了一个方法: bind()。这个方法会创建一个函数的实例,其 this 值会被绑定到传给 bind()函数的值。
    window.color = "red";
    var o = { color: "blue" };
    function sayColor(){
        document.write(this.color);
    }
    var objectSayColor = sayColor.bind(o);
    objectSayColor(); //blue
  • 每个函数继承的 toLocaleString()和 toString()方法 valueOf()方法始终都返回函数的代码。
5.6 基本包装类型
  • 为了便于操作基本类型值, ECMAScript 还提供了 3 个特殊的引用类型: Boolean、 Number 和String。
  • 每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象,从而让我们能够调用一些方法来操作这些数据。
  • 引用类型与基本包装类型的主要区别就是对象的生存期。使用 new 操作符创建的引用类型的实例,在执行流离开当前作用域之前都一直保存在内存中。而自动创建的基本包装类型的对象,则只存在于一
    行代码的执行瞬间,然后立即被销毁。这意味着我们不能在运行时为基本类型值添加属性和方法。
    var s1 = "some text";
    s1.color = "red";
    document.write(s1.color); //undefined
  • 当然,可以显式地调用 Boolean、 Number 和 String 来创建基本包装类型的对象。不过,应该在绝对必要的情况下再这样做,因为这种做法很容易让人分不清自己是在处理基本类型还是引用类型的值。
  • 把字符串传给 Object 构造函数,就会创建 String 的实例;而传入数值参数会得到 Number 的实例,传入布尔值参数就会得到 Boolean 的实例。
  • 要注意的是,使用 new 调用基本包装类型的构造函数,与直接调用同名的转型函数是不一样的。
    var value = "25";
    var number = Number(value); //转型函数
    document.write(typeof number); //"number"
    var obj = new Number(value); //构造函数
    document.write(typeof obj); //"object"
    //变量 number 中保存的是基本类型的值 25
    //变量 obj 中保存的是 Number 的实例
  • 5.6.1 Boolean类型
    • Boolean 类型是与布尔值对应的引用类型。
var booleanObject = new Boolean(true)
  • Boolean 类型的实例重写了 valueOf()方法,返回基本类型值 true 或 false;重写了 toString()方法,返回字符串"true"和"false"。
  • Boolean 对象在 ECMAScript 中的用处不大,因为它经常会造成人们的误解。其中最常见的问题就是在布尔表达式中使用 Boolean 对象;
    var falseObject = new Boolean(false);
    var result = falseObject && true;
    document.write(result); //true;布尔表达式中的所有对象都会被转换为 true;
    var falseValue = false;
    result = falseValue && true;
    document.write(result); //false
  • 基本类型与引用类型的布尔值还有两个区别:

    • typeof 操作符对基本类型返回"boolean",而对引用类型返回"object"。
    • 由于 Boolean 对象是 Boolean 类型的实例,所以使用instanceof操作符测试 Boolean 对象会返回 true,而测试基本类型的布尔值则返回false。
  • 5.6.3 String类型

  • String方法

  • 1.字符方法:这两个方法都接收一个参数,即基于 0 的字符位置。

    • charAt(): 返回字符
    • charCodeAt():返回字符编码
var stringValue = "hello world";
alert(stringValue.charAt(1)); //"e"
alert(stringValue.charCodeAt(1)); //输出"101"
    1. 字符串操作方法
    • concat():同“+”号;将一或多个字符串拼接起来,返回拼接得到的新字符串, 接受任意多个参数;
var stringValue = "hello ";
var result = stringValue.concat("world", "!");
alert(result); //"hello world!"
alert(stringValue); //"hello"
  • slice(a1, a2): a1指定子字符串的开始位置, a2表示子字符串到哪里结束;
  • substr(a1, a2): a1指定子字符串的开始位置, a2表示希望返回的字符个数。
  • substring(a1, a2):a1指定子字符串的开始位置, a2表示子字符串到哪里结束;
  • 以上三个方法如果没有给这些方法传递第二个参数,则将字符串的长度作为结束位置。
  • 与concat()方法一样, slice()、 substr()和 substring()也不会修改字符串本身的值, 只是返回一个基本类型的字符串值,对原始字符串没有任何影响。
var stringValue = "hello world";
alert(stringValue.slice(3)); //"lo world"
alert(stringValue.substring(3)); //"lo world"
alert(stringValue.substr(3)); //"lo world"
alert(stringValue.slice(3, 7)); //"lo w"
alert(stringValue.substring(3,7)); //"lo w"
alert(stringValue.substr(3, 7)); //"lo worl"
  • 如果传递给这些方法的参数是负值, slice()方法会将传入的负值与字符串的长度相加,substr()方法将负的第一个参数加上字符串的长度,而将负的第二个参数转换为 0。最后, substring()方法会把所有负值参数都转换为 0。
var stringValue = "hello world";
alert(stringValue.slice(-3)); //"rld"
alert(stringValue.substring(-3)); //"hello world"
alert(stringValue.substr(-3)); //"rld"
alert(stringValue.slice(3, -4)); //"lo w"
alert(stringValue.substring(3, -4)); //"hel"
alert(stringValue.substr(3, -4)); //""(空字符串)
    1. 字符串位置方法
    • indexOf() :从字符串的开头向后搜索子字符串
    • lastIndexOf() : 从字符串的末尾向前搜索子字符串。
    • 以上两个方法第二个参数都表示从字符串中的哪个位置开始搜索。
    1. trim()方法(ES6):这个方法会创建一个字符串的副本,删除前置及后缀的所有空格,然后返回结果。
var stringValue = " hello world ";
var trimmedStringValue = stringValue.trim();
alert(stringValue); //" hello world "
alert(trimmedStringValue); //"hello world"
    1. 字符串大小写转换方法
    • toLowerCase()
    • toUpperCase()
    • toLocaleLowerCase()
    • toLocaleUpperCase()
    • toLocaleLowerCase()和 toLocaleUpperCase()方法则是针对特定地区的实现。一般来说,在不知道自己的代码将在哪种语言环境中运行的情况下,还是使用针对地区的方法更稳妥一些。
    1. 字符串的模式匹配方法
    • match():本质上与调用 RegExp 的 exec()方法相同。只接受一个参数,要么是一个正则表达式,要么是一个 RegExp 对象。
var text = "cat, bat, sat, fat";
var pattern = /.at/;
//与 pattern.exec(text)相同
var matches = text.match(pattern);
alert(matches.index); //0
alert(matches[0]); //"cat"
alert(pattern.lastIndex); //0
  • search():search()方法返回字符串中第一个匹配项的索引;如果没有找到匹配项,则返回-1。而且, search()方法始终是从字符串开头向后查找模式。
var text = "cat, bat, sat, fat";
var pos = text.search(/at/);
alert(pos); //1
  • replace():这个方法接受两个参数:第一个参数可以是一个 RegExp 对象或者一个字符串(这个字符串不会被转换成正则表达式),第二个参数可以是一个字符串或者一个函数。如果第一个参数是字符串,那么只会替换第一个子字符串。要想替换所有子字符串,唯一的办法就是提供一个正则表达式,而且要指定全局(g)标志。
var text = "cat, bat, sat, fat";
var result = text.replace("at", "ond");
alert(result); //"cond, bat, sat, fat"
result = text.replace(/at/g, "ond");
alert(result); //"cond, bond, sond, fond"
  • 如果第二个参数是字符串,那么还可以使用一些特殊的字符序列,将正则表达式操作得到的值插入到结果字符串中。下表列出了 ECMAScript 提供的这些特殊的字符序列。
$$ :$
$& :匹配整个模式的子字符串。与RegExp.lastMatch的值相同
$' :匹配的子字符串之前的子字符串。与RegExp.leftContext的值相同
$` : 匹配的子字符串之后的子字符串。与RegExp.rightContext的值相同
$n :匹配第n个捕获组的子字符串,其中n等于0~9。例如, $1是匹配第一个捕获组的子字符串, $2是匹配第二个捕获组的子字符串,以此类推。如果正则表达式中没有定义捕获组,则使用空字符串
$nn :匹配第nn个捕获组的子字符串,其中nn等于01~99。例如, $01是匹配第一个捕获组的子字符串, $02:是匹配第二个捕获组的子字符串,以此类推。如果正则表达式中没有定义捕获组,则使用空字符串
\\通过这些特殊的字符序列,可以使用最近一次匹配结果中的内容,如下面的例子所示。
var text = "cat, bat, sat, fat";
result = text.replace(/(.at)/g, "word ($1)");
alert(result); //word (cat), word (bat), word (sat), word (fat)
  • 如果第二个参数是函数, 在只有一个匹配项(即与模式匹配的字符串)的情况下,会向这个函数传递 3 个参数:模式的匹配项、模式匹配项在字符串中的位置和原始字符串。在正则表达式中定义了多个捕获组的情况下,传递给函数的参数依次是模式的匹配项、第一个捕获组的匹配项、第二个捕获组的匹配项……,但最后两个参数仍然分别是模式的匹配项在字符串中的位置和原始字符串。
    function htmlEscape(text){
        return text.replace(/[<>"&]/g, function(match, pos, originalText){
            switch(match){
                case "<":
                    return "<";
                case ">":
                    return ">";
                case "&":
                    return "&";
                case "\"":
                    return """;
            }
        });
    }
    document.write(htmlEscape("

Hello world!

")); //<p class="greeting">Hello world!</p>
  • split():基于指定的分隔符将一个字符串分割成多个子字符串,并将结果放在一个数组中。
    • 分隔符可以是字符串,也可以是一个 RegExp 对象(这个方法不会将字符串看成正则表达式)。 split()方法可以接受可选的第二个参数,用于指定数组的大小,
      以便确保返回的数组不会超过既定大小。
    var colorText = "red,blue,green,yellow";
    var colors1 = colorText.split(","); //["red", "blue", "green", "yellow"]
    var colors2 = colorText.split(",", 2); //["red", "blue"]
    var colors3 = colorText.split(/[^\,]+/); //["", ",", ",", ",", ""]
    1. localeCompare()方法
    • 如果字符串在字母表中应该排在字符串参数之前,则返回一个负数(大多数情况下是-1,具体的值要视实现而定);
    • 如果字符串等于字符串参数,则返回 0;
    • 如果字符串在字母表中应该排在字符串参数之后,则返回一个正数(大多数情况下是 1,具体的值同样要视实现而定);
var stringValue = "yellow";
alert(stringValue.localeCompare("brick")); //1
alert(stringValue.localeCompare("yellow")); //0
alert(stringValue.localeCompare("zoo")); //-1
  • 因为 localeCompare()返回的数值取决于实现,所以最好是像下面例子所示
    的这样使用这个方法。
    var stringValue = "yellow";
    function determineOrder(value) {
        var result = stringValue.localeCompare(value);
        if (result < 0){
            document.write("The string 'yellow' comes before the string '" + value + "'.");
        }
        else if (result > 0) {
            document.write("The string 'yellow' comes after the string '" + value + "'.");
        }
        else {
            document.write("The string 'yellow' is equal to the string '" + value + "'.");
        }
    }
    determineOrder("brick");//The string 'yellow' comes after the string 'brick'.
    determineOrder("yellow");//The string 'yellow' is equal to the string 'yellow'.
    determineOrder("zoo");//The string 'yellow' comes before the string 'zoo'. 
  • localeCompare()实现所支持的地区(国家和语言)决定了这个方法的行为。比如,美国以英语作为 ECMAScript 实现的标准语言,因此 localeCompare()就是区分大小写的,于是大写字母在字母表中排在小写字母前头就成为了一项决定性的比较规则。不过,在其他地区恐怕就不是这种情况了。

    1. fromCharCode()方法
    • 接收一或多个字符编码,然后将它们转换成一个字符串。从本质上来看,这个方法与实例方法 charCodeAt()执行的是相反的操作。
alert(String.fromCharCode(104, 101, 108, 108, 111)); //"hello"
    1. HTML 方法
    • 这是一些专门用于简化常见 HTML 格式化任务的方法。下表列出了这些 HTML 方法。不过,需要请读者注意的是,应该尽量不使用这些方法,因为它们创建的标记通常无法表达语义。
      anchor(name) 方法输出结果:string
      big() 方法输出结果:string
      bold() 方法输出结果:string
      fixed() 方法输出结果:string
      fontcolor(color) 方法输出结果:string
      fontsize(size) 方法输出结果:string
      italics()方法输出结果: string
      link(url) 方法输出结果:string
      small()方法输出结果: string
      strike()方法输出结果: string
      sub() 方法输出结果:string
      sup()方法输出结果: string
  • 5.7 单体内置对象

    • ECMA-262 对内置对象的定义是:“由 ECMAScript 实现提供的、不依赖于宿主环境的对象,这些对象在 ECMAScript 程序执行之前就已经存在了。”意思就是说,开发人员不必显式地实例化内置对象,因为它们已经实例化了。前面我们已经介绍了大多数内置对象,例如 Object、 Array 和 String。ECMA-262 还定义了两个单体内置对象: Global 和 Math。
    • 5.7.1 Global对象
      • Global(全局)对象可以说是 ECMAScript 中最特别的一个对象了,因为不管你从什么角度上看,这个对象都是不存在的。 不属于任何其他对象的属性和方法,最终都是它的属性和方法。所有在全局作用域中定义的属性和函数,都是 Global 对象的属性。比如 isNaN()、isFinite()、parseInt()以及 parseFloat()。除此之外, Global 对象还包含其他一些方法。
          1. URI 编码方法
          • Global 对象的 encodeURI()encodeURIComponent()方法可以对 URI(Uniform ResourceIdentifiers,通用资源标识符)进行编码,以便发送给浏览器。有效的 URI 中不能包含某些字符,例如空格。而这两个 URI 编码方法就可以对 URI 进行编码,它们用特殊的 UTF-8 编码替换所有无效的字符,从而让浏览器能够接受和理解。
          • encodeURI():主要用于整个 URI(例如, http://www.wrox.com/illegal value.htm);不会对本身属于 URI 的特殊字符进行编码,例如冒号、正斜杠、问号和井字号;
          • encodeURIComponent():主要用于对 URI 中的某一段(例如前面 URI 中的 illegal value.htm)进行编码, 并会对任何非标准字符进行编码。
    var uri = "http://www.wrox.com/illegal value.htm#start";
    //"http://www.wrox.com/illegal%20value.htm#start"
    //只有空格被替换成了%20。
    document.write(encodeURI(uri));
    //"http%3A%2F%2Fwww.wrox.com%2Fillegal%20value.htm%23start"
    //替换了所有非字母数字字符
    document.write(encodeURIComponent(uri));
  • decodeURI():对应 encodeURI() 的解码方法;

  • decodeURIComponent():对应 encodeURIComponent() 的解码方法;

    1. eval()方法:整个 ECMAScript 语言中最强大的方法; eval()方法就像是一个完整的 ECMAScript 解析器,它只接受一个参数,即要执行的 ECMAScript (或 JavaScript)字符串。
    • 通过 eval()执行的代码被认为是包含该次调用的执行环境的一部分,
      因此被执行的代码具有与该执行环境相同的作用域链。这意味着通过 eval()执行的代码可以引用在包含环境中定义的变量:
eval("alert('hi')");
//这行代码的作用等价于下面这行代码:
alert("hi");

eval("function sayHi() { alert('hi'); }");
sayHi(); //hi

eval("var msg = 'hello world'; ");
document.write(msg); //"hello world"
  • 在 eval()中创建的任何变量或函数都不会被提升,因为在解析代码的时候,它们被包含在一个字
    符串中;它们只在 eval()执行的时候创建。
  • 严格模式下,在外部访问不到 eval()中创建的任何变量或函数,因此前面两个例子都会导致错误。同样,在严格模式下,为 eval 赋值也会导致错误;
    1. Global 对象的属性:
      undefined 特殊值undefined
      Date 构造函数Date
      NaN 特殊值NaN
      RegExp 构造函数RegExp
      Infinity 特殊值Infinity
      Error 构造函数Error
      Object 构造函数Object
      EvalError 构造函数EvalError
      Array 构造函数Array
      RangeError 构造函数RangeError
      Function 构造函数Function
      ReferenceError 构造函数ReferenceError
      Boolean 构造函数Boolean
      SyntaxError 构造函数SyntaxError
      String 构造函数String
      TypeError 构造函数TypeError
      Number 构造函数Number
      URIError 构造函数URIError
  1. window 对象:全局作用域中声明的所有变量和函数,都是 window对象的属性。
var color = "red";
function sayColor(){
alert(window.color);
}
window.sayColor(); //"red"
    //另一种取得 Global 对象的方法
    var global = function(){
        return this;
    }();
  • 5.7.2 Math对象
    • 为保存数学公式和信息提供的一个公共位置

      1. Math 对象的属性
        Math.E > 自然对数的底数,即常量e的值
        Math.LN10 > 10的自然对数
        Math.LN2 > 2的自然对数
        Math.LOG2E > 以2为底e的对数
        Math.LOG10E > 以10为底e的对数
        Math.PI > π的值
        Math.SQRT1_2 > 1/2的平方根(即2的平方根的倒数)
        Math.SQRT2 > 2的平方根
      1. min()max()方法:用于确定一组数值中的最小值和最大值。这两个方法都可以接收任意多
        个数值参数;经常用于避免多余的循环和在 if 语句中确定一组数的最大值;
    var max = Math.max(3, 54, 32, 16);
    document.write(max); //54
    var min = Math.min(3, 54, 32, 16);
    document.write(min); //3
  • 要找到数组中的最大或最小值,可以像下面这样使用 apply()方法。这个技巧的关键是把 Math 对象作为 apply()的第一个参数,从而正确地设置 this 值。然后,可以将任何数组作为第二个参数。
    var values = [1, 2, 3, 4, 5, 6, 7, 8];
    var max = Math.max.apply(Math, values);
    var max2 = Math.max(values)
    document.write(max) // 8
    document.write(max2)  //NaN
    1. 舍入方法
    • Math.ceil()执行向上舍入,即它总是将数值向上舍入为最接近的整数;
    • Math.floor()执行向下舍入,即它总是将数值向下舍入为最接近的整数;
    • Math.round()执行标准舍入,即它总是将数值四舍五入为最接近的整数(这也是我们在数学课上学到的舍入规则)。
    document.write(Math.ceil(25.9)); //26
    document.write(Math.ceil(25.5)); //26
    document.write(Math.ceil(25.1)); //26

    document.write(Math.round(25.9)); //26
    document.write(Math.round(25.5)); //26
    document.write(Math.round(25.1)); //25

    document.write(Math.floor(25.9)); //25
    document.write(Math.floor(25.5)); //25
    document.write(Math.floor(25.1)); //25
    1. random()方法:返回大于等于 0 小于 1 的一个随机数。
    • 可以利用 Math.random()从某个整数范围内随机选择一个值:
值 = Math.floor(Math.random() * 可能值的总数 + 第一个可能的值)
//如果你想选择一个 1到 10 之间的数值:
var num = Math.floor(Math.random() * 10 + 1);
//如果想要选择一个介于 2 到 10 之间的值:
var num = Math.floor(Math.random() * 9 + 2);//从 2 数到 10 要数 9 个数,因此可能值的总数就是 9,而第一个可能的值就是 2。
  • 可以通过一个函数来计算可能值的总数和第一个可能的值
    function selectFrom(lowerValue, upperValue) {
        var choices = upperValue - lowerValue + 1;
        return Math.floor(Math.random() * choices + lowerValue);
    }
    var num = selectFrom(2, 10);
    document.write(num); // 介于 2 和 10 之间(包括 2 和 10)的一个数值

    var colors = ["red", "green", "blue", "yellow", "black", "purple", "brown"];
    var color = colors[selectFrom(0, colors.length-1)];
    document.write(color); // 可能是数组中包含的任何一个字符串
    1. 其他方法
      Math.abs(num) 返回num 的绝对值
      Math.asin(x) 返回x 的反正弦值
      Math.exp(num) 返回Math.E 的num 次幂
      Math.atan(x) 返回x 的反正切值
      Math.log(num) 返回num 的自然对数
      Math.atan2(y,x) 返回y/x 的反正切值
      Math.pow(num,power) 返回num 的power 次幂
      Math.cos(x) 返回x 的余弦值
      Math.sqrt(num) 返回num 的平方根
      Math.sin(x) 返回x 的正弦值
      Math.acos(x) 返回x 的反余弦值
      Math.tan(x) 返回x 的正切值

page 146 /153 没看懂

    function selectFrom(lowerValue, upperValue) {
        var choices = upperValue - lowerValue + 1;
        return Math.floor(Math.random() * choices + lowerValue);
    }
    var num = selectFrom(2, 10);
    document.write(num); // 介于 2 和 10 之间(包括 2 和 10)的一个数值
  • ;

你可能感兴趣的:(JavaScript高级程序设计(第三版)5章)